From 3f510aa1df86c5141c4ac993aba3141d53ac16b0 Mon Sep 17 00:00:00 2001 From: Matthieu Bessat Date: Wed, 17 Jan 2024 22:38:37 +0100 Subject: [PATCH] feat: vim config extracted from dot files --- .xinitrc | 68 ++ nvim/init.lua | 1529 +++++++++++++++++++++++++++++++++ nvim/lua/popequer.lua | 9 + nvim/lua/popequer/init.lua | 19 + nvim/lua/popequer/pickers.lua | 141 +++ 5 files changed, 1766 insertions(+) create mode 100644 .xinitrc create mode 100644 nvim/init.lua create mode 100644 nvim/lua/popequer.lua create mode 100644 nvim/lua/popequer/init.lua create mode 100644 nvim/lua/popequer/pickers.lua diff --git a/.xinitrc b/.xinitrc new file mode 100644 index 0000000..46537ee --- /dev/null +++ b/.xinitrc @@ -0,0 +1,68 @@ +#!/bin/sh + +# Setup display +xrandr --auto && xrandr --output HDMI1 --mode 1920x1080 --left-of eDP1 + +# Setup dependencies (this section is REQUIRED, don't remove) +if [ -d /etc/X11/xinit/xinitrc.d ] ; then + for f in /etc/X11/xinit/xinitrc.d/?*.sh ; do + [ -x "$f" ] && . "$f" + done + unset f +fi + +# to only use the HDM1 output use the command: +# xrandr --output HDMI1 --mode 1920x1080 --output + +# setup remap +[[ -f ~/.Xmodmap ]] && xmodmap ~/.Xmodmap + +# touchpad deamon with synaptic +# disable the touchpad when the user is typing to avoid confusion +syndaemon -i 0.5 -K -R -d + +picom & + +# old xflux (with french location) +#xflux -l 49.1754262 -g 1.3301737 & + +# Start xflux in location russia +xflux -l 54.784568 -g 37.106110 & + +# Start notification deamon +dunst & + +# Start network manager applet +# nm-applet + +# Prevent paste mouseblock +# I had to install it without using pacman +~/.apps/XMousePasteBlock/xmousepasteblock & + +# Start greenclip +greenclip daemon & + +# Start batterytator +/usr/bin/batterytator mbess BAT0 & + +# old: start laptop monitor (now replaced with batterytator) +#env LAPTOP_MONITOR_PERIOD_IN_MINUTES=2 /home/mbess/dots/laptop_monitor & > /home/mbess/dots/monitor.log + +# setup keychain +eval $(gnome-keyring-daemon --start) +export SSH_AUTH_SOCK + +# Start blueman +blueman-applet & + +# Start network manager applet +nm-applet & + +sh $HOME/dots/scripts/refresh_wallpapers.sh & + +xautolock -detectsleep -time 5 -locker ~/dots/scripts/lock.sh -notify 30 -notifier "notify-send -u critical -t 10000 -- 'locking screen in 30 seconds'" & + +element-desktop & + +i3 + diff --git a/nvim/init.lua b/nvim/init.lua new file mode 100644 index 0000000..34d79d3 --- /dev/null +++ b/nvim/init.lua @@ -0,0 +1,1529 @@ +-- Mbess lefuturiste nvim config (2024-01-17) (sorry, not very well organized) + +-- TODO: add lot of keybindings +-- +-- Add keybinding to close a tab (all views in a tab neotree + buffer) +-- Investigate why it's taking so long to switch tabs in vim +-- Individually sort files by updated_at date inside each directory in nvim-neo-tree/neo-tree.nvim (recent files in each dir) +-- Debugger feature +-- Twig treesitter support +-- Change name of variable with LSP -> rn +-- PHP helpers? +-- Python helpers? +-- Tabs features? Or recent tabs? Quickly switch between tabs +-- Add shortcut to open symbol definition in new tab + +local ensure_packer = function() + local fn = vim.fn + local install_path = fn.stdpath('data')..'/site/pack/packer/start/packer.nvim' + if fn.empty(fn.glob(install_path)) > 0 then + fn.system({'git', 'clone', '--depth', '1', 'https://github.com/wbthomason/packer.nvim', install_path}) + vim.cmd [[packadd packer.nvim]] + return true + end + return false +end + +function str2bool(str_inp) + return str_inp ~= nil and (str_inp == "1" or str_inp:lower() == "true" or str_inp:lower() == "yes") +end + +local packer_bootstrap = ensure_packer() + +-- disable some built-in +local disabled_built_ins = { + "netrw", + "netrwPlugin", + "netrwSettings", + "netrwFileHandlers", + -- "gzip", + -- "zip", + -- "zipPlugin", + -- "tar", + -- "tarPlugin", + "getscript", + "getscriptPlugin", + "vimball", + "vimballPlugin", + "2html_plugin", + "logipat", + "rrhelper", + -- "spellfile_plugin", + "matchit" +} + +local user_log = function(message) + local log_file_path = '/home/mbess/.logs/neovim.log' + local log_file = io.open(log_file_path, "a") + io.output(log_file) + io.write(message.."\n") + io.close(log_file) +end + +for _, plugin in pairs(disabled_built_ins) do + vim.g["loaded_" .. plugin] = 1 +end + +local opt = vim.opt + +vim.cmd("set background=dark") + +opt.guifont = "Fira Code" +opt.background = "dark" +opt.number = true +opt.relativenumber = true +opt.hidden = true + +-- Hide default menu mode status (I have lualine so this is duplicated) +opt.showmode = false + +-- Tabs options +opt.autoindent = true +opt.cindent = true +opt.wrap = true + +opt.expandtab = true +opt.smartindent = true + +opt.tabstop = 4 +opt.softtabstop = 4 +opt.shiftwidth = 4 + +opt.breakindent = true +opt.showbreak = string.rep(" ", 3) -- Make it so that long lines wrap smartly +opt.linebreak = true + +-- + +opt.wildmenu = true +opt.updatetime = 50 +opt.termguicolors = true + +opt.signcolumn = 'yes' +opt.belloff = 'all' + +-- Keep padding +opt.scrolloff = 10 + +-- Always ignore case when searching, unless there is a capital letter in the query +opt.ignorecase = true +opt.smartcase = true + +opt.splitright = true +opt.splitbelow = true + +-- Cool floating window popup menu for completion on command line +opt.pumblend = 17 +opt.wildmode = "longest:full" +opt.wildoptions = "pum" + +-- Ignore compiled files +opt.wildignore = "__pycache__" +opt.wildignore:append { "*.o", "*~", "*.pyc", "*pycache*" } +opt.wildignore:append "Cargo.lock" + +opt.colorcolumn = "100" + +-- Highlight on yank (copy). It will do a nice highlight blink of the thing you just copied. +-- use [[ ]] to do multi-line strings +vim.api.nvim_exec( + [[ + augroup YankHighlight + autocmd! + autocmd TextYankPost * silent! lua vim.highlight.on_yank() + augroup end +]], + false +) + +vim.g.mapleader = " " + +-- Plugin list +-- Packer +require("packer").startup(function() + use("wbthomason/packer.nvim") + + use("lewis6991/impatient.nvim") + + use("nvim-lua/plenary.nvim") + use("nvim-lua/popup.nvim") + use { + "nvim-telescope/telescope.nvim", + config = function() + local actions = require('telescope.actions') + + require('telescope').setup { + defaults = { + mappings = { + i = { + [''] = actions.cycle_history_next, + [''] = actions.cycle_history_prev + } + } + } + } + end + } + use { + "nvim-telescope/telescope-live-grep-args.nvim" + } + + use { + -- neotree + "nvim-neo-tree/neo-tree.nvim", + branch = "v2.x", + requires = { + "nvim-lua/plenary.nvim", + "kyazdani42/nvim-web-devicons", -- not strictly required, but recommended + "MunifTanjim/nui.nvim", + }, + config = function () + require('neo-tree').setup({ + enable_refresh_on_write = true, + + filesystem = { + use_libuv_file_watcher = true, + window = { + mappings = { + ["W"] = function (state) + local Node = state.tree:get_node() + print(node.name) + end + } + } + } + }) + end + } + -- TODO: figure how to show an outline for only the first level element, limit the depth + -- have a choice of precision between the top levels components only and the deeper components + -- the basic choice is to hop between functions or methods in a file + use { + "simrat39/symbols-outline.nvim", + config = function () + require("symbols-outline").setup({ + autofold_depth = 1 -- not working? + }) + end + -- commons shortcuts by default o, K, Ctrl+Space, r, a, h, l, W, E, R, ? + } + + -- Language Server Protocol stuff + use("neovim/nvim-lspconfig") + use("hrsh7th/nvim-cmp") + use("hrsh7th/cmp-nvim-lsp") + use("hrsh7th/cmp-buffer") + use("hrsh7th/cmp-path") + use("ray-x/cmp-treesitter") + use("saadparwaiz1/cmp_luasnip") + -- use("WhoIsSethDaniel/toggle-lsp-diagnostics.nvim") + + use { + "L3MON4D3/LuaSnip", + tag = "v1.2.1", + config = function () + on_luasnip_load() + end + } + use("rafamadriz/friendly-snippets") + + --use("williamboman/mason.nvim") + + + -- Tree sitter stuff + use { + "nvim-treesitter/nvim-treesitter", + -- commit = "26105050aae3a15dd85feaeb0439e253e31d5ceb", -- end of september + run = ":TSUpdate" + } + use("nvim-treesitter/playground") + -- add text objects like class, function + use { + "nvim-treesitter/nvim-treesitter-textobjects" + } + use { + "nvim-treesitter/nvim-treesitter-context", + config = function () + require("treesitter-context").setup{ + enable = true + } + end + } + use { + "JoosepAlviste/nvim-ts-context-commentstring", + config = function () + require("nvim-treesitter.configs").setup{ + context_commentstring = {enable = true} + } + end + } + -- use treesitter to auto add HTML tags + -- use { + -- 'windwp/nvim-ts-autotag', + -- config = function () + -- require('nvim-ts-autotag').setup({ + -- autotag = { + -- enable = false, + -- } + -- }) + -- end + -- } + -- use treesitter to swap arguments + use { + 'mizlan/iswap.nvim', + -- '~/workspace/iswap.nvim', + config = function () + require('iswap').setup({ + autoswap = true + }) + end + } + -- Smart comments + use("tpope/vim-commentary") + + -- Git integration + -- use("tpope/vim-fugitive") + use { + 'TimUntersberger/neogit', + commit = "74c9e29b61780345d3ad9d7a4a4437607caead4a", + requires = 'nvim-lua/plenary.nvim', + config = function () + require('neogit').setup{ + disable_builtin_notifications = true, + disable_commit_confirmation = true + } + end + } + use { + 'lewis6991/gitsigns.nvim', + config = function () + require('gitsigns').setup() + end, + on_attach = function(bufnr) + end + } + + -- Format + use("sbdchd/neoformat") + + -- Resume issues found with LSP + use { + "folke/trouble.nvim", + requires = "kyazdani42/nvim-web-devicons", + config = function() + require("trouble").setup {} + end + } + + use { + "windwp/nvim-autopairs", + config = function() require("nvim-autopairs").setup {} end + } + + -- Enhanced increment and decrement + use("monaqa/dial.nvim") + + -- Toggle helper + -- plugin to toggle boolean values + use { + "rmagatti/alternate-toggler" + } + + -- Lua pad: REPL lua in neovim context + -- Useful to mess around with the lua API + use { 'rafcamlet/nvim-luapad', requires = "antoinemadec/FixCursorHold.nvim" } + + -- Spell check helper + -- + -- use("kamykn/spelunker.vim") + + -- File navigation helper + use { + "ThePrimeagen/harpoon", + -- config = function() + -- require('harpoon').setup({ + + -- }) + -- end + } + + -- -- Colorscheme section + use { + "catppuccin/nvim", + as = "catppuccin", + config = function () + end + } + use { + 'kyazdani42/nvim-web-devicons', + config = function() + require'nvim-web-devicons'.setup { + -- your personnal icons can go here (to override) + -- you can specify color or cterm_color instead of specifying both of them + -- DevIcon will be appended to `name` + override = { + vue = { + icon = "", + color = "#428850", + cterm_color = "65", + name = "Vue" + } + }; + -- globally enable default icons (default to false) + -- will get overriden by `get_icons` option + default = true; + } + end + } + + -- Preview HTML colors + use("lilydjwg/colorizer") + + -- Add Sticky Buffers + use { + "stevearc/stickybuf.nvim", + config = function() + require("stickybuf").setup() + end + } + + -- add surround with 's' + use { + "ur4ltz/surround.nvim", + config = function() + require"surround".setup {mappings_style = "sandwich"} + end + } + + use { + "tpope/vim-unimpaired" + } + + use { + "tpope/vim-repeat" + } + + -- In-buffer navigation + use { + "mfussenegger/nvim-treehopper" + } + use { + "phaazon/hop.nvim", + branch = 'v2', + config = function() + require'hop'.setup { keys = 'etovxqpdygfblzhckisuran' } + end + } + use { + "indianboy42/hop-extensions", + requires = {'phaazon/hop.nvim'} + } + + -- Align things by comma + -- use : `:Tabularize /,` + -- It would be nicer if someone (me?) could develop a plugin that is based on treesitter and can automagically detect when it's a array, object etc. + use("godlygeek/tabular") + + -- Ascii boxes + -- Diagramms + use("jbyuki/venn.nvim") + use("gyim/vim-boxdraw") + + -- Old tab plugin + -- use { + -- 'romgrk/barbar.nvim', + -- requires = {'kyazdani42/nvim-web-devicons'} + -- } + + -- Implement the editorconfig specification (format rules for each project) + use('editorconfig/editorconfig-vim') + + -- Non-LSP Language config + -- Language specific config + + -- Use emmet + use('mattn/emmet-vim') + + -- Consider using https://github.com/danymat/neogen to easily create functions annotation (can support php docs) + -- use('lervag/vimtex') -- tex support is already here? + -- + use "folke/lua-dev.nvim" + + -- Trying to have gohtmltemplate Highlighting + use "fatih/vim-go" + + use { 'mfussenegger/nvim-dap' } + + use { "rcarriga/nvim-dap-ui", requires = {"mfussenegger/nvim-dap"} } + + use { + 'nvim-lualine/lualine.nvim', + requires = { 'kyazdani42/nvim-web-devicons', opt = true }, + config = function () + require('lualine').setup { + options = { + icons_enabled = true, + theme = 'auto', + component_separators = { left = '', right = ''}, + section_separators = { left = '', right = ''}, + disabled_filetypes = { + statusline = {}, + winbar = {}, + }, + ignore_focus = {}, + always_divide_middle = true, + globalstatus = false, + refresh = { + statusline = 1000, + tabline = 1000, + winbar = 1000, + } + }, + sections = { + lualine_a = {'mode'}, + lualine_b = {'branch', 'diff', 'diagnostics'}, + lualine_c = {{'filename', path = 1}}, + -- lualine_x = {'filetype'}, + lualine_y = {'progress'}, + lualine_z = {'location'} + }, + inactive_sections = { + lualine_a = {}, + lualine_b = {}, + lualine_c = {'filename'}, + lualine_x = {'location'}, + lualine_y = {}, + lualine_z = {} + }, + tabline = {}, + winbar = {}, + inactive_winbar = {}, + extensions = {} + } + end + } + + -- Language specific plugins + use "aklt/plantuml-syntax" + + use "tyru/open-browser.vim" + use "weirongxu/plantuml-previewer.vim" + + -- allow to easily create new telescope pickers + -- useful to create ppq git recent files + use { + 'axkirillov/easypick.nvim', + requires = 'nvim-telescope/telescope.nvim', + config = function () + local easypick = require("easypick") + local base_branch = "master" + easypick.setup({ + pickers = { + -- list recent updated files tracked by git + { + name = "recent_files", + -- don't use the uniq util with sort, to preserve the original sorting order + command = "git -c core.quotepath=off log --name-only --format='' | head -n 100 | awk '!seen[$0]++'", + previewer = easypick.previewers.default() + } + } + }) + end + } + + use { + 'ethanholz/nvim-lastplace', + config = function () + require'nvim-lastplace'.setup { + lastplace_ignore_buftype = {"quickfix", "nofile", "help"}, + lastplace_ignore_filetype = {"gitcommit", "gitrebase", "svn", "hgcommit"}, + lastplace_open_folds = true + } + end + } + + -- markdown note plugins + use({ + "iamcco/markdown-preview.nvim", + run = function() vim.fn["mkdp#util#install"]() end, + }) + + -- disable it for now bc it overrode shit in NeoTree + -- use({'jakewvincent/mkdnflow.nvim', + -- config = function() + -- require('mkdnflow').setup({ + -- -- Config goes here; leave blank for defaults + -- }) + -- end + -- }) + + + -- new plugins + -- append new plugins here + + if packer_bootstrap then + require('packer').sync() + end + +end) + + +-- local map = vim.api.nvim_set_keymap +local map = vim.keymap.set + +-- reload nvim config +map("n", "r", "source ~/.config/nvim/init.lua") + +-- short cut to access system clipboard +map("n", "Y", '"+y') +map("v", "Y", '"+y') + +-- handy little things +map("n", "", ":q") -- close a single buffer +map("n", "", ":tabclose") -- close a whole tab (with Q uppercase) +map("n", "", ":w") + +-- back to last buffer +map("n", "bb", "") + +-- No highlights +map("n", "nh", "noh") +map("n", "h", "noh") + +-- Copy current buffer paths to system clipboard +map("n", "yp", function() copy_rel_path_with_line() end) +map("n", "ypr", function() copy_rel_path() end) +map("n", "ypr", function() copy_rel_path_with_line() end) +map("n", "ypa", function() copy_abs_path() end) + +-- Open URL in browser (replace netrw-gx) +map("n", "gx", function() + print() + vim.fn.jobstart( + {"xdg-open", vim.fn.expand("")}, + { on_stdout = print_stdout, detach = true } + ) +end) + +-- Insert date + time +map("n", "dt", function() + local res = os.date("%Y-%m-%d %H:%M:%S") + vim.api.nvim_put({res}, "", true, false) +end) + +-- Insert only day date +map("n", "dd", function() + local res = os.date("%Y-%m-%d") + vim.api.nvim_put({res}, "", true, false) +end) + +-- using netrw +-- map("n", "tt", "Explore") +-- map("n", "th", "Sexplore") +-- map("n", "tv", "Vexplore") + +-- launch neotree +map("n", "tt", function() vim.api.nvim_command('Neotree') end) +-- focus file in tree +-- locate file, locate path, locate buffer in tree +map("n", "tf", function() vim.api.nvim_command('Neotree reveal') end) +map("n", "tb", function() vim.api.nvim_command('Neotree buffers') end) + +-- launch neogit +map("n", "ng", function() vim.api.nvim_command('Neogit') end) + +-- launch neoformat +map("n", "nf", function() vim.api.nvim_command('Neoformat') end) + +-- launch troubles +map("n", "tr", function() vim.api.nvim_command('Trouble') end) + + +-- in buffer navigation +-- map("v", "", function() require('tsht').nodes() end) +-- map("n", "", function() require('tsht').move({ side = "start" }) end) + +-- Hop nvim keybindings (quick jumps) +-- Similar function can be triggered with Ctrl+BackSpace +map("n", "H", function() + -- hop in all the buffer by word + require('hop').hint_words() +end) +map("n", "hl", function() + -- hop to a line + require('hop').hint_lines_skip_whitespace() +end) +map("n", "hv", function() + -- keep the position of the cursor column wise + require('hop').hint_vertical() +end) +map("n", "hs", function() + require('hop-extensions').hint_textobjects() +end) +map("n", "", function() + require('hop-extensions').hint_textobjects() +end) + +-- Symbols outline +-- TODO: add a command variant to only show the top-level elements +map("n", "so", function () + vim.cmd("SymbolsOutline") +end) + +-- map("n", "sO", function () +-- vim.cmd("SymbolsOutlineOpen") +-- end) + +-- Harpoon +-- map("n", "h", function() require("harpoon.ui").toggle_quick_menu() end) +-- map("n", "a", function() require("harpoon.mark").add_file() end) + +-- map("n", "", function () require("harpoon.ui").nav_file(1) end) +-- map("n", "", function () require("harpoon.ui").nav_file(2) end) +-- map("n", "", function () require("harpoon.ui").nav_file(3) end) +-- map("n", "", function () require("harpoon.ui").nav_file(4) end) + +-- reserved for style file +-- map("n", "", function () require("harpoon.ui").nav_file(1) end) + +-- reserved for template file + +-- reserved for controller file +-- map("n", "", function () require("harpoon.ui").nav_file("Controller") end) + +-- Dial: Improved increment +map("n", "", require("dial.map").inc_normal(), {noremap = true}) +map("n", "", require("dial.map").dec_normal(), {noremap = true}) +map("v", "", require("dial.map").inc_visual(), {noremap = true}) +map("v", "", require("dial.map").dec_visual(), {noremap = true}) +map("v", "g", require("dial.map").inc_gvisual(), {noremap = true}) +map("v", "g", require("dial.map").dec_gvisual(), {noremap = true}) + +-- let g:at_custom_alternates = {'===': '!==', 'yes':'no'} +-- vim.cmd [[ +-- let g:at_custom_alternates = {'===': '!==', 'yes': 'no'} +-- ]] + +-- https://github.com/rmagatti/alternate-toggler/issues/6 +vim.g.at_custom_alternates = { + ['==='] = '!==', + ['yes'] = 'no', + ['open'] = 'close', + ['always'] = 'never', + ['allow'] = 'deny', + ['before'] = 'after', + ['let'] = 'var', + ['public'] = 'private', + ['begin'] = 'end' +} + +map("n", "ta", ":ToggleAlternate") + +-- swap with +map("n", "ss", function() vim.api.nvim_command('ISwap') end) +map("n", "sw", function() vim.api.nvim_command('ISwapWith') end) +map("n", "sl", function() vim.api.nvim_command('ISwapNodeWithLeft') end) +map("n", "sr", function() vim.api.nvim_command('ISwapNodeWithRight') end) + +-- Telescope binding +map("n", "ff", function () + require('telescope.builtin').find_files() +end) + +-- Ctrl+P +map("n", "", function () + -- It would be great if we could enter regex pattern to match on files + require('telescope.builtin').find_files() +end) + +-- TODO: find files with telescope but also search in the ignored files +-- map("n", "", function () +-- require('telescope.builtin').find_files() +-- end) + +-- live grep keybind +map("n", "fg", function () + -- previously was: + -- require('telescope.builtin').live_grep() + -- + -- arguments of ripgrep + + -- use '"search" --type py' to search in python file only + -- or use '"search" -g "*.py"' to do glob search on file name + -- or use '"search" -g "!*.py"' to exclude file name pattern + + -- another cool feature will be to do only search on a subdirectory (preferentially the current directory of neotree) + require('telescope').extensions.live_grep_args.live_grep_args() +end) + +map("n", "SS", function () + require('telescope').extensions.live_grep_args.live_grep_args({search = "hello world"}) +end) + +map("n", "fb", function () + require('telescope.builtin').buffers() +end) + +map("n", "fh", function () + require('telescope.builtin').help_tags() +end) + +map("n", "fs", function () + require('telescope.builtin').lsp_workspace_symbols() +end) + +map("n", "fw", function () + -- useful to quickly jump to ANY workspace symbols (also include random variables) + require('telescope.builtin').lsp_dynamic_workspace_symbols() +end) + +map("n", "fo", function () + -- recent files history + require('telescope.builtin').oldfiles({only_cwd = true}) +end) + +map("n", "fW", function () + -- useful to quickly jump to major workspace symbols (class, functions, interfaces, etc...) + -- require('telescope.builtin').lsp_dynamic_workspace_symbols() +end) + +-- Search for symbols accross project +-- map("n", "fs", function () +-- require('telescope.builtin').lsp() +-- end) + +-- find recent files +map("n", "fr", function () + vim.api.nvim_command('Easypick recent_files') +end) + +-- Treesitter config +require'nvim-treesitter.configs'.setup { + ensure_installed = "all", + sync_install = false, + + highlight = { + enable = true, + additional_vim_regex_highlighting = false, + }, + indent = { + enable = true + }, + incremental_selection = { + enable = true, + keymaps = { + init_selection = "", + node_incremental = "", + scope_incremental = "", + node_decremental = "", + }, + }, + textobjects = { + select = { + enable = true, + + -- Automatically jump forward to textobj, similar to targets.vim + lookahead = true, + + keymaps = { + -- You can use the capture groups defined in textobjects.scm + ["af"] = "@function.outer", + ["if"] = "@function.inner", + ["ac"] = "@class.outer", + ["ic"] = "@class.inner", + ["aa"] = "@block.outer", + ["ii"] = "@block.inner", + ["i,"] = '@parameter.inner', + ["a,"] = '@parameter.outer', + }, + -- You can choose the select mode (default is charwise 'v') + selection_modes = { + ['@parameter.outer'] = 'v', -- charwise + ['@function.outer'] = 'V', -- linewise + ['@class.outer'] = '', -- blockwise + }, + -- Useful to include whitespace after a function for example (so the whitespace get deleted or copied and stick with the belonging block) + include_surrounding_whitespace = true, + }, + move = { + enable = true, + set_jumps = true, -- whether to set jumps in the jumplist + goto_next_start = { + ["]m"] = "@function.outer", + ["]]"] = { query = "@class.outer", desc = "Next class start" }, + -- + -- You can use regex matching (i.e. lua pattern) and/or pass a list in a "query" key to group multiple queires. + ["]o"] = "@loop.*", + -- ["]o"] = { query = { "@loop.inner", "@loop.outer" } } + -- + -- You can pass a query group to use query from `queries//.scm file in your runtime path. + -- Below example nvim-treesitter's `locals.scm` and `folds.scm`. They also provide highlights.scm and indent.scm. + ["]s"] = { query = "@scope", query_group = "locals", desc = "Next scope" }, + ["]z"] = { query = "@fold", query_group = "folds", desc = "Next fold" }, + }, + goto_next_end = { + ["]M"] = "@function.outer", + ["]["] = "@class.outer", + }, + goto_previous_start = { + ["[m"] = "@function.outer", + ["[["] = "@class.outer", + }, + goto_previous_end = { + ["[M"] = "@function.outer", + ["[]"] = "@class.outer", + }, + -- Below will go to either the start or the end, whichever is closer. + -- Use if you want more granular movements + -- Make it even more gradual by adding multiple queries and regex. + goto_next = { + ["]d"] = "@conditional.outer", + }, + goto_previous = { + ["[d"] = "@conditional.outer", + } + }, + }, +} + +vim.opt.foldmethod = "expr" +vim.opt.foldexpr = "nvim_treesitter#foldexpr()" +vim.opt.foldlevelstart = 8 + +-- LSP Config +local nvim_lsp = require 'lspconfig' + +-- TODO: fix auto-imports not working with rust + +-- LSP Servers +-- docs: WHERE IS THE FING DOCS? +-- https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md +local servers = {'clangd', 'pyright', 'tsserver', 'gopls', 'volar', 'svelte' } + +for _, lsp in ipairs(servers) do + nvim_lsp[lsp].setup { + on_attach = on_attach, + } +end + +nvim_lsp['rust_analyzer'].setup{ + on_attach = on_attach, + init_options = { + ["rust-analyzer.checkOnSave.command"] = "clippy" + } +} +nvim_lsp.phpactor.setup{ + on_attach = on_attach, + init_options = { + ["language_server_phpstan.enabled"] = false, + ["language_server_psalm.enabled"] = false, + } +} +nvim_lsp.svelte.setup{ + init_options = { + ["svelte.plugin.typescript.enable"] = false, + ["svelte.plugin.typescript.diagnostics.enable"] = false, + } +} + +nvim_lsp['hls'].setup{ + filetypes = { 'haskell', 'lhaskell', 'cabal' } +} + +local capabilities = vim.lsp.protocol.make_client_capabilities() +capabilities.textDocument.completion.completionItem.snippetSupport = true + +nvim_lsp.cssls.setup{ + capabilities = capabilities +} + + +local runtime_path = vim.split(package.path, ';') +table.insert(runtime_path, 'lua/?.lua') +table.insert(runtime_path, 'lua/?/init.lua') + +-- Cmp config +local cmp = require'cmp' + +cmp.setup({ + snippet = { + -- REQUIRED - you must specify a snippet engine + expand = function(args) + -- vim.fn["vsnip#anonymous"](args.body) -- For `vsnip` users. + require('luasnip').lsp_expand(args.body) -- For `luasnip` users. + -- require('snippy').expand_snippet(args.body) -- For `snippy` users. + -- vim.fn["UltiSnips#Anon"](args.body) -- For `ultisnips` users. + end, + }, + window = { + -- completion = cmp.config.window.bordered(), + -- documentation = cmp.config.window.bordered(), + }, + mapping = cmp.mapping.preset.insert({ + [''] = cmp.mapping.scroll_docs(-4), + [''] = cmp.mapping.scroll_docs(4), + [''] = cmp.mapping.complete(), + [''] = cmp.mapping.abort(), + [''] = cmp.mapping.confirm({ select = true }), -- Accept currently selected item. Set `select` to `false` to only confirm explicitly selected items. + }), + sources = { + { name = 'nvim_lsp', keyword_length = 4 }, + { name = 'nvim_lua', keyword_length = 4 }, + + { name = 'path', keyword_length = 4 }, + { name = 'treesitter', keyword_length = 4 }, + { name = "luasnip", keyword_length = 4 }, + { name = "buffer", keyword_length = 5 }, + }, + experimental = { + -- I like the new menu better! Nice work hrsh7th + native_menu = false, + + -- Let's play with this for a day or two + ghost_text = false, + }, + sorting = { + -- TODO: Would be cool to add stuff like "See variable names before method names" in rust, or something like that. + comparators = { + cmp.config.compare.offset, + cmp.config.compare.exact, + cmp.config.compare.score, + + -- copied from cmp-under, but I don't think I need the plugin for this. + -- I might add some more of my own. + function(entry1, entry2) + local _, entry1_under = entry1.completion_item.label:find "^_+" + local _, entry2_under = entry2.completion_item.label:find "^_+" + entry1_under = entry1_under or 0 + entry2_under = entry2_under or 0 + if entry1_under > entry2_under then + return false + elseif entry1_under < entry2_under then + return true + end + end, + + cmp.config.compare.kind, + cmp.config.compare.sort_text, + cmp.config.compare.length, + cmp.config.compare.order, + }, + }, + -- sources = cmp.config.sources({ + -- { name = 'nvim_lsp' }, + -- -- { name = 'vsnip' }, -- For vsnip users. + -- -- { name = 'luasnip' }, -- For luasnip users. + -- -- { name = 'ultisnips' }, -- For ultisnips users. + -- -- { name = 'snippy' }, -- For snippy users. + -- }, { + -- { + -- name = 'buffer', + -- options = { + -- keyword_length = 5 + -- } + -- }, + -- }) +}) + +-- Toggle diags +DiagnosticsConfig = vim.diagnostic.config() +DiagnosticsEnabled = true +function toggle_lsp_diag() + if not DiagnosticsEnabled then + vim.diagnostic.config(DiagnosticsConfig) + DiagnosticsEnabled = true + else + DiagnosticsConfig = vim.diagnostic.config() + vim.diagnostic.config({ + virtual_text = false, + sign = false, + float = false, + update_in_insert = false, + severity_sort = false, + underline = false, + }) + DiagnosticsEnabled = false + end +end + +-- Language server keybindings +-- LSP keybindings +map("n", "gd", function () + vim.lsp.buf.definition() +end) + +map("n", "od", function () + -- open definition in a new tab + -- vim.lsp.buf.definition() + print("Open def in new tab") +-- vim.api.nvim_exec( +-- [[ normal ] ]], +-- -- [[normal dd]], +-- false +-- ) +end) + +map("n", "gD", function () + vim.lsp.buf.declaration() +end) + +-- go to implementation +map("n", "gi", function () + vim.lsp.buf.implementation() +end) + +-- go to usage +-- go to callers of a function +map("n", "lc", function () + vim.lsp.buf.incoming_calls() +end) + +map("n", "gw", function () + vim.lsp.buf.document_symbol() +end) + +map("n", "gr", function () + vim.lsp.buf.references() +end) + +map("n", "ld", function () + vim.lsp.buf.type_definition() +end) + +map("n", "K", function () + vim.lsp.buf.hover() +end) + +map("n", "", function () + vim.lsp.buf.signature_help() +end) + +map("n", "ac", function () + vim.lsp.buf.code_action() +end) + +-- Rename action +map("n", "rn", function () + vim.lsp.buf.rename() +end) + +-- Show_line_diagnostics +map("n", "di", function () + vim.diagnostic.open_float() +end) + +-- Format whole buffer with LSP +map("n", "F", function () + vim.lsp.buf.format { async = true } +end) + +-- Toggle LSP diags +-- keywords: disable lsp +map("n", "td", function() toggle_lsp_diag() end) + +-- Tabs keymaps + +-- -- Move to previous/next +-- map('n', '', 'BufferPrevious') +-- map('n', '', 'BufferNext') +-- -- Re-order to previous/next +-- map('n', '', 'BufferMovePrevious') +-- map('n', '>', 'BufferMoveNext') +-- -- Goto buffer in position... +-- map('n', '', 'BufferGoto 1') +-- map('n', '', 'BufferGoto 2') +-- map('n', '', 'BufferGoto 3') +-- map('n', '', 'BufferGoto 4') +-- map('n', '', 'BufferGoto 5') +-- map('n', '', 'BufferGoto 6') +-- map('n', '', 'BufferGoto 7') +-- map('n', '', 'BufferGoto 8') +-- map('n', '', 'BufferGoto 9') +-- map('n', '', 'BufferLast') +-- -- Pin/unpin buffer +-- map('n', '', 'BufferPin') +-- -- Close buffer +-- map('n', '', 'BufferClose') +-- -- Wipeout buffer +-- -- :BufferWipeout +-- -- Close commands +-- -- :BufferCloseAllButCurrent +-- -- :BufferCloseAllButPinned +-- -- :BufferCloseAllButCurrentOrPinned +-- -- :BufferCloseBuffersLeft +-- -- :BufferCloseBuffersRight +-- -- Magic buffer-picking mode +-- map('n', '', 'BufferPick') +-- -- Sort automatically by... +-- map('n', 'bb', 'BufferOrderByBufferNumber') +-- map('n', 'bd', 'BufferOrderByDirectory') +-- map('n', 'bl', 'BufferOrderByLanguage') +-- map('n', 'bw', 'BufferOrderByWindowNumber') + +map("n", "gh", ":lua print('this is a msg')") + +vim.g.hook_cmp_toggle = true + + +-- LuaSnip config / Snippets + +-- imap luasnip#expand_or_jumpable() ? 'luasnip-expand-or-jump' : '' +-- " -1 for jumping backwards. +-- inoremap lua require'luasnip'.jump(-1) + +-- snoremap lua require('luasnip').jump(1) +-- snoremap lua require('luasnip').jump(-1) + +-- " For changing choices in choiceNodes (not strictly necessary for a basic setup). +-- imap luasnip#choice_active() ? 'luasnip-next-choice' : '' +-- smap luasnip#choice_active() ? 'luasnip-next-choice' : '' +function on_luasnip_load() + local ls = require("luasnip") + + ls.config.set_config({ + history = true, + updateevents = "TextChanged,TextChangedI", + enable_autosnippets = true, + }) + ls.filetype_extend("svelte", { "html" }) + ls.filetype_extend("svelte", { "typescript" }) + + require("luasnip.loaders.from_vscode").lazy_load() + + + -- This replace the diagraph menu + vim.keymap.set({"i", "s"}, "", function () + if ls.expand_or_jumpable() then + ls.expand_or_jump() + end + end) + + vim.keymap.set({"i", "s"}, "", function () + if ls.jumpable(-1) then + ls.jump(-1) + end + end) + + vim.keymap.set("i", "", function () + if ls.choice_active() then + ls.change_choice() + end + end) + + + local events = require("luasnip.util.events") + local ai = require("luasnip.nodes.absolute_indexer") + local fmt = require("luasnip.extras.fmt").fmt + local extras = require("luasnip.extras") + local m = extras.m + local l = extras.l + local rep = extras.rep + local postfix = require("luasnip.extras.postfix").postfix + + ls.add_snippets("all", { + ls.snippet("somefoobarlel", { + -- equivalent to "${1:cond} ? ${2:then} : ${3:else}" + ls.insert_node(1, "cond"), ls.text_node(" ? "), ls.insert_node(2, "then"), ls.text_node(" : "), ls.insert_node(3, "else") + }), + ls.snippet("lorem", { + ls.text_node("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.") + }) + }) + + ls.add_snippets("rust", { + ls.snippet("dbg", { + ls.text_node("dbg!("), ls.insert_node(1, "value"), ls.text_node(");") + }) + }) + + function mysplit (inputstr, sep) + if sep == nil then + sep = "%s" + end + local t={} + for str in string.gmatch(inputstr, "([^"..sep.."]+)") do + table.insert(t, str) + end + return t + end + + vim.api.nvim_create_user_command('SnipList', function () + -- Will create a read only buffer and show the description of all the snippets + local res = vim.inspect(require'luasnip'.available()) + + if win and vim.api.nvim_win_is_valid(win) then + vim.api.nvim_set_current_win(win) + else + -- We open a new buffer + vim.api.nvim_command('botright vnew') + + win = vim.api.nvim_get_current_win() + buf = vim.api.nvim_get_current_buf() + + vim.api.nvim_buf_set_name(buf, "SnipList") + + vim.api.nvim_buf_set_option(buf, 'buftype', 'nofile') + vim.api.nvim_buf_set_option(buf, 'swapfile', false) + vim.api.nvim_buf_set_option(buf, 'bufhidden', 'wipe') + + vim.api.nvim_buf_set_option(buf, 'modifiable', true) + vim.api.nvim_buf_set_option(buf, 'filetype', 'lua') + -- Uncomment to disable numbers + -- vim.api.nvim_set_option_value('number', false, { scope = "local" }) + -- vim.api.nvim_set_option_value('relativenumber', false, { scope = "local" }) + + -- We set the buffer content + vim.api.nvim_buf_set_lines(buf, 0, -1, false, mysplit(res, "\n")) + vim.api.nvim_buf_set_option(buf, 'modifiable', false) + end + + end, {}) + +end + +require("catppuccin").setup({ + flavour = "mocha", -- redondant + color_overrides = { + all = { + } + }, + custom_highlights = function(colors) + return { + ["@constant.builtin"] = { fg = colors.peach, style = {} }, + -- change the syntax highlighting of comments to make them easier to read and notice + -- I once read a blog post about how comments in code should be put in front and not hidden with some gray colorscheme + ["@comment"] = { fg = colors.red, style = { "italic", "bold" } }, + } + end +}) + +vim.cmd.colorscheme "catppuccin" + +vim.api.nvim_exec( +[[ +function! DetectGoHtmlTmpl() + if expand('%:e') == "html" && search("{{") != 0 + set filetype=gohtmltmpl + endif +endfunction + +augroup filetypedetect + au! BufRead,BufNewFile * call DetectGoHtmlTmpl() +augroup END +]], true +) + +-- vim.g.gruvbox_contrast_dark = "hard" + +-- little shortcut to insert new line without going into insert mode with Ctrl+Enter +map("n", "", function () + vim.api.nvim_put({"",""}, "", true, false) +end) + +-- Tabs manipulations +map("n", "T0", function() vim.api.nvim_command('tabm 0') end) +map("n", "Ti", function() vim.api.nvim_command('tabm +1') end) +map("n", "Td", function() vim.api.nvim_command('tabm -1') end) + +-- Move after last tab +vim.api.nvim_create_user_command('MoveTabAtLastTab', function () + local tabpages = vim.api.nvim_list_tabpages() + vim.api.nvim_command('tabm '..#tabpages) +end, {}) + +map("n", "Te", function() vim.api.nvim_command('MoveTabAtLastTab') end) + +-- Tabs/Tabspages navigation with alt +map("n", "", function () vim.api.nvim_command("tabp") end) +map("n", "", function () vim.api.nvim_command("tabn") end) +map("n", "", function () vim.api.nvim_command("tabp") end) + +-- Go to nth tab +local function jump_to_nth_tab(tab_position) + local tabpages = vim.api.nvim_list_tabpages() + if tab_position > #tabpages then + return + end + print(tab_position) + vim.api.nvim_set_current_tabpage(tabpages[tab_position]) +end + +local function jump_to_last_tab() + local tabpages = vim.api.nvim_list_tabpages() + print(#tabpages) +end + +map("n", "", function () jump_to_nth_tab(0) end) +map("n", "", function () jump_to_last_tab() end) +map("n", "", function () jump_to_nth_tab(10) end) +map("n", "", function () jump_to_nth_tab(11) end) +map("n", "", function () jump_to_nth_tab(12) end) +for i = 1, 9 do + map("n", "", function () + jump_to_nth_tab(i) + end) +end + +-- common utils function to accept user input from bottom status line +local function user_input(message) + vim.api.nvim_call_function("inputsave", {}) + local val = vim.api.nvim_call_function("input", { message }) + vim.api.nvim_call_function("inputrestore", {}) + return val +end + +-- Now a way to jump to specific tabs via file name match +map("n", "", function () + -- Ask user the file startup + user_res = user_input("TabJump: ") + + pages = vim.api.nvim_list_tabpages() + if #pages == 1 then + return + end + + for tab_pos in ipairs(pages) do + win = vim.api.nvim_tabpage_get_win(tab_pos) + buf = vim.api.nvim_win_get_buf(win) + file_path = vim.api.nvim_buf_get_name(buf) + res = mysplit(file_path, "/") + file_name = res[#res] + + search_res = string.find(file_name, user_res) + if search_res then + vim.api.nvim_set_current_tabpage(tab_pos) + vim.api.nvim_echo({}, false, {}) + return + end + end + vim.api.nvim_notify("TabJump: No match found", 0, {}) +end) + +-- Search helper + +local function visual_selection_range() + local _, csrow, cscol, _ = unpack(vim.fn.getpos("'<")) + local _, cerow, cecol, _ = unpack(vim.fn.getpos("'>")) + if csrow < cerow or (csrow == cerow and cscol <= cecol) then + return csrow - 1, cscol - 1, cerow - 1, cecol + else + return cerow - 1, cecol - 1, csrow - 1, cscol + end +end + +function get_current_selected() + local current_mode = vim.api.nvim_get_mode()['mode'] + if ( + current_mode == "v" or + current_mode == "V" + ) then + local _, select_start_row, select_start_col, _ = unpack(vim.fn.getpos("'<")) + local _, select_end_row, select_end_col, _ = unpack(vim.fn.getpos("'>")) + + -- get the range + -- print(select_start_row, select_start_col) + -- print(select_end_row, select_end_col) + selected_text = vim.api.nvim_buf_get_text(0, select_start_row-1, select_start_col-1, select_end_row-1, select_end_col-1, {}) + if #selected_text == 0 then + return nil + end + return selected_text[1] + end + return nil +end + +function copy_rel_path() + -- get full path: expand("%:p") + -- get relative path: expand("%") + -- vim.fn.setreg("+", vim.fn.expand("%")) + path = vim.fn.fnamemodify(vim.fn.expand("%"), ":~:.") + vim.fn.setreg("+", path) + print("Copied relative to system clipboard") +end + +function copy_rel_path_with_line() + path = vim.fn.fnamemodify(vim.fn.expand("%"), ":~:.") .. ':' .. vim.fn.getpos('.')[2] + vim.fn.setreg("+", path) +end + +function copy_abs_path() + vim.fn.setreg("+", vim.fn.expand("%:p")) + print("Copied absolute to system clipboard") +end + +function copy_abs_path_with_line() + path = vim.fn.setreg("+", vim.fn.expand("%:p")) .. ':' .. vim.fn.getpos('.')[2] + + vim.fn.setreg("+", path) +end + +-- Search the term selected +function handle_search_selection() + print("handle search selection") + + selected = get_current_selected() + if selected == nil then + return nil + end + + vim.api.nvim_exec( + "normal! /lelhello", + false + ) +end + +map("n", "S", handle_search_selection) +map("v", "S", handle_search_selection) + +-- Restrict the search to a range +-- map("n", "S", function () + +-- end) + +-- Handy Git signs shortcuts +map("n", "gb", function() vim.api.nvim_command('Gitsigns blame_line') end) +map("n", "gs", function() vim.api.nvim_command('Gitsigns stage_hunk') end) +map("n", "gu", function() vim.api.nvim_command('Gitsigns undo_stage_hunk') end) +map("n", "gd", function() vim.api.nvim_command('Gitsigns toggle_deleted') end) +map("n", "gD", function() vim.api.nvim_command('Gitsigns diffthis') end) +map("n", "gS", function() vim.api.nvim_command('Gitsigns stage_buffer') end) +map("n", "ghr", function() vim.api.nvim_command('Gitsigns reset_hunk') end) +map("n", "ghp", function() vim.api.nvim_command('Gitsigns preview_hunk') end) + +vim.api.nvim_create_user_command('CopyRelPath', function () copy_rel_path() end, {}) +vim.api.nvim_create_user_command('CopyAbsPath', copy_abs_path, {}) +vim.api.nvim_create_user_command('CopyRelPathWithLine', copy_rel_path_with_line, {}) +vim.api.nvim_create_user_command('CopyAbsPathWithLine', copy_abs_path_with_line, {}) + +vim.api.nvim_create_user_command('ReverseLinesOder', function () + -- https://superuser.com/questions/189947/how-do-i-reverse-selected-lines-order-in-vim + -- step 1: select lines + -- 2: hit : + -- 3: type !tac + -- 4: profit + print("select lines : then !tac") +end, {}) + +-- PATCH: in order to address the message: +-- vim.treesitter.query.get_query() is deprecated, use vim.treesitter.query.get() instead. :help deprecated +-- This feature will be removed in Nvim version 0.10 +local orig_notify = vim.notify +local filter_notify = function(text, level, opts) + -- more specific to this case + if type(text) == "string" and (string.find(text, "get_query", 1, true) or string.find(text, "get_node_text", 1, true)) then + -- for all deprecated and stack trace warnings + -- if type(text) == "string" and (string.find(text, ":help deprecated", 1, true) or string.find(text, "stack trace", 1, true)) then + return + end + orig_notify(text, level, opts) +end +vim.notify = filter_notify + +-- Check for POPEQUER notebook env var +-- launch the popequer lua file +local popequer_enabled = str2bool(os.getenv("POPEQUER_ENABLED")) +if popequer_enabled then + require "popequer" +end + +vim.cmd("set wrap") diff --git a/nvim/lua/popequer.lua b/nvim/lua/popequer.lua new file mode 100644 index 0000000..4ce7140 --- /dev/null +++ b/nvim/lua/popequer.lua @@ -0,0 +1,9 @@ +print("WOOWOWO! Popequer enabled from dedicated file!!!!") + +-- modify neotree config to add custom command + +vim.api.nvim_create_user_command('PopequerMakeNote', function () + -- get the user current working directory opened on Neotree +end, {}) + +vim.cmd("set autowriteall") diff --git a/nvim/lua/popequer/init.lua b/nvim/lua/popequer/init.lua new file mode 100644 index 0000000..f24c6bc --- /dev/null +++ b/nvim/lua/popequer/init.lua @@ -0,0 +1,19 @@ +local builtin = {} + +-- Ref: https://github.com/tjdevries/lazy.nvim +local function require_on_exported_call(mod) + return setmetatable({}, { + __index = function(_, picker) + return function(...) + return require(mod)[picker](...) + end + end, + }) +end + +builtin.git_status = require_on_exported_call("pickers").files + + +builtin = apply_config(builtin) +return builtin + diff --git a/nvim/lua/popequer/pickers.lua b/nvim/lua/popequer/pickers.lua new file mode 100644 index 0000000..ab70eb6 --- /dev/null +++ b/nvim/lua/popequer/pickers.lua @@ -0,0 +1,141 @@ +local actions = require "telescope.actions" +local action_state = require "telescope.actions.state" +local finders = require "telescope.finders" +local make_entry = require "telescope.make_entry" +local operators = require "telescope.operators" +local pickers = require "telescope.pickers" +local previewers = require "telescope.previewers" +local utils = require "telescope.utils" +local entry_display = require "telescope.pickers.entry_display" +local strings = require "plenary.strings" +local Path = require "plenary.path" + +local conf = require("telescope.config").values +local git_command = utils.__git_command + +local ppq_pickers = {} + +local get_git_command_output = function(args, opts) + return utils.get_os_command_output(git_command(args, opts), opts.cwd) +end + +ppq_pickers.files = function(opts) + if opts.is_bare then + utils.notify("builtin.git_files", { + msg = "This operation must be run in a work tree", + level = "ERROR", + }) + return + end + + local show_untracked = vim.F.if_nil(opts.show_untracked, false) + local recurse_submodules = vim.F.if_nil(opts.recurse_submodules, false) + if show_untracked and recurse_submodules then + utils.notify("builtin.git_files", { + msg = "Git does not support both --others and --recurse-submodules", + level = "ERROR", + }) + return + end + + -- By creating the entry maker after the cwd options, + -- we ensure the maker uses the cwd options when being created. + opts.entry_maker = vim.F.if_nil(opts.entry_maker, make_entry.gen_from_file(opts)) + opts.git_command = vim.F.if_nil(opts.git_command, git_command({ "ls-files", "--exclude-standard", "--cached" }, opts)) + + pickers + .new(opts, { + prompt_title = "Git Files", + finder = finders.new_oneshot_job( + vim.tbl_flatten { + opts.git_command, + show_untracked and "--others" or nil, + recurse_submodules and "--recurse-submodules" or nil, + }, + opts + ), + previewer = conf.file_previewer(opts), + sorter = conf.file_sorter(opts), + }) + :find() +end + +local get_current_buf_line = function(winnr) + local lnum = vim.api.nvim_win_get_cursor(winnr)[1] + return vim.trim(vim.api.nvim_buf_get_lines(vim.api.nvim_win_get_buf(winnr), lnum - 1, lnum, false)[1]) +end + +local try_worktrees = function(opts) + local worktrees = conf.git_worktrees + + if vim.tbl_isarray(worktrees) then + for _, wt in ipairs(worktrees) do + if vim.startswith(opts.cwd, wt.toplevel) then + opts.toplevel = wt.toplevel + opts.gitdir = wt.gitdir + if opts.use_git_root then + opts.cwd = wt.toplevel + end + return + end + end + end + + error(opts.cwd .. " is not a git directory") +end + +local current_path_toplevel = function() + local gitdir = vim.fn.finddir(".git", vim.fn.expand "%:p" .. ";") + if gitdir == "" then + return nil + end + return Path:new(gitdir):parent():absolute() +end + +local set_opts_cwd = function(opts) + opts.use_git_root = vim.F.if_nil(opts.use_git_root, true) + if opts.cwd then + opts.cwd = vim.fn.expand(opts.cwd) + elseif opts.use_file_path then + opts.cwd = current_path_toplevel() + if not opts.cwd then + opts.cwd = vim.fn.expand "%:p:h" + try_worktrees(opts) + return + end + else + opts.cwd = vim.loop.cwd() + end + + local toplevel, ret = utils.get_os_command_output({ "git", "rev-parse", "--show-toplevel" }, opts.cwd) + + if ret ~= 0 then + local in_worktree = utils.get_os_command_output({ "git", "rev-parse", "--is-inside-work-tree" }, opts.cwd) + local in_bare = utils.get_os_command_output({ "git", "rev-parse", "--is-bare-repository" }, opts.cwd) + + if in_worktree[1] ~= "true" and in_bare[1] ~= "true" then + try_worktrees(opts) + elseif in_worktree[1] ~= "true" and in_bare[1] == "true" then + opts.is_bare = true + end + else + if opts.use_git_root then + opts.cwd = toplevel[1] + end + end +end + +local function apply_checks(mod) + for k, v in pairs(mod) do + mod[k] = function(opts) + opts = vim.F.if_nil(opts, {}) + + set_opts_cwd(opts) + v(opts) + end + end + + return mod +end + +return apply_checks(ppq_pickers)