commit f75cd771c03c893d3fd2b7e8cc91bbf459657969 Author: Scott E. Graves Date: Wed Mar 25 12:19:28 2026 -0500 Initial commit diff --git a/.cspell/words.txt b/.cspell/words.txt new file mode 100644 index 0000000..8cbf1ff --- /dev/null +++ b/.cspell/words.txt @@ -0,0 +1,481 @@ +--dearmor +--userns +-declipse +-dlog +-dosgi +1nh1shungry +_mbcs +abap +abaqus +acpiasl +ahdl +ahmedkhalf +aidl +airblade +akinsho +alacritty +ale_virtualtext_cursor +alepez +alsaconf +alskdjfhgwoeiruty +ampl +antoinemadec +apachestyle +applescript +appname +aptconf +astyle +augroup +autocmd +autocmds +autogen +autoload +autopairs +autotrigger +barbar +bartosz +bashls +bbuild +belowright +berard +bjarne +blankline +blinkoff400 +blinkon +blinkwait700 +block-blinkwait175-blinkoff150-blinkon175 +blockwise +booch +borderchars +briones +bufhidden +buflisted +bufname +bufnr +bufs +buftype +buildifier +builtins +cargill +catgoose +cclose +cflags +changedelete +chatgpt +chdir +checktime +choosewin +clangd +clangformat +clangtidy +classobj +closeoff +cmake +cmap +cmdheight +cmdline +cmp_luasnip +cnext +cnoreabbrev +codeaction +codefmt +codespell +colorcolumn +colorterm +commandline +completefunc +completeopt +conceallevel +copen +cowsay +cppcheck +cppdbg +cpplint +cppman +cpptools +cppvsdbg +cprev +ctermbg +ctermfg +cursorcolumn +cursorline +cust_ +cword +dapui +darcula +dartfmt +dartformat +dartls +datapath +dcmake_build_type +deallocating +delims +deluser +dennie +deutsch +devicons +diffoff +diffopt +diffutils +dotfiles +doums +dpkg +drucker +dstein64 +dsun +dviml +dviml2 +dviml_common +easymotion +echohl +editmsg +edsger +enable_autosnippets +enabledelayedexpansion +enableextensions +endfunction +endlocal +equalalways +errorbells +eslint +eval +executable +expandtab +extmark +fannheyward +fernflower +fifthgrid +fileencoding +fileformat +filereadable +fillchars +findstr +findutils +fname +fnamemodify +focusable +foldcolumn +folke +force_twostep +freepos +fs_copyfile +fs_scandir +fs_scandir_next +ftplugin +funcobj +gerrand +getbufinfo +getcmdline +getcmdtype +getcwd +getreg +gettype +gitsigns +globalstatus +glyn +gname +gofmt +gofumpt +gopls +gos +gpath +gradlew +gruvbox +gtest +guibg +guicursor +guifg +guifont +guioptions +guipopupmenu +helpclose +hinz +hlsearch +hoare +homedrive +homepath +honza +hrsh7th +hrtime +ignorecase +imap +incsearch +indentexpr +invrelativenumber +invwrap +isdirectory +iskeyword +javaagent +javaw +jdtls +joinpath +jsdoc +kanagawa +keeppattern +kernighan +keycodes +keymap +keymaps +keyrings +keywordprg +kosayoda +kyazdani42 +kylechui +lamport +laststatus +lclose +leoluz +linder +linehl +linematch +listchars +lldb +lnext +localappdata +localedef +loclist +lopen +lprev +lspconfig +luadev +luadoc +luafmt +luaformat +luaformatter +luaformatterfiveone +lualine +luap +luaparenerror +luasnip +lukas +madskjeldgaard +maktaba +malloc +map_multistep +mapleader +maplocalleader +markdownlint +matchpairs +matchparen +matchparenforeground +mathisen +maxmempattern +menuone +messagesopt +mfussenegger +mhartington +mhinz +milewski +minipairs +minipairs_cr +minisnippets +minisnippets_expand +minisnippets_next +mkdir +mosher +mosher's +mousehide +msgsep +multibyte +multigrid +muniftanjim +mvdan +mvnw +nbsp +neoclide +neodev +neomake +neotest +neovide +neovim +nmakeprg +nmap +nobackup +nocp +noequalalways +nofile +nohl +noice +noinsert +nokernelcrypto +nomousehide +nopasswd +norcalli +noremap +noselect +noshowmode +notificationss +nowait +nowrap +nowritebackup +nuff +numberwidth +numhl +nv_darcula_open_nvim_tree +nvim +nvim_feedkeys +nvimrc +olivercederborg +omnifunc +omnisharp +openai_params +opleader +outputresource +packadd +packloadall +pcbp +phaazon +phpdoc +pmenu +poimandres +popd +popupmenu +precondit +proto +pubspec +pumborder +pumvisible +puremourning +pushd +python3-venv +pythonpath +qall +qflist +quickfix +rcarriga +readfile +readlink +rebelot +redrawtime +reflog +reindent_linewise +reineke +relativenumber +ringbuf +rktjmp +rustfmt +saadparwaiz1 +sainnhe +sbar +scrolloff +scrollview +setlocal +setloclist +setreg +setup_jsonls +sgraves +shada +sheerun +shellcheck +shellcmdflag +shfmt +shiftwidth +shortmess +show_autosnippets +showbreak +showmatch +showmode +sidescrolloff +signcolumn +skynet_mount +smartcase +softtabstop +splitbelow +splitright +starlark +statox +statusline +stdpath +stevearc +stlnc +stroustrup +struct +strwidth +stsewd +sumhexa +sumneko +swapfile +swartz +sysname +systemlist +tabclose +tabfirst +tablast +tabline +tabnew +tabnext +tabprevious +terje +termcodes +termguicolors +texthl +textobjects +thirdparty +tmap +to_vimscript +topdelete +tpope +treesitter +truecolor +tspunctbracket +tspunctdelimiter +tspunctspecial +tsuri +ttimeoutlen +tufte +ultisnips +undodir +undofile +unittests +unnamedplus +unstaged +updatetime +usercmds +userprofile +utctime +utils +vala +valac +venv +vim_startify +vimc +vimdoc +vimfiles +vimgrep +viminfo +vimls +vimlsp +vimo +vimrc +vimruntime +vimspector +vimspectorballooneval +vimspectorbpcond +vimspectoreval +virt +vmap +vmargs +vsdbg +vsplit +wadler +wilczek +wildmenu +wildmode +williamboman +winblend +winborder +wincmd +windwp +winfixheight +winfixwidth +winhighlight +wmdocker +writebackup +writefile +xbootclasspath +xiyaowong +xlog +xmap +xvzf +yapf +yaps \ No newline at end of file diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..eef6906 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,3 @@ +# .dockerignore +nvim/coc-settings.json +nvim/nvim-pack-lock.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..eee97eb --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +.git/ +coc-settings.json +cspell.json +dap/ +nvim-pack-lock.json +nvim/lua/darcula/custom.lua +pkg/ diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..13b40b8 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,275 @@ +## The MIT License (MIT) +## +## Copyright © 2026 Scott E. Graves +## +## Permission is hereby granted, free of charge, to any person obtaining a copy of this software +## and associated documentation files (the “Software”), to deal in the Software without restriction, +## including without limitation the rights to use, copy, modify, merge, publish, distribute, +## sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +## furnished to do so, subject to the following conditions: +## +## The above copyright notice and this permission notice shall be included in all copies or +## substantial portions of the Software. +## +## THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +## BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +## NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +## DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +## +FROM ubuntu:noble +MAINTAINER Scott E. Graves + +USER root + +ARG NVIM_ARCH +ARG NVIM_ARCH2 +ARG NVIM_OS +ARG NV_DARCULA_ENABLE_COC + +ENV \ + GID="1000" \ + GNAME="neovim" \ + LANG=en_US.utf8 \ + NVIM_APPNAME=nvim \ + NV_DARCULA_APPS="/home/neovim/.local/share/nvim/" \ + NV_DARCULA_ENABLE_COC=${NV_DARCULA_ENABLE_COC} \ + PATH="/nvim-${NVIM_OS}-${NVIM_ARCH}/bin:/python/bin:/home/neovim/go/bin:/home/neovim/.local/bin:/home/neovim/flutter/bin:/home/neovim/.pub-cache/bin:/usr/bin/core_perl:${PATH}" \ + PYTHONPATH="/python" \ + SHELL="/bin/bash" \ + TMPDIR=/tmp \ + UID="1000" \ + UNAME="neovim" + +RUN \ + apt-get update -y && apt-get upgrade -y && \ + apt-get install -y curl locales software-properties-common && \ + localedef -i en_US -c -f UTF-8 -A /usr/share/locale/locale.alias en_US.UTF-8 && \ + curl -fsSL https://deb.nodesource.com/setup_lts.x | bash - && \ + install -m 0755 -d /etc/apt/keyrings && \ + curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg && \ + chmod a+r /etc/apt/keyrings/docker.gpg && \ + echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null && \ + add-apt-repository ppa:unit193/encryption -y && \ + apt-get update -y && \ + apt-get install -y \ + android-sdk \ + android-sdk-build-tools \ + autoconf \ + automake \ + bash \ + bzip2 \ + clang \ + cmake \ + codespell \ + containerd.io \ + cppcheck \ + curl \ + diffutils \ + docker-buildx-plugin \ + docker-ce \ + docker-ce-cli \ + docker-compose-plugin \ + findutils \ + fuse3 \ + fzf \ + gcc \ + git \ + gnupg \ + golang \ + grep \ + gzip \ + jq \ + less \ + libtool \ + llvm \ + m4 \ + make \ + nano \ + ninja-build \ + nodejs \ + openjdk-21-jdk \ + openssh-client \ + openssh-server \ + patch \ + perl \ + pkgconf \ + python3 \ + python3-pip \ + python3-venv \ + ripgrep \ + rsync \ + shellcheck \ + sed \ + tar \ + tidy \ + unrar \ + unzip \ + valac \ + valgrind \ + veracrypt \ + vlc \ + wget \ + wmdocker \ + zip && \ + apt clean && \ + rm -rf /var/lib/apt/lists/* && \ + deluser ubuntu && \ + rm -rf /home/ubuntu && \ + groupadd -g ${GID} "${GNAME}" && \ + useradd -m -u ${UID} -g ${GNAME} -s ${SHELL} ${UNAME} && \ + echo "${UNAME} ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers && \ + groupmod -g 962 docker && \ + groupmod -a -U ${UNAME} docker + +COPY \ + entrypoint.sh /entrypoint.sh + +RUN \ + chmod +x /entrypoint.sh && \ + chown ${UNAME}:${GNAME} /entrypoint.sh + +RUN \ + git clone https://github.com/LuaLS/lua-language-server && \ + cd lua-language-server && \ + chmod +x ./make.sh && \ + ./make.sh && \ + mv lua-language-server /usr/bin && \ + chmod +x /usr/bin/lua-language-server && \ + cd - && \ + rm -rf lua-language-server + +RUN \ + npm i -g cspell && \ + npm i -g eslint && \ + npm i -g js-beautify && \ + npm i -g lua-fmt && \ + npm i -g neovim && \ + npm i -g npm && \ + npm i -g prettier && \ + npm i -g tree-sitter-cli + +RUN \ + python3 -m venv /python && \ + pip3 install -U pip && \ + pip3 install -U cmake-language-server && \ + pip3 install -U coverage && \ + pip3 install -U cpplint && \ + pip3 install -U jedi && \ + pip3 install -U jedi-language-server && \ + pip3 install -U neovim && \ + pip3 install -U pylint && \ + CFLAGS=-Wno-incompatible-pointer-types pip3 install -U cppman + +COPY \ + nvim/ /root/.config/nvim/ + +COPY \ + dap/ /root/.config/nvim/dap/ + +COPY \ + pkg/ /root/.config/nvim/pkg/ + +RUN \ + tar xvzf /root/.config/nvim/pkg/nvim-${NVIM_OS}-${NVIM_ARCH}.tar.gz -C / + +RUN \ + mkdir -p "${NV_DARCULA_APPS}/dap/cpp" && \ + unzip /root/.config/nvim/dap/cpptools-${NVIM_OS}-${NVIM_ARCH2}.vsix -d "${NV_DARCULA_APPS}/dap/cpp" && \ + chmod +x "${NV_DARCULA_APPS}/dap/cpp/extension/debugAdapters/bin/OpenDebugAD7" && \ + cd "${NV_DARCULA_APPS}" && \ + git clone https://github.com/Dart-Code/Dart-Code.git && \ + cd "${NV_DARCULA_APPS}/Dart-Code" && \ + npm i && \ + npx webpack --mode production + +RUN \ + nvim --headless "+qall" + +RUN \ + if [ "$NV_DARCULA_ENABLE_COC" = "true" ]; then \ + nvim --headless "+CocInstall -sync coc-calc" "+qall" && \ + nvim --headless "+CocInstall -sync coc-clang-format-style-options" "+qall" && \ + nvim --headless "+CocInstall -sync coc-clangd" "+qall" && \ + nvim --headless "+CocInstall -sync coc-cmake" "+qall" && \ + nvim --headless "+CocInstall -sync coc-css" "+qall" && \ + nvim --headless "+CocInstall -sync coc-eslint" "+qall" && \ + nvim --headless "+CocInstall -sync coc-flutter" "+qall" && \ + nvim --headless "+CocInstall -sync coc-go" "+qall" && \ + nvim --headless "+CocInstall -sync coc-highlight" "+qall" && \ + nvim --headless "+CocInstall -sync coc-html" "+qall" && \ + nvim --headless "+CocInstall -sync coc-java" "+qall" && \ + nvim --headless "+CocInstall -sync coc-jedi" "+qall" && \ + nvim --headless "+CocInstall -sync coc-jest" "+qall" && \ + nvim --headless "+CocInstall -sync coc-json" "+qall" && \ + nvim --headless "+CocInstall -sync coc-lightbulb" "+qall" && \ + nvim --headless "+CocInstall -sync coc-markdownlint" "+qall" && \ + nvim --headless "+CocInstall -sync coc-omnisharp" "+qall" && \ + nvim --headless "+CocInstall -sync coc-powershell" "+qall" && \ + nvim --headless "+CocInstall -sync coc-react-refactor" "+qall" && \ + nvim --headless "+CocInstall -sync coc-sh" "+qall" && \ + nvim --headless "+CocInstall -sync coc-snippets" "+qall" && \ + nvim --headless "+CocInstall -sync coc-spell-checker" "+qall" && \ + nvim --headless "+CocInstall -sync coc-sumneko-lua" "+qall" && \ + nvim --headless "+CocInstall -sync coc-tsserver" "+qall" && \ + nvim --headless "+CocInstall -sync coc-vimlsp" "+qall" && \ + nvim --headless init.lua +CocStart \ + "+lua vim.defer_fn(function() vim.cmd('CocCommand sumneko-lua.install') end, 5000)" \ + "+lua vim.defer_fn(function() vim.cmd('qall') end, 15000)" && \ + nvim --headless init.lua +CocStart \ + "+lua vim.defer_fn(function() vim.cmd('CocCommand sumneko-lua.downloadNvimLuaTypes') end, 5000)" \ + "+lua vim.defer_fn(function() vim.cmd('qall') end, 15000)"; \ + fi + +RUN \ + nvim --headless "+TSUpdate" \ + "+lua vim.defer_fn(function() vim.cmd('qall') end, 60000)" + +RUN \ + rsync -av --progress --delete /root/.config/ /home/${UNAME}/.config/ && \ + rsync -av --progress --delete /root/.local/ /home/${UNAME}/.local/ + +RUN \ + chown -R ${UNAME}:${GNAME} /home/${UNAME} + +USER ${UNAME} + +ENV \ + GID="1000" \ + GNAME="neovim" \ + LANG=en_US.utf8 \ + NVIM_APPNAME=nvim \ + NV_DARCULA_APPS="/home/neovim/.local/share/nvim/" \ + NV_DARCULA_ENABLE_COC=${NV_DARCULA_ENABLE_COC} \ + PATH="/nvim-${NVIM_OS}-${NVIM_ARCH}/bin:/python/bin:/home/neovim/go/bin:/home/neovim/.local/bin:/home/neovim/flutter/bin:/home/neovim/.pub-cache/bin:/usr/bin/core_perl:${PATH}" \ + PYTHONPATH="/python" \ + SHELL="/bin/bash" \ + TMPDIR=/tmp \ + UID="1000" \ + UNAME="neovim" + +RUN \ + cd "/home/${UNAME}" && \ + git clone https://github.com/flutter/flutter.git -b stable flutter && \ + cd - && \ + flutter && \ + flutter doctor && \ + flutter pub global activate dart_style + +RUN \ + if [ "$NV_DARCULA_ENABLE_COC" = "false" ]; then \ + nvim --headless "+MasonToolsInstallSync" "+qall" && \ + nvim --headless "+LspInstall bashls" "+qall" && \ + nvim --headless "+LspInstall clangd" "+qall" && \ + nvim --headless "+LspInstall cspell_ls" "+qall" && \ + nvim --headless "+LspInstall gopls" "+qall" && \ + nvim --headless "+LspInstall lua_ls" "+qall" && \ + nvim --headless "+LspInstall vimls" "+qall"; \ + fi + +RUN \ + go install mvdan.cc/sh/v3/cmd/shfmt@latest + +ENTRYPOINT ["/entrypoint.sh"] + +# vim:filetype=dockerfile diff --git a/build_all.sh b/build_all.sh new file mode 100755 index 0000000..860787e --- /dev/null +++ b/build_all.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash + +## The MIT License (MIT) +## +## Copyright © 2026 Scott E. Graves +## +## Permission is hereby granted, free of charge, to any person obtaining a copy of this software +## and associated documentation files (the “Software”), to deal in the Software without restriction, +## including without limitation the rights to use, copy, modify, merge, publish, distribute, +## sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +## furnished to do so, subject to the following conditions: +## +## The above copyright notice and this permission notice shall be included in all copies or +## substantial portions of the Software. +## +## THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +## BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +## NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +## DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +## +SCRIPT_DIR="$(dirname "$(readlink -f "$0")")" + +docker system prune -a -f +"${SCRIPT_DIR}/build_nvim.sh" +"${SCRIPT_DIR}/build_nvim2.sh" diff --git a/build_common.sh b/build_common.sh new file mode 100755 index 0000000..31df5f7 --- /dev/null +++ b/build_common.sh @@ -0,0 +1,34 @@ +#!/usr/bin/env bash + +## The MIT License (MIT) +## +## Copyright © 2026 Scott E. Graves +## +## Permission is hereby granted, free of charge, to any person obtaining a copy of this software +## and associated documentation files (the “Software”), to deal in the Software without restriction, +## including without limitation the rights to use, copy, modify, merge, publish, distribute, +## sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +## furnished to do so, subject to the following conditions: +## +## The above copyright notice and this permission notice shall be included in all copies or +## substantial portions of the Software. +## +## THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +## BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +## NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +## DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +## +SCRIPT_DIR="$(dirname "$(readlink -f "$0")")" +. "${SCRIPT_DIR}/common.sh" + +pushd "${SCRIPT_DIR}" 1>/dev/null 2>&1 || error_exit "failed to pushd: ${SCRIPT_DIR}" +docker build \ + --build-arg NVIM_ARCH="${NVIM_ARCH}" \ + --build-arg NVIM_ARCH2="${NVIM_ARCH2}" \ + --build-arg NVIM_OS="${NVIM_OS}" \ + --build-arg NV_DARCULA_ENABLE_COC="${NV_DARCULA_ENABLE_COC}" \ + --no-cache \ + -f "Dockerfile" \ + -t "darcula:${NVIM_APPNAME}" . +popd 1>/dev/null 2>&1 || error_exit "failed to popd: ${SCRIPT_DIR}" diff --git a/build_nvim.sh b/build_nvim.sh new file mode 100755 index 0000000..fd95a8e --- /dev/null +++ b/build_nvim.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash + +## The MIT License (MIT) +## +## Copyright © 2026 Scott E. Graves +## +## Permission is hereby granted, free of charge, to any person obtaining a copy of this software +## and associated documentation files (the “Software”), to deal in the Software without restriction, +## including without limitation the rights to use, copy, modify, merge, publish, distribute, +## sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +## furnished to do so, subject to the following conditions: +## +## The above copyright notice and this permission notice shall be included in all copies or +## substantial portions of the Software. +## +## THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +## BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +## NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +## DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +## +SCRIPT_DIR="$(dirname "$(readlink -f "$0")")" + +NVIM_APPNAME=nvim +export NVIM_APPNAME + +NV_DARCULA_ENABLE_COC=true +export NV_DARCULA_ENABLE_COC + +"${SCRIPT_DIR}/build_common.sh" "$@" diff --git a/build_nvim2.sh b/build_nvim2.sh new file mode 100755 index 0000000..cd96fcd --- /dev/null +++ b/build_nvim2.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash + +## The MIT License (MIT) +## +## Copyright © 2026 Scott E. Graves +## +## Permission is hereby granted, free of charge, to any person obtaining a copy of this software +## and associated documentation files (the “Software”), to deal in the Software without restriction, +## including without limitation the rights to use, copy, modify, merge, publish, distribute, +## sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +## furnished to do so, subject to the following conditions: +## +## The above copyright notice and this permission notice shall be included in all copies or +## substantial portions of the Software. +## +## THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +## BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +## NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +## DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +## +SCRIPT_DIR="$(dirname "$(readlink -f "$0")")" + +NVIM_APPNAME=nvim2 +export NVIM_APPNAME + +NV_DARCULA_ENABLE_COC=false +export NV_DARCULA_ENABLE_COC + +"${SCRIPT_DIR}/build_common.sh" "$@" diff --git a/common.sh b/common.sh new file mode 100755 index 0000000..e8e4071 --- /dev/null +++ b/common.sh @@ -0,0 +1,97 @@ +#!/usr/bin/env bash + +## The MIT License (MIT) +## +## Copyright © 2026 Scott E. Graves +## +## Permission is hereby granted, free of charge, to any person obtaining a copy of this software +## and associated documentation files (the “Software”), to deal in the Software without restriction, +## including without limitation the rights to use, copy, modify, merge, publish, distribute, +## sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +## furnished to do so, subject to the following conditions: +## +## The above copyright notice and this permission notice shall be included in all copies or +## substantial portions of the Software. +## +## THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +## BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +## NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +## DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +## +SCRIPT_DIR="$(dirname "$(readlink -f "$0")")" + +NVIM_CPPTOOLS_VERSION=1.30.5 +NVIM_VERSION=nightly + +NVIM_ARCH=x86_64 +NVIM_ARCH2=x64 +if uname -m | grep arm; then + NVIM_ARCH=arm64 + NVIM_ARCH2=arm64 +fi + +if uname | grep 'Darwin'; then + NVIM_OS="macOS" +else + NVIM_OS="linux" +fi + +function create_link() { + local cur + local res + + cur=$(readlink -f "$2") + res=$(readlink -f "$1") + if [ ! -L "$2" ] || [ "${cur}" != "${res}" ]; then + echo "linking $1->$2" + rm -f "$2" 1>/dev/null 2>&1 + ln -sf "$1" "$2" + fi +} + +function error_exit() { + echo "$1" + exit 1 +} + +pushd "${SCRIPT_DIR}" 1>/dev/null 2>&1 || error_exit "failed to push: ${SCRIPT_DIR}" +FNAME=cpptools-${NVIM_OS}-${NVIM_ARCH2}.vsix +if [ ! -f "dap/${FNAME}" ]; then + mkdir -p dap/ + wget "https://github.com/microsoft/vscode-cpptools/releases/download/v${NVIM_CPPTOOLS_VERSION}/${FNAME}" \ + -O "dap/${FNAME}" +fi + +if [ ! -d "${HOME}/.local/share/${NVIM_APPNAME}/dap/cpp/extension" ]; then + mkdir -p "${HOME}/.local/share/${NVIM_APPNAME}/dap/cpp" + unzip "dap/${FNAME}" -d "${HOME}/.local/share/${NVIM_APPNAME}/dap/cpp" +fi + +mkdir -p pkg/ +if [ ! -f "/tmp/nvim-${NVIM_OS}-${NVIM_ARCH}/bin/nvim" ]; then + FNAME=nvim-${NVIM_OS}-${NVIM_ARCH}.tar.gz + [[ -f "pkg/${FNAME}" ]] && rm -f "pkg/${FNAME}" + + wget "https://github.com/neovim/neovim/releases/download/${NVIM_VERSION}/${FNAME}" \ + -O "pkg/${FNAME}" +fi + +if [ ! -d "${HOME}/.local/share/${NVIM_APPNAME}/Dart-Code" ]; then + mkdir -p "${HOME}/.local/share/${NVIM_APPNAME}" + pushd "${HOME}/.local/share/${NVIM_APPNAME}" 1>/dev/null 2>&1 || + error_exit "failed to pushd: ${HOME}/.local/share/${NVIM_APPNAME}" + git clone https://github.com/Dart-Code/Dart-Code.git + pushd "Dart-Code" 1>/dev/null 2>&1 || error_exit "failed to pushd: Dart-Code" + npm i + npx webpack --mode production + popd 1>/dev/null 2>&1 || error_exit "failed to popd: Dart-Code" + popd 1>/dev/null 2>&1 || error_exit "failed to popd: ${HOME}/.local/share/${NVIM_APPNAME}" +fi +popd 1>/dev/null 2>&1 || error_exit "failed to popd: ${SCRIPT_DIR}" + +export NVIM_ARCH +export NVIM_ARCH2 +export NVIM_CPPTOOLS_VERSION +export NVIM_VERSION +export NVIM_OS diff --git a/create_tarballs.sh b/create_tarballs.sh new file mode 100755 index 0000000..a52dc77 --- /dev/null +++ b/create_tarballs.sh @@ -0,0 +1,55 @@ +#!/usr/bin/env bash + +## The MIT License (MIT) +## +## Copyright © 2026 Scott E. Graves +## +## Permission is hereby granted, free of charge, to any person obtaining a copy of this software +## and associated documentation files (the “Software”), to deal in the Software without restriction, +## including without limitation the rights to use, copy, modify, merge, publish, distribute, +## sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +## furnished to do so, subject to the following conditions: +## +## The above copyright notice and this permission notice shall be included in all copies or +## substantial portions of the Software. +## +## THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +## BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +## NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +## DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +## +# shellcheck source=../../.desktop/scripts/functions.sh +. "${HOME}/.desktop/scripts/functions.sh" + +CUR_DIR=$(pwd) + +HOME_FILE="${CUR_DIR}/home.tar.gz" +NEOVIM_FILE="${CUR_DIR}/neovim.tar.gz" + +TAR_EXCLUDES=( + --exclude=.android + --exclude=.bash* + --exclude=.cache + --exclude=.config/go + --exclude=.config/nvim/dap + --exclude=.config/nvim/pkg + --exclude=.dart-tool + --exclude=.flutter + --exclude=.npm + --exclude=.profile + --exclude=.pub-cache + --exclude=flutter + --exclude=go/pkg + --exclude=go/src +) + +pushd "${HOME}" 1>/dev/null 2>&1 || error_exit "failed to pushd: ${HOME}" +rm -f "${HOME_FILE}" +tar czvf "${HOME_FILE}" "${TAR_EXCLUDES[@]}" . +popd 1>/dev/null 2>&1 || error_exit "failed to popd: ${HOME}" + +rm -f "${NEOVIM_FILE}" +tar czvf "${NEOVIM_FILE}" \ + "$(npm root -g)/neovim/" \ + "$(npm prefix -g)/bin/neovim-node-host" diff --git a/dviml.sh b/dviml.sh new file mode 100755 index 0000000..4e57d3e --- /dev/null +++ b/dviml.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash + +## The MIT License (MIT) +## +## Copyright © 2026 Scott E. Graves +## +## Permission is hereby granted, free of charge, to any person obtaining a copy of this software +## and associated documentation files (the “Software”), to deal in the Software without restriction, +## including without limitation the rights to use, copy, modify, merge, publish, distribute, +## sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +## furnished to do so, subject to the following conditions: +## +## The above copyright notice and this permission notice shall be included in all copies or +## substantial portions of the Software. +## +## THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +## BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +## NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +## DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +## +SCRIPT_DIR="$(dirname "$(readlink -f "$0")")" + +NVIM_APPNAME=nvim +export NVIM_APPNAME + +"${SCRIPT_DIR}/dviml_common.sh" "$@" diff --git a/dviml2.sh b/dviml2.sh new file mode 100755 index 0000000..23c27fa --- /dev/null +++ b/dviml2.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash + +## The MIT License (MIT) +## +## Copyright © 2026 Scott E. Graves +## +## Permission is hereby granted, free of charge, to any person obtaining a copy of this software +## and associated documentation files (the “Software”), to deal in the Software without restriction, +## including without limitation the rights to use, copy, modify, merge, publish, distribute, +## sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +## furnished to do so, subject to the following conditions: +## +## The above copyright notice and this permission notice shall be included in all copies or +## substantial portions of the Software. +## +## THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +## BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +## NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +## DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +## +SCRIPT_DIR="$(dirname "$(readlink -f "$0")")" + +NVIM_APPNAME=nvim2 +export NVIM_APPNAME + +"${SCRIPT_DIR}/dviml_common.sh" "$@" diff --git a/dviml_common.sh b/dviml_common.sh new file mode 100755 index 0000000..412735f --- /dev/null +++ b/dviml_common.sh @@ -0,0 +1,45 @@ +#!/usr/bin/env bash + +## The MIT License (MIT) +## +## Copyright © 2026 Scott E. Graves +## +## Permission is hereby granted, free of charge, to any person obtaining a copy of this software +## and associated documentation files (the “Software”), to deal in the Software without restriction, +## including without limitation the rights to use, copy, modify, merge, publish, distribute, +## sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +## furnished to do so, subject to the following conditions: +## +## The above copyright notice and this permission notice shall be included in all copies or +## substantial portions of the Software. +## +## THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +## BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +## NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +## DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +## +APP_DIR="${HOME}/.nv_darcula/${NVIM_APPNAME}" +APP_PERSIST_DIR="${APP_DIR}/persist" + +# SCRIPT_DIR="$(dirname "$(readlink -f "$0")")" +# -v "${SCRIPT_DIR}/${NVIM_APPNAME}":/home/neovim/.config/nvim:z \ + +mkdir -p "${APP_PERSIST_DIR}/cache" +mkdir -p "${APP_PERSIST_DIR}/nvim-haven" +mkdir -p "${APP_PERSIST_DIR}/shada" +mkdir -p "${APP_PERSIST_DIR}/swap" +mkdir -p "${APP_PERSIST_DIR}/undo" + +docker run --rm -it \ + --device /dev/fuse \ + --privileged=true \ + -v "${APP_PERSIST_DIR}/cache":/home/neovim/.cache:z \ + -v "${APP_PERSIST_DIR}/nvim-haven":/home/neovim/.local/share/nvim/nvim-haven:z \ + -v "${APP_PERSIST_DIR}/shada":/home/neovim/.local/state/nvim/shada:z \ + -v "${APP_PERSIST_DIR}/swap":/home/neovim/.local/state/nvim/swap:z \ + -v "${APP_PERSIST_DIR}/undo":/home/neovim/.local/share/nvim/.undo:z \ + -v /var/run/docker.sock:/var/run/docker.sock \ + -v "$(pwd)":"$(pwd)" \ + -w "$(pwd)" \ + darcula:"${NVIM_APPNAME}" "$@" diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100755 index 0000000..c168262 --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,37 @@ +#!/usr/bin/env bash + +## The MIT License (MIT) +## +## Copyright © 2026 Scott E. Graves +## +## Permission is hereby granted, free of charge, to any person obtaining a copy of this software +## and associated documentation files (the “Software”), to deal in the Software without restriction, +## including without limitation the rights to use, copy, modify, merge, publish, distribute, +## sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +## furnished to do so, subject to the following conditions: +## +## The above copyright notice and this permission notice shall be included in all copies or +## substantial portions of the Software. +## +## THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +## BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +## NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +## DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +## +export PATH + +if [ -f "/data" ]; then + mkdir -p ~/mnt/data + veracrypt -t -m=nokernelcrypto /data ~/mnt/data || exit 1 +fi + +if [[ -z $* ]]; then + /bin/bash +else + /bin/bash -c 'exec nvim "$@"' /bin/bash "$@" +fi + +if [ -f "/data" ]; then + veracrypt -d ~/mnt/data || (echo "sleeping" && sleep 5 && veracrypt -d ~/mnt/data) +fi diff --git a/icons/COblivion.ico b/icons/COblivion.ico new file mode 100644 index 0000000..160fe65 Binary files /dev/null and b/icons/COblivion.ico differ diff --git a/icons/Oblivion.ico b/icons/Oblivion.ico new file mode 100644 index 0000000..7b459fe Binary files /dev/null and b/icons/Oblivion.ico differ diff --git a/icons/dracula.ico b/icons/dracula.ico new file mode 100644 index 0000000..f94e96a Binary files /dev/null and b/icons/dracula.ico differ diff --git a/nvim/coc-settings.unix.json b/nvim/coc-settings.unix.json new file mode 100644 index 0000000..6fe6014 --- /dev/null +++ b/nvim/coc-settings.unix.json @@ -0,0 +1,4 @@ +{ + "Lua.telemetry.enable": false, + "snippets.ultisnips.pythonPrompt": false +} diff --git a/nvim/coc-settings.windows.json b/nvim/coc-settings.windows.json new file mode 100644 index 0000000..6fe6014 --- /dev/null +++ b/nvim/coc-settings.windows.json @@ -0,0 +1,4 @@ +{ + "Lua.telemetry.enable": false, + "snippets.ultisnips.pythonPrompt": false +} diff --git a/nvim/init.lua b/nvim/init.lua new file mode 100644 index 0000000..a0fd39e --- /dev/null +++ b/nvim/init.lua @@ -0,0 +1,35 @@ +-- The MIT License (MIT) +-- +-- Copyright © 2026 Scott E. Graves +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software +-- and associated documentation files (the “Software”), to deal in the Software without restriction, +-- including without limitation the rights to use, copy, modify, merge, publish, distribute, +-- sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in all copies or +-- substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +-- BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +-- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +-- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-- + +require("darcula.config") +require("darcula.plugins") + +require("darcula.utils.globals") + +require("darcula.options") +require("darcula.cspell") + +require("darcula.setup") + +require("darcula.keymaps") +require("darcula.autocmds") +require("darcula.usercmds") + +pcall(require, "darcula.custom") diff --git a/nvim/lua/darcula/autocmds.lua b/nvim/lua/darcula/autocmds.lua new file mode 100644 index 0000000..cb48895 --- /dev/null +++ b/nvim/lua/darcula/autocmds.lua @@ -0,0 +1,238 @@ +-- The MIT License (MIT) +-- +-- Copyright © 2026 Scott E. Graves +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software +-- and associated documentation files (the “Software”), to deal in the Software without restriction, +-- including without limitation the rights to use, copy, modify, merge, publish, distribute, +-- sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in all copies or +-- substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +-- BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +-- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +-- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-- +local utils = require("darcula.utils") + +local group = + utils.augroup_with_autocmd( + "DarculaAutoCommands", + "BufReadPost", + "*", + function() + local pos = vim.fn.line('\'"') + if + pos >= 1 and pos <= vim.fn.line("$") and vim.bo.filetype ~= "commit" and + vim.bo.filetype ~= "rebase" + then + vim.cmd('normal! g`"') + end + end +) + +utils.autocmd( + group, + "FileChangedShellPost", + "*", + function(args) + local filename = utils.get_current_filename(args.buf) + vim.notify("File changed on disk:\n" .. filename, vim.log.levels.WARN) + end +) + +utils.autocmd( + group, + {"FocusGained", "BufEnter", "CursorHold", "CursorHoldI"}, + "*", + function() + local m = vim.fn.mode(0) + if m ~= "c" and m ~= "cv" and m ~= "t" and vim.o.buftype ~= "nofile" then + vim.cmd("silent! checktime") + end + end +) + +utils.autocmd( + group, + "TextYankPost", + "*", + function() + vim.highlight.on_yank({timeout = 250}) + end +) + +utils.autocmd( + group, + "FileType", + "lua", + function() + vim.cmd("hi luaParenError guibg=NONE") + end +) + +utils.autocmd( + group, + "ColorScheme", + "*", + function() + NV_DARCULA_COLOR_SCHEME = + vim.api.nvim_exec2("colorscheme", {output = true}).output + end +) + +utils.autocmd( + group, + "VimEnter", + "*", + function() + NV_Darcula_Set_Gui_Font(0) + NV_Darcula_Set_Gui_Popup(false) + end +) + +utils.autocmd(group, "DirChanged", "*", NV_Darcula_Load_RC) +utils.autocmd(group, "VimEnter", "*", NV_Darcula_Load_RC) + +utils.autocmd( + group, + "FileType", + "help", + function() + vim.opt_local.signcolumn = "no" + end +) + +utils.autocmd( + group, + "User", + {"FugitiveChanged", "GitSignsUpdate"}, + function() + local api = require("nvim-tree.api") + if api.tree.is_visible() then + pcall(api.tree.reload) + end + end +) + +utils.autocmd( + group, + "FileType", + "*", + function(args) + pcall(vim.treesitter.start, args.buf) + end +) + +if not NV_DARCULA_ENABLE_COC then + utils.autocmd( + group, + "User", + { + "MiniCompletionWindowOpen", + "MiniCompletionWindowUpdate" + }, + function(args) + local data = args.data + if not data or not data.win_id then + return + end + + if data.kind ~= "info" and data.kind ~= "signature" then + return + end + + if vim.api.nvim_win_is_valid(data.win_id) then + vim.api.nvim_win_set_config( + data.win_id, + { + title = "" + } + ) + end + end + ) +end + +utils.autocmd( + group, + "BufEnter", + "*", + function() + if vim.bo.filetype == "fugitive" or vim.bo.filetype == "gitcommit" then + vim.cmd("resize 15") + end + end +) + +utils.autocmd( + group, + "BufWritePost", + "*", + function() + if NV_DARCULA_ENABLE_FORMATTING then + vim.cmd("FormatWriteLock") + end + end +) + +if not NV_DARCULA_ENABLE_COC then + utils.autocmd( + group, + {"CursorHold"}, + "*", + function() + vim.diagnostic.open_float(nil, {focus = false}) + end + ) +end + +if NV_DARCULA_ENABLE_COC then + local show_signature_help = function() + if vim.bo.buftype ~= "prompt" and vim.bo.buftype ~= "nofile" then + vim.fn.CocActionAsync("showSignatureHelp") + end + end + + utils.autocmd(group, "User", "CocJumpPlaceholder", show_signature_help) + + utils.autocmd( + group, + {"InsertEnter", "TextChangedI"}, + "*", + show_signature_help + ) + + utils.autocmd( + group, + "CursorHold", + "*", + function() + if vim.bo.buftype ~= "prompt" and vim.bo.buftype ~= "nofile" then + vim.fn.CocActionAsync("highlight") + end + end + ) + + utils.autocmd( + group, + "User", + "CocNvimInit", + function() + vim.notify("Initialized coc.nvim for LSP support", vim.log.levels.INFO) + end + ) +end + +utils.autocmd( + group, + "VimResized", + "*", + function() + MiniNotify.refresh() + end +) diff --git a/nvim/lua/darcula/config/init.lua b/nvim/lua/darcula/config/init.lua new file mode 100644 index 0000000..5135de5 --- /dev/null +++ b/nvim/lua/darcula/config/init.lua @@ -0,0 +1,230 @@ +-- The MIT License (MIT) +-- +-- Copyright © 2026 Scott E. Graves +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software +-- and associated documentation files (the “Software”), to deal in the Software without restriction, +-- including without limitation the rights to use, copy, modify, merge, publish, distribute, +-- sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in all copies or +-- substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +-- BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +-- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +-- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-- +local utils = require("darcula.utils") + +NV_DARCULA_COLOR_COLUMN = utils.parse_env("NV_DARCULA_COLOR_COLUMN", "80") +NV_DARCULA_COLOR_SCHEME = + utils.parse_env("NV_DARCULA_COLOR_SCHEME", "darcula_lush") +NV_DARCULA_ENABLE_COC = utils.parse_env("NV_DARCULA_ENABLE_COC", true) +NV_DARCULA_ENABLE_CODE_LENS = + utils.parse_env("NV_DARCULA_ENABLE_CODE_LENS", false) +NV_DARCULA_ENABLE_DAP = utils.parse_env("NV_DARCULA_ENABLE_DAP", true) +NV_DARCULA_ENABLE_FORMATTING = + utils.parse_env("NV_DARCULA_ENABLE_FORMATTING", true) +NV_DARCULA_ENABLE_GIT_LINE_BLAME = + utils.parse_env("NV_DARCULA_ENABLE_GIT_LINE_BLAME", false) +NV_DARCULA_ENABLE_HIDDEN_FILES = + utils.parse_env("NV_DARCULA_ENABLE_HIDDEN_FILES", false) +NV_DARCULA_ENABLE_INLAY_HINTS = + utils.parse_env("NV_DARCULA_ENABLE_INLAY_HINTS", false) +NV_DARCULA_ENABLE_VIRTUAL_TEXT = + utils.parse_env("NV_DARCULA_ENABLE_VIRTUAL_TEXT", false) + +NV_DARCULA_CLANGD_ARGS = + utils.parse_env_list( + "NV_DARCULA_CLANGD_ARGS", + { + "--all-scopes-completion", + "--background-index", + "--clang-tidy", + "--completion-style=detailed", + "--cross-file-rename", + "--enable-config", + "--header-insertion-decorators", + "--log=info", + "--pch-storage=disk", + "--suggest-missing-includes", + "-j=4" + } +) + +NV_DARCULA_COC_EXTENSIONS = + utils.parse_env_list( + "NV_DARCULA_COC_EXTENSIONS", + { + "coc-calc", + "coc-clang-format-style-options", + "coc-clangd", + "coc-cmake", + "coc-css", + "coc-eslint", + "coc-flutter", + "coc-go", + "coc-highlight", + "coc-html", + "coc-java", + "coc-jedi", + "coc-jest", + "coc-json", + "coc-lightbulb", + "coc-markdownlint", + "coc-omnisharp", + "coc-powershell", + "coc-react-refactor", + "coc-sh", + "coc-snippets", + "coc-spell-checker", + "coc-sumneko-lua", + "coc-tsserver", + "coc-vimlsp" + } +) + +NV_DARCULA_CSPELL_LANGUAGES = + utils.parse_env_list( + "NV_DARCULA_CSPELL_LANGUAGES", + { + "asciidoc", + "c", + "cmake", + "cpp", + "csharp", + "css", + "dart", + "git-commit", + "go", + "handlebars", + "haskell", + "html", + "jade", + "java", + "javascript", + "javascriptreact", + "json", + "jsonc", + "latex", + "less", + "lua", + "markdown", + "php", + "plaintext", + "pug", + "python", + "restructuredtext", + "rust", + "scala", + "scss", + "text", + "typescript", + "typescriptreact", + "vim", + "yaml", + "yml" + } +) + +NV_DARCULA_LUA_GLOBALS = + utils.parse_env_list( + "NV_DARCULA_LUA_GLOBALS", + { + "MiniIcons", + "MiniNotify", + "MiniSnippets", + "MiniStarter", + "_G", + "vim" + } +) + +NV_DARCULA_MASON_INST_LIST = + utils.parse_env_list( + "NV_DARCULA_MASON_INST_LIST", + { + "bashls", + "clangd", + "cspell_ls", + "gopls", + "lua_ls", + "vimls" + } +) + +NV_DARCULA_MASON_LSP_LIST = + utils.parse_env_list( + "NV_DARCULA_MASON_LSP_LIST", + { + "bashls", + "clangd", + "cmake", + "cspell_ls", + "gopls", + "lua_ls", + "vimls" + } +) + +NV_DARCULA_MASON_TOOL_LIST = + utils.parse_env_list( + "NV_DARCULA_MASON_TOOL_LIST", + { + "clang-format", + "gofumpt", + "google-java-format", + "prettier", + "shellcheck", + "shfmt", + "yapf" + } +) + +NV_DARCULA_TREESITTER_LIST = + utils.parse_env_list( + "NV_DARCULA_TREESITTER_LIST", + { + "angular", + "awk", + "bash", + "cmake", + "cpp", + "css", + "dockerfile", + "git_config", + "git_rebase", + "gitattributes", + "gitcommit", + "gitignore", + "html", + "http", + "ini", + "java", + "javascript", + "jsdoc", + "json", + "lua", + "luadoc", + "luap", + "luau", + "markdown", + "markdown_inline", + "meson", + "ninja", + "pug", + "python", + "query", + "rust", + "starlark", + "toml", + "typescript", + "vim", + "vimdoc", + "xml", + "yaml" + } +) diff --git a/nvim/lua/darcula/cspell/init.lua b/nvim/lua/darcula/cspell/init.lua new file mode 100644 index 0000000..17e7270 --- /dev/null +++ b/nvim/lua/darcula/cspell/init.lua @@ -0,0 +1,211 @@ +-- The MIT License (MIT) +-- +-- Copyright © 2026 Scott E. Graves +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software +-- and associated documentation files (the “Software”), to deal in the Software without restriction, +-- including without limitation the rights to use, copy, modify, merge, publish, distribute, +-- sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in all copies or +-- substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +-- BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +-- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +-- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-- +local utils = require("darcula.utils") +local utils_os = require("darcula.utils.os") + +local user_directory = + vim.fs.joinpath( + utils.iff(utils_os.is_windows, vim.env.NV_DARCULA_DRIVE, vim.env.HOME), + ".desktop" +) + +local user_dictionary = + vim.fs.joinpath(user_directory, ".cspell", "user_words.txt") + +local config_data = { + "{", + ' "$schema": "https://raw.githubusercontent.com/streetsidesoftware/cspell/main/cspell.schema.json",', + ' "version": "0.2",', + ' "dictionaries": ["workspace-words", "user-words"],', + ' "dictionaryDefinitions": [{', + ' "name": "workspace-words",', + ' "path": "./.cspell/words.txt",', + ' "addWords": true', + " },", + " {", + ' "name": "user-words",', + ' "path": "' .. user_dictionary .. '",', + ' "addWords": true', + " }", + " ]", + "}" +} + +local get_workspace_directory = function() + return vim.fs.joinpath(NV_Darcula_Git_Root(vim.fn.getcwd())) +end + +local get_workspace_dictionary = function() + return vim.fs.joinpath(get_workspace_directory(), ".cspell", "words.txt") +end + +local create_config_file = function(force) + force = force and true + + if + force or vim.fn.filereadable(get_workspace_dictionary()) ~= 0 or + vim.fn.filereadable(user_dictionary) ~= 0 + then + local config_file = + vim.fs.joinpath(get_workspace_directory(), "cspell.json") + if vim.fn.filereadable(config_file) == 0 then + vim.fn.writefile(config_data, config_file, "b") + end + end +end + +local refresh_buffer = function() + -- NV_Darcula_Refresh_Buffer() + NV_Darcula_LSP_Restart() +end + +local group = + utils.augroup_with_autocmd( + "cspell_cfg", + "User", + "RooterChDir", + function() + create_config_file(false) + end +) + +utils.autocmd( + group, + "VimEnter", + "*", + function() + create_config_file(false) + end +) + +NV_Darcula_Cspell_Cleanup = function() + local get_lines = function(location) + if vim.fn.filereadable(location) ~= 0 then + return vim.fn.readfile(location, "") + end + + return {} + end + + local cleanup = function(lines) + local clean_lines = {} + for _, word in pairs(lines) do + word = vim.fn.trim(word:lower()) + if #word > 0 and not table.contains(clean_lines, word) then + table.insert(clean_lines, word) + end + end + + return clean_lines + end + + local user_lines = cleanup(get_lines(user_dictionary)) + local workspace_lines = cleanup(get_lines(get_workspace_dictionary())) + if vim.fn.filereadable(user_dictionary) ~= 0 then + table.sort(user_lines) + + vim.fn.writefile(user_lines, user_dictionary, "b") + if vim.fn.filereadable(get_workspace_dictionary()) ~= 0 then + local unique_lines = {} + for _, word in pairs(workspace_lines) do + if not table.contains(user_lines, word) then + table.insert(unique_lines, word) + end + end + + table.sort(unique_lines) + vim.fn.writefile(unique_lines, get_workspace_dictionary(), "b") + refresh_buffer() + end + end + + vim.notify("Cleaned cspell dictionaries", vim.log.levels.INFO) +end + +local cspell_read_file = function(user) + user = user or false + + local spell_directory = + vim.fs.joinpath( + utils.iff(user, user_directory, get_workspace_directory()), + ".cspell" + ) + + local is_directory = vim.fn.isdirectory(spell_directory) + if is_directory == 0 then + vim.fn.mkdir(spell_directory, "p") + end + + create_config_file(true) + + local spell_file = vim.fs.joinpath(spell_directory, "words.txt") + local lines = (function() + if vim.fn.filereadable(spell_file) ~= 0 then + return vim.fn.readfile(spell_file, "") + end + + return {} + end)() + + return lines, spell_file +end + +local cspell_write_word = function(user, lines, spell_file, word) + user = user or false + + word = vim.fn.trim(word) + if word ~= nil and #word > 0 and lines ~= nil then + for _, value in pairs(lines) do + if word:lower() == value:lower() then + return + end + end + table.insert(lines, word:lower()) + table.sort(lines) + vim.fn.writefile(lines, spell_file, "b") + + vim.notify( + "Added '" .. + word .. "' to " .. utils.iff(user, "user", "workspace") .. " dictionary", + vim.log.levels.INFO + ) + + refresh_buffer() + end +end + +NV_Darcula_Cspell_Add_Selected_Word = function(user) + user = user or false + + local lines, spell_file = cspell_read_file(user) + NV_Darcula_Grab_Selection( + function(word) + cspell_write_word(user, lines, spell_file, word) + end + ) +end + +NV_Darcula_Cspell_Add_Word = function(user) + user = user or false + + local lines, spell_file = cspell_read_file(user) + local word = utils.cword() or "" + cspell_write_word(user, lines, spell_file, word) +end diff --git a/nvim/lua/darcula/flutter/init.lua b/nvim/lua/darcula/flutter/init.lua new file mode 100644 index 0000000..4f58b3b --- /dev/null +++ b/nvim/lua/darcula/flutter/init.lua @@ -0,0 +1,365 @@ +-- The MIT License (MIT) +-- +-- Copyright © 2026 Scott E. Graves +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software +-- and associated documentation files (the “Software”), to deal in the Software without restriction, +-- including without limitation the rights to use, copy, modify, merge, publish, distribute, +-- sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in all copies or +-- substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +-- BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +-- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +-- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-- +local Job = require("plenary.job") +local action_state = require "telescope.actions.state" +local actions = require "telescope.actions" +local conf = require("telescope.config").values +local finders = require("telescope.finders") +local global_state = require("telescope.state") +local pickers = require("telescope.pickers") +local symbols = require("darcula.utils.symbols") +local utils = require("darcula.utils") +local utils_os = require("darcula.utils.os") + +local M = {} + +local spinner_id = nil +local config = { + use_coc = true +} + +local callbacks = {nil, nil} +local flutter_busy = false + +local EMULATOR = 1 +local DEVICE = 2 + +local get_config_path = function() + return vim.fs.joinpath(vim.fn.getcwd(), ".flutter-companion") +end + +local get_flutter_command = function() + local cmd = "flutter" .. utils.iff(utils_os.is_windows, ".bat", "") + return cmd +end + +local flutter_run_device = function(id) + if config.use_coc then + vim.api.nvim_command("CocCommand flutter.run -d " .. id) + return + end + + if vim.fn.exists(":FlutterRun") ~= 0 then + vim.api.nvim_command("FlutterRun -d " .. id) + return + end + + vim.notify( + "Run device requires 'coc-flutter/coc-flutter-tools' if using CoC or 'flutter-tools.nvim' if using native LSP.", + vim.log.levels.ERROR + ) +end + +local load_table = function(path) + local file, err = io.open(path, "r") + if err or file == nil then + return {} + end + + local lines = file:read("a") + file:close() + + local ok, json = + pcall( + function() + return vim.json.decode(lines) + end + ) + return utils.iff(ok, json, {}) +end + +local parse = function(line, device_type) + local parts = vim.split(line, "•") + local is_emulator = device_type == EMULATOR + local name_index = not is_emulator and 1 or 2 + local id_index = not is_emulator and 2 or 1 + if #parts == 4 then + return { + name = vim.trim(parts[name_index]), + id = vim.trim(parts[id_index]), + platform = vim.trim(parts[3]), + system = vim.trim(parts[4]), + type = device_type + } + end +end + +local save_table = function(data, filename) + local file, err = io.open(filename, "wb") + if err or file == nil then + return err + end + + file:write(vim.json.encode(data)) + file:close() +end + +local get_devices = function(result, type) + local devices = {} + for _, line in pairs(result) do + local device = parse(line, type) + if device then + table.insert(devices, device) + end + end + return devices +end + +local extract_device_props = function(result, device_type) + device_type = device_type or DEVICE + local devices = {} + local device_list = get_devices(result, device_type) + if #device_list > 0 then + for _, device in pairs(device_list) do + table.insert(devices, device) + end + end + return devices +end + +local parse_devices_output = function(job, callback) + local result = job:result() + local devices = extract_device_props(result, DEVICE) + callback(devices) +end + +local list_devices = function(callback) + local job = Job:new({command = get_flutter_command(), args = {"devices"}}) + job:after_success( + vim.schedule_wrap( + function() + parse_devices_output(job, callback) + end + ) + ) + job:start() +end + +local function list_emulators(callback) + local job = Job:new({command = get_flutter_command(), args = {"emulators"}}) + job:after_success( + vim.schedule_wrap( + function() + local emulators = extract_device_props(job:result(), EMULATOR) + callback(emulators) + end + ) + ) + job:start() +end + +local start_spinner = function(name, get_active) + local icon_idx = 0 + local function update_spinner() + if get_active() then + local msg = + "Detecting " .. + name .. "... " .. symbols.spinner[(icon_idx % #symbols.spinner) + 1] + + if spinner_id == nil then + spinner_id = MiniNotify.add(msg, "INFO") + else + MiniNotify.update( + spinner_id, + { + msg = msg + } + ) + end + + icon_idx = icon_idx + 1 + vim.defer_fn(update_spinner, 100) + end + end + + update_spinner() +end + +local stop_spinner = function(set_inactive) + set_inactive() + MiniNotify.remove(spinner_id) + spinner_id = nil +end + +function M.flutter_clear(is_emulator) + local config_path = get_config_path() + local config_data = load_table(config_path) + if is_emulator then + if config_data.emulator ~= nil then + config_data.emulator = nil + save_table(config_data, config_path) + end + else + if config_data.device ~= nil then + config_data.device = nil + save_table(config_data, config_path) + end + end +end + +function M.flutter_list(is_emulators) + if flutter_busy == true then + return + end + flutter_busy = true + + local config_path = get_config_path() + local config_data = load_table(config_path) + + local callback_index = utils.iff(is_emulators, 2, 1) + local list_function = utils.iff(is_emulators, list_emulators, list_devices) + local name = utils.iff(is_emulators, "Emulators", "Devices") + + local completed_callback + if callbacks[callback_index] ~= nil then + completed_callback = callbacks[callback_index] + callbacks[callback_index] = nil + end + + local active = true + start_spinner( + name, + function() + return active + end + ) + + list_function( + function(items) + stop_spinner( + function() + active = false + end + ) + + if #items == 0 then + vim.notify("No " .. name .. " were found", vim.log.levels.ERROR) + else + global_state.set_global_key("selected_entry", nil) + + local opts = {} + pickers.new( + opts, + { + prompt_title = "Flutter " .. name, + sorter = conf.generic_sorter(opts), + finder = finders.new_table( + { + results = items, + entry_maker = function(item) + return { + value = item, + ordinal = item.name, + display = item.name + } + end + } + ), + attach_mappings = function(prompt_bufnr --[[, map ]]) + actions.select_default:replace( + function() + actions.close(prompt_bufnr) + local selection = action_state.get_selected_entry() + if is_emulators then + config_data.emulator = selection.value + else + config_data.device = selection.value + end + save_table(config_data, config_path) + if completed_callback ~= nil then + completed_callback() + end + end + ) + return true + end + } + ):find() + end + flutter_busy = false + end + ) +end + +M.flutter_run = function(is_emulator) + local config_path = get_config_path() + local config_data = load_table(config_path) + if is_emulator then + if config_data.emulator == nil then + if callbacks[2] == nil then + callbacks[2] = function() + M.flutter_run(is_emulator) + end + M.flutter_list(true) + end + else + local job = + Job:new( + { + command = get_flutter_command(), + args = {"emulators", "--launch", config_data.emulator.id} + } + ) + job:start() + end + else + if config_data.device == nil then + if callbacks[1] == nil then + callbacks[1] = function() + M.flutter_run(is_emulator) + end + M.flutter_list(false) + end + else + flutter_run_device(config_data.device.id) + end + end +end + +M.setup = function(opts) + opts = opts or {} + config.use_coc = vim.F.if_nil(opts.use_coc, config.use_coc) +end + +_G.Flutter_Companion_Clear_Selected_Device = function() + M.flutter_clear(false) +end + +_G.Flutter_Companion_Run_Selected_Device = function() + M.flutter_run(false) +end + +_G.Flutter_Companion_Select_Device = function() + M.flutter_list(false) +end + +_G.Flutter_Companion_Clear_Selected_Emulator = function() + M.flutter_clear(true) +end + +_G.Flutter_Companion_Run_Selected_Emulator = function() + M.flutter_run(true) +end + +_G.Flutter_Companion_Select_Emulator = function() + M.flutter_list(true) +end + +return M diff --git a/nvim/lua/darcula/haven/init.lua b/nvim/lua/darcula/haven/init.lua new file mode 100644 index 0000000..0855e10 --- /dev/null +++ b/nvim/lua/darcula/haven/init.lua @@ -0,0 +1,718 @@ +-- The MIT License (MIT) +-- +-- Copyright © 2026 Scott E. Graves +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software +-- and associated documentation files (the “Software”), to deal in the Software without restriction, +-- including without limitation the rights to use, copy, modify, merge, publish, distribute, +-- sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in all copies or +-- substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +-- BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +-- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +-- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-- +require("darcula.utils.string") +require("darcula.utils.table") + +local Path = require("plenary.path") +local action_state = require("telescope.actions.state") +local actions = require("telescope.actions") +local conf = require("telescope.config").values +local finders = require("telescope.finders") +local utils = require("darcula.utils") +local global_state = require("telescope.state") +local utils_os = require("darcula.utils.os") +local utils_path = require("darcula.utils.path") +local pickers = require("telescope.pickers") +local plenary_filetype = require("plenary.filetype") +local previewer_utils = require("telescope.previewers.utils") +local previewers = require("telescope.previewers") +local scan = require("plenary.scandir") + +local M = {} + +local active_saves = {} +local changed_lookup = {} +local haven_config = { + enabled = true, + exclusions = { + function(path, _) + if utils_os.is_windows then + return path:lower():starts_with( + (vim.fn.eval("$VIMRUNTIME") .. utils_path.directory_sep):lower() + ) + end + return path:starts_with( + vim.fn.eval("$VIMRUNTIME") .. utils_path.directory_sep + ) + end, + function(path, _) + if utils_os.is_windows then + return path:lower():starts_with( + (vim.fn.stdpath("data") .. utils_path.directory_sep):lower() + ) + end + return path:starts_with( + vim.fn.stdpath("data") .. utils_path.directory_sep + ) + end, + function(path, _) + if utils_os.is_windows then + return path:lower():starts_with( + (vim.fs.joinpath(vim.fn.eval("$XDG_CONFIG_HOME"), "coc") .. + utils_path.directory_sep):lower() + ) + end + return path:starts_with( + vim.fs.joinpath(vim.fn.eval("$XDG_CONFIG_HOME"), "coc") .. + utils_path.directory_sep + ) + end, + function(path, _) + if utils_os.is_windows then + return path:lower():ends_with( + (utils_path.directory_sep .. + ".git" .. utils_path.directory_sep .. "COMMIT_EDITMSG"):lower() + ) + end + return path:ends_with( + utils_path.directory_sep .. + ".git" .. utils_path.directory_sep .. "COMMIT_EDITMSG" + ) + end, + function(path, config) + if utils_os.is_windows then + return path:lower():starts_with( + (config.haven_path .. utils_path.directory_sep):lower() + ) + end + return path:starts_with(config.haven_path .. utils_path.directory_sep) + end + }, + haven_path = vim.fs.joinpath(vim.fn.stdpath("data"), "nvim-haven"), + inclusions = {}, + max_history_count = 200, + save_timeout = 10000 +} +local line_ending = utils.iff(utils_os.is_windows, "\r\n", "\n") +local ns_previewer = vim.api.nvim_create_namespace("telescope.previewers") + +local print_message = function(is_error, msg) + vim.notify( + msg, + utils.iff(is_error, "error", "info"), + { + title = "nvim-haven" + } + ) +end + +local diff_strings = function(a, b) + return vim.text.diff(a, b, {algorithm = "minimal"}) +end + +local create_save_file_path = function(buf_info) + local encode = function(str) + return str:gsub("\r?\n", "\r\n"):gsub( + "([^%w%-%.%_%~ ])", + function(c) + return string.format("%%%02X", string.byte(c)) + end + ):gsub(" ", "+") + end + + return vim.fs.joinpath( + haven_config.haven_path, + encode(buf_info.name) .. ".save" + ) +end + +local save_change_file = function(buf_info, lines, save_file) + active_saves[save_file] = nil + + local file, err = io.open(save_file, "a") + if file == nil then + print_message(true, err) + return + end + + local file_entry = + vim.json.encode( + { + date = os.time(), + ft = plenary_filetype.detect(buf_info.name, {}), + lines = lines + } + ) + _, err = file:write(file_entry .. line_ending) + if err ~= nil then + print_message(true, err) + end + file:close() +end + +local save_change_file_entries = function(entries, save_file) + active_saves[save_file] = nil + + local file, err = io.open(save_file, "w+") + if file == nil then + print_message(true, err) + return + end + + for _, entry in pairs(entries) do + _, err = file:write(vim.json.encode(entry) .. line_ending) + if err ~= nil then + print_message(true, err) + end + end + file:close() +end + +local read_change_file = function(save_file) + local file, err = io.open(save_file, "r") + if file == nil then + return nil, err + end + + local save_data + save_data, err = file:read("a") + if err ~= nil then + return nil, err + end + file:close() + + local entries = + vim.json.decode( + "[" .. table.concat(save_data:split(line_ending), ",") .. "]" + ) + if #entries > haven_config.max_history_count then + while #entries > haven_config.max_history_count do + table.remove(entries, 1) + end + save_change_file_entries(entries, save_file) + end + + return entries +end + +local process_file_changed = function(buf_info) + local save_file = create_save_file_path(buf_info) + local changed_data = changed_lookup[save_file] + local immediate = vim.fn.filereadable(save_file) == 0 + + local update_changed_lookup = function() + changed_lookup[save_file] = { + changed = buf_info.changed, + changedtick = buf_info.changedtick + } + end + + if + not immediate and + (changed_data == nil or + (buf_info.changed == 0 and changed_data.changed == 0) or + buf_info.changedtick == changed_data.changedtick) + then + update_changed_lookup() + return + end + + if active_saves[save_file] ~= nil then + active_saves[save_file].timer:stop() + active_saves[save_file] = nil + end + + update_changed_lookup() + + local lines = vim.api.nvim_buf_get_lines(buf_info.bufnr, 0, -1, true) + + local entries, _ = read_change_file(save_file) + if entries ~= nil then + if + diff_strings( + table.concat(entries[#entries].lines, line_ending), + table.concat(lines, line_ending) + ):len() == 0 + then + return + end + entries = nil + end + + local saved = false + local do_save = function() + if not saved then + saved = true + save_change_file(buf_info, lines, save_file) + end + end + + if immediate then + do_save() + else + active_saves[save_file] = { + timer = vim.defer_fn(do_save, haven_config.save_timeout), + do_save = do_save + } + end +end + +local check_requirements = function() + if vim.o.modifiable ~= 0 and vim.o.buftype ~= "nofile" then + local buf_info = vim.fn.getbufinfo(vim.fn.bufname()) + if buf_info ~= nil and #buf_info > 0 then + buf_info = buf_info[1] + if buf_info.name:len() ~= 0 and vim.fn.filereadable(buf_info.name) ~= 0 then + if changed_lookup[create_save_file_path(buf_info)] == nil then + for _, is_included in pairs(haven_config.inclusions) do + if is_included(buf_info.name, haven_config) then + return true, buf_info + end + end + + for _, is_excluded in pairs(haven_config.exclusions) do + if is_excluded(buf_info.name, haven_config) then + return false + end + end + end + return true, buf_info + end + end + end + return false +end + +local handle_buffer_changed = function() + local ok, buf_info = check_requirements() + if ok and buf_info ~= nil then + process_file_changed(buf_info) + end +end + +local handle_vim_leave = function() + for _, active in pairs(active_saves) do + if active.timer ~= nil then + active.timer:stop() + end + active.do_save() + end + active_saves = {} + changed_lookup = {} +end + +local setup_autocmds = function() + local group_id = + vim.api.nvim_create_augroup("nvim-haven-internal", {clear = true}) + if haven_config.enabled then + vim.api.nvim_create_autocmd( + "BufEnter", + { + group = group_id, + pattern = "*", + callback = handle_buffer_changed + } + ) + vim.api.nvim_create_autocmd( + "BufWritePost", + { + group = group_id, + pattern = "*", + callback = handle_buffer_changed + } + ) + vim.api.nvim_create_autocmd( + "InsertLeave", + { + group = group_id, + pattern = "*", + callback = handle_buffer_changed + } + ) + vim.api.nvim_create_autocmd( + "TextChanged", + { + group = group_id, + pattern = "*", + callback = handle_buffer_changed + } + ) + vim.api.nvim_create_autocmd( + "VimLeave", + { + group = group_id, + pattern = "*", + callback = handle_vim_leave + } + ) + else + vim.api.nvim_del_augroup_by_id(group_id) + end +end + +local apply_diff_to_lines = function(diff, source_lines) + local diff_lines = diff:split(line_ending) + local changes = {} + local current_diff + + for _, line in pairs(diff_lines) do + if line:len() > 0 then + if line:starts_with("@@") and line:ends_with("@@") then + local diff_range = line:sub(3, -1):sub(1, -3):split(" ")[1]:split(",") + if #diff_range == 1 then + table.insert(diff_range, "1") + end + + local diff_start = math.abs(tonumber(diff_range[1], 10)) + local diff_count = tonumber(diff_range[2], 10) + if diff_count == 0 then + diff_start = diff_start + 1 + end + + current_diff = { + diff = {line}, + next = diff_start + diff_count, + start = diff_start + } + table.insert(changes, current_diff) + elseif current_diff ~= nil then + table.insert(current_diff.diff, line) + end + else + current_diff = nil + end + end + + local actual_line = 1 + local buffer_lines = {} + local diff_rows = {} + local source_line = 1 + for _, change in pairs(changes) do + while source_line < change.start do + table.insert(buffer_lines, source_lines[source_line]) + actual_line = actual_line + 1 + source_line = source_line + 1 + end + + table.insert(diff_rows, actual_line) + for _, change_diff_lines in pairs(change.diff) do + table.insert(buffer_lines, change_diff_lines) + actual_line = actual_line + 1 + end + + source_line = change.next + end + + while source_line <= #source_lines do + table.insert(buffer_lines, source_lines[source_line]) + actual_line = actual_line + 1 + source_line = source_line + 1 + end + + return buffer_lines, diff_rows +end + +local show_picker = function(entries) + global_state.set_global_key("selected_entry", nil) + + local jump_state + + local jump_to_line = function(self, bufnr, lnum) + pcall(vim.api.nvim_buf_clear_namespace, bufnr, ns_previewer, 0, -1) + if lnum and lnum > 0 then + pcall( + vim.api.nvim_buf_add_highlight, + bufnr, + ns_previewer, + "TelescopePreviewLine", + lnum - 1, + 0, + -1 + ) + pcall(vim.api.nvim_win_set_cursor, self.state.winid, {lnum, 0}) + vim.api.nvim_buf_call( + bufnr, + function() + vim.cmd "norm! zz" + end + ) + end + end + + local do_forward_jump = function() + if jump_state ~= nil and #jump_state.diff_rows > 0 then + jump_state.cur = + utils.iff( + (jump_state.cur + 1) <= #jump_state.diff_rows, + jump_state.cur + 1, + #jump_state.diff_rows + ) + jump_to_line( + jump_state.self, + jump_state.self.state.bufnr, + jump_state.diff_rows[jump_state.cur] + ) + end + end + + local do_reverse_jump = function() + if jump_state ~= nil and #jump_state.diff_rows > 0 then + jump_state.cur = + utils.iff((jump_state.cur - 1) > 0, jump_state.cur - 1, 1) + jump_to_line( + jump_state.self, + jump_state.self.state.bufnr, + jump_state.diff_rows[jump_state.cur] + ) + end + end + + pickers.new( + {}, + { + prompt_title = "File History", + previewer = previewers.new_buffer_previewer( + { + define_preview = function(self, entry) + jump_state = nil + if entry.index < #entries then + local previous_lines = entries[entry.index + 1].lines + local buffer_lines, diff_rows = + apply_diff_to_lines( + diff_strings( + table.concat(previous_lines, line_ending), + table.concat(entry.value.lines, line_ending) + ), + previous_lines + ) + previous_lines = nil + + vim.api.nvim_buf_set_lines( + self.state.bufnr, + 0, + -1, + false, + buffer_lines + ) + previewer_utils.regex_highlighter(self.state.bufnr, "diff") + + jump_state = {self = self, cur = 0, diff_rows = diff_rows} + vim.schedule( + function() + do_forward_jump() + end + ) + else + vim.api.nvim_buf_set_lines( + self.state.bufnr, + 0, + -1, + false, + entry.value.lines + ) + previewer_utils.highlighter(self.state.bufnr, entry.value.ft, {}) + end + end + } + ), + sorter = conf.generic_sorter({}), + finder = finders.new_table( + { + results = entries, + entry_maker = function(item) + return { + value = item, + ordinal = tostring(item.date), + display = os.date("%m-%d-%Y %H:%M:%S", item.date) + } + end + } + ), + attach_mappings = function(prompt_bufnr, map) + actions.select_default:replace( + function() + actions.close(prompt_bufnr) + local selection = action_state.get_selected_entry() + if selection ~= nil then + vim.api.nvim_buf_set_lines(0, 0, -1, false, selection.value.lines) + end + end + ) + map("i", "", do_forward_jump) + map("n", "", do_forward_jump) + map("i", "", do_reverse_jump) + map("n", "", do_reverse_jump) + return true + end + } + ):find() +end + +M.setup = function(config) + if config == nil then + config = {} + end + + if config.exclusions ~= nil then + for _, e in pairs(config.exclusions) do + if type(e) ~= "function" then + print_message( + true, + "'exclusions' contains an entry that is not a function. Skipping all exclusions until this is corrected:" + ) + table.print_table(e) + break + end + table.insert(haven_config.exclusions, e) + end + end + haven_config.enabled = vim.F.if_nil(config.enabled, haven_config.enabled) + haven_config.haven_path = + vim.F.if_nil(config.haven_path, haven_config.haven_path) + + if config.inclusions ~= nil then + for _, e in pairs(config.inclusions) do + if type(e) ~= "function" then + print_message( + true, + "'inclusions' contains an entry that is not a function. Skipping this inclusion until it is corrected:" + ) + table.print_table(e) + end + table.insert(haven_config.inclusions, e) + end + end + + haven_config.max_history_count = + vim.F.if_nil(config.max_history_count, haven_config.max_history_count) + if haven_config.max_history_count < 10 then + print_message( + true, + "'max_history_count' too low: " .. haven_config.max_history_count + ) + haven_config.max_history_count = 100 + print_message( + true, + "reset 'max_history_count': " .. haven_config.max_history_count + ) + elseif haven_config.max_history_count > 500 then + print_message( + true, + "'max_history_count' too high: " .. haven_config.max_history_count + ) + haven_config.max_history_count = 500 + print_message( + true, + "reset 'max_history_count': " .. haven_config.max_history_count + ) + end + + haven_config.save_timeout = + vim.F.if_nil(config.save_timeout, haven_config.save_timeout) + if haven_config.save_timeout < 135 then + print_message(true, "'save_timeout' too low: " .. haven_config.save_timeout) + haven_config.save_timeout = 135 + print_message(true, "reset 'save_timeout': " .. haven_config.save_timeout) + elseif haven_config.save_timeout > 10000 then + print_message( + true, + "'save_timeout' too high: " .. haven_config.save_timeout + ) + haven_config.save_timeout = 10000 + print_message(true, "reset 'save_timeout': " .. haven_config.save_timeout) + end + + if vim.fn.mkdir(haven_config.haven_path, "p") == 0 then + print_message(true, "directory create failed: " .. haven_config.haven_path) + haven_config.enabled = false + return + end + + if vim.fn.isdirectory(haven_config.haven_path) == 0 then + print_message(true, "directory not found: " .. haven_config.haven_path) + haven_config.enabled = false + return + end + + setup_autocmds() +end + +M.clean = function() + local decode = function(str) + if str == nil then + return "" + end + + return str:gsub("+", " "):gsub( + "%%(%x%x)", + function(x) + return string.char(tonumber(x, 16)) + end + ) + end + + local history_files = + scan.scan_dir(haven_config.haven_path, {hidden = true, depth = 1}) + for _, history_file in ipairs(history_files) do + local source_path = + Path:new( + decode(Path:new(history_file):make_relative(haven_config.haven_path)):sub( + 1, + -6 + ) + ) + if not source_path:exists() then + local history_path = Path:new(history_file) + print("removing: " .. history_path:absolute()) + history_path:rm() + end + end +end + +M.disable = function() + if haven_config.enabled then + haven_config.enabled = false + setup_autocmds() + handle_vim_leave() + end +end + +M.enable = function() + if not haven_config.enabled then + haven_config.enabled = true + handle_buffer_changed() + setup_autocmds() + end +end + +M.history = function(bufname) + bufname = vim.F.if_nil(bufname, vim.fn.bufname()) + local buf_info = vim.fn.getbufinfo(bufname) + if buf_info ~= nil and #buf_info > 0 then + buf_info = buf_info[1] + local save_file = create_save_file_path(buf_info) + if vim.fn.filereadable(save_file) ~= 0 then + local entries, err = read_change_file(save_file) + if entries == nil then + print_message(true, err) + return + end + + show_picker(table.reverse(entries)) + end + end +end + +_G.Nvim_Haven_Clean = M.clean +_G.Nvim_Haven_Disable = M.disable +_G.Nvim_Haven_Enable = M.enable +_G.Nvim_Haven_History = M.history + +return M diff --git a/nvim/lua/darcula/keymaps.lua b/nvim/lua/darcula/keymaps.lua new file mode 100644 index 0000000..4270c40 --- /dev/null +++ b/nvim/lua/darcula/keymaps.lua @@ -0,0 +1,1460 @@ +-- The MIT License (MIT) +-- +-- Copyright © 2026 Scott E. Graves +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software +-- and associated documentation files (the “Software”), to deal in the Software without restriction, +-- including without limitation the rights to use, copy, modify, merge, publish, distribute, +-- sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in all copies or +-- substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +-- BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +-- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +-- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-- +local M = {} + +require("darcula.utils.string") + +local km = require("darcula.utils.keymap") +local telescope_builtin = require("telescope.builtin") +local utils = require("darcula.utils") +local utils_ui = require("darcula.utils.ui") + +if NV_DARCULA_ENABLE_COC then + local coc_command = function(command) + vim.cmd("CocCommand " .. command) + end + + local telescope_coc_command = function(command) + vim.cmd("Telescope coc " .. command) + end + + function M.coc() + local opts = {remap = true, silent = true} + km.vmap( + km.leader "gs", + function() + vim.cmd("CocSearch -F " .. vim.fn.escape(utils.get_visual_text(), " ")) + end, + opts + ) + + km.nmap( + km.leader "gs", + function() + vim.cmd("CocSearch -F " .. vim.fn.escape(utils.cword(), " ")) + end, + opts + ) + + opts = {expr = true, nowait = true, remap = false, silent = true} + + km.set( + "i", + "", + function() + vim.fn.CocActionAsync("showSignatureHelp") + end, + opts + ) + + km.map( + km.leader "ii", + function() + vim.cmd("CocInfo") + end, + {remap = false, silent = true} + ) + + km.map( + km.leader "is", + function() + vim.notify( + utils.iff( + vim.g.coc_status ~= nil and #vim.g.coc_status > 0, + vim.g.coc_status, + "None" + ), + vim.log.levels.INFO + ) + end, + {remap = false, silent = true} + ) + + km.set( + {"n", "v"}, + "", + function() + return NV_Darcula_Coc_Float_Scroll(true) + end, + opts + ) + + km.set( + {"n", "v"}, + "", + function() + return NV_Darcula_Coc_Float_Scroll(false) + end, + opts + ) + + km.imap( + "", + function() + return NV_Darcula_Coc_Float_Scroll_Insert_Mode(true) + end, + opts + ) + + km.imap( + "", + function() + return NV_Darcula_Coc_Float_Scroll_Insert_Mode(false) + end, + opts + ) + + km.imap( + "", + function() + if vim.bo.buftype ~= "nofile" and vim.fn["coc#pum#visible"]() ~= 0 then + return "=coc#start()" + end + return "" + end, + {expr = true, remap = false, silent = true} + ) + + opts = {remap = true, silent = true} + km.imap( + "", + NV_Darcula_Coc_Shift_Tab_Complete, + {remap = false, expr = true} + ) + km.imap( + "", + NV_Darcula_Coc_Tab_Complete, + {remap = false, expr = true, silent = true} + ) + km.imap( + "", + NV_Darcula_Coc_Completion_Confirm, + {remap = false, silent = true, expr = true} + ) + km.nmap(km.leader "cl", "(coc-codelens-action)", opts) + km.nmap(km.leader "gn", "(coc-diagnostic-next)", opts) + km.nmap(km.leader "gp", "(coc-diagnostic-prev)", opts) + km.nmap(km.leader "qf", "(coc-fix-current)", opts) + km.nmap(km.leader "rn", "(coc-rename)", opts) + km.xmap(km.leader "rs", "(coc-range-select)", opts) + km.set({"n", "v"}, km.leader "rs", "(coc-range-select)", opts) + km.set({"n", "x"}, km.leader "a", "(coc-codeaction-selected)", opts) + + km.nmap( + km.leader "ac", + function() + telescope_coc_command("code_actions") + end, + opts + ) + + km.nmap( + km.leader "ca", + function() + telescope_coc_command("code_actions") + end, + opts + ) + + km.nmap( + km.leader "dl", + function() + vim.cmd("CocDiagnostics") + end, + opts + ) + + km.nmap( + km.leader "di", + function() + telescope_coc_command("diagnostics") + end, + opts + ) + + km.nmap( + km.leader "dw", + function() + telescope_coc_command("workspace_diagnostics") + end, + opts + ) + + km.nmap( + km.leader "fs", + function() + telescope_coc_command("document_symbols") + end, + opts + ) + + km.nmap( + km.leader "fw", + function() + telescope_coc_command("workspace_symbols") + end, + opts + ) + + km.nmap( + km.leader "gd", + function() + telescope_coc_command("definitions") + end, + opts + ) + + km.nmap( + km.leader "gD", + function() + telescope_coc_command("declarations") + end, + opts + ) + + km.nmap( + km.leader "gh", + function() + coc_command("clangd.switchSourceHeader") + end, + {silent = true, remap = false, nowait = true} + ) + + km.nmap( + km.leader "gi", + function() + telescope_coc_command("implementations") + end, + opts + ) + + km.nmap( + km.leader "gr", + function() + telescope_coc_command("references") + end, + opts + ) + + km.nmap( + km.leader "gy", + function() + telescope_coc_command("type_definitions") + end, + opts + ) + end +end + +function M.commenting() + local opts = {remap = true, silent = true} + + km.nmap(km.leader "ub", "gcc", opts) + km.nmap(km.leader "uu", "gcc", opts) + km.vmap(km.leader "ub", "gcc", opts) + km.vmap(km.leader "uu", "gcc", opts) +end + +function M.cppman() + local opts = {silent = true} + km.nmap(km.leader "dM", require("cppman").search, opts) +end + +function M.cspell() + local opts = {silent = true} + + km.nmap(km.leader2 "sc", NV_Darcula_Cspell_Cleanup, opts) + + km.nmap( + km.leader2 "su", + function() + NV_Darcula_Cspell_Add_Word(true) + end, + opts + ) + + km.vmap( + km.leader2 "su", + function() + NV_Darcula_Cspell_Add_Selected_Word(true) + end, + opts + ) + + km.nmap( + km.leader2 "sw", + function() + NV_Darcula_Cspell_Add_Word(false) + end, + opts + ) + + km.vmap( + km.leader2 "sw", + function() + NV_Darcula_Cspell_Add_Selected_Word(false) + end, + opts + ) +end + +function M.diff() + km.nmap(km.leader "dn", "]c", {remap = false}) + km.nmap(km.leader "do", ":diffoff", {silent = true, remap = false}) + km.nmap(km.leader "dp", "[c", {remap = false}) +end + +function M.editing() + local opts = {remap = false, silent = true} + + km.nmap("J", "mzJ`z", opts) + + km.nmap(km.leader "O", "O", opts) + km.nmap(km.leader "o", "o", opts) + + km.vmap("<", "", ">gv", opts) +end + +function M.flutter() + local companion = require("darcula.flutter") + local opts = {remap = false, silent = true} + + if NV_DARCULA_ENABLE_COC then + local coc_command = function(command) + vim.cmd("CocCommand " .. command) + end + + km.nmap( + km.leader "fld", + function() + companion.flutter_list(false) + end, + opts + ) + + km.nmap( + km.leader "flv", + function() + companion.flutter_list(false) + end, + opts + ) + + km.nmap( + km.leader "fle", + function() + companion.flutter_list(true) + end, + opts + ) + + km.nmap( + km.leader "flm", + function() + companion.flutter_run(true) + end, + opts + ) + + km.nmap( + km.leader "flx", + function() + companion.flutter_run(false) + end, + opts + ) + + km.nmap( + km.leader "flc", + function() + coc_command("flutter.dev.clearDevLog") + end, + opts + ) + + km.nmap( + km.leader "flg", + function() + coc_command("flutter.pub.get") + end, + opts + ) + km.nmap( + km.leader "fll", + function() + coc_command("flutter.dev.openDevLog") + end, + opts + ) + + km.nmap( + km.leader "flo", + function() + coc_command("flutter.toggleOutline") + end, + opts + ) + + km.nmap( + km.leader "flp", + function() + coc_command("flutter.dev.openDevToolsProfiler") + end, + opts + ) + + km.nmap( + km.leader "flq", + function() + coc_command("flutter.dev.quit") + end, + opts + ) + + km.nmap( + km.leader "flr", + function() + coc_command("flutter.dev.hotReload") + end, + opts + ) + + km.nmap( + km.leader "fls", + function() + coc_command("flutter.dev.hotRestart") + end, + opts + ) + else + km.nmap( + km.leader "flc", + function() + vim.cmd("Telescope flutter commands") + end, + opts + ) + km.nmap( + km.leader "fld", + function() + companion.flutter_list(false) + end, + opts + ) + km.nmap( + km.leader "fle", + function() + companion.flutter_list(true) + end, + opts + ) + km.nmap( + km.leader "flm", + function() + companion.flutter_run(true) + end, + opts + ) + km.nmap( + km.leader "flv", + function() + companion.flutter_list(false) + end, + opts + ) + km.nmap( + km.leader "flx", + function() + companion.flutter_run(false) + end, + opts + ) + end +end + +function M.gitsigns(bufnr) + local opts = {remap = false, silent = true, buffer = bufnr} + + km.nmap( + km.leader2 "tb", + function() + NV_DARCULA_ENABLE_GIT_LINE_BLAME = not NV_DARCULA_ENABLE_GIT_LINE_BLAME + require("gitsigns").toggle_current_line_blame( + NV_DARCULA_ENABLE_GIT_LINE_BLAME + ) + utils.notify_setting_enabled( + "Git line blame", + NV_DARCULA_ENABLE_GIT_LINE_BLAME + ) + end, + opts + ) + + km.nmap( + km.leader "bl", + function() + vim.cmd("Gitsigns blame_line") + end, + opts + ) +end + +function M.gui() + if utils_ui.is_gui() then + km.cmap("", "+", {remap = true}) + km.cmap("", "+", {remap = true}) + km.imap("", "+", {remap = true}) + km.imap("", "+", {remap = true}) + km.map("", "p", {remap = true}) + km.map("", "p", {remap = true}) + + local opts = {remap = true, silent = true} + km.nmap( + km.leader2 "gd", + function() + NV_Darcula_Set_Gui_Font(0) + end, + opts + ) + + km.nmap( + km.leader2 "gl", + function() + NV_Darcula_Set_Gui_Font(3) + end, + opts + ) + + km.nmap( + km.leader2 "gm", + function() + NV_Darcula_Set_Gui_Font(2) + end, + opts + ) + + km.nmap( + km.leader2 "gs", + function() + NV_Darcula_Set_Gui_Font(1) + end, + opts + ) + end +end + +if not NV_DARCULA_ENABLE_COC then + function M.lsp() + local opts = {remap = false, silent = true} + + km.nmap(km.leader "dl", vim.diagnostic.setloclist, opts) + km.nmap(km.leader "dw", telescope_builtin.diagnostics, opts) + km.nmap(km.leader "fs", telescope_builtin.lsp_document_symbols, opts) + km.nmap(km.leader "fw", telescope_builtin.lsp_workspace_symbols, opts) + km.nmap( + km.leader "gn", + function() + vim.diagnostic.jump({count = 1, float = true}) + end, + opts + ) + km.nmap( + km.leader "gp", + function() + vim.diagnostic.jump({count = -1, float = true}) + end, + opts + ) + + km.nmap( + km.leader "di", + function() + telescope_builtin.diagnostics({bufnr = 0}) + end, + opts + ) + + km.nmap( + km.leader "df", + function() + vim.diagnostic.open_float(nil, {focus = false}) + end, + opts + ) + + km.map( + km.leader "ii", + function() + vim.cmd("LspInfo") + end, + opts + ) + + km.set( + {"i", "n"}, + "", + function() + vim.lsp.buf.signature_help({border = "rounded"}) + end + ) + end +end + +if not NV_DARCULA_ENABLE_COC then + function M.lsp_on_attach(ev) + local client = vim.lsp.get_client_by_id(ev.data.client_id) + if not client then + return + end + + local opts = {remap = false, silent = true, buffer = ev.buf} + + km.nmap(km.leader "aw", vim.lsp.buf.code_action, opts) + km.nmap(km.leader "ca", vim.lsp.buf.code_action, opts) + km.nmap(km.leader "gD", vim.lsp.buf.declaration, opts) + km.nmap(km.leader "gd", telescope_builtin.lsp_definitions, opts) + km.nmap(km.leader "gi", telescope_builtin.lsp_implementations, opts) + km.nmap(km.leader "gr", telescope_builtin.lsp_references, opts) + km.nmap(km.leader "gy", telescope_builtin.lsp_type_definitions, opts) + km.nmap(km.leader "rn", vim.lsp.buf.rename, opts) + + km.vmap( + km.leader "ac", + function() + vim.lsp.buf.range_code_action(nil, nil, nil) + end, + opts + ) + + km.vmap( + km.leader "aw", + function() + vim.lsp.buf.range_code_action(nil, nil, nil) + end, + opts + ) + + km.vmap( + km.leader "ca", + function() + vim.lsp.buf.range_code_action(nil, nil, nil) + end, + opts + ) + end +end + +if not NV_DARCULA_ENABLE_COC then + function M.mason() + km.map(km.leader "in", ":Mason", {remap = true, silent = true}) + end +end + +function M.mini() + if not NV_DARCULA_ENABLE_COC then + local map_multistep = require("mini.keymap").map_multistep + + map_multistep( + "i", + "", + { + "minisnippets_next", + "minisnippets_expand", + "pmenu_next" + } + ) + + map_multistep( + "i", + "", + { + "minisnippets_prev", + "pmenu_prev" + } + ) + + map_multistep( + "i", + "", + { + "pmenu_accept", + "minipairs_cr" + } + ) + + map_multistep( + "i", + "", + { + "minipairs_bs" + } + ) + end +end + +function M.navigation() + km.nmap( + "", + '"vertical resize -" . v:count1 . ""', + {expr = true, replace_keycodes = false} + ) + km.nmap( + "", + '"resize -" . v:count1 . ""', + {expr = true, replace_keycodes = false} + ) + km.nmap( + "", + '"resize +" . v:count1 . ""', + {expr = true, replace_keycodes = false} + ) + km.nmap( + "", + '"vertical resize +" . v:count1 . ""', + {expr = true, replace_keycodes = false} + ) + + km.cmap("", "", {silent = false}) + km.cmap("", "", {silent = false}) + + km.imap("", "", {remap = true}) + km.imap("", "", {remap = true}) + + km.tmap("", "") + km.tmap("", "") + + km.map(km.leader "0", "", {remap = false}) + km.map(km.leader "8", "", {remap = false}) + km.map(km.leader "9", "", {remap = false}) + km.map(km.leader "h", "h", {remap = true, silent = true}) + km.map(km.leader "j", "j", {remap = true, silent = true}) + km.map(km.leader "k", "k", {remap = true, silent = true}) + km.map(km.leader "l", "l", {remap = true, silent = true}) + + km.map(km.leader "mh", "H", {remap = false}) + km.map(km.leader "mj", "J", {remap = false}) + km.map(km.leader "mk", "K", {remap = false}) + km.map(km.leader "ml", "L", {remap = false}) + + km.nmap("", "Nzz", {remap = false}) + km.nmap("n", "nzz", {remap = false}) + + km.nmap("j", "gj") + km.nmap("k", "gk") +end + +function M.nvim_dap() + local dap = require("dap") + km.nmap("", dap.continue, {remap = true, silent = true}) + km.nmap("", dap.toggle_breakpoint, {remap = true, silent = true}) + km.nmap("", dap.step_over, {remap = true, silent = true}) + km.nmap("", dap.step_into, {remap = true, silent = true}) + km.nmap("", dap.step_out, {remap = true, silent = true}) + km.set( + {"n", "v", "x"}, + km.leader "vi", + function() + require("dapui").eval() + require("dapui").eval() + end, + {remap = true, silent = true} + ) +end + +function M.nvim_haven() + km.nmap( + km.leader "fy", + require("darcula.haven").history, + {remap = true, silent = true} + ) + + km.nmap( + km.leader "ch", + require("darcula.haven").clean, + {remap = true, silent = true} + ) +end + +function M.nvim_tree() + local opts = {remap = false, silent = true} + + km.map( + km.leader "ns", + function() + NV_Darcula_Open_Nvim_Tree(true) + end, + opts + ) + + km.map( + km.leader "nt", + function() + NV_Darcula_Open_Nvim_Tree(false) + end, + opts + ) +end + +function M.nvim_tree_on_attach(bufnr) + local api = require("nvim-tree.api") + + local opts = function(desc) + return { + desc = "nvim-tree: " .. desc, + buffer = bufnr, + noremap = true, + silent = true, + nowait = true + } + end + + -- Default mappings. Feel free to modify or remove as you wish. + -- + -- BEGIN_DEFAULT_ON_ATTACH + vim.keymap.set("n", "", api.tree.change_root_to_node, opts("CD")) + vim.keymap.set( + "n", + "", + api.node.open.replace_tree_buffer, + opts("Open: In Place") + ) + vim.keymap.set("n", "", api.node.show_info_popup, opts("Info")) + vim.keymap.set("n", "", api.fs.rename_sub, opts("Rename: Omit Filename")) + vim.keymap.set("n", "", api.node.open.tab, opts("Open: New Tab")) + vim.keymap.set( + "n", + "", + api.node.open.vertical, + opts("Open: Vertical Split") + ) + vim.keymap.set( + "n", + "", + api.node.open.horizontal, + opts("Open: Horizontal Split") + ) + vim.keymap.set( + "n", + "", + api.node.navigate.parent_close, + opts("Close Directory") + ) + vim.keymap.set("n", "", api.node.open.edit, opts("Open")) + vim.keymap.set("n", "", api.node.open.preview, opts("Open Preview")) + vim.keymap.set("n", ">", api.node.navigate.sibling.next, opts("Next Sibling")) + vim.keymap.set( + "n", + "<", + api.node.navigate.sibling.prev, + opts("Previous Sibling") + ) + vim.keymap.set("n", ".", api.node.run.cmd, opts("Run Command")) + vim.keymap.set("n", "-", api.tree.change_root_to_parent, opts("Up")) + vim.keymap.set("n", "a", api.fs.create, opts("Create")) + vim.keymap.set("n", "bmv", api.marks.bulk.move, opts("Move Bookmarked")) + vim.keymap.set( + "n", + "B", + api.tree.toggle_no_buffer_filter, + opts("Toggle No Buffer") + ) + vim.keymap.set("n", "c", api.fs.copy.node, opts("Copy")) + vim.keymap.set( + "n", + "C", + api.tree.toggle_git_clean_filter, + opts("Toggle Git Clean") + ) + vim.keymap.set("n", "[c", api.node.navigate.git.prev, opts("Prev Git")) + vim.keymap.set("n", "]c", api.node.navigate.git.next, opts("Next Git")) + vim.keymap.set("n", "d", api.fs.remove, opts("Delete")) + vim.keymap.set("n", "D", api.fs.trash, opts("Trash")) + vim.keymap.set("n", "E", api.tree.expand_all, opts("Expand All")) + vim.keymap.set("n", "e", api.fs.rename_basename, opts("Rename: Basename")) + vim.keymap.set( + "n", + "]e", + api.node.navigate.diagnostics.next, + opts("Next Diagnostic") + ) + vim.keymap.set( + "n", + "[e", + api.node.navigate.diagnostics.prev, + opts("Prev Diagnostic") + ) + vim.keymap.set("n", "F", api.live_filter.clear, opts("Clean Filter")) + vim.keymap.set("n", "f", api.live_filter.start, opts("Filter")) + vim.keymap.set("n", "g?", api.tree.toggle_help, opts("Help")) + vim.keymap.set( + "n", + "gy", + api.fs.copy.absolute_path, + opts("Copy Absolute Path") + ) + vim.keymap.set( + "n", + "H", + api.tree.toggle_hidden_filter, + opts("Toggle Dotfiles") + ) + vim.keymap.set( + "n", + "I", + api.tree.toggle_gitignore_filter, + opts("Toggle Git Ignore") + ) + vim.keymap.set("n", "J", api.node.navigate.sibling.last, opts("Last Sibling")) + vim.keymap.set( + "n", + "K", + api.node.navigate.sibling.first, + opts("First Sibling") + ) + vim.keymap.set("n", "m", api.marks.toggle, opts("Toggle Bookmark")) + vim.keymap.set("n", "o", api.node.open.edit, opts("Open")) + vim.keymap.set( + "n", + "O", + api.node.open.no_window_picker, + opts("Open: No Window Picker") + ) + vim.keymap.set("n", "p", api.fs.paste, opts("Paste")) + vim.keymap.set("n", "P", api.node.navigate.parent, opts("Parent Directory")) + vim.keymap.set("n", "q", api.tree.close, opts("Close")) + vim.keymap.set("n", "r", api.fs.rename, opts("Rename")) + vim.keymap.set("n", "R", api.tree.reload, opts("Refresh")) + -- vim.keymap.set("n", "s", api.node.run.system, opts("Run System")) + vim.keymap.set("n", "S", api.tree.search_node, opts("Search")) + vim.keymap.set("n", "U", api.tree.toggle_custom_filter, opts("Toggle Hidden")) + vim.keymap.set("n", "W", api.tree.collapse_all, opts("Collapse")) + vim.keymap.set("n", "x", api.fs.cut, opts("Cut")) + vim.keymap.set("n", "y", api.fs.copy.filename, opts("Copy Name")) + vim.keymap.set( + "n", + "Y", + api.fs.copy.relative_path, + opts("Copy Relative Path") + ) + vim.keymap.set("n", "<2-LeftMouse>", api.node.open.edit, opts("Open")) + vim.keymap.set( + "n", + "<2-RightMouse>", + api.tree.change_root_to_node, + opts("CD") + ) + -- END_DEFAULT_ON_ATTACH + + -- Mappings migrated from view.mappings.list + -- + -- You will need to insert "your code goes here" for any mappings with a custom action_cb + vim.keymap.set("n", "-", api.tree.change_root_to_parent, opts("Up")) + vim.keymap.set( + "n", + "<", + api.node.navigate.sibling.prev, + opts("Previous Sibling") + ) + vim.keymap.set("n", "", api.node.open.edit, opts("Open")) + vim.keymap.set("n", "o", api.node.open.edit, opts("Open")) + vim.keymap.set("n", "<2-LeftMouse>", api.node.open.edit, opts("Open")) + vim.keymap.set( + "n", + "<2-RightMouse>", + api.tree.change_root_to_node, + opts("CD") + ) + vim.keymap.set("n", "CC", api.tree.change_root_to_node, opts("CD")) + vim.keymap.set( + "n", + "", + api.node.navigate.parent_close, + opts("Close Directory") + ) + vim.keymap.set("n", "", api.fs.rename_sub, opts("Rename: Omit Filename")) + vim.keymap.set("n", ">", api.node.navigate.sibling.next, opts("Next Sibling")) + vim.keymap.set( + "n", + "I", + api.tree.toggle_hidden_filter, + opts("Toggle Dotfiles") + ) + vim.keymap.set("n", "P", api.node.open.preview, opts("Open Preview")) + vim.keymap.set( + "n", + "Y", + api.fs.copy.relative_path, + opts("Copy Relative Path") + ) + vim.keymap.set("n", "a", api.fs.create, opts("Create")) + vim.keymap.set("n", "c", api.fs.copy.node, opts("Copy")) + vim.keymap.set( + "n", + "gy", + api.fs.copy.absolute_path, + opts("Copy Absolute Path") + ) + vim.keymap.set( + "n", + "i", + api.node.open.horizontal, + opts("Open: Horizontal Split") + ) + vim.keymap.set("n", "d", api.fs.remove, opts("Delete")) + vim.keymap.set("n", "r", api.fs.rename, opts("Rename")) + vim.keymap.set("n", "p", api.fs.paste, opts("Paste")) + vim.keymap.set("n", "q", api.tree.close, opts("Close")) + vim.keymap.set("n", "R", api.tree.reload, opts("Refresh")) + vim.keymap.set("n", "s", api.node.open.vertical, opts("Open: Vertical Split")) + vim.keymap.set("n", "x", api.fs.cut, opts("Cut")) + vim.keymap.set("n", "y", api.fs.copy.filename, opts("Copy Name")) + vim.keymap.set("n", "", api.node.open.tab, opts("Open: New Tab")) + vim.keymap.set("n", "f", api.node.navigate.parent, opts("Parent Directory")) + vim.keymap.set( + "n", + "K", + api.node.navigate.sibling.first, + opts("First Sibling") + ) + vim.keymap.set("n", "J", api.node.navigate.sibling.last, opts("Last Sibling")) + vim.keymap.set("n", "[c", api.node.navigate.git.prev, opts("Prev Git")) + vim.keymap.set("n", "]c", api.node.navigate.git.next, opts("Next Git")) + vim.keymap.set("n", "?", api.tree.toggle_help, opts("Help")) +end + +function M.nvim_window_picker() + local opts = {remap = true, silent = true} + km.map(km.leader "sw", ":WindowPick", opts) + km.map(km.leader "sW", ":WindowSwap", opts) +end + +function M.quickfix() + local opts = {remap = false, silent = true} + + km.nmap(km.leader "co", NV_Darcula_Copen, opts) + km.nmap(km.leader "qc", ":cclose", opts) + km.nmap(km.leader "qn", ":cn", opts) + km.nmap(km.leader "qo", ":copen", opts) + km.nmap(km.leader "qp", ":cp", opts) + + km.nmap(km.leader2 "lc", ":lclose", opts) + km.nmap(km.leader2 "ln", ":lnext", opts) + km.nmap(km.leader2 "lo", ":lopen", opts) + km.nmap(km.leader2 "lp", ":lprevious", opts) +end + +function M.starter() + km.nmap( + km.leader "st", + function() + if vim.fn.bufname("%"):starts_with("NvimTree") then + vim.cmd("wincmd l") + end + + vim.cmd("NvimTreeClose") + MiniStarter.open() + end, + {remap = false, silent = true} + ) +end + +function M.tab() + local opts = {remap = false, silent = true} + + km.nmap(km.leader2 "bb", ":tabnext #", opts) + km.nmap(km.leader2 "bc", ":tabnew", opts) + km.nmap(km.leader2 "bf", ":tabfirst", opts) + km.nmap(km.leader2 "bl", ":tablast", opts) + km.nmap(km.leader2 "bn", ":tabnext", opts) + km.nmap(km.leader2 "bp", ":tabprevious", opts) + km.nmap(km.leader2 "bq", ":tabclose", opts) + km.nmap(km.leader2 "bs", ":tab split", opts) +end + +function M.telescope() + local opts = {remap = false, silent = true} + + km.nmap(km.leader "es", telescope_builtin.grep_string, opts) + km.vmap( + km.leader "es", + function() + NV_Darcula_Grab_Selection( + function(word) + telescope_builtin.grep_string({search = word}) + end + ) + end, + opts + ) + + km.nmap(km.leader "fb", telescope_builtin.buffers, opts) + km.nmap(km.leader "fc", telescope_builtin.colorscheme, opts) + km.nmap(km.leader "fg", telescope_builtin.git_files, opts) + km.nmap(km.leader "fh", telescope_builtin.help_tags, opts) + km.nmap(km.leader "fi", telescope_builtin.command_history, opts) + km.nmap(km.leader "fm", telescope_builtin.man_pages, opts) + km.nmap(km.leader "fo", telescope_builtin.git_commits, opts) + km.nmap(km.leader "fp", telescope_builtin.keymaps, opts) + km.nmap(km.leader "ft", telescope_builtin.git_status, opts) + km.nmap(km.leader "fz", telescope_builtin.current_buffer_fuzzy_find, opts) + km.nmap(km.leader "rg", telescope_builtin.live_grep, opts) + + km.nmap( + km.leader "ff", + function() + telescope_builtin.find_files({hidden = true}) + end, + opts + ) +end + +function M.toggle() + local opts = {remap = false, silent = true} + + -- Fixed height + km.nmap( + km.leader2 "fh", + function() + vim.cmd("setlocal winfixheight!") + utils.notify_setting_enabled("Fixed height", vim.opt.winfixheight:get()) + end, + opts + ) + + -- Fixed width + km.nmap( + km.leader2 "fw", + function() + vim.cmd("setlocal winfixwidth!") + utils.notify_setting_enabled("Fixed width", vim.opt.winfixwidth:get()) + end, + opts + ) + + -- Colorizer + km.nmap( + km.leader2 "tc", + function() + vim.cmd("ColorizerToggle") + end, + opts + ) + + -- Document Formatting + km.nmap( + km.leader2 "tf", + function() + NV_DARCULA_ENABLE_FORMATTING = not NV_DARCULA_ENABLE_FORMATTING + utils.notify_setting_enabled( + "Text formatting", + NV_DARCULA_ENABLE_FORMATTING + ) + end, + opts + ) + + km.nmap( + km.leader2 "tF", + function() + utils.notify_setting_enabled( + "Text formatting", + NV_DARCULA_ENABLE_FORMATTING + ) + end, + opts + ) + + -- List mode + km.map( + km.leader2 "tl", + function() + vim.cmd("set list!") + utils.notify_setting_enabled("List mode", vim.opt.list:get()) + end, + opts + ) + + km.map( + km.leader2 "tL", + function() + utils.notify_setting_enabled("List mode", vim.opt.list:get()) + end, + opts + ) + + -- Relative line numbers + km.nmap( + km.leader2 "tr", + function() + vim.cmd("set invrelativenumber") + utils.notify_setting_enabled( + "Relative numbers", + vim.opt.relativenumber:get() + ) + end, + opts + ) + + km.nmap( + km.leader2 "tR", + function() + utils.notify_setting_enabled( + "Relative numbers", + vim.opt.relativenumber:get() + ) + end, + opts + ) + + -- Line wrapping + km.nmap( + km.leader2 "tw", + function() + vim.cmd("set invwrap") + utils.notify_setting_enabled("Line wrapping", vim.opt.wrap:get()) + end, + opts + ) + + km.nmap( + km.leader2 "tW", + function() + utils.notify_setting_enabled("Line wrapping", vim.opt.wrap:get()) + end, + opts + ) +end + +function M.treesitter() + local swap = require("nvim-treesitter-textobjects.swap") + + km.nmap( + "mar", + function() + swap.swap_next "@parameter.inner" + end + ) + + km.nmap( + "mal", + function() + swap.swap_previous "@parameter.inner" + end + ) +end + +function M.vim() + local opts = {remap = false, silent = true} + + km.tmap("", "", opts) + + km.map(km.leader "wa", NV_Darcula_Write_All, opts) + km.nmap("K", NV_Darcula_Show_Documentation, opts) + km.nmap(km.leader "=", "=", opts) + km.nmap( + km.leader "bq", + function() + local buffer_name = vim.fn.bufname() + if buffer_name ~= nil then + if buffer_name:starts_with("NvimTree") then + vim.cmd("wincmd l") + end + + for _, value in pairs(vim.api.nvim_list_bufs()) do + if value ~= vim.fn.bufnr() then + buffer_name = vim.fn.bufname(value) + if + buffer_name ~= nil and not buffer_name:starts_with("NvimTree") and + not buffer_name:starts_with("term:") + then + vim.cmd("silent! bd! " .. value) + end + end + end + end + end, + opts + ) + km.nmap(km.leader2 "m", ":Messages", opts) + km.nmap( + km.leader2 "n", + function() + vim.cmd("vert new") + vim.opt_local.wrap = true + MiniNotify.show_history() + end, + opts + ) + -- km.nmap(km.leader "cf", ":echo expand('%:p')", opts) + km.nmap(km.leader "ci", NV_Darcula_Close_Invalid, opts) + -- km.nmap(km.leader "cn", ":echo expand('%:t')", opts) + -- km.nmap(km.leader "cp", ":echo expand('%:p')", opts) + -- km.nmap(km.leader "cr", ":echo @%", opts) + km.nmap(km.leader "ee", NV_Darcula_Refresh_Buffer, opts) + km.nmap(km.leader "nh", ":noh", opts) + -- km.nmap(km.leader "nm", "]m", opts) + -- km.nmap(km.leader "pm", "[m", opts) + km.nmap( + km.leader "sla", + ":%s/\\ /\\r/g:noh", + {remap = true, silent = true} + ) + km.nmap( + km.leader "sll", + ":s/\\ /\\r/g:noh", + {remap = true, silent = true} + ) + km.nmap(km.leader "sp", ":sp", opts) + km.nmap(km.leader "te", ":term", opts) + km.nmap(km.leader "v", "", opts) + km.nmap(km.leader "vs", ":vs", opts) + km.vmap("p", '"_dP', opts) + km.vmap(km.leader "ss", ":sort", opts) + + km.set( + {"n", "v"}, + km.leader "dd", + NV_Darcula_Show_Documentation, + {remap = true, silent = true} + ) + km.set( + {"n", "v"}, + km.leader "dh", + NV_Darcula_Show_Documentation, + {remap = true, silent = true} + ) + + km.nmap( + km.leader "dm", + function() + NV_Darcula_Show_Man_Documentation(false) + end, + opts + ) + + km.vmap( + km.leader "dm", + function() + NV_Darcula_Show_Man_Documentation(true) + end, + opts + ) + + km.map( + km.leader "qa", + function() + NV_Darcula_Close_All(false) + end, + opts + ) + + km.map( + km.leader "qq", + function() + if vim.bo.buftype == "prompt" then + vim.api.nvim_input("") + return + end + vim.cmd("q") + end, + opts + ) + + km.map( + km.leader "wqa", + function() + NV_Darcula_Close_All(true) + end, + opts + ) + + km.map( + km.leader "ww", + function() + if vim.bo.buftype ~= "prompt" then + vim.cmd("w") + end + end, + opts + ) + + km.nmap( + km.leader "dv", + function() + NV_Darcula_Show_Vim_Documentation(false) + end, + opts + ) + + km.vmap( + km.leader "dv", + function() + NV_Darcula_Show_Vim_Documentation(true) + end, + opts + ) +end + +function M.vim_fugitive() + local opts = {remap = false, silent = true} + + km.nmap(km.leader "tc", ":Git commit", opts) + km.nmap(km.leader "tp", ":Git push", opts) + km.nmap(km.leader "ts", ":Git", opts) + km.nmap(km.leader "tu", ":Git pull", opts) + km.nmap(km.leader "ttl", ":Git reflog", opts) + km.nmap(km.leader "ttL", ":GcLog", opts) +end + +(function() + if NV_DARCULA_ENABLE_COC then + M.coc() + end + M.commenting() + M.cppman() + M.cspell() + M.diff() + M.editing() + M.flutter() + M.gui() + if not NV_DARCULA_ENABLE_COC then + M.lsp() + end + if not NV_DARCULA_ENABLE_COC then + M.mason() + end + M.mini() + M.navigation() + M.nvim_dap() + M.nvim_haven() + M.nvim_tree() + M.nvim_window_picker() + M.quickfix() + M.starter() + M.tab() + M.telescope() + M.toggle() + M.treesitter() + M.vim() + M.vim_fugitive() +end)() + +return M diff --git a/nvim/lua/darcula/options.lua b/nvim/lua/darcula/options.lua new file mode 100644 index 0000000..55d1430 --- /dev/null +++ b/nvim/lua/darcula/options.lua @@ -0,0 +1,113 @@ +-- The MIT License (MIT) +-- +-- Copyright © 2026 Scott E. Graves +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software +-- and associated documentation files (the “Software”), to deal in the Software without restriction, +-- including without limitation the rights to use, copy, modify, merge, publish, distribute, +-- sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in all copies or +-- substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +-- BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +-- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +-- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-- +local symbols = require("darcula.utils.symbols") + +vim.g.mapleader = " " +vim.g.maplocalleader = " " +if require("darcula.utils.os").is_mac then + vim.g.python3_host_prog = "/usr/bin/python3" +end +vim.g.viminfo = "100,n" .. vim.fs.joinpath(vim.fn.stdpath("state"), "viminfo") + +vim.opt.background = "dark" +vim.opt.backspace = "indent,eol,start" +vim.opt.backup = false +vim.opt.clipboard = "unnamedplus" +vim.opt.cmdheight = 1 +vim.opt.colorcolumn = NV_DARCULA_COLOR_COLUMN +vim.opt.completeopt = "menu,menuone,noselect,fuzzy" +vim.opt.cursorline = true +vim.opt.diffopt = { + "internal", + "filler", + "closeoff", + "context:6", + "algorithm:histogram", + "indent-heuristic", + "linematch:60" +} +vim.opt.encoding = "UTF-8" +vim.opt.equalalways = false +vim.opt.errorbells = false +vim.opt.expandtab = true +vim.opt.fileencoding = "UTF-8" +vim.opt.fillchars = "vert: ,eob: ,stl: ,stlnc: " +vim.opt.foldcolumn = "0" +vim.opt.guicursor = + "n-v-c:block,i-ci-ve:ver25,r-cr:hor20,o:hor50,a:blinkwait700-blinkoff400-blinkon250-Cursor/lCursor,sm:block-blinkwait175-blinkoff150-blinkon175" +vim.opt.hidden = true +vim.opt.hlsearch = true +vim.opt.ignorecase = true +vim.opt.incsearch = true +vim.opt.iskeyword:append("-") +vim.opt.laststatus = 2 +vim.opt.listchars = + "tab:" .. + symbols.listchars.tab .. + ",space:" .. + symbols.listchars.space .. + ",nbsp:" .. + symbols.listchars.nbsp .. + ",trail:" .. + symbols.listchars.trail .. + ",eol:" .. + symbols.listchars.eol .. + ",precedes:" .. + symbols.listchars.precedes .. + ",extends:" .. symbols.listchars.extends +vim.opt.matchpairs:append("<:>") +vim.opt.maxmempattern = 20000 +vim.opt.more = false +vim.opt.mouse = "" +vim.opt.mousehide = false +vim.opt.number = true +vim.opt.numberwidth = 4 +if not NV_DARCULA_ENABLE_COC then + vim.opt.pumborder = "rounded" +end +vim.opt.redrawtime = 10000 +vim.opt.relativenumber = true +vim.opt.rtp:append(vim.fn.fnamemodify(vim.fn.stdpath("data") .. "/site", ":p")) +vim.opt.scrolloff = 8 +vim.opt.selection = "inclusive" +vim.opt.shell = "bash" +vim.opt.shellcmdflag = "-lc" +vim.opt.shiftwidth = 2 +vim.opt.shortmess = vim.o.shortmess .. "cI" +vim.opt.showmatch = true +vim.opt.showmode = false +vim.opt.sidescrolloff = 8 +vim.opt.signcolumn = "yes" +vim.opt.smartcase = true +vim.opt.softtabstop = 2 +vim.opt.splitbelow = true +vim.opt.splitright = true +vim.opt.syntax = "enable" +vim.opt.tabstop = 2 +vim.opt.termguicolors = true +vim.opt.undodir = vim.fs.joinpath(vim.fn.stdpath("data"), ".undo") +vim.opt.undofile = true +vim.opt.updatetime = 250 +vim.opt.wildmode = "longest:full,full" +if not NV_DARCULA_ENABLE_COC then + vim.opt.winborder = "rounded" +end +vim.opt.wrap = false +vim.opt.writebackup = false diff --git a/nvim/lua/darcula/plugins.lua b/nvim/lua/darcula/plugins.lua new file mode 100644 index 0000000..ff09726 --- /dev/null +++ b/nvim/lua/darcula/plugins.lua @@ -0,0 +1,135 @@ +-- The MIT License (MIT) +-- +-- Copyright © 2026 Scott E. Graves +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software +-- and associated documentation files (the “Software”), to deal in the Software without restriction, +-- including without limitation the rights to use, copy, modify, merge, publish, distribute, +-- sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in all copies or +-- substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +-- BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +-- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +-- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-- +require("darcula.config") + +vim.api.nvim_create_autocmd( + "PackChanged", + { + callback = function(ev) + local kind = ev.data.kind + if (ev.data.kind ~= "install" and kind ~= "update") then + return + end + + local name = ev.data.spec.name + if NV_DARCULA_ENABLE_COC then + if name == "coc.nvim" then + vim.system( + {"npm", "i"}, + { + cwd = vim.fs.joinpath( + vim.fn.stdpath("data"), + "site", + "pack", + "core", + "opt", + "coc.nvim" + ) + } + ):wait() + return + end + end + end + } +) + +local packages = { + {src = "https://github.com/nvim-lua/plenary.nvim"}, + {src = "https://github.com/rktjmp/lush.nvim"}, + {src = "https://git.fifthgrid.com/sgraves/darcula_lush"} +} + +if NV_DARCULA_ENABLE_COC then + vim.list_extend( + packages, + { + {src = "https://github.com/neoclide/coc.nvim", {version = "release"}}, + {src = "https://github.com/fannheyward/telescope-coc.nvim"}, + {src = "https://github.com/honza/vim-snippets"} + } + ) +else + vim.list_extend( + packages, + { + {src = "https://github.com/neovim/nvim-lspconfig"}, + {src = "https://github.com/WhoIsSethDaniel/mason-tool-installer.nvim"}, + {src = "https://github.com/akinsho/flutter-tools.nvim"}, + {src = "https://github.com/kosayoda/nvim-lightbulb"}, + {src = "https://github.com/mason-org/mason-lspconfig.nvim"}, + {src = "https://github.com/mason-org/mason.nvim"} + } + ) +end + +vim.list_extend( + packages, + { + { + src = "https://github.com/catgoose/nvim-colorizer.lua", + version = "85a5e83cd4daa258cf95c3204e277991d6fbe747" + }, + {src = "https://github.com/dart-lang/dart-vim-plugin"}, + {src = "https://github.com/dstein64/nvim-scrollview"}, + {src = "https://github.com/kyazdani42/nvim-tree.lua"}, + {src = "https://github.com/leoluz/nvim-dap-go"}, + {src = "https://github.com/lewis6991/gitsigns.nvim"}, + {src = "https://github.com/mfussenegger/nvim-dap"}, + {src = "https://github.com/mhartington/formatter.nvim"}, + {src = "https://github.com/nvim-mini/mini.nvim"}, + {src = "https://github.com/nvim-neotest/nvim-nio"}, + {src = "https://github.com/nvim-telescope/telescope-ui-select.nvim"}, + {src = "https://github.com/nvim-telescope/telescope.nvim"}, + {src = "https://github.com/nvim-treesitter/nvim-treesitter"}, + {src = "https://github.com/nvim-treesitter/nvim-treesitter-textobjects"}, + {src = "https://github.com/rcarriga/nvim-dap-ui"}, + {src = "https://github.com/rktjmp/shipwright.nvim"}, + {src = "https://github.com/sgraves76/cppman.nvim"}, + {src = "https://github.com/stevearc/dressing.nvim"}, + {src = "https://github.com/ten3roberts/window-picker.nvim"}, + {src = "https://github.com/tpope/vim-dispatch"}, + {src = "https://github.com/tpope/vim-fugitive"} + } +) + +vim.pack.add(packages, {confirm = false}) + +local theme_set = false +local set_colorscheme = function() + if theme_set then + return + end + + vim.cmd("colorscheme " .. NV_DARCULA_COLOR_SCHEME) + theme_set = true +end + +for _, pkg in ipairs(packages) do + local parts = vim.split(pkg.src, "/", {plain = true}) + local name = parts[#parts] + vim.cmd("packadd! " .. name) + + if name == NV_DARCULA_COLOR_SCHEME then + set_colorscheme() + end +end + +set_colorscheme() diff --git a/nvim/lua/darcula/setup.lua b/nvim/lua/darcula/setup.lua new file mode 100644 index 0000000..a3d1b59 --- /dev/null +++ b/nvim/lua/darcula/setup.lua @@ -0,0 +1,26 @@ +-- The MIT License (MIT) +-- +-- Copyright © 2026 Scott E. Graves +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software +-- and associated documentation files (the “Software”), to deal in the Software without restriction, +-- including without limitation the rights to use, copy, modify, merge, publish, distribute, +-- sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in all copies or +-- substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +-- BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +-- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +-- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-- +local setup_list = + require("darcula.utils").get_files_sorted_without_extension( + vim.fs.joinpath(vim.fn.stdpath("config"), "lua", "darcula", "setup") +) +for _, name in pairs(setup_list) do + require("darcula.setup." .. name) +end diff --git a/nvim/lua/darcula/setup/100_coc.lua b/nvim/lua/darcula/setup/100_coc.lua new file mode 100644 index 0000000..ac96826 --- /dev/null +++ b/nvim/lua/darcula/setup/100_coc.lua @@ -0,0 +1,168 @@ +-- The MIT License (MIT) +-- +-- Copyright © 2026 Scott E. Graves +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software +-- and associated documentation files (the “Software”), to deal in the Software without restriction, +-- including without limitation the rights to use, copy, modify, merge, publish, distribute, +-- sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in all copies or +-- substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +-- BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +-- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +-- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-- +if not NV_DARCULA_ENABLE_COC then + return +end + +require("darcula.utils.table") + +local coc_config = vim.fn["coc#config"] +local utils = require("darcula.utils") +local utils_os = require("darcula.utils.os") + +utils.copy_file( + utils.iff( + utils_os.is_windows, + vim.fs.joinpath(vim.fn.stdpath("config"), "coc-settings.windows.json"), + vim.fs.joinpath(vim.fn.stdpath("config"), "coc-settings.unix.json") + ), + vim.fs.joinpath(vim.fn.stdpath("config"), "coc-settings.json") +) + +vim.g.coc_data_home = vim.fs.joinpath(vim.fn.stdpath("data"), "coc") + +-- local coc_get_config = vim.fn["coc#util#get_config"] +-- M.plug_end = function(lua_library_list) +-- utils.augroup_with_autocmd( +-- "coc_config_lua_cfg", +-- "User", +-- "CocNvimInit", +-- function() +-- local workspace = coc_get_config("Lua").workspace or {} +-- local library = workspace.library or {} +-- +-- for _, name in pairs(lua_library_list) do +-- local lib = vim.fs.joinpath(vim.g.plug_home, name, "lua") +-- if not table.contains(library, lib) then +-- table.insert(library, lib) +-- end +-- end +-- +-- table.insert(library, "/usr/share/awesome/lib") +-- +-- coc_config("Lua.workspace", {library = library}) +-- end +-- ) +-- end + +local symbols = require("darcula.utils.symbols") + +vim.g.coc_global_extensions = NV_DARCULA_COC_EXTENSIONS +vim.g.coc_snippet_next = "" +vim.g.coc_snippet_prev = "" + +local float_config = { + winblend = 0, + border = true, + rounded = true, + maxWidth = 120 +} +coc_config("Lua.codeLens.enable", NV_DARCULA_ENABLE_CODE_LENS) +coc_config("Lua.completion.callSnippet", "Replace") +coc_config("Lua.diagnostics.globals", NV_DARCULA_LUA_GLOBALS) +coc_config("Lua.diagnostics.workspaceDelay", 30000) +coc_config("Lua.hint.enable", NV_DARCULA_ENABLE_INLAY_HINTS) +coc_config("Lua.telemetry.enable", false) +coc_config("Lua.workspace.checkThirdParty", false) +coc_config("Lua.workspace.maxPreload", 10000) +coc_config("Lua.workspace.preloadFileSize", 3000) +coc_config("cSpell.enabledLanguageIds", NV_DARCULA_CSPELL_LANGUAGES) +coc_config("cSpell.import", {"./"}) +coc_config("clangd.arguments", NV_DARCULA_CLANGD_ARGS) +if utils_os.is_windows then + coc_config("clangd.path", "c:\\bin\\clangd.cmd") +end +coc_config("clangd.inlayHint.enable", NV_DARCULA_ENABLE_INLAY_HINTS) +coc_config("coc.preferences.colorSupport", false) +coc_config("coc.preferences.maxFileSize", "10MB") +coc_config("codeLens.enable", NV_DARCULA_ENABLE_CODE_LENS) +coc_config("diagnostic.enableHighlightLineNumber", true) +coc_config("diagnostic.errorSign", symbols.line.errors) +coc_config("diagnostic.floatConfig", float_config) +coc_config("diagnostic.hintSign", symbols.line.hints) +coc_config("diagnostic.infoSign", symbols.line.info) +coc_config("diagnostic.level", "hint") +coc_config("diagnostic.virtualText", NV_DARCULA_ENABLE_VIRTUAL_TEXT) +coc_config("diagnostic.virtualTextPrefix", symbols.line.info .. " ") +coc_config("diagnostic.warningSign", symbols.line.warnings) +coc_config("highlight.colorNames.enable", false) +coc_config("highlight.colors.enable", false) +coc_config("highlight.document.enable", false) +coc_config("hover.autoHide", false) +coc_config("hover.floatConfig", float_config) +coc_config("inlayHint.display", NV_DARCULA_ENABLE_INLAY_HINTS) +coc_config("inlayHint.enable", NV_DARCULA_ENABLE_INLAY_HINTS) +coc_config("inlayHint.enableParameter", NV_DARCULA_ENABLE_INLAY_HINTS) +coc_config("inlayHint.refreshOnInsertMode", NV_DARCULA_ENABLE_INLAY_HINTS) +if not utils_os.is_windows then + coc_config("jedi.executable.command", "jedi-language-server") +end +coc_config("java.import.maven.enabled", true) +coc_config("java.jdt.ls.lombokSupport.enabled", true) +coc_config( + "java.jdt.ls.vmargs", + "-XX:+UseParallelGC -XX:GCTimeRatio=4 -XX:AdaptiveSizePolicyWeight=90 -Dsun.zip.disableMemoryMapping=true -Xmx4G -Xms4G -Xlog:disable" +) +coc_config("java.maven.downloadSources", false) +coc_config("java.maven.updateSnapshots", true) +coc_config("java.referencesCodeLens.enabled", NV_DARCULA_ENABLE_CODE_LENS) +coc_config("java.trace.server", "verbose") +coc_config("lightbulb.enableSign", not NV_DARCULA_ENABLE_VIRTUAL_TEXT) +coc_config("lightbulb.enableVirtualText", NV_DARCULA_ENABLE_VIRTUAL_TEXT) +coc_config( + "lightbulb.text", + {default = symbols.status.info, quickfix = symbols.status.fix} +) +coc_config("notification.border", true) +coc_config("notification.highlightGroup", "CocFloating") +coc_config("notification.statusLineProgress", true) +coc_config("notification.winblend", 0) +coc_config("signature.floatConfig", float_config) +coc_config("signature.hideOnTextChange", false) +coc_config("suggest.floatConfig", float_config) +coc_config("suggest.keepCompleteopt", true) +coc_config("suggest.noselect", true) +coc_config("suggest.virtualText", NV_DARCULA_ENABLE_VIRTUAL_TEXT) +coc_config("sumneko-lua.enableNvimLuaDev", true) + +coc_config( + "languageserver", + { + vala = { + command = "vala-language-server", + filetypes = {"vala", "genie"} + } + } +) + +if utils_os.is_windows then + coc_config( + "sh.commandPath", + vim.fs.joinpath( + vim.g.coc_data_home, + "extensions", + "node_modules", + "coc-sh", + "node_modules", + ".bin", + "bash-language-server.cmd" + ) + ) +end diff --git a/nvim/lua/darcula/setup/100_mason.lua b/nvim/lua/darcula/setup/100_mason.lua new file mode 100644 index 0000000..64b2e15 --- /dev/null +++ b/nvim/lua/darcula/setup/100_mason.lua @@ -0,0 +1,105 @@ +-- The MIT License (MIT) +-- +-- Copyright © 2026 Scott E. Graves +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software +-- and associated documentation files (the “Software”), to deal in the Software without restriction, +-- including without limitation the rights to use, copy, modify, merge, publish, distribute, +-- sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in all copies or +-- substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +-- BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +-- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +-- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-- +if NV_DARCULA_ENABLE_COC then + return +end + +local symbols = require("darcula.utils.symbols") +---@diagnostic disable-next-line: deprecated +local unpacker = table.unpack or unpack + +require("mason").setup { + ui = { + border = "rounded", + icons = { + package_installed = symbols.status.ok, + package_pending = symbols.status.checking, + package_uninstalled = symbols.status.uninstalled + } + } +} + +require("mason-lspconfig").setup { + automatic_enable = NV_DARCULA_MASON_LSP_LIST, + ensure_installed = NV_DARCULA_MASON_INST_LIST +} + +require("mason-tool-installer").setup { + ensure_installed = NV_DARCULA_MASON_TOOL_LIST, + run_on_start = true +} + +vim.lsp.config( + "*", + { + capabilities = require("mini.completion").get_lsp_capabilities() + } +) + +for _, name in pairs(NV_DARCULA_MASON_LSP_LIST) do + if name == "clangd" then + vim.lsp.config( + "clangd", + { + cmd = { + "clangd", + unpacker(NV_DARCULA_CLANGD_ARGS) + } + } + ) + elseif name == "lua_ls" then + vim.lsp.config( + name, + { + settings = { + Lua = { + completion = { + callSnippet = "Both", + keywordSnippet = "Both" + }, + diagnostics = {globals = NV_DARCULA_LUA_GLOBALS}, + runtime = { + version = "LuaJIT" + }, + telemetry = {enable = false}, + workspace = { + checkThirdParty = false, + library = { + vim.env.VIMRUNTIME, + vim.fn.stdpath("config") + -- vim.fs.joinpath( + -- vim.fn.stdpath("data"), + -- "site", + -- "pack", + -- "core", + -- "opt" + -- ) + } + -- maxPreload = 1000, + -- preloadFileSize = 200 + } + } + } + } + ) + else + vim.lsp.config(name, {}) + end +end diff --git a/nvim/lua/darcula/setup/200_lsp.lua b/nvim/lua/darcula/setup/200_lsp.lua new file mode 100644 index 0000000..1a24c6c --- /dev/null +++ b/nvim/lua/darcula/setup/200_lsp.lua @@ -0,0 +1,89 @@ +-- The MIT License (MIT) +-- +-- Copyright © 2026 Scott E. Graves +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software +-- and associated documentation files (the “Software”), to deal in the Software without restriction, +-- including without limitation the rights to use, copy, modify, merge, publish, distribute, +-- sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in all copies or +-- substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +-- BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +-- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +-- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-- +if NV_DARCULA_ENABLE_COC then + return +end + +local symbols = require("darcula.utils.symbols") +local utils = require("darcula.utils") + +vim.diagnostic.config( + { + float = { + border = "rounded", + source = "if_many" + }, + signs = { + max = 1, + text = { + [vim.diagnostic.severity.ERROR] = symbols.line.errors, + [vim.diagnostic.severity.WARN] = symbols.line.warnings, + [vim.diagnostic.severity.INFO] = symbols.line.hints, + [vim.diagnostic.severity.HINT] = symbols.line.hints + }, + numhl = { + [vim.diagnostic.severity.ERROR] = "DiagnosticLineNrError", + [vim.diagnostic.severity.WARN] = "DiagnosticLineNrWarn", + [vim.diagnostic.severity.INFO] = "DiagnosticLineNrInfo", + [vim.diagnostic.severity.HINT] = "DiagnosticLineNrHint" + } + }, + virtual_text = NV_DARCULA_ENABLE_VIRTUAL_TEXT + } +) + +utils.augroup_with_autocmd( + "DarculaLspAutoCommands", + "LspAttach", + "*", + function(ev) + local client = vim.lsp.get_client_by_id(ev.data.client_id) + if not client then + return + end + + if client:supports_method("textDocument/codeLens") then + vim.lsp.codelens.enable(NV_DARCULA_ENABLE_CODE_LENS, {bufnr = ev.buf}) + end + + if client:supports_method("textDocument/documentHighlight") then + local group = + utils.augroup_with_autocmd_buffer( + "DarculaLspBufferAutoCommands", + {"CursorHold", "CursorHoldI"}, + ev.buf, + vim.lsp.buf.document_highlight + ) + + utils.autocmd_buffer( + group, + {"CursorMoved", "CursorMovedI"}, + ev.buf, + vim.lsp.buf.clear_references + ) + end + + if client:supports_method("textDocument/inlayHint") then + vim.lsp.inlay_hint.enable(NV_DARCULA_ENABLE_INLAY_HINTS) + end + + require("darcula.keymaps").lsp_on_attach(ev) + end +) diff --git a/nvim/lua/darcula/setup/300_mini_fuzzy.lua b/nvim/lua/darcula/setup/300_mini_fuzzy.lua new file mode 100644 index 0000000..0465e43 --- /dev/null +++ b/nvim/lua/darcula/setup/300_mini_fuzzy.lua @@ -0,0 +1,20 @@ +-- The MIT License (MIT) +-- +-- Copyright © 2026 Scott E. Graves +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software +-- and associated documentation files (the “Software”), to deal in the Software without restriction, +-- including without limitation the rights to use, copy, modify, merge, publish, distribute, +-- sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in all copies or +-- substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +-- BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +-- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +-- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-- +require("mini.fuzzy").setup() diff --git a/nvim/lua/darcula/setup/300_mini_icons.lua b/nvim/lua/darcula/setup/300_mini_icons.lua new file mode 100644 index 0000000..c5394d3 --- /dev/null +++ b/nvim/lua/darcula/setup/300_mini_icons.lua @@ -0,0 +1,22 @@ +-- The MIT License (MIT) +-- +-- Copyright © 2026 Scott E. Graves +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software +-- and associated documentation files (the “Software”), to deal in the Software without restriction, +-- including without limitation the rights to use, copy, modify, merge, publish, distribute, +-- sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in all copies or +-- substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +-- BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +-- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +-- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-- +require("mini.icons").setup() +MiniIcons.mock_nvim_web_devicons() +MiniIcons.tweak_lsp_kind() diff --git a/nvim/lua/darcula/setup/300_mini_keymap.lua b/nvim/lua/darcula/setup/300_mini_keymap.lua new file mode 100644 index 0000000..191f138 --- /dev/null +++ b/nvim/lua/darcula/setup/300_mini_keymap.lua @@ -0,0 +1,20 @@ +-- The MIT License (MIT) +-- +-- Copyright © 2026 Scott E. Graves +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software +-- and associated documentation files (the “Software”), to deal in the Software without restriction, +-- including without limitation the rights to use, copy, modify, merge, publish, distribute, +-- sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in all copies or +-- substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +-- BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +-- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +-- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-- +require("mini.keymap").setup() diff --git a/nvim/lua/darcula/setup/300_mini_misc.lua b/nvim/lua/darcula/setup/300_mini_misc.lua new file mode 100644 index 0000000..105a606 --- /dev/null +++ b/nvim/lua/darcula/setup/300_mini_misc.lua @@ -0,0 +1,20 @@ +-- The MIT License (MIT) +-- +-- Copyright © 2026 Scott E. Graves +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software +-- and associated documentation files (the “Software”), to deal in the Software without restriction, +-- including without limitation the rights to use, copy, modify, merge, publish, distribute, +-- sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in all copies or +-- substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +-- BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +-- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +-- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-- +require("mini.misc").setup_auto_root() diff --git a/nvim/lua/darcula/setup/400_mini_ai.lua b/nvim/lua/darcula/setup/400_mini_ai.lua new file mode 100644 index 0000000..e8e1fa3 --- /dev/null +++ b/nvim/lua/darcula/setup/400_mini_ai.lua @@ -0,0 +1,33 @@ +-- The MIT License (MIT) +-- +-- Copyright © 2026 Scott E. Graves +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software +-- and associated documentation files (the “Software”), to deal in the Software without restriction, +-- including without limitation the rights to use, copy, modify, merge, publish, distribute, +-- sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in all copies or +-- substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +-- BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +-- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +-- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-- +local spec_treesitter = require("mini.ai").gen_spec.treesitter +require("mini.ai").setup { + mappings = { + around_last = "", -- disable + inside_last = "" -- disable + }, + custom_textobjects = { + c = spec_treesitter({a = "@class.outer", i = "@class.inner"}), + i = spec_treesitter({a = "@conditional.outer", i = "@conditional.inner"}), + l = spec_treesitter({a = "@loop.outer", i = "@loop.inner"}), + m = spec_treesitter({a = "@function.outer", i = "@function.inner"}), + B = spec_treesitter({a = "@block.outer", i = "@block.inner"}) + } +} diff --git a/nvim/lua/darcula/setup/400_mini_comment.lua b/nvim/lua/darcula/setup/400_mini_comment.lua new file mode 100644 index 0000000..1b0f8c4 --- /dev/null +++ b/nvim/lua/darcula/setup/400_mini_comment.lua @@ -0,0 +1,20 @@ +-- The MIT License (MIT) +-- +-- Copyright © 2026 Scott E. Graves +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software +-- and associated documentation files (the “Software”), to deal in the Software without restriction, +-- including without limitation the rights to use, copy, modify, merge, publish, distribute, +-- sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in all copies or +-- substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +-- BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +-- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +-- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-- +require("mini.comment").setup() diff --git a/nvim/lua/darcula/setup/400_mini_completion.lua b/nvim/lua/darcula/setup/400_mini_completion.lua new file mode 100644 index 0000000..0a8d1ec --- /dev/null +++ b/nvim/lua/darcula/setup/400_mini_completion.lua @@ -0,0 +1,41 @@ +-- The MIT License (MIT) +-- +-- Copyright © 2026 Scott E. Graves +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software +-- and associated documentation files (the “Software”), to deal in the Software without restriction, +-- including without limitation the rights to use, copy, modify, merge, publish, distribute, +-- sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in all copies or +-- substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +-- BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +-- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +-- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-- +if NV_DARCULA_ENABLE_COC then + return +end + +require("mini.completion").setup { + delay = {completion = 100, info = 100, signature = 50}, + window = { + info = {height = 25, width = 80, border = "rounded"}, + signature = {height = 25, width = 80, border = "rounded"} + }, + lsp_completion = { + auto_setup = true, + source_func = "omnifunc" + }, + fallback_action = "", + mappings = { + force_twostep = "", + force_fallback = "", + scroll_down = "", + scroll_up = "" + } +} diff --git a/nvim/lua/darcula/setup/400_mini_move.lua b/nvim/lua/darcula/setup/400_mini_move.lua new file mode 100644 index 0000000..a2c03cf --- /dev/null +++ b/nvim/lua/darcula/setup/400_mini_move.lua @@ -0,0 +1,34 @@ +-- The MIT License (MIT) +-- +-- Copyright © 2026 Scott E. Graves +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software +-- and associated documentation files (the “Software”), to deal in the Software without restriction, +-- including without limitation the rights to use, copy, modify, merge, publish, distribute, +-- sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in all copies or +-- substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +-- BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +-- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +-- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-- +require("mini.move").setup { + mappings = { + left = "", + right = "", + down = "", + up = "", + line_left = "", + line_right = "", + line_down = "", + line_up = "" + }, + options = { + reindent_linewise = true + } +} diff --git a/nvim/lua/darcula/setup/400_mini_notify.lua b/nvim/lua/darcula/setup/400_mini_notify.lua new file mode 100644 index 0000000..42e6ed3 --- /dev/null +++ b/nvim/lua/darcula/setup/400_mini_notify.lua @@ -0,0 +1,44 @@ +-- The MIT License (MIT) +-- +-- Copyright © 2026 Scott E. Graves +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software +-- and associated documentation files (the “Software”), to deal in the Software without restriction, +-- including without limitation the rights to use, copy, modify, merge, publish, distribute, +-- sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in all copies or +-- substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +-- BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +-- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +-- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-- +require("mini.notify").setup { + window = { + config = { + row = vim.o.lines - 3, + col = vim.o.columns - 3, + anchor = "SE" + } + } +} + +vim.notify = + MiniNotify.make_notify( + { + DEBUG = {duration = 0}, + ERROR = {duration = 3500, hl_group = "DiagnosticFloatingError"}, + INFO = {duration = 3500, hl_group = "DiagnosticFloatingInfo"}, + OFF = {duration = 0}, + TRACE = {duration = 0}, + WARN = {duration = 3500, hl_group = "DiagnosticFloatingWarn"} + } +) + +vim.cmd("hi! link MiniNotifyBorder NotifyINFOBorder") +vim.cmd("hi! link MiniNotifyNormal NotifyINFOBody") +vim.cmd("hi! link MiniNotifyTitle Number") diff --git a/nvim/lua/darcula/setup/400_mini_pairs.lua b/nvim/lua/darcula/setup/400_mini_pairs.lua new file mode 100644 index 0000000..250a5a6 --- /dev/null +++ b/nvim/lua/darcula/setup/400_mini_pairs.lua @@ -0,0 +1,20 @@ +-- The MIT License (MIT) +-- +-- Copyright © 2026 Scott E. Graves +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software +-- and associated documentation files (the “Software”), to deal in the Software without restriction, +-- including without limitation the rights to use, copy, modify, merge, publish, distribute, +-- sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in all copies or +-- substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +-- BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +-- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +-- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-- +require("mini.pairs").setup() diff --git a/nvim/lua/darcula/setup/400_mini_snippets.lua b/nvim/lua/darcula/setup/400_mini_snippets.lua new file mode 100644 index 0000000..47adfcb --- /dev/null +++ b/nvim/lua/darcula/setup/400_mini_snippets.lua @@ -0,0 +1,60 @@ +-- The MIT License (MIT) +-- +-- Copyright © 2026 Scott E. Graves +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software +-- and associated documentation files (the “Software”), to deal in the Software without restriction, +-- including without limitation the rights to use, copy, modify, merge, publish, distribute, +-- sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in all copies or +-- substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +-- BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +-- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +-- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-- +if NV_DARCULA_ENABLE_COC then + return +end + +local snippets = require("mini.snippets") +local gen_loader = snippets.gen_loader +local match_strict = function(snips) + return snippets.default_match(snips, {pattern_fuzzy = "%S+"}) +end + +snippets.setup { + mappings = { + expand = "", + jump_next = "", + jump_prev = "", + stop = "" + }, + expand = {match = match_strict}, + snippets = { + gen_loader.from_file( + vim.fs.joinpath(vim.fn.stdpath("config"), "snippets", "global.json") + ), + gen_loader.from_lang() + } +} + +vim.api.nvim_set_hl( + 0, + "MiniSnippetsCurrentReplace", + {link = "DiagnosticVirtualTextInfo"} +) +vim.api.nvim_set_hl( + 0, + "MiniSnippetsFinal", + {link = "DiagnosticVirtualTextInfo"} +) +vim.api.nvim_set_hl( + 0, + "MiniSnippetsVisited", + {link = "DiagnosticVirtualTextInfo"} +) diff --git a/nvim/lua/darcula/setup/400_mini_starter.lua b/nvim/lua/darcula/setup/400_mini_starter.lua new file mode 100644 index 0000000..3b1ead1 --- /dev/null +++ b/nvim/lua/darcula/setup/400_mini_starter.lua @@ -0,0 +1,147 @@ +-- The MIT License (MIT) +-- +-- Copyright © 2026 Scott E. Graves +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software +-- and associated documentation files (the “Software”), to deal in the Software without restriction, +-- including without limitation the rights to use, copy, modify, merge, publish, distribute, +-- sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in all copies or +-- substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +-- BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +-- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +-- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-- +local starter = require("mini.starter") + +local header_cache +local wrap_action = function(input) + local parse_items = function(items) + for idx, val in ipairs(items) do + local orig_action = val.action + items[idx].action = function() + if type(orig_action) == "string" then + vim.cmd(orig_action) + elseif type(orig_action) == "function" then + orig_action() + end + + header_cache = nil + NV_Darcula_LSP_Restart() + end + end + + return items + end + + if type(input) == "function" then + return function() + return parse_items(input()) + end + end + + return parse_items(input) +end + +local main_section = "Bookmarks" +local add_line_under_sections = function(content) + local out = {} + + for _, line in ipairs(content) do + table.insert(out, line) + if line[1].type == "section" then + table.insert(out, {{type = "empty", string = ""}}) + end + end + + return out +end + +starter.setup { + content_hooks = { + add_line_under_sections, + starter.gen_hook.indexing("all", {"Builtin actions", main_section}), + starter.gen_hook.aligning("left", "top"), + starter.gen_hook.padding(5, 2) + }, + evaluate_single = true, + header = function() + if not header_cache then + header_cache = + table.concat(require("darcula.utils.fortune").cowsay(), "\n") + end + return header_cache + end, + items = { + wrap_action(starter.sections.builtin_actions()), + wrap_action(starter.sections.recent_files(5, true)), + wrap_action(starter.sections.recent_files(5, false)), + wrap_action( + { + { + action = "e " .. + vim.fs.joinpath(vim.env.HOME, ".desktop", "scripts", "setup.sh"), + name = "Desktop (" .. + vim.fs.joinpath(vim.env.HOME, ".desktop", "scripts", "setup.sh") .. + ")", + section = main_section + }, + { + action = "e " .. vim.fs.joinpath(vim.fn.stdpath("config"), "init.lua"), + name = "Lua Configuration (" .. + vim.fs.joinpath(vim.fn.stdpath("config"), "init.lua") .. ")", + section = main_section + }, + { + action = "e " .. + vim.fs.joinpath( + vim.fn.stdpath("config"), + "lua", + "darcula", + "keymaps.lua" + ), + name = "Maps (" .. + vim.fs.joinpath( + vim.fn.stdpath("config"), + "lua", + "darcula", + "keymaps.lua" + ) .. + ")", + section = main_section + }, + { + action = "e " .. + vim.fs.joinpath( + vim.fn.stdpath("config"), + "lua", + "darcula", + "setup", + "305_mini_starter.lua" + ), + name = "Starter (" .. + vim.fs.joinpath( + vim.fn.stdpath("config"), + "lua", + "darcula", + "setup", + "305_mini_starter.lua" + ) .. + ")", + section = main_section + } + } + ) + }, + footer = "" +} + +vim.cmd("hi! link MiniStarterHeader Comment") +vim.cmd("hi! link MiniStarterItem Comment") +vim.cmd("hi! link MiniStarterItemPrefix Normal") +vim.cmd("hi! link MiniStarterQuery Search") diff --git a/nvim/lua/darcula/setup/400_mini_statusline.lua b/nvim/lua/darcula/setup/400_mini_statusline.lua new file mode 100644 index 0000000..9c30beb --- /dev/null +++ b/nvim/lua/darcula/setup/400_mini_statusline.lua @@ -0,0 +1,20 @@ +-- The MIT License (MIT) +-- +-- Copyright © 2026 Scott E. Graves +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software +-- and associated documentation files (the “Software”), to deal in the Software without restriction, +-- including without limitation the rights to use, copy, modify, merge, publish, distribute, +-- sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in all copies or +-- substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +-- BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +-- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +-- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-- +require("mini.statusline").setup() diff --git a/nvim/lua/darcula/setup/400_mini_surround.lua b/nvim/lua/darcula/setup/400_mini_surround.lua new file mode 100644 index 0000000..791c73e --- /dev/null +++ b/nvim/lua/darcula/setup/400_mini_surround.lua @@ -0,0 +1,37 @@ +-- The MIT License (MIT) +-- +-- Copyright © 2026 Scott E. Graves +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software +-- and associated documentation files (the “Software”), to deal in the Software without restriction, +-- including without limitation the rights to use, copy, modify, merge, publish, distribute, +-- sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in all copies or +-- substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +-- BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +-- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +-- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-- +require("mini.surround").setup { + custom_surroundings = nil, + highlight_duration = 500, + mappings = { + add = "S", + delete = "ds", + find = "Sf", + find_left = "SF", + highlight = "Sh", + replace = "cs", + suffix_last = "l", + suffix_next = "n" + }, + n_lines = 20, + respect_selection_type = false, + search_method = "cover", + silent = false +} diff --git a/nvim/lua/darcula/setup/500_colorizer.lua b/nvim/lua/darcula/setup/500_colorizer.lua new file mode 100644 index 0000000..5b02867 --- /dev/null +++ b/nvim/lua/darcula/setup/500_colorizer.lua @@ -0,0 +1,20 @@ +-- The MIT License (MIT) +-- +-- Copyright © 2026 Scott E. Graves +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software +-- and associated documentation files (the “Software”), to deal in the Software without restriction, +-- including without limitation the rights to use, copy, modify, merge, publish, distribute, +-- sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in all copies or +-- substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +-- BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +-- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +-- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-- +require("colorizer").setup() diff --git a/nvim/lua/darcula/setup/500_cppman.lua b/nvim/lua/darcula/setup/500_cppman.lua new file mode 100644 index 0000000..d0de5b0 --- /dev/null +++ b/nvim/lua/darcula/setup/500_cppman.lua @@ -0,0 +1,20 @@ +-- The MIT License (MIT) +-- +-- Copyright © 2026 Scott E. Graves +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software +-- and associated documentation files (the “Software”), to deal in the Software without restriction, +-- including without limitation the rights to use, copy, modify, merge, publish, distribute, +-- sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in all copies or +-- substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +-- BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +-- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +-- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-- +require("cppman").setup {win = {split = "right"}} diff --git a/nvim/lua/darcula/setup/500_dap.lua b/nvim/lua/darcula/setup/500_dap.lua new file mode 100644 index 0000000..7c26637 --- /dev/null +++ b/nvim/lua/darcula/setup/500_dap.lua @@ -0,0 +1,177 @@ +-- The MIT License (MIT) +-- +-- Copyright © 2026 Scott E. Graves +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software +-- and associated documentation files (the “Software”), to deal in the Software without restriction, +-- including without limitation the rights to use, copy, modify, merge, publish, distribute, +-- sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in all copies or +-- substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +-- BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +-- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +-- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-- +local dap = require("dap") +local utils = require("darcula.utils") +local utils_os = require("darcula.utils.os") + +-- DOES NOT CURRENTLY WORK +-- dap.adapters.cppvsdbg = { +-- id = "cppvsdbg", +-- type = "executable", +-- command = vim.fs.joinpath( +-- vim.fn.stdpath("data"), +-- "dap", "cpp", "extension", "debugAdapters", "vsdbg", "bin", "vsdbg.exe" +-- ), +-- args = { +-- "--interpreter=vscode" +-- }, +-- options = { +-- detached = false +-- } +-- } +dap.adapters.cppdbg = { + id = "cppdbg", + type = "executable", + command = vim.fs.joinpath( + vim.fn.stdpath("data"), + "dap", + "cpp", + "extension", + "debugAdapters", + "bin", + utils.iff(utils_os.is_windows, "OpenDebugAD7.exe", "OpenDebugAD7") + ), + options = { + detached = false + } +} + +dap.adapters.dart = { + type = "executable", + command = "dart", + args = {"debug_adapter"} +} +dap.adapters.flutter = { + type = "executable", + command = "flutter", + args = {"debug_adapter"} +} +dap.configurations.dart = { + { + type = "dart", + request = "launch", + name = "Launch dart", + dartSdkPath = vim.fs.joinpath( + utils.iff(utils_os.is_windows, vim.env.NV_DARCULA_DRIVE, vim.env.HOME), + "flutter", + "bin", + "cache", + "dart-sdk", + "bin", + "dart" + ), + flutterSdkPath = vim.fs.joinpath( + utils.iff(utils_os.is_windows, vim.env.NV_DARCULA_DRIVE, vim.env.HOME), + "flutter", + "bin", + "flutter" + ), + program = "${workspaceFolder}/lib/main.dart", -- ensure this is correct + cwd = "${workspaceFolder}" + }, + { + type = "flutter", + request = "launch", + name = "Launch flutter", + dartSdkPath = vim.fs.joinpath( + utils.iff(utils_os.is_windows, vim.env.NV_DARCULA_DRIVE, vim.env.HOME), + "flutter", + "bin", + "cache", + "dart-sdk", + "bin", + "dart" + ), + flutterSdkPath = vim.fs.joinpath( + utils.iff(utils_os.is_windows, vim.env.NV_DARCULA_DRIVE, vim.env.HOME), + "flutter", + "bin", + "flutter" + ), + program = "${workspaceFolder}/lib/main.dart", -- ensure this is correct + cwd = "${workspaceFolder}" + } +} + +require("dap-go").setup() + +local symbols = require("darcula.utils.symbols") +vim.fn.sign_define( + "DapBreakpoint", + { + text = symbols.debug.breakpoint, + texthl = "ErrorSign", + linehl = "", + numhl = "" + } +) + +vim.fn.sign_define( + "DapBreakpointCondition", + { + text = symbols.debug.conditional_breakpoint, + texthl = "ErrorSign", + linehl = "", + numhl = "" + } +) + +vim.fn.sign_define( + "DapBreakpointRejected", + { + text = symbols.debug.breakpoint_disabled, + texthl = "ErrorSign", + linehl = "", + numhl = "" + } +) + +vim.fn.sign_define( + "DapLogPoint", + { + text = symbols.debug.breakpoint, + texthl = "WarningSign", + linehl = "", + numhl = "" + } +) + +vim.fn.sign_define( + "DapStopped", + { + text = symbols.debug.current_line, + texthl = "WarningSign", + linehl = "", + numhl = "" + } +) + +local dapui = require("dapui") +dapui.setup() + +dap.listeners.after.event_initialized["dapui_config"] = function() + dapui.open() +end +dap.listeners.before.event_terminated["dapui_config"] = function() + dapui.close() +end +dap.listeners.before.event_exited["dapui_config"] = function() + dapui.close() +end diff --git a/nvim/lua/darcula/setup/500_dispatch.lua b/nvim/lua/darcula/setup/500_dispatch.lua new file mode 100644 index 0000000..5d66798 --- /dev/null +++ b/nvim/lua/darcula/setup/500_dispatch.lua @@ -0,0 +1,20 @@ +-- The MIT License (MIT) +-- +-- Copyright © 2026 Scott E. Graves +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software +-- and associated documentation files (the “Software”), to deal in the Software without restriction, +-- including without limitation the rights to use, copy, modify, merge, publish, distribute, +-- sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in all copies or +-- substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +-- BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +-- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +-- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-- +vim.g.dispatch_no_maps = 1 diff --git a/nvim/lua/darcula/setup/500_dressing.lua b/nvim/lua/darcula/setup/500_dressing.lua new file mode 100644 index 0000000..fd790d7 --- /dev/null +++ b/nvim/lua/darcula/setup/500_dressing.lua @@ -0,0 +1,30 @@ +-- The MIT License (MIT) +-- +-- Copyright © 2026 Scott E. Graves +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software +-- and associated documentation files (the “Software”), to deal in the Software without restriction, +-- including without limitation the rights to use, copy, modify, merge, publish, distribute, +-- sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in all copies or +-- substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +-- BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +-- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +-- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-- +require("dressing").setup { + input = { + relative = "editor", + win_options = { + winhighlight = "Title:Pmenu" + } + }, + select = { + relative = "editor" + } +} diff --git a/nvim/lua/darcula/setup/500_flutter.lua b/nvim/lua/darcula/setup/500_flutter.lua new file mode 100644 index 0000000..f9aa866 --- /dev/null +++ b/nvim/lua/darcula/setup/500_flutter.lua @@ -0,0 +1,20 @@ +-- The MIT License (MIT) +-- +-- Copyright © 2026 Scott E. Graves +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software +-- and associated documentation files (the “Software”), to deal in the Software without restriction, +-- including without limitation the rights to use, copy, modify, merge, publish, distribute, +-- sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in all copies or +-- substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +-- BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +-- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +-- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-- +require("darcula.flutter").setup({use_coc = NV_DARCULA_ENABLE_COC}) diff --git a/nvim/lua/darcula/setup/500_flutter_tools.lua b/nvim/lua/darcula/setup/500_flutter_tools.lua new file mode 100644 index 0000000..7f0ef7b --- /dev/null +++ b/nvim/lua/darcula/setup/500_flutter_tools.lua @@ -0,0 +1,24 @@ +-- The MIT License (MIT) +-- +-- Copyright © 2026 Scott E. Graves +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software +-- and associated documentation files (the “Software”), to deal in the Software without restriction, +-- including without limitation the rights to use, copy, modify, merge, publish, distribute, +-- sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in all copies or +-- substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +-- BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +-- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +-- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-- +if NV_DARCULA_ENABLE_COC then + return +end + +require("flutter-tools").setup {} diff --git a/nvim/lua/darcula/setup/500_formatter.lua b/nvim/lua/darcula/setup/500_formatter.lua new file mode 100644 index 0000000..2c617a2 --- /dev/null +++ b/nvim/lua/darcula/setup/500_formatter.lua @@ -0,0 +1,69 @@ +-- The MIT License (MIT) +-- +-- Copyright © 2026 Scott E. Graves +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software +-- and associated documentation files (the “Software”), to deal in the Software without restriction, +-- including without limitation the rights to use, copy, modify, merge, publish, distribute, +-- sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in all copies or +-- substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +-- BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +-- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +-- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-- +local formatter_util = require("formatter.util") + +require("formatter").setup { + logging = true, + log_level = vim.log.levels.WARN, + filetype = { + c = {require("formatter.filetypes.c").clangformat}, + cpp = {require("formatter.filetypes.cpp").clangformat}, + dart = {require("formatter.filetypes.dart").dartformat}, + go = {require("formatter.filetypes.go").gofumpt}, + java = { + function() + return { + exe = "google-java-format", + args = { + formatter_util.escape_path( + formatter_util.get_current_buffer_file_path() + ), + "--replace" + }, + stdin = true + } + end + }, + javascript = {require("formatter.filetypes.javascript").prettier}, + javascriptreact = {require("formatter.filetypes.javascriptreact").prettier}, + json = {require("formatter.filetypes.json").prettier}, + lua = { + require("formatter.filetypes.lua").luafmt, + function() + return { + exe = "luafmt", + args = { + "--stdin", + "-l", + "80", + "-i", + "2" + }, + stdin = true + } + end + }, + python = {require("formatter.filetypes.python").yapf}, + sh = {require("formatter.filetypes.sh").shfmt}, + typescript = {require("formatter.filetypes.typescript").prettier}, + typescriptreact = {require("formatter.filetypes.typescriptreact").prettier}, + xml = {require("formatter.filetypes.xml").tidy} + } +} diff --git a/nvim/lua/darcula/setup/500_gitsigns.lua b/nvim/lua/darcula/setup/500_gitsigns.lua new file mode 100644 index 0000000..dc903ea --- /dev/null +++ b/nvim/lua/darcula/setup/500_gitsigns.lua @@ -0,0 +1,41 @@ +-- The MIT License (MIT) +-- +-- Copyright © 2026 Scott E. Graves +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software +-- and associated documentation files (the “Software”), to deal in the Software without restriction, +-- including without limitation the rights to use, copy, modify, merge, publish, distribute, +-- sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in all copies or +-- substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +-- BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +-- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +-- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-- +local keymaps = require("darcula.keymaps") +local symbols = require("darcula.utils.symbols") + +require("gitsigns").setup { + current_line_blame = NV_DARCULA_ENABLE_GIT_LINE_BLAME, + current_line_blame_opts = { + virt_text = true, + virt_text_pos = "eol", + delay = 1000, + ignore_whitespace = false + }, + current_line_blame_formatter = symbols.git.blame .. + " , - ", + linehl = false, + numhl = false, + preview_config = {border = "rounded"}, + signcolumn = false, + word_diff = false, + on_attach = function(bufnr) + keymaps.gitsigns(bufnr) + end +} diff --git a/nvim/lua/darcula/setup/500_haven.lua b/nvim/lua/darcula/setup/500_haven.lua new file mode 100644 index 0000000..9b4340f --- /dev/null +++ b/nvim/lua/darcula/setup/500_haven.lua @@ -0,0 +1,36 @@ +-- The MIT License (MIT) +-- +-- Copyright © 2026 Scott E. Graves +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software +-- and associated documentation files (the “Software”), to deal in the Software without restriction, +-- including without limitation the rights to use, copy, modify, merge, publish, distribute, +-- sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in all copies or +-- substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +-- BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +-- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +-- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-- +local utils_os = require("darcula.utils.os") + +require("darcula.haven").setup { + exclusions = { + function(path, _) + local tmp = vim.env.TEMP or vim.env.TMP + if tmp ~= nil and tmp:len() > 0 then + if utils_os.is_windows then + return path:lower():starts_with(tmp:lower()) + end + + return path:starts_with(tmp) + end + return false + end + } +} diff --git a/nvim/lua/darcula/setup/500_lightbulb.lua b/nvim/lua/darcula/setup/500_lightbulb.lua new file mode 100644 index 0000000..a271bc6 --- /dev/null +++ b/nvim/lua/darcula/setup/500_lightbulb.lua @@ -0,0 +1,56 @@ +-- The MIT License (MIT) +-- +-- Copyright © 2026 Scott E. Graves +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software +-- and associated documentation files (the “Software”), to deal in the Software without restriction, +-- including without limitation the rights to use, copy, modify, merge, publish, distribute, +-- sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in all copies or +-- substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +-- BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +-- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +-- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-- +if NV_DARCULA_ENABLE_COC then + return +end + +local symbols = require("darcula.utils.symbols") + +require("nvim-lightbulb").setup( + { + hide_in_unfocused_buffer = true, + link_highlights = false, + sign = { + enabled = true, + text = symbols.status.info, + hl = "WarningSign" + }, + virtual_text = { + enabled = false + }, + float = { + enabled = false + }, + status_text = { + enabled = false + }, + number = { + enabled = false + }, + line = { + enabled = false + }, + autocmd = { + enabled = true, + events = {"CursorHold", "CursorHoldI"}, + pattern = {"*"} + } + } +) diff --git a/nvim/lua/darcula/setup/500_nvim_tree.lua b/nvim/lua/darcula/setup/500_nvim_tree.lua new file mode 100644 index 0000000..6b52510 --- /dev/null +++ b/nvim/lua/darcula/setup/500_nvim_tree.lua @@ -0,0 +1,77 @@ +-- The MIT License (MIT) +-- +-- Copyright © 2026 Scott E. Graves +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software +-- and associated documentation files (the “Software”), to deal in the Software without restriction, +-- including without limitation the rights to use, copy, modify, merge, publish, distribute, +-- sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in all copies or +-- substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +-- BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +-- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +-- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-- +local keymaps = require("darcula.keymaps") +local symbols = require("darcula.utils.symbols") + +vim.g.nvim_tree_refresh_wait = 250 + +require "nvim-tree".setup { + diagnostics = { + enable = false, + icons = { + error = symbols.status.errors, + hint = symbols.status.hints, + info = symbols.status.info, + warning = symbols.status.warnings + } + }, + filters = {dotfiles = not NV_DARCULA_ENABLE_HIDDEN_FILES}, + git = {enable = true, ignore = false, timeout = 5000}, + hijack_directories = {enable = false, auto_open = false}, + on_attach = keymaps.nvim_tree_on_attach, + renderer = { + icons = { + show = {file = true, folder = true, folder_arrow = false, git = true}, + glyphs = { + default = symbols.file, + symlink = symbols.file, + folder = { + arrow_open = symbols.directory.expanded, + arrow_closed = symbols.directory.collapsed, + default = symbols.directory.directory, + empty = symbols.directory.directory, + empty_open = symbols.directory.directory_open, + open = symbols.directory.directory_open, + symlink = symbols.directory.directory, + symlink_open = symbols.directory.directory_open + }, + git = { + unstaged = symbols.git.unstaged, + staged = symbols.git.staged, + unmerged = symbols.git.unmerged, + renamed = symbols.git.renamed, + untracked = symbols.git.untracked, + deleted = symbols.git.deleted, + ignored = symbols.git.ignored + } + } + }, + special_files = {}, + indent_markers = { + enable = false, + icons = {corner = "└ ", edge = "│ ", none = " "} + } + }, + respect_buf_cwd = false, + sync_root_with_cwd = true, + update_cwd = false, + update_focused_file = {enable = true, update_root = false}, + view = {width = 35} +} diff --git a/nvim/lua/darcula/setup/500_scrollview.lua b/nvim/lua/darcula/setup/500_scrollview.lua new file mode 100644 index 0000000..f1f43bd --- /dev/null +++ b/nvim/lua/darcula/setup/500_scrollview.lua @@ -0,0 +1,28 @@ +-- The MIT License (MIT) +-- +-- Copyright © 2026 Scott E. Graves +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software +-- and associated documentation files (the “Software”), to deal in the Software without restriction, +-- including without limitation the rights to use, copy, modify, merge, publish, distribute, +-- sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in all copies or +-- substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +-- BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +-- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +-- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-- +local utils = require("darcula.utils") +local utils_os = require("darcula.utils.os") + +require("scrollview").setup { + winblend = utils.iff(utils_os.is_windows, 85, 90), + winblend_gui = utils.iff(utils_os.is_windows, 85, 90), + current_only = true, + signs_on_startup = {} +} diff --git a/nvim/lua/darcula/setup/500_telescope.lua b/nvim/lua/darcula/setup/500_telescope.lua new file mode 100644 index 0000000..6bf0637 --- /dev/null +++ b/nvim/lua/darcula/setup/500_telescope.lua @@ -0,0 +1,101 @@ +-- The MIT License (MIT) +-- +-- Copyright © 2026 Scott E. Graves +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software +-- and associated documentation files (the “Software”), to deal in the Software without restriction, +-- including without limitation the rights to use, copy, modify, merge, publish, distribute, +-- sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in all copies or +-- substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +-- BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +-- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +-- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-- +local symbols = require("darcula.utils.symbols") + +local telescope_actions = require("telescope.actions") +require("telescope").setup { + defaults = { + vimgrep_arguments = { + "rg", + "--color=never", + "--no-heading", + "--with-filename", + "--line-number", + "--column", + "--hidden", + "--smart-case" + }, + mappings = { + i = { + [""] = telescope_actions.preview_scrolling_up, + [""] = telescope_actions.preview_scrolling_down, + [""] = nil, + [""] = nil + }, + n = { + [""] = telescope_actions.preview_scrolling_up, + [""] = telescope_actions.preview_scrolling_down, + [""] = nil, + [""] = nil + } + }, + prompt_prefix = " " .. symbols.search .. " ", + selection_caret = " ", + entry_prefix = " ", + initial_mode = "normal", + selection_strategy = "reset", + sorting_strategy = "descending", + layout_strategy = "horizontal", + layout_config = { + horizontal = {mirror = false}, + vertical = {mirror = false}, + height = 0.7, + width = 0.8, + preview_cutoff = 120 + }, + file_sorter = require "telescope.sorters".get_fuzzy_file, + file_ignore_patterns = {}, + generic_sorter = require "telescope.sorters".get_generic_fuzzy_sorter, + path_display = {smart = 1}, + winblend = 0, + border = true, + borderchars = {" ", " ", " ", " ", " ", " ", " ", " "}, + color_devicons = true, + use_less = true, + set_env = {["COLORTERM"] = "truecolor"}, -- default = nil, + file_previewer = require "telescope.previewers".vim_buffer_cat.new, + grep_previewer = require "telescope.previewers".vim_buffer_vimgrep.new, + qflist_previewer = require "telescope.previewers".vim_buffer_qflist.new, + -- Developer configurations: Not meant for general override + buffer_previewer_maker = require "telescope.previewers".buffer_previewer_maker + }, + extensions = { + fzf = { + fuzzy = true, + override_generic_sorter = true, + override_file_sorter = true, + case_mode = "smart_case" + }, + ["ui-select"] = require("telescope.themes").get_dropdown( + { + width = 0.6, + previewer = false + } + ) + } +} + +require("telescope").load_extension("ui-select") +if NV_DARCULA_ENABLE_COC then + require("telescope").load_extension("coc") +end +if not NV_DARCULA_ENABLE_COC then + require("telescope").load_extension("flutter") +end diff --git a/nvim/lua/darcula/setup/500_treesitter.lua b/nvim/lua/darcula/setup/500_treesitter.lua new file mode 100644 index 0000000..ffeaaa7 --- /dev/null +++ b/nvim/lua/darcula/setup/500_treesitter.lua @@ -0,0 +1,31 @@ +-- The MIT License (MIT) +-- +-- Copyright © 2026 Scott E. Graves +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software +-- and associated documentation files (the “Software”), to deal in the Software without restriction, +-- including without limitation the rights to use, copy, modify, merge, publish, distribute, +-- sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in all copies or +-- substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +-- BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +-- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +-- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-- +require("nvim-treesitter").setup { + install_dir = vim.fs.joinpath(vim.fn.stdpath("data"), "site") +} + +require("nvim-treesitter").install(NV_DARCULA_TREESITTER_LIST) + +vim.defer_fn( + function() + vim.cmd("TSUpdate") + end, + 1000 +) diff --git a/nvim/lua/darcula/setup/500_vim_dart_plugin.lua b/nvim/lua/darcula/setup/500_vim_dart_plugin.lua new file mode 100644 index 0000000..df4eefc --- /dev/null +++ b/nvim/lua/darcula/setup/500_vim_dart_plugin.lua @@ -0,0 +1,24 @@ +-- The MIT License (MIT) +-- +-- Copyright © 2026 Scott E. Graves +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software +-- and associated documentation files (the “Software”), to deal in the Software without restriction, +-- including without limitation the rights to use, copy, modify, merge, publish, distribute, +-- sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in all copies or +-- substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +-- BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +-- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +-- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-- +if not NV_DARCULA_ENABLE_COC then + return +end + +vim.g.dart_style_guide = 2 diff --git a/nvim/lua/darcula/setup/500_window_picker.lua b/nvim/lua/darcula/setup/500_window_picker.lua new file mode 100644 index 0000000..8554d3d --- /dev/null +++ b/nvim/lua/darcula/setup/500_window_picker.lua @@ -0,0 +1,27 @@ +-- The MIT License (MIT) +-- +-- Copyright © 2026 Scott E. Graves +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software +-- and associated documentation files (the “Software”), to deal in the Software without restriction, +-- including without limitation the rights to use, copy, modify, merge, publish, distribute, +-- sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in all copies or +-- substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +-- BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +-- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +-- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-- +require "window-picker".setup { + keys = "alskdjfhgwoeiruty", + swap_shift = true, + exclude = {qf = true, NvimTree = true, aerial = true}, + flash_duration = 300 +} + +vim.g.choosewin_blink_on_land = 1 diff --git a/nvim/lua/darcula/usercmds.lua b/nvim/lua/darcula/usercmds.lua new file mode 100644 index 0000000..6310bbb --- /dev/null +++ b/nvim/lua/darcula/usercmds.lua @@ -0,0 +1,80 @@ +-- The MIT License (MIT) +-- +-- Copyright © 2026 Scott E. Graves +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software +-- and associated documentation files (the “Software”), to deal in the Software without restriction, +-- including without limitation the rights to use, copy, modify, merge, publish, distribute, +-- sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in all copies or +-- substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +-- BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +-- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +-- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-- +local utils = require("darcula.utils") +utils.create_vert_display("Messages", "messages") + +vim.cmd( + [[ + cnoreabbrev h getcmdtype() ==# ':' && getcmdline() ==# 'h' ? 'vert help' : 'h' + cnoreabbrev help getcmdtype() ==# ':' && getcmdline() ==# 'help' ? 'vert help' : 'help' +]] +) + +vim.api.nvim_create_user_command( + "PlugUpdate", + function() + vim.pack.update(nil, {force = true}) + if NV_DARCULA_ENABLE_COC then + vim.cmd("CocUpdate") + end + end, + {} +) + +if not NV_DARCULA_ENABLE_COC then + vim.api.nvim_create_user_command( + "LspInfo", + function() + local clients = vim.lsp.get_clients({bufnr = 0}) + if #clients == 0 then + vim.notify("No LSP attached", vim.log.levels.INFO) + return + end + + local res = {""} + for _, client in ipairs(clients) do + table.insert(res, "• " .. client.name .. " (id: " .. client.id .. ")") + end + + vim.notify(table.concat(res, "\n") .. "\n", vim.log.levels.INFO) + end, + {} + ) + + vim.api.nvim_create_user_command( + "LspRestart", + function() + local bufnr = vim.api.nvim_get_current_buf() + local clients = vim.lsp.get_clients({bufnr = bufnr}) + + for _, client in ipairs(clients) do + client:stop() + end + + if + (vim.bo.buftype == "" or vim.bo.buftype == "normal") and + vim.api.nvim_buf_get_name(0) ~= "" + then + vim.cmd("edit") + end + end, + {} + ) +end diff --git a/nvim/lua/darcula/utils/fortune.lua b/nvim/lua/darcula/utils/fortune.lua new file mode 100644 index 0000000..5c70ebb --- /dev/null +++ b/nvim/lua/darcula/utils/fortune.lua @@ -0,0 +1,883 @@ +-- Converted from Vimscript to Lua for use in Neovim (init.lua or a module) +-- Original: https://github.com/mhinz/vim-startify/blob/master/autoload/startify/fortune.vim + +-- The MIT License (MIT) +-- +-- Copyright (c) 2015 Marco Hinz +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy of +-- this software and associated documentation files (the "Software"), to deal in +-- the Software without restriction, including without limitation the rights to +-- use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +-- the Software, and to permit persons to whom the Software is furnished to do so, +-- subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in all +-- copies or substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +-- FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +-- COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +-- IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +-- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-- +-- Variables (module-local "s" table to mimic script-local "s:" in Vimscript) +local fortune_cfg = {} + +-- Utility: get a monotonically-varying high-resolution time and use it for a pseudo-random offset +local function get_random_offset(max) + -- vim.loop.hrtime() returns nanoseconds (integer); use modulo to get an offset in [0, max-1] + if max <= 0 then + return 0 + end + local n = vim.loop.hrtime() + return (n % max) +end + +-- Draw a box around an array-like table of lines. +local function draw_box(lines) + -- compute longest visual width using vim.fn.strwidth (handles multibyte nicely) + local longest = 0 + for _, l in ipairs(lines) do + local w = vim.fn.strwidth(l) + if w > longest then + longest = w + end + end + + local top_bottom_without_corners = + string.rep(fortune_cfg.char_top_bottom, longest + 2) + local top = + fortune_cfg.char_top_left .. + top_bottom_without_corners .. fortune_cfg.char_top_right + local bottom = + fortune_cfg.char_bottom_left .. + top_bottom_without_corners .. fortune_cfg.char_bottom_right + + local out = {top} + for _, l in ipairs(lines) do + local offset = longest - vim.fn.strwidth(l) + local padded = + fortune_cfg.char_sides .. + " " .. l .. string.rep(" ", offset) .. " " .. fortune_cfg.char_sides + table.insert(out, padded) + end + table.insert(out, bottom) + return out +end + +-- Return a random quote from g:startify_custom_header_quotes +local function quote() + local quotes = vim.g.startify_custom_header_quotes + if not quotes or #quotes == 0 then + return {} + end + local idx = get_random_offset(#quotes) + 1 -- Lua 1-based + local q = quotes[idx] + -- if it's a function (lua function or vimscript function reference wrapped), try to call it + if type(q) == "function" then + return q() + else + return q + end +end + +-- Wrap a quote (table of lines or function returning lines) and put it in a box. +-- Usage: boxed(opt_quote_table_or_function) +local function boxed(...) + local arg = select(1, ...) + local quote_val + + if arg and type(arg) == "table" then + quote_val = arg + else + local q = quote() + if type(q) == "function" then + quote_val = q() + else + quote_val = q + end + end + + -- wrap each line at ~50 columns using Vim's split (keeppattern=1 -> do not remove empty) + local wrapped = {} + for _, line in ipairs(quote_val) do + -- reuse vim.fn.split with the same regex used originally + local parts = vim.fn.split(line, "\\%50c.\\{-}\\zs\\s", true) + for _, p in ipairs(parts) do + table.insert(wrapped, p) + end + end + + return draw_box(wrapped) +end + +-- Cowsay: return boxed quote concatenated with cow art. +-- If an argument table is passed, it's treated as the quote; optionally pass characters to override box chars. +-- Usage examples: +-- cowsay() -> uses randomly chosen quote +-- cowsay(quote_table) -> uses provided quote table +-- cowsay(quote_table, char_top_bottom, char_sides, top_left, top_right, bottom_right, bottom_left) +local function cowsay(...) + local args = {...} + local quote_arg + if #args >= 1 and type(args[1]) == "table" then + quote_arg = args[1] + else + quote_arg = quote() + end + + -- optional overrides for the box characters (positions correspond to original script) + if #args >= 6 then + fortune_cfg.char_top_bottom = args[2] or fortune_cfg.char_top_bottom + fortune_cfg.char_sides = args[3] or fortune_cfg.char_sides + fortune_cfg.char_top_left = args[4] or fortune_cfg.char_top_left + fortune_cfg.char_top_right = args[5] or fortune_cfg.char_top_right + fortune_cfg.char_bottom_right = args[6] or fortune_cfg.char_bottom_right + fortune_cfg.char_bottom_left = args[7] or fortune_cfg.char_bottom_left + end + + local boxed_quote = boxed(quote_arg) + -- concatenate boxed_quote with cow art (both are lists of lines); return combined table + local out = {} + for _, line in ipairs(boxed_quote) do + table.insert(out, line) + end + for _, line in ipairs(fortune_cfg.cow) do + table.insert(out, line) + end + return out +end + +-- Expose a function to return predefined_quotes (just returns the table) +local function predefined_quotes() + return fortune_cfg.predefined_quotes +end + +fortune_cfg.cow = { + " o", + " o ^__^", + " o (oo)\\_______", + " (__)\\ )\\/\\", + " ||----w |", + " || ||" +} + +-- whether to use unicode box characters; attempt to preserve original behavior: +-- g:startify_fortune_use_unicode defaults to current encoding == 'utf-8' and optional g var +vim.g.startify_fortune_use_unicode = + (vim.o.encoding == "utf-8") and + (vim.g.startify_fortune_use_unicode and true or false) + +local use_unicode = vim.g.startify_fortune_use_unicode and 2 or 1 +-- Note: choose between ascii (index 1) and unicode (index 2) +-- we'll pick characters with a small table lookup (Lua arrays are 1-based) +local tb_top_bottom = {"-", "─"} +local tb_sides = {"|", "│"} +local tb_top_left = {"*", "╭"} +local tb_top_right = {"*", "╮"} +local tb_bottom_right = {"*", "╯"} +local tb_bottom_left = {"*", "╰"} + +fortune_cfg.char_top_bottom = tb_top_bottom[use_unicode] +fortune_cfg.char_sides = tb_sides[use_unicode] +fortune_cfg.char_top_left = tb_top_left[use_unicode] +fortune_cfg.char_top_right = tb_top_right[use_unicode] +fortune_cfg.char_bottom_right = tb_bottom_right[use_unicode] +fortune_cfg.char_bottom_left = tb_bottom_left[use_unicode] + +-- Predefined quotes: directly translated as a Lua table of arrays/strings. +fortune_cfg.predefined_quotes = { + { + "Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.", + "", + "- Brian Kernighan" + }, + {"If you don't finish then you're just busy, not productive."}, + { + "Adapting old programs to fit new machines usually means adapting new machines to behave like old ones.", + "", + "- Alan Perlis" + }, + { + "Fools ignore complexity. Pragmatists suffer it. Some can avoid it. Geniuses remove it.", + "", + "- Alan Perlis" + }, + { + "It is easier to change the specification to fit the program than vice versa.", + "", + "- Alan Perlis" + }, + { + "Simplicity does not precede complexity, but follows it.", + "", + "- Alan Perlis" + }, + {"Optimization hinders evolution.", "", "- Alan Perlis"}, + { + "Recursion is the root of computation since it trades description for time.", + "", + "- Alan Perlis" + }, + { + "It is better to have 100 functions operate on one data structure than 10 functions on 10 data structures.", + "", + "- Alan Perlis" + }, + { + "There is nothing quite so useless as doing with great efficiency something that should not be done at all.", + "", + "- Peter Drucker" + }, + { + "If you don't fail at least 90% of the time, you're not aiming high enough.", + "", + "- Alan Kay" + }, + { + "I think a lot of new programmers like to use advanced data structures and advanced language features as a way of demonstrating their ability. I call it the lion-tamer syndrome. Such demonstrations are impressive, but unless they actually translate into real wins for the project, avoid them.", + "", + "- Glyn Williams" + }, + {"I would rather die of passion than of boredom.", "", "- Vincent Van Gogh"}, + { + "If a system is to serve the creative spirit, it must be entirely comprehensible to a single individual." + }, + { + "The computing scientist's main challenge is not to get confused by the complexities of his own making.", + "", + "- Edsger W. Dijkstra" + }, + { + "Progress in a fixed context is almost always a form of optimization. Creative acts generally don't stay in the context that they are in.", + "", + "- Alan Kay" + }, + { + "The essence of XML is this: the problem it solves is not hard, and it does not solve the problem well.", + "", + "- Phil Wadler" + }, + { + "A good programmer is someone who always looks both ways before crossing a one-way street.", + "", + "- Doug Linder" + }, + {'Patterns mean "I have run out of language."', "", "- Rich Hickey"}, + { + "Always code as if the person who ends up maintaining your code is a violent psychopath who knows where you live.", + "", + "- John Woods" + }, + { + "Unix was not designed to stop its users from doing stupid things, as that would also stop them from doing clever things." + }, + { + "Contrary to popular belief, Unix is user friendly. It just happens to be very selective about who it decides to make friends with." + }, + { + "Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away." + }, + { + "There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies.", + "", + "- C.A.R. Hoare" + }, + { + "If you don't make mistakes, you're not working on hard enough problems.", + "", + "- Frank Wilczek" + }, + { + "If you don't start with a spec, every piece of code you write is a patch.", + "", + "- Leslie Lamport" + }, + {"Caches are bugs waiting to happen.", "", "- Rob Pike"}, + { + "Abstraction is not about vagueness, it is about being precise at a new semantic level.", + "", + "- Edsger W. Dijkstra" + }, + { + "dd is horrible on purpose. It's a joke about OS/360 JCL. But today it's an internationally standardized joke. I guess that says it all.", + "", + "- Rob Pike" + }, + {"All loops are infinite ones for faulty RAM modules."}, + { + "All idioms must be learned. Good idioms only need to be learned once.", + "", + "- Alan Cooper" + }, + { + "For a successful technology, reality must take precedence over public relations, for Nature cannot be fooled.", + "", + "- Richard Feynman" + }, + { + "If programmers were electricians, parallel programmers would be bomb disposal experts. Both cut wires.", + "", + "- Bartosz Milewski" + }, + { + "Computers are harder to maintain at high altitude. Thinner air means less cushion between disk heads and platters. Also more radiation." + }, + { + "Almost every programming language is overrated by its practitioners.", + "", + "- Larry Wall" + }, + { + "Fancy algorithms are slow when n is small, and n is usually small.", + "", + "- Rob Pike" + }, + { + "Methods are just functions with a special first argument.", + "", + "- Andrew Gerrand" + }, + { + "Care about your craft.", + "", + "Why spend your life developing software unless you care about doing it well?" + }, + { + "Provide options, don't make lame excuses.", + "", + "Instead of excuses, provide options. Don't say it can't be done; explain what can be done." + }, + { + "Be a catalyst for change.", + "", + "You can't force change on people. Instead, show them how the future might be and help them participate in creating it." + }, + { + "Make quality a requirements issue.", + "", + "Involve your users in determining the project's real quality requirements." + }, + { + "Critically analyze what you read and hear.", + "", + "Don't be swayed by vendors, media hype, or dogma. Analyze information in terms of you and your project." + }, + { + "DRY - Don't Repeat Yourself.", + "", + "Every piece of knowledge must have a single, unambiguous, authoritative representation within a system." + }, + { + "Eliminate effects between unrelated things.", + "", + "Design components that are self-contained, independent, and have a single, well-defined purpose." + }, + { + "Use tracer bullets to find the target.", + "", + "Tracer bullets let you home in on your target by trying things and seeing how close they land." + }, + { + "Program close to the problem domain.", + "", + "Design and code in your user's language." + }, + { + "Iterate the schedule with the code.", + "", + "Use experience you gain as you implement to refine the project time scales." + }, + { + "Use the power of command shells.", + "", + "Use the shell when graphical user interfaces don't cut it." + }, + { + "Always use source code control.", + "", + "Source code control is a time machine for your work - you can go back." + }, + { + "Don't panic when debugging", + "", + "Take a deep breath and THINK! about what could be causing the bug." + }, + { + "Don't assume it - prove it.", + "", + "Prove your assumptions in the actual environment - with real data and boundary conditions." + }, + { + "Write code that writes code.", + "", + "Code generators increase your productivity and help avoid duplication." + }, + { + "Design With contracts.", + "", + "Use contracts to document and verify that code does no more and no less than it claims to do." + }, + { + "Use assertions to prevent the impossible.", + "", + "Assertions validate your assumptions. Use them to protect your code from an uncertain world." + }, + { + "Finish what you start.", + "", + "Where possible, the routine or object that allocates a resource should be responsible for deallocating it." + }, + { + "Configure, don't integrate.", + "", + "Implement technology choices for an application as configuration options, not through integration or engineering." + }, + { + "Analyze workflow to improve concurrency.", + "", + "Exploit concurrency in your user's workflow." + }, + { + "Always design for concurrency.", + "", + "Allow for concurrency, and you'll design cleaner interfaces with fewer assumptions." + }, + { + "Use blackboards to coordinate workflow.", + "", + "Use blackboards to coordinate disparate facts and agents, while maintaining independence and isolation among participants." + }, + { + "Estimate the order of your algorithms.", + "", + "Get a feel for how long things are likely to take before you write code." + }, + { + "Refactor early, refactor often.", + "", + "Just as you might weed and rearrange a garden, rewrite, rework, and re-architect code when it needs it. Fix the root of the problem." + }, + { + "Test your software, or your users will.", + "", + "Test ruthlessly. Don't make your users find bugs for you." + }, + { + "Don't gather requirements - dig for them.", + "", + "Requirements rarely lie on the surface. They're buried deep beneath layers of assumptions, misconceptions, and politics." + }, + { + "Abstractions live longer than details.", + "", + "Invest in the abstraction, not the implementation. Abstractions can survive the barrage of changes from different implementations and new technologies." + }, + { + "Don't think outside the box - find the box.", + "", + 'When faced with an impossible problem, identify the real constraints. Ask yourself: "Does it have to be done this way? Does it have to be done at all?"' + }, + { + "Some things are better done than described.", + "", + "Don't fall into the specification spiral - at some point you need to start coding." + }, + { + "Costly tools don't produce better designs.", + "", + "Beware of vendor hype, industry dogma, and the aura of the price tag. Judge tools on their merits." + }, + { + "Don't use manual procedures.", + "", + "A shell script or batch file will execute the same instructions, in the same order, time after time." + }, + {"Coding ain't done 'til all the Tests run.", "", "'Nuff said."}, + { + "Test state coverage, not code coverage.", + "", + "Identify and test significant program states. Just testing lines of code isn't enough." + }, + { + "English is just a programming language.", + "", + "Write documents as you would write code: honor the DRY principle, use metadata, MVC, automatic generation, and so on." + }, + { + "Gently exceed your users' expectations.", + "", + "Come to understand your users' expectations, then deliver just that little bit more." + }, + { + "Think about your work.", + "", + "Turn off the autopilot and take control. Constantly critique and appraise your work." + }, + { + "Don't live with broken windows.", + "", + "Fix bad designs, wrong decisions, and poor code when you see them." + }, + { + "Remember the big picture.", + "", + "Don't get so engrossed in the details that you forget to check what's happening around you." + }, + { + "Invest regularly in your knowledge portfolio.", + "", + "Make learning a habit." + }, + { + "It's both what you say and the way you say it.", + "", + "There's no point in having great ideas if you don't communicate them effectively." + }, + { + "Make it easy to reuse.", + "", + "If it's easy to reuse, people will. Create an environment that supports reuse." + }, + { + "There are no final decisions.", + "", + "No decision is cast in stone. Instead, consider each as being written in the sand at the beach, and plan for change." + }, + { + "Prototype to learn.", + "", + "Prototyping is a learning experience. Its value lies not in the code you produce, but in the lessons you learn." + }, + { + "Estimate to avoid surprises.", + "", + "Estimate before you start. You'll spot potential problems up front." + }, + { + "Keep knowledge in plain text.", + "", + "Plain text won't become obsolete. It helps leverage your work and simplifies debugging and testing." + }, + { + "Use a single editor well.", + "", + "The editor should be an extension of your hand; make sure your editor is configurable, extensible, and programmable." + }, + { + "Fix the problem, not the blame.", + "", + "It doesn't really matter whether the bug is your fault or someone elses - it is still your problem, and it still needs to be fixed." + }, + { + '"select" isn\'t broken.', + "", + "It is rare to find a bug in the OS or the compiler, or even a third-party product or library. The bug is most likely in the application." + }, + { + "Learn a text manipulation language.", + "", + "You spend a large part of each day working with text. Why not have the computer do some of it for you?" + }, + { + "You can't write perfect software.", + "", + "Software can't be perfect. Protect your code and users from the inevitable errors." + }, + { + "Crash early.", + "", + "A dead program normally does a lot less damage than a crippled one." + }, + { + "Use exceptions for exceptional problems.", + "", + "Exceptions can suffer from all the readability and maintainability problems of classic spaghetti code. Reserve exceptions for exceptional things." + }, + { + "Minimize coupling between modules.", + "", + 'Avoid coupling by writing "shy" code and applying the Law of Demeter.' + }, + { + "Put abstractions in code, details in metadata.", + "", + "Program for the general case, and put the specifics outside the compiled code base." + }, + { + "Design using services.", + "", + "Design in terms of services-independent, concurrent objects behind well-defined, consistent interfaces." + }, + { + "Separate views from models.", + "", + "Gain flexibility at low cost by designing your application in terms of models and views." + }, + { + "Don't program by coincidence.", + "", + "Rely only on reliable things. Beware of accidental complexity, and don't confuse a happy coincidence with a purposeful plan." + }, + { + "Test your estimates.", + "", + "Mathematical analysis of algorithms doesn't tell you everything. Try timing your code in its target environment." + }, + { + "Design to test.", + "", + "Start thinking about testing before you write a line of code." + }, + { + "Don't use wizard code you don't understand.", + "", + "Wizards can generate reams of code. Make sure you understand all of it before you incorporate it into your project." + }, + { + "Work with a user to think like a user.", + "", + "It's the best way to gain insight into how the system will really be used." + }, + { + "Use a project glossary.", + "", + "Create and maintain a single source of all the specific terms and vocabulary for a project." + }, + { + "Start when you're ready.", + "", + "You've been building experience all your life. Don't ignore niggling doubts." + }, + { + "Don't be a slave to formal methods.", + "", + "Don't blindly adopt any technique without putting it into the context of your development practices and capabilities." + }, + { + "Organize teams around functionality.", + "", + "Don't separate designers from coders, testers from data modelers. Build teams the way you build code." + }, + { + "Test early. Test often. Test automatically.", + "", + "Tests that run with every build are much more effective than test plans that sit on a shelf." + }, + { + "Use saboteurs to test your testing.", + "", + "Introduce bugs on purpose in a separate copy of the source to verify that testing will catch them." + }, + { + "Find bugs once.", + "", + "Once a human tester finds a bug, it should be the last time a human tester finds that bug. Automatic tests should check for it from then on." + }, + { + "Sign your work.", + "", + "Craftsmen of an earlier age were proud to sign their work. You should be, too." + }, + {"Think twice, code once."}, + {"No matter how far down the wrong road you have gone, turn back now."}, + { + "Why do we never have time to do it right, but always have time to do it over?" + }, + {"Weeks of programming can save you hours of planning."}, + {"To iterate is human, to recurse divine.", "", "- L. Peter Deutsch"}, + { + "Computers are useless. They can only give you answers.", + "", + "- Pablo Picasso" + }, + { + "The question of whether computers can think is like the question of whether submarines can swim.", + "", + "- Edsger W. Dijkstra" + }, + { + "It's ridiculous to live 100 years and only be able to remember 30 million bytes. You know, less than a compact disc. The human condition is really becoming more obsolete every minute.", + "", + "- Marvin Minsky" + }, + { + "The city's central computer told you? R2D2, you know better than to trust a strange computer!", + "", + "- C3PO" + }, + { + "Most software today is very much like an Egyptian pyramid with millions of bricks piled on top of each other, with no structural integrity, but just done by brute force and thousands of slaves.", + "", + "- Alan Kay" + }, + { + 'I\'ve finally learned what "upward compatible" means. It means we get to keep all our old mistakes.', + "", + "- Dennie van Tassel" + }, + { + "There are two major products that come out of Berkeley: LSD and UNIX. We don't believe this to be a coincidence.", + "", + "- Jeremy S. Anderson" + }, + { + "The bulk of all patents are crap. Spending time reading them is stupid. It's up to the patent owner to do so, and to enforce them.", + "", + "- Linus Torvalds" + }, + { + "Controlling complexity is the essence of computer programming.", + "", + "- Brian Kernighan" + }, + { + "Complexity kills. It sucks the life out of developers, it makes products difficult to plan, build and test, it introduces security challenges, and it causes end-user and administrator frustration.", + "", + "- Ray Ozzie" + }, + { + "The function of good software is to make the complex appear to be simple.", + "", + "- Grady Booch" + }, + { + "There's an old story about the person who wished his computer were as easy to use as his telephone. That wish has come true, since I no longer know how to use my telephone.", + "", + "- Bjarne Stroustrup" + }, + { + 'There are only two industries that refer to their customers as "users".', + "", + "- Edward Tufte" + }, + { + "Most of you are familiar with the virtues of a programmer. There are three, of course: laziness, impatience, and hubris.", + "", + "- Larry Wall" + }, + { + "Computer science education cannot make anybody an expert programmer any more than studying brushes and pigment can make somebody an expert painter.", + "", + "- Eric S. Raymond" + }, + { + "Optimism is an occupational hazard of programming; feedback is the treatment.", + "", + "- Kent Beck" + }, + {"First, solve the problem. Then, write the code.", "", "- John Johnson"}, + { + "Measuring programming progress by lines of code is like measuring aircraft building progress by weight.", + "", + "- Bill Gates" + }, + { + "Don't worry if it doesn't work right. If everything did, you'd be out of a job.", + "", + "- Mosher's Law of Software Engineering" + }, + { + "A LISP programmer knows the value of everything, but the cost of nothing.", + "", + "- Alan J. Perlis" + }, + { + "All problems in computer science can be solved with another level of indirection.", + "", + "- David Wheeler" + }, + { + "Functions delay binding; data structures induce binding. Moral: Structure data late in the programming process.", + "", + "- Alan J. Perlis" + }, + { + "Easy things should be easy and hard things should be possible.", + "", + "- Larry Wall" + }, + {"Nothing is more permanent than a temporary solution."}, + { + "If you can't explain something to a six-year-old, you really don't understand it yourself.", + "", + "- Albert Einstein" + }, + {"All programming is an exercise in caching.", "", "- Terje Mathisen"}, + {"Software is hard.", "", "- Donald Knuth"}, + {"They did not know it was impossible, so they did it!", "", "- Mark Twain"}, + { + "The object-oriented model makes it easy to build up programs by accretion. What this often means, in practice, is that it provides a structured way to write spaghetti code.", + "", + "- Paul Graham" + }, + { + "Question: How does a large software project get to be one year late?", + "Answer: One day at a time!" + }, + { + "The first 90% of the code accounts for the first 90% of the development time. The remaining 10% of the code accounts for the other 90% of the development time.", + "", + "- Tom Cargill" + }, + { + "In software, we rarely have meaningful requirements. Even if we do, the only measure of success that matters is whether our solution solves the customer's shifting idea of what their problem is.", + "", + "- Jeff Atwood" + }, + { + "If debugging is the process of removing bugs, then programming must be the process of putting them in.", + "", + "- Edsger W. Dijkstra" + }, + {"640K ought to be enough for anybody.", "", "- Bill Gates, 1981"}, + { + "To understand recursion, one must first understand recursion.", + "", + "- Stephen Hawking" + }, + { + "Developing tolerance for imperfection is the key factor in turning chronic starters into consistent finishers.", + "", + "- Jon Acuff" + }, + { + "Every great developer you know got there by solving problems they were unqualified to solve until they actually did it.", + "", + "- Patrick McKenzie" + }, + { + "The average user doesn't give a damn what happens, as long as (1) it works and (2) it's fast.", + "", + "- Daniel J. Bernstein" + }, + { + "Walking on water and developing software from a specification are easy if both are frozen.", + "", + "- Edward V. Berard" + }, + { + "Be curious. Read widely. Try new things. I think a lot of what people call intelligence boils down to curiosity.", + "", + "- Aaron Swartz" + }, + { + "What one programmer can do in one month, two programmers can do in two months.", + "", + "- Frederick P. Brooks" + } +} + +-- If g:startify_custom_header_quotes isn't set, initialize it to the predefined list +if vim.g.startify_custom_header_quotes == nil then + vim.g.startify_custom_header_quotes = fortune_cfg.predefined_quotes +end + +-- Expose functions for use from other Lua code or for compatibility +return { + cowsay = cowsay, + fortune_cfg = fortune_cfg, + predefined_quotes = predefined_quotes +} diff --git a/nvim/lua/darcula/utils/globals.lua b/nvim/lua/darcula/utils/globals.lua new file mode 100644 index 0000000..2ca57a0 --- /dev/null +++ b/nvim/lua/darcula/utils/globals.lua @@ -0,0 +1,315 @@ +-- The MIT License (MIT) +-- +-- Copyright © 2026 Scott E. Graves +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software +-- and associated documentation files (the “Software”), to deal in the Software without restriction, +-- including without limitation the rights to use, copy, modify, merge, publish, distribute, +-- sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in all copies or +-- substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +-- BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +-- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +-- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-- +require("darcula.utils.string") +require("darcula.utils.table") + +local utils = require("darcula.utils") +local utils_os = require("darcula.utils.os") +local utils_ui = require("darcula.utils.ui") + +NV_Darcula_Close_Invalid = function() + local buffer_numbers = vim.api.nvim_list_bufs() + for _, buffer_number in pairs(buffer_numbers) do + local buf_info = vim.fn.getbufinfo(buffer_number) + if buf_info ~= nil then + buf_info = buf_info[1] + if buf_info.windows ~= nil and #buf_info.windows > 0 then + local win_type = vim.fn.win_gettype(buf_info.windows[1]) + if win_type ~= nil and win_type == "popup" then + vim.api.nvim_buf_delete(buffer_number, {force = true}) + end + end + end + end +end + +NV_Darcula_Close_All = function(write_all) + NV_Darcula_Close_Invalid() + + write_all = write_all or false + vim.cmd(utils.iff(write_all, "wqa!", "qa!")) +end + +NV_Darcula_Coc_Completion_Confirm = function() + if vim.fn["coc#pum#visible"]() ~= 0 then + return vim.fn["coc#pum#confirm"]() + end + + return "u=coc#on_enter()" +end + +NV_Darcula_Coc_Float_Scroll = function(fwd) + if vim.fn["coc#float#has_scroll"]() == 1 then + vim.fn["coc#float#scroll"](utils.iff(fwd and fwd ~= 0, 1, 0)) + return + end + return "" +end + +NV_Darcula_Coc_Float_Scroll_Insert_Mode = function(fwd) + if vim.fn["coc#float#has_scroll"]() == 1 then + return "=coc#float#scroll(" .. + utils.iff(fwd and fwd ~= 0, 1, 0) .. ")" + end + + return "<" .. utils.iff(fwd and fwd ~= 0, "Right", "Left") .. ">" +end + +NV_Darcula_Coc_Shift_Tab_Complete = function() + if vim.fn["coc#pum#visible"]() ~= 0 then + return vim.fn["coc#pum#prev"](1) + end + + return "" +end + +NV_Darcula_Coc_Tab_Complete = function() + if vim.fn["coc#pum#visible"]() ~= 0 then + return vim.fn["coc#pum#next"](1) + end + + local check_backspace = function() + local col = vim.api.nvim_win_get_cursor(0)[2] + return (col == 0 or + vim.api.nvim_get_current_line():sub(col, col):match("%s")) and + true + end + + if check_backspace() then + return "" + end + + return vim.fn["coc#refresh"]() +end + +NV_Darcula_Copen = function() + vim.cmd(":Copen") + vim.cmd(":wincmd j") +end + +NV_Darcula_Font_Name = function() + return "JetBrainsMonoNL NFM" +end + +NV_Darcula_Git_Root = function(cwd) + cwd = cwd or vim.loop.cwd() + local cmd = {"git", "-C", cwd, "rev-parse", "--show-toplevel"} + local output = vim.fn.systemlist(cmd) + if vim.v.shell_error == 0 and output[1] and #output[1] > 0 then + return vim.fn.fnamemodify(output[1], ":p") + end + + return cwd +end + +NV_Darcula_Grab_Selection = function(cb) + local selection = utils.get_visual_text() + vim.schedule( + function() + cb(selection) + end + ) +end + +NV_Darcula_Load_RC = function() + local local_vimrc = vim.fn.getcwd() .. "/.nvimrc" + if vim.loop.fs_stat(local_vimrc) then + vim.cmd("source " .. local_vimrc) + end +end + +NV_Darcula_LSP_Restart = function() + if NV_DARCULA_ENABLE_COC then + pcall( + function() + if vim.fn["coc#rpc#ready"] ~= nil and vim.fn["coc#rpc#ready"]() == 1 then + vim.cmd(":silent! :CocRestart") + NV_Darcula_Refresh_Buffer() + end + end + ) + return + end + + vim.cmd("LspRestart") + NV_Darcula_Refresh_Buffer() +end + +NV_Darcula_LSP_Stop = function() + if NV_DARCULA_ENABLE_COC then + vim.cmd(":silent! :CocStop") + end +end + +NV_Darcula_Open_Nvim_Tree = function(sync) + if sync and sync ~= 0 then + vim.cmd("NvimTreeFindFile") + return + end + + vim.cmd("NvimTreeFindFileToggle") +end + +NV_Darcula_Refresh_Buffer = function() + vim.cmd(":silent! :e%") +end + +NV_Darcula_Set_Gui_Font = function(size) + if utils_ui.is_gui() then + if vim.env.MY_STATE_HOME ~= nil and not utils_os.is_windows then + if utils.file_exists(vim.env.MY_STATE_HOME .. "/.desktop") then + if size == 0 then + vim.opt.guifont = + NV_Darcula_Font_Name() .. utils.iff(utils_os.is_mac, ":h12", ":h18") + return + end + + if size == 1 then + vim.opt.guifont = + NV_Darcula_Font_Name() .. utils.iff(utils_os.is_mac, ":h12", ":h15") + return + end + + if size == 2 then + vim.opt.guifont = + NV_Darcula_Font_Name() .. utils.iff(utils_os.is_mac, ":h12", ":h21") + return + end + + if size == 3 then + vim.opt.guifont = + NV_Darcula_Font_Name() .. utils.iff(utils_os.is_mac, ":h12", ":h28") + return + end + end + + if utils.file_exists(vim.env.MY_STATE_HOME .. "/.laptop2") then + if size == 0 then + vim.opt.guifont = + NV_Darcula_Font_Name() .. utils.iff(utils_os.is_mac, ":h12", ":h22") + return + end + + if size == 1 then + vim.opt.guifont = + NV_Darcula_Font_Name() .. utils.iff(utils_os.is_mac, ":h12", ":h19") + return + end + + if size == 2 then + vim.opt.guifont = + NV_Darcula_Font_Name() .. utils.iff(utils_os.is_mac, ":h12", ":h25") + return + end + + if size == 3 then + vim.opt.guifont = + NV_Darcula_Font_Name() .. utils.iff(utils_os.is_mac, ":h12", ":h32") + return + end + return + end + + if utils.file_exists(vim.env.MY_STATE_HOME .. "/.laptop") then + -- vim.opt.guifont = + -- NV_Darcula_Font_Name() .. utils.iff(util_os.is_mac, ":h12", ":h18") + return + end + end + + vim.opt.guifont = + NV_Darcula_Font_Name() .. utils.iff(utils_os.is_mac, ":h15", ":h18") + end +end + +NV_Darcula_Set_Gui_Popup = function(enable) + if utils_ui.is_gui() and vim.fn.exists(":GuiPopupmenu") ~= 0 then + vim.cmd("GuiPopupmenu " .. utils.iff(enable, "1", "0")) + end +end + +NV_Darcula_Show_Documentation = function() + local file_type = vim.bo.filetype + if table.contains({"vim", "help"}, file_type) then + NV_Darcula_Show_Vim_Documentation(false) + return + end + + if NV_DARCULA_ENABLE_COC then + if vim.fn.CocAction("hasProvider", "hover") then + vim.api.nvim_feedkeys( + vim.api.nvim_replace_termcodes("", true, false, true), + "n", + true + ) + + vim.fn.CocActionAsync("doHover") + return + end + return + end + + local bufnr = vim.api.nvim_get_current_buf() + local clients = + vim.lsp.get_clients( + { + bufnr = bufnr, + method = "textDocument/hover" + } + ) + + if #clients == 0 then + return + end + + vim.lsp.buf.hover() +end + +NV_Darcula_Show_Man_Documentation = function(visual) + local is_cpp = utils.is_c_family_file() + if visual then + if is_cpp then + require("cppman").open(utils.get_visual_text(), true) + return + end + + vim.cmd("vertical Man " .. vim.fn.escape(utils.get_visual_text(), " ")) + return + end + + if is_cpp then + require("cppman").open(utils.cword(), true) + return + end + vim.cmd("vertical Man") +end + +NV_Darcula_Show_Vim_Documentation = function(visual) + if visual then + vim.cmd("vertical help " .. utils.get_visual_text()) + return + end + + vim.cmd("vertical help " .. utils.cword()) +end + +NV_Darcula_Write_All = function() + vim.cmd("silent! wa!") +end diff --git a/nvim/lua/darcula/utils/init.lua b/nvim/lua/darcula/utils/init.lua new file mode 100644 index 0000000..b42e398 --- /dev/null +++ b/nvim/lua/darcula/utils/init.lua @@ -0,0 +1,234 @@ +-- The MIT License (MIT) +-- +-- Copyright © 2026 Scott E. Graves +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software +-- and associated documentation files (the “Software”), to deal in the Software without restriction, +-- including without limitation the rights to use, copy, modify, merge, publish, distribute, +-- sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in all copies or +-- substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +-- BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +-- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +-- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-- +local cword = function() + ---@diagnostic disable-next-line: missing-parameter + return vim.fn.expand("") +end + +local coc_command = function(command) + vim.cmd("CocCommand " .. command) +end + +local autocmd = function(group, event, pattern, callback) + vim.api.nvim_create_autocmd( + event, + { + callback = callback, + group = group, + pattern = pattern + } + ) +end + +local autocmd_buffer = function(group, event, buffer, callback) + vim.api.nvim_create_autocmd( + event, + { + buffer = buffer, + callback = callback, + group = group + } + ) +end + +local augroup_with_autocmd = function(name, event, pattern, callback) + local group = vim.api.nvim_create_augroup(name, {clear = true}) + autocmd(group, event, pattern, callback) + return group +end + +local augroup_with_autocmd_buffer = function(name, event, buffer, callback) + local group = vim.api.nvim_create_augroup(name, {clear = true}) + autocmd_buffer(group, event, buffer, callback) + return group +end + +local file_exists = function(name) + local f = io.open(name, "r") + return f ~= nil and io.close(f) +end + +local get_visual_text = function() + vim.cmd('normal! "ry') + return vim.fn.getreg("r") +end + +local is_c_family_file = function() + local name = vim.api.nvim_buf_get_name(0) + if name == nil or name == "" then + return false + end + + local ext = name:match("%.([^.]+)$") + if not ext then + return false + end + + ext = ext:lower() + return ext == "h" or ext == "hh" or ext == "hxx" or ext == "hpp" or ext == "c" or + ext == "cc" or + ext == "cpp" or + ext == "cxx" +end + +local function get_files_sorted_without_extension(dir) + local files = {} + local scanner = vim.loop.fs_scandir(dir) + if not scanner then + return files + end + + while true do + local name, typ = vim.loop.fs_scandir_next(scanner) + if not name then + break + end + if typ == "file" then + local base = name:match("(.+)%.[^%.]+$") or name + table.insert(files, base) + end + end + + table.sort(files) + return files +end + +local function create_vert_display(name, command) + vim.api.nvim_create_user_command( + name, + function() + vim.cmd("vert new") + local buf = vim.api.nvim_get_current_buf() + + vim.bo[buf].buftype = "nofile" + vim.bo[buf].bufhidden = "wipe" + vim.bo[buf].buflisted = false + vim.bo[buf].swapfile = false + vim.bo[buf].modifiable = true + vim.opt_local.wrap = true + + local lines = vim.fn.execute(command, "silent") + vim.api.nvim_buf_set_lines( + buf, + 0, + -1, + false, + vim.split(lines, "\n", {plain = true, trimempty = true}) + ) + + vim.bo[buf].modifiable = false + vim.api.nvim_win_set_cursor(0, {vim.api.nvim_buf_line_count(buf), 0}) + end, + {} + ) +end + +local function copy_file(src, dst) + local uv = vim.uv + local ok, err = uv.fs_copyfile(src, dst) + if not ok then + error(("copy failed: %s"):format(err)) + end +end + +local function iff(b, l, r) + if b then + return l + end + + return r +end + +local parse_env = function(var, def) + if vim.env[var] ~= nil then + if type(def) == "boolean" then + local result = + ({ + ["0"] = false, + ["1"] = true, + ["false"] = false, + ["n"] = false, + ["no"] = false, + ["off"] = false, + ["on"] = true, + ["true"] = true, + ["y"] = true, + ["yes"] = true + })[tostring(vim.env[var]):lower()] + if result == nil then + return def + end + return result + end + + return vim.env[var] + end + + return def +end + +local parse_env_list = function(var, def) + if vim.env[var] ~= nil then + local items = vim.split(var, " ", {plain = true, trimempty = true}) + for i, v in ipairs(items) do + items[i] = vim.fn.trim(v) + end + return items + end + + return def +end + +local function get_current_filename(buffer) + buffer = buffer or 0 + local name = vim.api.nvim_buf_get_name(buffer) + if name == "" then + return "" + end + + return vim.fn.fnamemodify(name, ":t") +end + +local notify_setting_enabled = function(text, enabled) + vim.notify( + text .. ": " .. iff(enabled, "ENABLED", "DISABLED"), + vim.log.levels.INFO + ) +end + +return { + augroup_with_autocmd = augroup_with_autocmd, + augroup_with_autocmd_buffer = augroup_with_autocmd_buffer, + autocmd = autocmd, + autocmd_buffer = autocmd_buffer, + coc_command = coc_command, + copy_file = copy_file, + create_vert_display = create_vert_display, + cword = cword, + file_exists = file_exists, + get_current_filename = get_current_filename, + get_files_sorted_without_extension = get_files_sorted_without_extension, + get_visual_text = get_visual_text, + iff = iff, + is_c_family_file = is_c_family_file, + notify_setting_enabled = notify_setting_enabled, + parse_env = parse_env, + parse_env_list = parse_env_list +} diff --git a/nvim/lua/darcula/utils/keymap.lua b/nvim/lua/darcula/utils/keymap.lua new file mode 100644 index 0000000..fc19ee9 --- /dev/null +++ b/nvim/lua/darcula/utils/keymap.lua @@ -0,0 +1,76 @@ +-- The MIT License (MIT) +-- +-- Copyright © 2026 Scott E. Graves +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software +-- and associated documentation files (the “Software”), to deal in the Software without restriction, +-- including without limitation the rights to use, copy, modify, merge, publish, distribute, +-- sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in all copies or +-- substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +-- BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +-- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +-- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-- +local cmap = function(...) + vim.keymap.set("c", ...) +end + +local imap = function(...) + vim.keymap.set("i", ...) +end + +local leader = function(chars) + return "" .. chars +end + +local leader2 = function(chars) + return "'" .. chars +end + +local leader3 = function(chars) + return "`" .. chars +end + +local map = function(...) + vim.keymap.set("", ...) +end + +local nmap = function(...) + vim.keymap.set("n", ...) +end + +local set = function(...) + vim.keymap.set(...) +end + +local tmap = function(...) + vim.keymap.set("t", ...) +end + +local vmap = function(...) + vim.keymap.set("v", ...) +end + +local xmap = function(...) + vim.keymap.set("x", ...) +end + +return { + cmap = cmap, + imap = imap, + leader = leader, + leader2 = leader2, + leader3 = leader3, + map = map, + nmap = nmap, + set = set, + tmap = tmap, + vmap = vmap, + xmap = xmap +} diff --git a/nvim/lua/darcula/utils/os/init.lua b/nvim/lua/darcula/utils/os/init.lua new file mode 100644 index 0000000..04419f2 --- /dev/null +++ b/nvim/lua/darcula/utils/os/init.lua @@ -0,0 +1,23 @@ +-- The MIT License (MIT) +-- +-- Copyright © 2026 Scott E. Graves +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software +-- and associated documentation files (the “Software”), to deal in the Software without restriction, +-- including without limitation the rights to use, copy, modify, merge, publish, distribute, +-- sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in all copies or +-- substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +-- BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +-- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +-- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-- +local M = {} +M.is_mac = vim.fn.has("mac") == 1 +M.is_windows = vim.fn.has("win32") == 1 or vim.fn.has("win64") == 1 +return M diff --git a/nvim/lua/darcula/utils/path/init.lua b/nvim/lua/darcula/utils/path/init.lua new file mode 100644 index 0000000..552ad8d --- /dev/null +++ b/nvim/lua/darcula/utils/path/init.lua @@ -0,0 +1,49 @@ +-- The MIT License (MIT) +-- +-- Copyright © 2026 Scott E. Graves +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software +-- and associated documentation files (the “Software”), to deal in the Software without restriction, +-- including without limitation the rights to use, copy, modify, merge, publish, distribute, +-- sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in all copies or +-- substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +-- BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +-- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +-- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-- +require("darcula.utils.string") + +local g = require("darcula.utils") +local os = require("darcula.utils.os") +local path = require("plenary.path") +local scan = require("plenary.scandir") + +local M = {} + +M.directory_sep = g.iff(os.is_windows, "\\", "/") +M.not_directory_sep = g.iff(os.is_windows, "/", "\\") + +function M.get_file_name_list(dir, remove_extension, extension_no_dot) + extension_no_dot = (extension_no_dot or "lua"):lower() + local list = {} + + local files = scan.scan_dir(dir, {hidden = true, depth = 1}) + for _, name in ipairs(files) do + local file_name = path:new(name):make_relative(dir):lower() + if file_name:ends_with("." .. extension_no_dot) then + table.insert( + list, + g.iff(remove_extension, file_name:sub(1, -5), file_name) + ) + end + end + return list +end + +return M diff --git a/nvim/lua/darcula/utils/string/init.lua b/nvim/lua/darcula/utils/string/init.lua new file mode 100644 index 0000000..ff922bf --- /dev/null +++ b/nvim/lua/darcula/utils/string/init.lua @@ -0,0 +1,44 @@ +-- The MIT License (MIT) +-- +-- Copyright © 2026 Scott E. Graves +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software +-- and associated documentation files (the “Software”), to deal in the Software without restriction, +-- including without limitation the rights to use, copy, modify, merge, publish, distribute, +-- sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in all copies or +-- substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +-- BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +-- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +-- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-- +function string:contains(str) + return self:find(str, 1, true) ~= nil +end + +function string:ends_with(suffix) + return suffix == "" or self:sub(-(#suffix)) == suffix +end + +function string:split(sep) + sep = sep or ":" + local fields = {} + local pattern = string.format("([^%s]+)", sep) + _ = + self:gsub( + pattern, + function(c) + fields[#fields + 1] = c + end + ) + return fields +end + +function string:starts_with(prefix) + return self:sub(1, #prefix) == prefix +end diff --git a/nvim/lua/darcula/utils/symbols.lua b/nvim/lua/darcula/utils/symbols.lua new file mode 100644 index 0000000..2626d79 --- /dev/null +++ b/nvim/lua/darcula/utils/symbols.lua @@ -0,0 +1,104 @@ +-- The MIT License (MIT) +-- +-- Copyright © 2026 Scott E. Graves +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software +-- and associated documentation files (the “Software”), to deal in the Software without restriction, +-- including without limitation the rights to use, copy, modify, merge, publish, distribute, +-- sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in all copies or +-- substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +-- BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +-- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +-- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-- +return { + code_action = "󰜎", + debug = { + breakpoint = "", + conditional_breakpoint = "", + breakpoint_disabled = "", + current_frame = "", + current_line = "", + current_line_with_breakpoint = "", + current_thread = "" + }, + definition = "", + definition_preview = "", + diagnostic_header = "", + directory = { + collapsed = "", + expanded = "", + directory = "", + directory_empty = "", + directory_open = "" + }, + file = "󰈙", + git = { + added = "", + blame = "", + conflict = "", + unstaged = "", + staged = "", + unmerged = "", + renamed = "󰑕", + untracked = "", + deleted = "", + ignored = "◌" + }, + indent = "│", + listchars = { + eol = "↵", + extends = "»", + nbsp = "␣", + precedes = "«", + space = "·", + tab = "→\\ ", + trail = "•" + }, + os = { + unix = "󰌽", + dos = "", + mac = "" + }, + line = { + errors = "", + hints = "", + info = "", + warnings = "" + }, + references = "", + rename = "󰑕", + search = "", + separators = { + default = "•", + component = { + left = "", + right = "" + }, + section = { + left = "", + right = "" + } + }, + spinner = {"⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"}, + status = { + checking = "", + errors = "", + info = "", + fix = "", + hints = "", + locked = "", + modified = "󰆓", + not_ok = "", + ok = "", + uninstalled = "", + unlocked = "", + warnings = "" + } +} diff --git a/nvim/lua/darcula/utils/table/init.lua b/nvim/lua/darcula/utils/table/init.lua new file mode 100644 index 0000000..e0b3529 --- /dev/null +++ b/nvim/lua/darcula/utils/table/init.lua @@ -0,0 +1,42 @@ +-- The MIT License (MIT) +-- +-- Copyright © 2026 Scott E. Graves +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software +-- and associated documentation files (the “Software”), to deal in the Software without restriction, +-- including without limitation the rights to use, copy, modify, merge, publish, distribute, +-- sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in all copies or +-- substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +-- BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +-- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +-- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-- +function table.contains(table, val) + for i = 1, #table do + if table[i] == val then + return true + end + end + return false +end + +function table.print_table(o) + return print(vim.inspect(o)) +end + +function table.reverse(self) + local n = #self + local i = 1 + while i < n do + self[i], self[n] = self[n], self[i] + i = i + 1 + n = n - 1 + end + return self +end diff --git a/nvim/lua/darcula/utils/ui/init.lua b/nvim/lua/darcula/utils/ui/init.lua new file mode 100644 index 0000000..f9287b5 --- /dev/null +++ b/nvim/lua/darcula/utils/ui/init.lua @@ -0,0 +1,26 @@ +-- The MIT License (MIT) +-- +-- Copyright © 2026 Scott E. Graves +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software +-- and associated documentation files (the “Software”), to deal in the Software without restriction, +-- including without limitation the rights to use, copy, modify, merge, publish, distribute, +-- sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in all copies or +-- substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +-- BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +-- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +-- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-- +local M = {} + +M.is_gui = function() + return vim.g.GuiLoaded == 1 or vim.g.neovide +end + +return M diff --git a/viml.sh b/viml.sh new file mode 100755 index 0000000..ca1139c --- /dev/null +++ b/viml.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash + +## The MIT License (MIT) +## +## Copyright © 2026 Scott E. Graves +## +## Permission is hereby granted, free of charge, to any person obtaining a copy of this software +## and associated documentation files (the “Software”), to deal in the Software without restriction, +## including without limitation the rights to use, copy, modify, merge, publish, distribute, +## sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +## furnished to do so, subject to the following conditions: +## +## The above copyright notice and this permission notice shall be included in all copies or +## substantial portions of the Software. +## +## THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +## BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +## NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +## DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +## +SCRIPT_DIR="$(dirname "$(readlink -f "$0")")" + +NVIM_APPNAME=nvim +export NVIM_APPNAME + +NV_DARCULA_ENABLE_COC=true +export NV_DARCULA_ENABLE_COC + +"${SCRIPT_DIR}/viml_common.sh" "$@" diff --git a/viml2.sh b/viml2.sh new file mode 100755 index 0000000..4419b78 --- /dev/null +++ b/viml2.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash + +## The MIT License (MIT) +## +## Copyright © 2026 Scott E. Graves +## +## Permission is hereby granted, free of charge, to any person obtaining a copy of this software +## and associated documentation files (the “Software”), to deal in the Software without restriction, +## including without limitation the rights to use, copy, modify, merge, publish, distribute, +## sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +## furnished to do so, subject to the following conditions: +## +## The above copyright notice and this permission notice shall be included in all copies or +## substantial portions of the Software. +## +## THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +## BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +## NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +## DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +## +SCRIPT_DIR="$(dirname "$(readlink -f "$0")")" + +NVIM_APPNAME=nvim2 +export NVIM_APPNAME + +NV_DARCULA_ENABLE_COC=false +export NV_DARCULA_ENABLE_COC + +"${SCRIPT_DIR}/viml_common.sh" "$@" diff --git a/viml_common.sh b/viml_common.sh new file mode 100755 index 0000000..9b2461a --- /dev/null +++ b/viml_common.sh @@ -0,0 +1,38 @@ +#!/usr/bin/env bash + +## The MIT License (MIT) +## +## Copyright © 2026 Scott E. Graves +## +## Permission is hereby granted, free of charge, to any person obtaining a copy of this software +## and associated documentation files (the “Software”), to deal in the Software without restriction, +## including without limitation the rights to use, copy, modify, merge, publish, distribute, +## sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +## furnished to do so, subject to the following conditions: +## +## The above copyright notice and this permission notice shall be included in all copies or +## substantial portions of the Software. +## +## THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +## BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +## NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +## DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +## +SCRIPT_DIR="$(dirname "$(readlink -f "$0")")" +. "${SCRIPT_DIR}/common.sh" + +create_link "${SCRIPT_DIR}/nvim" "${HOME}/.config/${NVIM_APPNAME}" +create_link "${SCRIPT_DIR}/dviml.sh" "${HOME}/.local/bin/dviml" +create_link "${SCRIPT_DIR}/dviml2.sh" "${HOME}/.local/bin/dviml2" +create_link "${SCRIPT_DIR}/viml.sh" "${HOME}/.local/bin/viml" +create_link "${SCRIPT_DIR}/viml2.sh" "${HOME}/.local/bin/viml2" + +if [ ! -f "/tmp/nvim-${NVIM_OS}-${NVIM_ARCH}/bin/nvim" ]; then + pushd "${SCRIPT_DIR}" 1>/dev/null 2>&1 || error_exit "failed to pushd: ${SCRIPT_DIR}" + FNAME=nvim-${NVIM_OS}-${NVIM_ARCH}.tar.gz + tar xvzf "pkg/${FNAME}" -C /tmp + popd 1>/dev/null 2>&1 || error_exit "failed to popd: ${SCRIPT_DIR}" +fi + +exec "/tmp/nvim-${NVIM_OS}-${NVIM_ARCH}/bin/nvim" "$@"