4-dev.lua

  1-- Dev
  2-- Things you actively use for coding.
  3
  4--    Sections:
  5--       ## SNIPPETS
  6--       -> luasnip                        [snippet engine]
  7--       -> friendly-snippets              [snippet templates]
  8
  9--       ## GIT
 10--       -> gitsigns.nvim                  [git hunks]
 11--       -> fugitive.vim                   [git commands]
 12
 13--       ## ANALYZER
 14--       -> aerial.nvim                    [symbols tree]
 15--       -> litee-calltree.nvim            [calltree]
 16
 17--       ## CODE DOCUMENTATION
 18--       -> dooku.nvim                     [html doc generator]
 19--       -> markdown-preview.nvim          [markdown previewer]
 20--       -> markmap.nvim                   [markdown mindmap]
 21
 22--       ## ARTIFICIAL INTELLIGENCE
 23--       -> neural                         [chatgpt code generator]
 24--       -> copilot                        [github code suggestions]
 25--       -> guess-indent                   [guess-indent]
 26
 27--       ## COMPILER
 28--       -> compiler.nvim                  [compiler]
 29--       -> overseer.nvim                  [task runner]
 30
 31--       ## DEBUGGER
 32--       -> nvim-dap                       [debugger]
 33
 34--       ## TESTING
 35--       -> neotest.nvim                   [unit testing]
 36--       -> nvim-coverage                  [code coverage]
 37
 38--       ## LANGUAGE IMPROVEMENTS
 39--       -> guttentags_plus                [auto generate C/C++ tags]
 40
 41local is_windows = vim.fn.has('win32') == 1 -- true if on windows
 42
 43return {
 44  --  SNIPPETS ----------------------------------------------------------------
 45  --  Vim Snippets engine  [snippet engine] + [snippet templates]
 46  --  https://github.com/L3MON4D3/LuaSnip
 47  --  https://github.com/rafamadriz/friendly-snippets
 48  {
 49    "L3MON4D3/LuaSnip",
 50    build = not is_windows and "make install_jsregexp" or nil,
 51    dependencies = {
 52      "rafamadriz/friendly-snippets",
 53      "zeioth/NormalSnippets",
 54      "benfowler/telescope-luasnip.nvim",
 55    },
 56    event = "User BaseFile",
 57    opts = {
 58      history = true,
 59      delete_check_events = "TextChanged",
 60      region_check_events = "CursorMoved",
 61    },
 62    config = function(_, opts)
 63      if opts then require("luasnip").config.setup(opts) end
 64      vim.tbl_map(
 65        function(type) require("luasnip.loaders.from_" .. type).lazy_load() end,
 66        { "vscode", "snipmate", "lua" }
 67      )
 68      -- friendly-snippets - enable standardized comments snippets
 69      require("luasnip").filetype_extend("typescript", { "tsdoc" })
 70      require("luasnip").filetype_extend("javascript", { "jsdoc" })
 71      require("luasnip").filetype_extend("lua", { "luadoc" })
 72      require("luasnip").filetype_extend("python", { "pydoc" })
 73      require("luasnip").filetype_extend("rust", { "rustdoc" })
 74      require("luasnip").filetype_extend("cs", { "csharpdoc" })
 75      require("luasnip").filetype_extend("java", { "javadoc" })
 76      require("luasnip").filetype_extend("c", { "cdoc" })
 77      require("luasnip").filetype_extend("cpp", { "cppdoc" })
 78      require("luasnip").filetype_extend("php", { "phpdoc" })
 79      require("luasnip").filetype_extend("kotlin", { "kdoc" })
 80      require("luasnip").filetype_extend("ruby", { "rdoc" })
 81      require("luasnip").filetype_extend("sh", { "shelldoc" })
 82    end,
 83  },
 84
 85  --  GIT ---------------------------------------------------------------------
 86  --  Git signs [git hunks]
 87  --  https://github.com/lewis6991/gitsigns.nvim
 88  {
 89    "lewis6991/gitsigns.nvim",
 90    enabled = vim.fn.executable "git" == 1,
 91    event = "User BaseGitFile",
 92    opts = function()
 93      local get_icon = require("base.utils").get_icon
 94      return {
 95        max_file_length = vim.g.big_file.lines,
 96        signs = {
 97          add = { text = get_icon("GitSign") },
 98          change = { text = get_icon("GitSign") },
 99          delete = { text = get_icon("GitSign") },
100          topdelete = { text = get_icon("GitSign") },
101          changedelete = { text = get_icon("GitSign") },
102          untracked = { text = get_icon("GitSign") },
103        },
104      }
105    end
106  },
107
108  --  Git fugitive mergetool + [git commands]
109  --  https://github.com/lewis6991/gitsigns.nvim
110  --  PR needed: Setup keymappings to move quickly when using this feature.
111  --
112  --  We only want this plugin to use it as mergetool like "git mergetool".
113  --  To enable this feature, add this  to your global .gitconfig:
114  --
115  --  [mergetool "fugitive"]
116  --  	cmd = nvim -c \"Gvdiffsplit!\" \"$MERGED\"
117  --  [merge]
118  --  	tool = fugitive
119  --  [mergetool]
120  --  	keepBackup = false
121  {
122    "tpope/vim-fugitive",
123    enabled = vim.fn.executable "git" == 1,
124    dependencies = { "tpope/vim-rhubarb" },
125    cmd = {
126      "Gvdiffsplit",
127      "Gdiffsplit",
128      "Gedit",
129      "Gsplit",
130      "Gread",
131      "Gwrite",
132      "Ggrep",
133      "GMove",
134      "GRename",
135      "GDelete",
136      "GRemove",
137      "GBrowse",
138      "Git",
139      "Gstatus",
140    },
141    config = function()
142      -- NOTE: On vimplugins we use config instead of opts.
143      vim.g.fugitive_no_maps = 1
144    end,
145  },
146
147  --  ANALYZER ----------------------------------------------------------------
148  --  [symbols tree]
149  --  https://github.com/stevearc/aerial.nvim
150  {
151    "stevearc/aerial.nvim",
152    event = "User BaseFile",
153    opts = {
154      filter_kind = { -- Symbols that will appear on the tree
155        -- "Class",
156        "Constructor",
157        "Enum",
158        "Function",
159        "Interface",
160        -- "Module",
161        "Method",
162        -- "Struct",
163      },
164      open_automatic = false, -- Open if the buffer is compatible
165      autojump = true,
166      link_folds_to_tree = false,
167      link_tree_to_folds = false,
168      attach_mode = "global",
169      backends = { "lsp", "treesitter", "markdown", "man" },
170      disable_max_lines = vim.g.big_file.lines,
171      disable_max_size = vim.g.big_file.size,
172      layout = {
173        min_width = 28,
174        default_direction = "right",
175        placement = "edge",
176      },
177      show_guides = true,
178      guides = {
179        mid_item = "",
180        last_item = "",
181        nested_top = "",
182        whitespace = "  ",
183      },
184      keymaps = {
185        ["[y"] = "actions.prev",
186        ["]y"] = "actions.next",
187        ["[Y"] = "actions.prev_up",
188        ["]Y"] = "actions.next_up",
189        ["{"] = false,
190        ["}"] = false,
191        ["[["] = false,
192        ["]]"] = false,
193      },
194    },
195    config = function(_, opts)
196      require("aerial").setup(opts)
197      -- HACK: The first time you open aerial on a session, close all folds.
198      vim.api.nvim_create_autocmd({"FileType", "BufEnter"}, {
199        desc = "Aerial: When aerial is opened, close all its folds.",
200        callback = function()
201          local is_aerial = vim.bo.filetype == "aerial"
202          local is_ufo_available = require("base.utils").is_available("nvim-ufo")
203          if is_ufo_available and is_aerial and vim.b.new_aerial_session == nil then
204            vim.b.new_aerial_session = false
205            require("aerial").tree_set_collapse_level(0, 0)
206          end
207        end,
208      })
209    end
210  },
211
212  -- Litee calltree [calltree]
213  -- https://github.com/ldelossa/litee.nvim
214  -- https://github.com/ldelossa/litee-calltree.nvim
215  -- press ? inside the panel to show help.
216  {
217    'ldelossa/litee.nvim',
218    event = "User BaseFile",
219    opts = {
220      notify = { enabled = false },
221      panel = {
222          orientation = "bottom",
223          panel_size = 10,
224      },
225    },
226    config = function(_, opts)
227      require('litee.lib').setup(opts)
228    end
229  },
230  {
231    'ldelossa/litee-calltree.nvim',
232    dependencies = 'ldelossa/litee.nvim',
233    event = "User BaseFile",
234    opts = {
235      on_open = "panel", -- or popout
236      map_resize_keys = false,
237      keymaps = {
238        expand = "<CR>",
239        collapse = "c",
240        collapse_all = "C",
241        jump = "<C-CR>"
242      },
243    },
244    config = function(_, opts)
245      require('litee.calltree').setup(opts)
246
247      -- Highlight only while on calltree
248      vim.api.nvim_create_autocmd({ "WinEnter" }, {
249        desc = "Clear highlights when leaving calltree + UX improvements.",
250        callback = function()
251          vim.defer_fn(function()
252            if vim.bo.filetype == "calltree" then
253              vim.wo.colorcolumn = "0"
254              vim.wo.foldcolumn = "0"
255              vim.cmd("silent! PinBuffer") -- stickybuf.nvim
256              vim.cmd("silent! hi LTSymbolJump ctermfg=015 ctermbg=110 cterm=italic,bold,underline guifg=#464646 guibg=#87afd7 gui=italic,bold")
257              vim.cmd("silent! hi LTSymbolJumpRefs ctermfg=015 ctermbg=110 cterm=italic,bold,underline guifg=#464646 guibg=#87afd7 gui=italic,bold")
258            else
259              vim.cmd("silent! highlight clear LTSymbolJump")
260              vim.cmd("silent! highlight clear LTSymbolJumpRefs")
261            end
262          end, 100)
263        end
264      })
265    end
266  },
267
268  --  CODE DOCUMENTATION ------------------------------------------------------
269  --  dooku.nvim [html doc generator]
270  --  https://github.com/zeioth/dooku.nvim
271  {
272    "zeioth/dooku.nvim",
273    cmd = {
274      "DookuGenerate",
275      "DookuOpen",
276      "DookuAutoSetup"
277    },
278    opts = {},
279  },
280
281  --  [markdown previewer]
282  --  https://github.com/iamcco/markdown-preview.nvim
283  --  Note: If you change the build command, wipe ~/.local/data/nvim/lazy
284  {
285    "iamcco/markdown-preview.nvim",
286    build = function() vim.fn["mkdp#util#install"]() end,
287    ft = { "markdown" },
288    cmd = {
289      "MarkdownPreview",
290      "MarkdownPreviewStop",
291      "MarkdownPreviewToggle",
292    },
293  },
294
295  --  [markdown markmap]
296  --  https://github.com/zeioth/markmap.nvim
297  --  Important: Make sure you have yarn in your PATH before running markmap.
298  {
299    "zeioth/markmap.nvim",
300    build = "yarn global add markmap-cli",
301    cmd = { "MarkmapOpen", "MarkmapSave", "MarkmapWatch", "MarkmapWatchStop" },
302    config = function(_, opts) require("markmap").setup(opts) end,
303  },
304
305  --  ARTIFICIAL INTELLIGENCE  -------------------------------------------------
306  --  neural [chatgpt code generator]
307  --  https://github.com/dense-analysis/neural
308  --
309  --  NOTE: In order for this plugin to work, you will have to set
310  --        the next env var in your OS:
311  --        OPENAI_API_KEY="my_key_here"
312  {
313    "dense-analysis/neural",
314    cmd = { "Neural" },
315    config = function()
316      require("neural").setup {
317        source = {
318          openai = {
319            api_key = vim.env.OPENAI_API_KEY,
320          },
321        },
322        ui = {
323          prompt_icon = ">",
324        },
325      }
326    end,
327  },
328
329  --  copilot [github code suggestions]
330  --  https://github.com/github/copilot.vim
331  --  As alternative to chatgpt, you can use copilot uncommenting this.
332  --  Then you must run :Copilot setup
333  -- {
334  --   "github/copilot.vim",
335  --   event = "User BaseFile"
336  -- },
337  -- copilot-cmp
338  -- https://github.com/zbirenbaum/copilot-cmp
339  -- {
340  --   "zbirenbaum/copilot-cmp",
341  --   opts = { suggesion = { enabled = false }, panel = { enabled = false } },
342  --   config = function (_, opts) require("copilot_cmp").setup(opts) end
343  -- },
344
345  -- [guess-indent]
346  -- https://github.com/NMAC427/guess-indent.nvim
347  -- Note that this plugin won't autoformat the code.
348  -- It just set the buffer options to tabluate in a certain way.
349  {
350    "NMAC427/guess-indent.nvim",
351    event = "User BaseFile",
352    opts = {}
353  },
354
355  --  COMPILER ----------------------------------------------------------------
356  --  compiler.nvim [compiler]
357  --  https://github.com/zeioth/compiler.nvim
358  {
359    "zeioth/compiler.nvim",
360    cmd = {
361      "CompilerOpen",
362      "CompilerToggleResults",
363      "CompilerRedo",
364      "CompilerStop"
365    },
366    dependencies = { "stevearc/overseer.nvim" },
367    opts = {},
368  },
369
370  --  overseer [task runner]
371  --  https://github.com/stevearc/overseer.nvim
372  --  If you need to close a task immediately:
373  --  press ENTER in the output menu on the task you wanna close.
374  {
375    "stevearc/overseer.nvim",
376    cmd = {
377      "OverseerOpen",
378      "OverseerClose",
379      "OverseerToggle",
380      "OverseerSaveBundle",
381      "OverseerLoadBundle",
382      "OverseerDeleteBundle",
383      "OverseerRunCmd",
384      "OverseerRun",
385      "OverseerInfo",
386      "OverseerBuild",
387      "OverseerQuickAction",
388      "OverseerTaskAction",
389      "OverseerClearCache"
390    },
391    opts = {
392     task_list = { -- the window that shows the results.
393        direction = "bottom",
394        min_height = 25,
395        max_height = 25,
396        default_detail = 1,
397      },
398      -- component_aliases = {
399      --   default = {
400      --     -- Behaviors that will apply to all tasks.
401      --     "on_exit_set_status",                   -- don't delete this one.
402      --     "on_output_summarize",                  -- show last line on the list.
403      --     "display_duration",                     -- display duration.
404      --     "on_complete_notify",                   -- notify on task start.
405      --     "open_output",                          -- focus last executed task.
406      --     { "on_complete_dispose", timeout=300 }, -- dispose old tasks.
407      --   },
408      -- },
409    },
410  },
411
412  --  DEBUGGER ----------------------------------------------------------------
413  --  Debugger alternative to vim-inspector [debugger]
414  --  https://github.com/mfussenegger/nvim-dap
415  --  Here we configure the adapter+config of every debugger.
416  --  Debuggers don't have system dependencies, you just install them with mason.
417  --  We currently ship most of them with nvim.
418  {
419    "mfussenegger/nvim-dap",
420    enabled = vim.fn.has "win32" == 0,
421    event = "User BaseFile",
422    config = function()
423      local dap = require("dap")
424
425      -- C#
426      dap.adapters.coreclr = {
427        type = 'executable',
428        command = vim.fn.stdpath('data') .. '/mason/bin/netcoredbg',
429        args = { '--interpreter=vscode' }
430      }
431      dap.configurations.cs = {
432        {
433          type = "coreclr",
434          name = "launch - netcoredbg",
435          request = "launch",
436          program = function() -- Ask the user what executable wants to debug
437            return vim.fn.input('Path to dll: ', vim.fn.getcwd() .. '/bin/Program.exe', 'file')
438          end,
439        },
440      }
441
442      -- F#
443      dap.configurations.fsharp = dap.configurations.cs
444
445      -- Visual basic dotnet
446      dap.configurations.vb = dap.configurations.cs
447
448      -- Java
449      -- Note: The java debugger jdtls is automatically spawned and configured
450      -- by the plugin 'nvim-java' in './3-dev-core.lua'.
451
452      -- Python
453      dap.adapters.python = {
454        type = 'executable',
455        command = vim.fn.stdpath('data') .. '/mason/packages/debugpy/venv/bin/python',
456        args = { '-m', 'debugpy.adapter' },
457      }
458      dap.configurations.python = {
459        {
460          type = "python",
461          request = "launch",
462          name = "Launch file",
463          program = "${file}", -- This configuration will launch the current file if used.
464        },
465      }
466
467      -- Lua
468      dap.adapters.nlua = function(callback, config)
469        callback({ type = 'server', host = config.host or "127.0.0.1", port = config.port or 8086 })
470      end
471      dap.configurations.lua = {
472        {
473          type = 'nlua',
474          request = 'attach',
475          name = "Attach to running Neovim instance",
476          program = function() pcall(require "osv".launch({ port = 8086 })) end,
477        }
478      }
479
480      -- C
481      dap.adapters.codelldb = {
482        type = 'server',
483        port = "${port}",
484        executable = {
485          command = vim.fn.stdpath('data') .. '/mason/bin/codelldb',
486          args = { "--port", "${port}" },
487          detached = function() if is_windows then return false else return true end end,
488        }
489      }
490      dap.configurations.c = {
491        {
492          name = 'Launch',
493          type = 'codelldb',
494          request = 'launch',
495          program = function() -- Ask the user what executable wants to debug
496            return vim.fn.input('Path to executable: ', vim.fn.getcwd() .. '/bin/program', 'file')
497          end,
498          cwd = '${workspaceFolder}',
499          stopOnEntry = false,
500          args = {},
501        },
502      }
503
504      -- C++
505      dap.configurations.cpp = dap.configurations.c
506
507      -- Rust
508      dap.configurations.rust = {
509        {
510          name = 'Launch',
511          type = 'codelldb',
512          request = 'launch',
513          program = function() -- Ask the user what executable wants to debug
514            return vim.fn.input('Path to executable: ', vim.fn.getcwd() .. '/bin/program', 'file')
515          end,
516          cwd = '${workspaceFolder}',
517          stopOnEntry = false,
518          args = {},
519          initCommands = function() -- add rust types support (optional)
520            -- Find out where to look for the pretty printer Python module
521            local rustc_sysroot = vim.fn.trim(vim.fn.system('rustc --print sysroot'))
522
523            local script_import = 'command script import "' .. rustc_sysroot .. '/lib/rustlib/etc/lldb_lookup.py"'
524            local commands_file = rustc_sysroot .. '/lib/rustlib/etc/lldb_commands'
525
526            local commands = {}
527            local file = io.open(commands_file, 'r')
528            if file then
529              for line in file:lines() do
530                table.insert(commands, line)
531              end
532              file:close()
533            end
534            table.insert(commands, 1, script_import)
535
536            return commands
537          end,
538        }
539      }
540
541      -- Go
542      -- Requires:
543      -- * You have initialized your module with 'go mod init module_name'.
544      -- * You :cd your project before running DAP.
545      dap.adapters.delve = {
546        type = 'server',
547        port = '${port}',
548        executable = {
549          command = vim.fn.stdpath('data') .. '/mason/packages/delve/dlv',
550          args = { 'dap', '-l', '127.0.0.1:${port}' },
551        }
552      }
553      dap.configurations.go = {
554        {
555          type = "delve",
556          name = "Compile module and debug this file",
557          request = "launch",
558          program = "./${relativeFileDirname}",
559        },
560        {
561          type = "delve",
562          name = "Compile module and debug this file (test)",
563          request = "launch",
564          mode = "test",
565          program = "./${relativeFileDirname}"
566        },
567      }
568
569      -- Dart / Flutter
570      dap.adapters.dart = {
571        type = 'executable',
572        command = vim.fn.stdpath('data') .. '/mason/bin/dart-debug-adapter',
573        args = { 'dart' }
574      }
575      dap.adapters.flutter = {
576        type = 'executable',
577        command = vim.fn.stdpath('data') .. '/mason/bin/dart-debug-adapter',
578        args = { 'flutter' }
579      }
580      dap.configurations.dart = {
581        {
582          type = "dart",
583          request = "launch",
584          name = "Launch dart",
585          dartSdkPath = "/opt/flutter/bin/cache/dart-sdk/", -- ensure this is correct
586          flutterSdkPath = "/opt/flutter",                  -- ensure this is correct
587          program = "${workspaceFolder}/lib/main.dart",     -- ensure this is correct
588          cwd = "${workspaceFolder}",
589        },
590        {
591          type = "flutter",
592          request = "launch",
593          name = "Launch flutter",
594          dartSdkPath = "/opt/flutter/bin/cache/dart-sdk/", -- ensure this is correct
595          flutterSdkPath = "/opt/flutter",                  -- ensure this is correct
596          program = "${workspaceFolder}/lib/main.dart",     -- ensure this is correct
597          cwd = "${workspaceFolder}",
598        }
599      }
600
601      -- Kotlin
602      -- Kotlin projects have very weak project structure conventions.
603      -- You must manually specify what the project root and main class are.
604      dap.adapters.kotlin = {
605        type = 'executable',
606        command = vim.fn.stdpath('data') .. '/mason/bin/kotlin-debug-adapter',
607      }
608      dap.configurations.kotlin = {
609        {
610          type = 'kotlin',
611          request = 'launch',
612          name = 'Launch kotlin program',
613          projectRoot = "${workspaceFolder}/app",     -- ensure this is correct
614          mainClass = "AppKt",                        -- ensure this is correct
615        },
616      }
617
618      -- Javascript / Typescript (firefox)
619      dap.adapters.firefox = {
620        type = 'executable',
621        command = vim.fn.stdpath('data') .. '/mason/bin/firefox-debug-adapter',
622      }
623      dap.configurations.typescript = {
624        {
625          name = 'Debug with Firefox',
626          type = 'firefox',
627          request = 'launch',
628          reAttach = true,
629          url = 'http://localhost:4200', -- Write the actual URL of your project.
630          webRoot = '${workspaceFolder}',
631          firefoxExecutable = '/usr/bin/firefox'
632        }
633      }
634      dap.configurations.javascript = dap.configurations.typescript
635      dap.configurations.javascriptreact = dap.configurations.typescript
636      dap.configurations.typescriptreact = dap.configurations.typescript
637
638      -- Javascript / Typescript (chromium)
639      -- If you prefer to use this adapter, comment the firefox one.
640      -- But to use this adapter, you must manually run one of these two, first:
641      -- * chromium --remote-debugging-port=9222 --user-data-dir=remote-profile
642      -- * google-chrome-stable --remote-debugging-port=9222 --user-data-dir=remote-profile
643      -- After starting the debugger, you must manually reload page to get all features.
644      -- dap.adapters.chrome = {
645      --  type = 'executable',
646      --  command = vim.fn.stdpath('data')..'/mason/bin/chrome-debug-adapter',
647      -- }
648      -- dap.configurations.typescript = {
649      --  {
650      --   name = 'Debug with Chromium',
651      --   type = "chrome",
652      --   request = "attach",
653      --   program = "${file}",
654      --   cwd = vim.fn.getcwd(),
655      --   sourceMaps = true,
656      --   protocol = "inspector",
657      --   port = 9222,
658      --   webRoot = "${workspaceFolder}"
659      --  }
660      -- }
661      -- dap.configurations.javascript = dap.configurations.typescript
662      -- dap.configurations.javascriptreact = dap.configurations.typescript
663      -- dap.configurations.typescriptreact = dap.configurations.typescript
664
665      -- PHP
666      dap.adapters.php = {
667        type = 'executable',
668        command = vim.fn.stdpath("data") .. '/mason/bin/php-debug-adapter',
669      }
670      dap.configurations.php = {
671        {
672          type = 'php',
673          request = 'launch',
674          name = 'Listen for Xdebug',
675          port = 9000
676        }
677      }
678
679      -- Shell
680      dap.adapters.bashdb = {
681        type = 'executable',
682        command = vim.fn.stdpath("data") .. '/mason/packages/bash-debug-adapter/bash-debug-adapter',
683        name = 'bashdb',
684      }
685      dap.configurations.sh = {
686        {
687          type = 'bashdb',
688          request = 'launch',
689          name = "Launch file",
690          showDebugOutput = true,
691          pathBashdb = vim.fn.stdpath("data") .. '/mason/packages/bash-debug-adapter/extension/bashdb_dir/bashdb',
692          pathBashdbLib = vim.fn.stdpath("data") .. '/mason/packages/bash-debug-adapter/extension/bashdb_dir',
693          trace = true,
694          file = "${file}",
695          program = "${file}",
696          cwd = '${workspaceFolder}',
697          pathCat = "cat",
698          pathBash = "/bin/bash",
699          pathMkfifo = "mkfifo",
700          pathPkill = "pkill",
701          args = {},
702          env = {},
703          terminalKind = "integrated",
704        }
705      }
706
707      -- Elixir
708      dap.adapters.mix_task = {
709        type = 'executable',
710        command = vim.fn.stdpath("data") .. '/mason/bin/elixir-ls-debugger',
711        args = {}
712      }
713      dap.configurations.elixir = {
714        {
715          type = "mix_task",
716          name = "mix test",
717          task = 'test',
718          taskArgs = { "--trace" },
719          request = "launch",
720          startApps = true, -- for Phoenix projects
721          projectDir = "${workspaceFolder}",
722          requireFiles = {
723            "test/**/test_helper.exs",
724            "test/**/*_test.exs"
725          }
726        },
727      }
728    end, -- of dap config
729    dependencies = {
730      "rcarriga/nvim-dap-ui",
731      "rcarriga/cmp-dap",
732      "jay-babu/mason-nvim-dap.nvim",
733      "jbyuki/one-small-step-for-vimkind",
734      "nvim-java/nvim-java",
735    },
736  },
737
738  -- nvim-dap-ui [dap ui]
739  -- https://github.com/mfussenegger/nvim-dap-ui
740  -- user interface for the debugger dap
741  {
742    "rcarriga/nvim-dap-ui",
743    dependencies = { "nvim-neotest/nvim-nio" },
744    opts = { floating = { border = "rounded" } },
745    config = function(_, opts)
746      local dap, dapui = require("dap"), require("dapui")
747      dap.listeners.after.event_initialized["dapui_config"] = function(
748      )
749        dapui.open()
750      end
751      dap.listeners.before.event_terminated["dapui_config"] = function(
752      )
753        dapui.close()
754      end
755      dap.listeners.before.event_exited["dapui_config"] = function()
756        dapui.close()
757      end
758      dapui.setup(opts)
759    end,
760  },
761
762  -- cmp-dap [dap autocomplete]
763  -- https://github.com/mfussenegger/cmp-dap
764  -- Enables autocomplete for the debugger dap.
765  {
766    "rcarriga/cmp-dap",
767    dependencies = { "nvim-cmp" },
768    config = function()
769      require("cmp").setup.filetype(
770        { "dap-repl", "dapui_watches", "dapui_hover" },
771        {
772          sources = {
773            { name = "dap" },
774          },
775        }
776      )
777    end,
778  },
779
780  --  TESTING -----------------------------------------------------------------
781  --  Run tests inside of nvim [unit testing]
782  --  https://github.com/nvim-neotest/neotest
783  --
784  --
785  --  MANUAL:
786  --  -- Unit testing:
787  --  To tun an unit test you can run any of these commands:
788  --
789  --    :Neotest run      -- Runs the nearest test to the cursor.
790  --    :Neotest stop     -- Stop the nearest test to the cursor.
791  --    :Neotest run file -- Run all tests in the file.
792  --
793  --  -- E2e and Test Suite
794  --  Normally you will prefer to open your e2e framework GUI outside of nvim.
795  --  But you have the next commands in ../base/3-autocmds.lua:
796  --
797  --    :TestNodejs    -- Run all tests for this nodejs project.
798  --    :TestNodejsE2e -- Run the e2e tests/suite for this nodejs project.
799  {
800    "nvim-neotest/neotest",
801    cmd = { "Neotest" },
802    dependencies = {
803      "sidlatau/neotest-dart",
804      "Issafalcon/neotest-dotnet",
805      "jfpedroza/neotest-elixir",
806      "nvim-neotest/neotest-go",
807      "rcasia/neotest-java",
808      "nvim-neotest/neotest-jest",
809      "olimorris/neotest-phpunit",
810      "nvim-neotest/neotest-python",
811      "rouge8/neotest-rust",
812      "lawrence-laz/neotest-zig",
813    },
814    opts = function()
815      return {
816        -- your neotest config here
817        adapters = {
818          require("neotest-dart"),
819          require("neotest-dotnet"),
820          require("neotest-elixir"),
821          require("neotest-go"),
822          require("neotest-java"),
823          require("neotest-jest"),
824          require("neotest-phpunit"),
825          require("neotest-python"),
826          require("neotest-rust"),
827          require("neotest-zig"),
828        },
829      }
830    end,
831    config = function(_, opts)
832      -- get neotest namespace (api call creates or returns namespace)
833      local neotest_ns = vim.api.nvim_create_namespace "neotest"
834      vim.diagnostic.config({
835        virtual_text = {
836          format = function(diagnostic)
837            local message = diagnostic.message:gsub("\n", " "):gsub("\t", " "):gsub("%s+", " "):gsub("^%s+", "")
838            return message
839          end,
840        },
841      }, neotest_ns)
842      require("neotest").setup(opts)
843    end,
844  },
845
846  --  Shows a float panel with the [code coverage]
847  --  https://github.com/andythigpen/nvim-coverage
848  --
849  --  Your project must generate coverage/lcov.info for this to work.
850  --
851  --  On jest, make sure your packages.json file has this:
852  --  "tests": "jest --coverage"
853  --
854  --  If you use other framework or language, refer to nvim-coverage docs:
855  --  https://github.com/andythigpen/nvim-coverage/blob/main/doc/nvim-coverage.txt
856  {
857    "zeioth/nvim-coverage", -- Our fork until all our PRs are merged.
858    cmd = {
859      "Coverage",
860      "CoverageLoad",
861      "CoverageLoadLcov",
862      "CoverageShow",
863      "CoverageHide",
864      "CoverageToggle",
865      "CoverageClear",
866      "CoverageSummary",
867    },
868    dependencies = { "nvim-lua/plenary.nvim" },
869    opts = {
870      summary = {
871        min_coverage = 80.0, -- passes if higher than
872      },
873    },
874    config = function(_, opts) require("coverage").setup(opts) end,
875  },
876
877  -- LANGUAGE IMPROVEMENTS ----------------------------------------------------
878  -- guttentags_plus [auto generate C/C++ tags]
879  -- https://github.com/skywind3000/gutentags_plus
880  -- This plugin is necessary for using <C-]> (go to ctag).
881  {
882    "skywind3000/gutentags_plus",
883    ft = { "c", "cpp" },
884    dependencies = { "ludovicchabant/vim-gutentags" },
885    config = function()
886      -- NOTE: On vimplugins we use config instead of opts.
887      vim.g.gutentags_plus_nomap = 1
888      vim.g.gutentags_resolve_symlinks = 1
889      vim.g.gutentags_cache_dir = vim.fn.stdpath "cache" .. "/tags"
890      vim.api.nvim_create_autocmd("FileType", {
891        desc = "Auto generate C/C++ tags",
892        callback = function()
893          local is_c = vim.bo.filetype == "c" or vim.bo.filetype == "cpp"
894          if is_c then vim.g.gutentags_enabled = 1
895          else vim.g.gutentags_enabled = 0 end
896        end,
897      })
898    end,
899  },
900
901} -- end of return