Всего месяц назад я начал настраивать Neovim, сказав себе, что сделаю его своим основным средством редактирования кода. Я и не подозревал, что откушу гораздо больше, чем был готов прожевать. Даже проведя больше месяца с Вимом, я так и не понял, как бросить…

Давайте не будем бить дохлую лошадь: выйти из Vim так же просто, как выполнить :q, но выход из Vim — это совсем другая история. После публикации моего руководства по настройке виртуальной машины Ubuntu и настройке Neovim с нуля я решил добавить еще несколько плагинов. Я никогда не думал, что настройка текстового редактора в моем терминале будет таким классным занятием: добавление различных плагинов, которые я нашел на GitHub, настройка их параметров по своему вкусу и определение того, какие функции показались мне наиболее полезными. С каждым установленным плагином или каждой добавленной раскладкой я говорил себе: Это сделает мою конфигурацию идеальной. После этого мне не нужно будет ничего добавлять.

Конечно, именно в этом заключается ловушка конфигурации Vim: вы думаете, что однажды вы получите идеальную конфигурацию, которая не требует дополнительных плагинов, раскладок или изменений цветовой схемы. Этот день никогда не наступит, и вместо этого вы окажетесь в ловушке огненного ада Vim, где вы навсегда обречены на этот устаревший текстовый редактор на основе терминала на всю вечность, даже после выполнения :q.

Хорошо, это было немного драматизированной гиперболой, но это правда, что «однажды уйдя к Виму, ты никогда не вернешься». Чтобы продемонстрировать, что я имею в виду, давайте взглянем на мою текущую конфигурацию Neovim.

В процессе написания этого сообщения в блоге я, несомненно, внес изменения в свою конфигурацию, поэтому ради последовательности, говоря о моей текущей конфигурации Neovim, это на самом деле просто означает, что я говорю об этой ветке. » моей конфигурации Neovim (7ec9497). Кроме того, этот пост в блоге не будет полностью ограничен моей изолированной конфигурацией Neovim, но также расскажет о некоторых других инструментах, которые я использовал для рисования моего рабочего процесса Linux (кстати, гордый пользователь Ubuntu).

Вот мой путь с Neovim и Linux.

Примечание редактора: теперь, когда я написал всю эту статью (примерное время ее прочтения — ОДИН ЧАС) и просматриваю ее, чтобы внести изменения, я могу подтвердить, что моя конфигурация Neovim значительно изменилась…

Властелин Vims: Братство Emacs

В этом разделе моего путешествия по Neovim я расскажу о конфигурации, подробно описанной в моем предыдущем посте в блоге Neovim.

Мой файл plugins.lua с некоторыми из наиболее важных плагинов:

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

local packer_bootstrap = ensure_packer()

return require('packer').startup(function(use)
  use 'wbthomason/packer.nvim'
  use 'ellisonleao/gruvbox.nvim'
  use 'nvim-tree/nvim-tree.lua'
  use 'nvim-tree/nvim-web-devicons'
  use 'nvim-lualine/lualine.nvim'
  use 'marko-cerovac/material.nvim'
  use 'nvim-treesitter/nvim-treesitter'
  use {
    'nvim-telescope/telescope.nvim',
    tag = '0.1.0',
    requires = { {'nvim-lua/plenary.nvim'} }
  }
  use {
    'williamboman/mason.nvim',
    'williamboman/mason-lspconfig.nvim',
    'neovim/nvim-lspconfig',
  }
  use 'hrsh7th/nvim-cmp'
  use 'hrsh7th/cmp-nvim-lsp'
  use 'L3MON4D3/LuaSnip'
  use 'saadparwaiz1/cmp_luasnip'
  use 'rafamadriz/friendly-snippets'

  -- My plugins here
  -- use 'foo1/bar1.nvim'
  -- use 'foo2/bar2.nvim'

  -- Automatically set up your configuration after cloning packer.nvim
  -- Put this at the end after all plugins
  if packer_bootstrap then
    require('packer').sync()
  end
end)

Мое знакомство с Neovim началось с серии обучающих видеороликов по базовой настройке Neovim, в которых я слепо следовал предоставленным параметрам. И хотя я был в каком-то аду туториалов, дидактические приемы туториалов все же помогли мне немного понять, как настраивать Neovim с помощью плагинов, добавлять раскладки клавиш и настраивать собственные параметры. Я начал с не слишком большого количества настроек, но плагины, которые у меня были, имели решающее значение для любой хорошей конфигурации Neovim:

ЛСП

Возможно, одна из самых важных функций любого редактора кода или IDE. Language Server Protocol (LSP) является чрезвычайно мощным средством, предупреждающим вас о синтаксических ошибках, неиспользуемых локальных переменных, предлагающим завершение кода и т. д. В видеоролике ThePrimeagen о настройке Neovim с нуля даже подчеркивается переход от 0 к LSP, что, несомненно, подразумевает, что LSP является обязательным для Neovim. Хотя есть много способов сделать это, я добился этого с помощью Mason, который управляет серверами LSP, в сочетании с nvim-lspconfig, который имеет несколько конфигураций быстрого запуска для LSP внутри Neovim.

Еще один простой способ быстро настроить LSP — это LSP Zero, целью которого является объединение функций LSP и автозаполнения в один мега-плагин. Вы даже можете использовать LSP Zero для настройки фрагментов кода, что немного углубляется в следующую функцию…

Фрагменты кода

Хотя я только что упомянул дополнения для LSP, эта функция не ограничивается автозавершением имен переменных или функций, которые протокол языкового сервера обнаруживает в другом месте вашего файла. С помощью чего-то вроде комбинации LuaSnip, cmp_luasnip и friendly-snippets вы можете настроить мощную систему автозаполнения сниппетов, которая генерирует тонны скучного шаблонного контента, который никто не хочет писать (вспомните public static void main (String[] args). Когда я впервые Настроил фрагменты кода, я протестировал его, создав фиктивный HTML-файл, и обнаружил, что могу быстро сгенерировать весь шаблон HTML-кода в стиле Emmet всего несколькими нажатиями клавиш, опыт, с которым я был слишком хорошо знаком, работая в VS. Код:

Когда я говорю фрагменты кода для Neovim, это не слишком отличается от расширений фрагментов кода VS, которые вы можете получить на рынке. В VS Code, если вам нужны фрагменты кода React, вы можете установить расширение, такое как фрагменты кода Reactjs, и просто ввести rafce, чтобы создать компонент React, который использует функцию стрелки. Та же логика применима и к Neovim. Все, что вам нужно сделать, это предоставить Neovim исходные фрагменты кода, которые вы хотите. В моем случае я загрузил несколько фрагментов, похожих на VS Code, и включил их через конфигурацию LSP.

completions.lua

local cmp = require('cmp')

require('luasnip.loaders.from_vscode').lazy_load()

cmp.setup({
  mapping = cmp.mapping.preset.insert({
    ['<C-b>'] = cmp.mapping.scroll_docs(-4),
    ['<C-f>'] = cmp.mapping.scroll_docs(4),
    ['<C-o>'] = cmp.mapping.complete(),
    ['<C-e>'] = cmp.mapping.abort(),
    ['<CR>'] = cmp.mapping.confirm({ select = true }),
  }),
  snippet = {
    expand = function(args)
      require('luasnip').lsp_expand(args.body)
    end,
  },
  sources = cmp.config.sources({
    { name = 'nvim_lsp' },
    { name = 'luasnip' },
  }, {
    { name = 'buffer' },
  }),
})

lsp_config.lua

require('mason').setup()
require('mason-lspconfig').setup({
  ensure_installed = { 'lua_ls' }
})

local on_attach = function(_, _)
  vim.keymap.set('n', '<leader>rn', vim.lsp.buf.rename, {})
  vim.keymap.set('n', '<leader>ca', vim.lsp.buf.code_action, {})


  vim.keymap.set('n', 'gd', vim.lsp.buf.definition, {})
  vim.keymap.set('n', 'gi', vim.lsp.buf.implementation, {})
  vim.keymap.set('n', 'gr', require('telescope.builtin').lsp_references, {})
  vim.keymap.set('n', 'K', vim.lsp.buf.hover, {})
end

local capabilities = require('cmp_nvim_lsp').default_capabilities()

require('lspconfig').lua_ls.setup {
  on_attach = on_attach,
  capabilities = capabilities,
  settings = {
    Lua = {
      diagnostics = {
        -- the line below is necessary to ignore annoying Lua LSP for vim variables
        globals = { 'vim' }
      }
    }
  }
}

А с фрагментами кода, возможно, вам больше не придется так сильно биться лицом о клавиатуру! Пусть ваш редактор сделает половину работы (или всю, если вы используете Copilot).

Лесник

Treesitter абсолютно необходим, когда дело доходит до Neovim. Без Treesitter ваша стандартная подсветка синтаксиса Neovim не будет полной. Несмотря на то, что Neovim имеет некоторую базовую подсветку синтаксиса по умолчанию, он может не так много. Treesitter предоставляет невероятно быстрое абстрактное синтаксическое дерево, которое анализирует ваш код, пока вы его редактируете, чтобы обеспечить красивую подсветку синтаксиса, когда вы создаете свои программные шедевры.

Вот сравнение между традиционной подсветкой синтаксиса (слева) и подсветкой синтаксиса на основе Treesitter (справа) из репозитория Treesitter GitHub:

Вы заметите, что при традиционной подсветке синтаксиса слишком много токенов отображается в простом белом тексте (или, в случае светлой темы, это может быть черный текст), что значительно затрудняет различение ключевых слов, функций, имен переменных, и т. д.

"Телескоп"

По своей сути Telescope — это просто нечеткий искатель, работающий со списками. Однако его способность быть расширена на другие плагины или различные источники списков означает, что он может делать гораздо больше, чем просто находить файлы. Это не означает, что поиск файлов — неважная часть Telescope. На самом деле, это, вероятно, функция Telescope, которую я использую чаще всего. Подобно переключению файлов в VS Code с помощью CTRL + P, Telescope предоставляет те же функции и часто привязан к одной и той же раскладке клавиш в большинстве конфигураций, которые его используют. Если вы знаете имя файла, который вам нужен, вы можете добраться до него, не тянясь рукой за мышью. Возможности Telescope практически безграничны. Лишь некоторые из встроенных функций включают grep, поиск файлов и поиск старых файлов (иначе называемых недавно использованными файлами). Недавно я наткнулся на новый плагин, который обращается к функциям поиска кода GitHub и интегрирует их в Telescope, что, я думаю, говорит о расширяемости Telescope.

nvim-дерево

Теперь мы переходим к некоторым плагинам, благодаря которым Neovim ощущается как полноценная «IDE» (если вы хотите так называть VS Code). nvim-tree — это проводник дерева файлов для Neovim, который позволяет вам исследовать ваши файлы вместе с вашим кодом с помощью простого и понятного интерфейса. Когда вы фокусируетесь на nvim-tree, некоторые из ваших традиционных раскладок Vim превращаются в функции, чрезвычайно полезные для создания, переименования и перемещения файлов. Например, нажатие a в nvim-tree не переведет вас в режим вставки справа от курсора, как это обычно бывает в Vim. Вместо этого он предлагает вам создать файл там, где был сфокусирован ваш курсор. Просто введите имя и нажмите ENTER (или, лучше сказать, <CR>), чтобы создать файл. Завершите строку цифрой /, чтобы сделать ее папкой. r позволяет вам переименовать файл, x вырежет файл, который после вставки с помощью p приведет к его исчезновению (c просто скопирует файл, не удаляя его при вставке). d удалит файл, что вам будет предложено подтвердить с помощью y/n.

Существует множество раскладок по умолчанию, с которыми поставляется nvim-tree, и я нашел эту документацию от NvChad особенно полезной. Имейте в виду, что часть документации не совсем точна для чистой установки nvim-tree, так как у NvChad есть несколько собственных уникальных переназначений (первое несоответствие, которое я обнаружил, заключалось в том, что <C-h> и <C-l> не перескакивали между nvim-tree и моего буфера кода. По умолчанию вам придется выполнить <C-w>h и <C-w>l для этих раскладок соответственно (<C-w> инициирует перемещение между разными буферами). Из-за этих несоответствий между nvim-tree NvChad и чистой установкой вы можете просто проверить раскладки клавиатуры по умолчанию, которые nvim-tree поставляется с помощью команд :help или документации, найденной на GitHub, Я только что обнаружил, что документация NvChad выглядит довольно эстетично :).

луалин

lualine — это невероятно быстрый плагин строки состояния, что означает, что он отображает различную полезную информацию в нижней части Neovim. Он может отображать режим, в котором вы сейчас находитесь (вставка, визуальный, обычный), информацию о ветке Git, в которой вы находитесь, вашу операционную систему, процент файла, на котором находится ваш курсор по вертикали, и имя файла текущего файла. буфер, и это лишь некоторые из них.

lualine — один из тех плагинов, которые делают Neovim более похожим на полноценные IDE, не нарушая при этом никаких основных принципов Vim. Я упоминаю об этом, потому что есть другие плагины, такие как bufferline, которые имеют схожие принципы дизайна, но идут вразрез с философией Vim. В случае с этим плагином буферной строки он начинает обрабатывать буферы как вкладки в таких редакторах, как VS Code, и, кроме того, предоставляет больше возможностей для одновременного просмотра нескольких файлов. Это не означает, что наличие вкладок или просмотр вертикального разделения двух разных файлов по своей природе плохо, но они не обязательно соответствуют философии того, как был разработан Vim. Если вам нравится иметь вкладки, которые выглядят точно так же, как вкладки из Sublime Text, то, насколько я понимаю, для вас это больше возможностей.

nvim-веб-устройства

nvim-web-devicons — это плагин, который делает некоторые из ранее упомянутых плагинов более полными. nvim-web-devicons — это Lua-форк vim-web-devicons, и он очень хорошо сочетается с такими плагинами, как nvim-tree и lualine (обратите внимание, что пользователь GitHub, которому принадлежит этот репозиторий, сам является nvim-tree), предоставляя те же значки, что и у плагина vim-web-devicons, а также цвета для этих значков. Проще говоря, некоторые другие ваши плагины выглядят по-настоящему шикарно. Не забудьте использовать Nerd Font!

материал

Этот плагин зависит от ваших личных предпочтений, так как материал — это просто цветовая схема, которая мне нравится больше всего. Некоторые плагины цветовой схемы поддерживаются Treesitter (включая этот), и вы можете найти их список в коллекции потрясающих плагинов Neovim от rockerBOO.

(Все изображения взяты из репозитория material.nvim GitHub)

  • океанический

  • Глубокий океан

  • бледная ночь

  • Более легкий

  • Темнее

Я использую темы Material с тех пор, как начал использовать VS Code, но если бы мне нужно было назвать мою вторую любимую тему для Neovim, это должен был быть gruvbox.

Приветствуем также Treesitter-совместимую версию gruvbox.

упаковщик

Ни один из этих плагинов не имел бы значения, если бы не было менеджера пакетов для управления ими всеми. Вот тут-то и появляется упаковщик. Packer — это менеджер плагинов в стиле использования пакетов для Neovim, который допускает декларативную спецификацию плагинов, поддержку зависимостей Luarocks, а также параметры ленивой загрузки.

Самый популярный способ установки упаковщика — это метод ускорения, который позволяет очень легко клонировать вашу конфигурацию на другие машины и автоматически устанавливать все нужные вам плагины.

Если есть одна команда, о которой вам нужно знать при использовании упаковщика в качестве менеджера плагинов Neovim, это :PackerSync, которая по существу выполняет :PackerUpdate, а затем :PackerCompile. Эта комбинация команд позволяет вам обновить все ваши плагины и установить любые новые, которые вы добавили в свой список плагинов через упаковщик. Имейте в виду: обновление ваших плагинов не всегда «хорошо». Вполне возможно, что внесение изменений в плагин из репозитория GitHub может привести к его поломке.

В одном случае моя конфигурация LSP сломалась, когда Мейсон получил некоторые обновления, которые сделали так, что языковой сервер sumneko_lua больше не работал в моей конфигурации. Однако ошибка была временной, и вместо нее я просто использовал lua_ls.

Один из способов избежать этого — использовать функцию моментального снимка упаковщика. Если вы беспокоитесь, что :PackerSync может сломать один или два плагина, сохраните снимок конфигурации Neovim, пока он еще работает, а затем запустите :PackerSync. Если плагины, к сожалению, сломаются, вы можете вернуться к моментальному снимку, сделанному до обновления.

Властелин Vims: два менеджера плагинов

В этом разделе моего путешествия по Neovim я устанавливаю еще несколько эпических плагинов, а также заменяю упаковщик на lazy.nvim

С тех пор, как я создал свою первоначальную конфигурацию Neovim, я застрял в Vim. Я просто не могу убежать. Просто взглянув на историю своего репозитория neovim-config, я уже сделал сотни коммитов за месяц. Хотя некоторые из них представляют собой простые правки README, все они служат цели улучшения моей конфигурации. Правки README особенно полезны, так как я добавил внизу список дел, который помогает мне отслеживать, какие плагины я хочу опробовать, есть ли какие-либо нерешенные ошибки в моей конфигурации и т. д.

Я намеренно оставил свой plugins.lua несколько запутанным, так как плагины не организованы по релевантности. Вместо этого файл более или менее организован в хронологическом порядке установки плагина. Другими словами, первые плагины, которые я установил, находятся вверху файла, а самые новые — внизу. Я считаю, что организация моих плагинов таким образом помогает рассказать историю о том, как выросла моя конфигурация. Вот мой файл plugins.lua на данный момент:

local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
if not vim.loop.fs_stat(lazypath) then
  vim.fn.system({
    "git",
    "clone",
    "--filter=blob:none",
    "https://github.com/folke/lazy.nvim.git",
    "--branch=stable", -- latest stable release
    lazypath,
  })
end

vim.opt.rtp:prepend(lazypath)

local plugins = {
  {'nvim-tree/nvim-tree.lua', lazy = true},
  {'nvim-tree/nvim-web-devicons', lazy = true},
  {'nvim-lualine/lualine.nvim', lazy = true},
  {'marko-cerovac/material.nvim', lazy = true},
  {'nvim-treesitter/nvim-treesitter', lazy = true},
  {
    'nvim-telescope/telescope.nvim',
    version = '0.1.0',
    dependencies = {
      'nvim-lua/plenary.nvim'
    }, lazy = true
  },
  {
    'williamboman/mason.nvim',
    'williamboman/mason-lspconfig.nvim',
    'neovim/nvim-lspconfig',
    lazy = true
  },
  {'hrsh7th/nvim-cmp'},
  {'hrsh7th/cmp-nvim-lsp'},
  {'L3MON4D3/LuaSnip'},
  {'saadparwaiz1/cmp_luasnip'},
  {'rafamadriz/friendly-snippets'},
  { "akinsho/toggleterm.nvim",
    commit = "2a787c426ef00cb3488c11b14f5dcf892bbd0bda",
    config = "require('toggleterm')",
    lazy = true
  },
  -- This method works for lazy, but it doubles startup time
  -- {
  --     "iamcco/markdown-preview.nvim",
  --     config = function ()
  --       vim.fn["mkdp#util#install"]()
  --     end
  -- },
  {
    'iamcco/markdown-preview.nvim',
    build = 'cd app && npm install',
    -- using npm to install rather than the vim function leads to significantly faster startup time
    init = function()
      vim.g.mkdp_filetypes = { 'markdown' }
    end,
    config = function()
      vim.keymap.set("n", "<leader>m", "<Plug>MarkdownPreviewToggle", { desc = "Markdown Preview" })
    end
  },
  -- Peek works (assuming deno and JavaScript dependencies are installed), but there is a bug currently where the preview doesn't load
  -- {
  --   'toppair/peek.nvim',
  --   run = 'deno task --quiet build:fast',
  --   config = function()
  --     vim.api.nvim_create_user_command('PeekOpen', require('peek').open, {})
  --     vim.api.nvim_create_user_command('PeekClose', require('peek').close, {})
  --   end,
  -- },
  {'numToStr/Comment.nvim', lazy = true},
  {'JoosepAlviste/nvim-ts-context-commentstring', lazy = true},
  {'windwp/nvim-autopairs', lazy = true},
  {'windwp/nvim-ts-autotag', lazy = true},
  {
      'goolord/alpha-nvim',
      config = function ()
          require'alpha'.setup(require'alpha.themes.dashboard'.config)
      end, lazy = true
  },
  {'luk400/vim-lichess'},
  {'dstein64/vim-startuptime'},
  {'rhysd/clever-f.vim'},
  {
    'ggandor/leap.nvim',
    config = function()
      require('leap').add_default_mappings()
    end,
    lazy = true
  },
  {'ThePrimeagen/vim-be-good', lazy = true},
  {'alec-gibson/nvim-tetris'},
  {'tamton-aquib/zone.nvim', lazy = true, enabled = false},
  {
    'folke/noice.nvim',
    dependencies = {
      'MunifTanjim/nui.nvim',
      'rcarriga/nvim-notify',
    },
    lazy = true
  },
  {'xiyaowong/transparent.nvim'},
  {'ThePrimeagen/harpoon', lazy = true},
  {'alanfortlink/blackjack.nvim', lazy = true},
  {'0x100101/lab.nvim', build = 'cd js && npm ci', dependencies = { 'nvim-lua/plenary.nvim' }, lazy = true}
}

local opts = {}

require("lazy").setup(plugins, opts)

Если вы читали мою предыдущую запись в блоге Neovim, то знаете, что я упомянул две ключевые функции, отсутствовавшие в этой базовой конфигурации: Treesitter и встроенный терминал. Я смог довольно легко установить Treesitter, сославшись на некоторые другие конфигурации Neovim на GitHub, поэтому я подумал, что установка какого-либо терминального плагина сделает мою конфигурацию Neovim завершенной. Я даже отчетливо помню, как сказал другу: «Как только у меня будет этот плагин, все будет готово». Конечно, это было только начало моего безумия, так как я продолжал добавлять плагин за плагином, безнадежно ожидая того дополнения, которое сделает Neovim наконец-то идеальным. Спойлер: его не существует.

переключить термин

toggleterm — это плагин, который позволяет сохранять переключаемые терминалы в различных ориентациях. Хотя у Neovim есть эмуляция терминала (которую можно запустить с помощью команды :terminal), на самом деле она не сравнится со встроенным терминалом чего-то вроде VS Code, например, который можно легко переключить, сохраняется (поэтому он продолжает работать любые процессы, которые вы хотите), и, прежде всего, выглядит действительно круто.

Во время его установки я действительно думал, что toggleterm будет последним плагином, который мне нужен. В конце концов, чего еще я хотел? У меня уже был LSP, несколько классных фрагментов автозавершения кода и проводник по дереву файлов. Насколько я мог судить, у меня было что-то довольно близкое к VS Code, который, по сути, был тем, что я считал золотым стандартом для редактирования кода (подождите, это не Doom Emacs?)

Поскольку toggleterm был первым плагином, который я устанавливал без какого-либо учебника или руководства, я столкнулся с некоторыми очень простыми или, осмелюсь сказать, «глупыми» ошибками.

📂 ~/.config/nvim
├── 🌑 init.lua
├── 📂 lua
│  ├── 📂 v9
│     ├── 🌑 keymaps.lua
│     └── 🌑 plugins.lua
│     └── 📂 plugin_config
│        ├── 🌑 colorscheme.lua
│        └── 🌑 lualine.lua
│        └── 🌑 nvim-tree.lua
│        └── 🌑 init.lua

Как показано выше, мой конфиг Neovim имеет довольно простую структуру. Хотя показаны не все папки, показаны все основные компоненты. В корневом каталоге файл init.lua вызывает keymaps.lua, который содержит множество раскладок и основных параметров Vim, plugins.lua, который включает в себя любой используемый код диспетчера плагинов, и, наконец, plugin_config/, который представляет собой папку, содержащую все конкретные конфигурации плагины очень модульным и организованным образом.

-- this is the root directory's init.lua

require("v9.keymaps")
require("v9.plugins")
require("v9.plugin_config")

Хотя я был достаточно умен, чтобы включить toggleterm.lua в каталог plugin_config/, я также не был достаточно умен, чтобы потребовать его в plugin_config/init.lua или init.lua, который выделен жирным шрифтом на схеме структуры каталога выше.

-- this is plugin_config's init.lua

require('v9.plugin_config.colorscheme')
require('v9.plugin_config.lualine')
require('v9.plugin_config.nvim-tree')
require('v9.plugin_config.telescope')
require('v9.plugin_config.treesitter')
require('v9.plugin_config.lsp')
require('v9.plugin_config.completions')

-- I failed to include this line when I first installed toggleterm...
require('v9.plugin_config.toggleterm')
-- F in the chat :(

require('v9.plugin_config.alpha')
require('v9.plugin_config.lichess')
-- require('v9.plugin_config.zone')
require('v9.plugin_config.autopairs')
require('v9.plugin_config.comment-nvim')
require('v9.plugin_config.noice')
require('v9.plugin_config.harpoon')
-- require('v9.plugin_config.peek')
require('v9.plugin_config.blackjack')
require('v9.plugin_config.leap')
require('v9.plugin_config.vim-be-good')
require('v9.plugin_config.lab')

Этот второй файл init.lua вызывает все файлы конфигурации плагина, и отсутствие строки require('v9.plugin_config.toggleterm') означало, что моя конфигурация toggleterm никогда не вызывалась, поэтому любые раскладки клавиш, которые я включил, не будут работать. Что касается того, почему это может быть проблемой… Что ж, давайте просто посмотрим на мою конфигурацию toggleterm:

local status_ok, toggleterm = pcall(require, 'toggleterm')
if not status_ok then
  return
end

toggleterm.setup {
  size = 13,
  open_mapping = [[<c-\>]],
  shade_filetypes = {},
  shade_terminals = true,
  shading_factor = '1',
  start_in_insert = true,
  persist_size = true,
  direction = 'horizontal'
}

Как видите, open_mapping задает раскладку клавиш, которая будет переключать терминал, и если эта строка кода никогда не запустится, то эта комбинация клавиш не сработает.

Конечно, я говорю вам это задним числом, так как теперь я знаю глупую ошибку, которую я совершил, но в то время я совершенно не понимал, почему toggleterm не работает так, как я настроил.

Одна замечательная вещь, которую позволяет вам делать упаковщик, — это исходные файлы без выхода из Neovim с :source % или :so. Это по существу перезагрузит файл конфигурации, в котором вы находитесь, поэтому, пока я все еще отлаживал toggleterm, я заметил, что могу вручную получить toggleterm.lua и заставить плагин работать, но это было неприемлемо. Мне нужно было, чтобы плагин загружался при запуске и работал без каких-либо ручных команд.

Почитав официальную документацию Neovim.io, я обнаружил, что могу поместить свой код в ~/.config/nvim/plugin, чтобы он автоматически компилировался при запуске. Если вы посмотрите на эту конкретную фиксацию, то это именно то, что я сделал.

И всего два дня спустя я волшебным образом обнаружил правильное решение своей ошибки и просто вернулся к исходной структуре плагина, требуя toggleterm.lua в plugin_config/init.lua .

Это величайший ключ лидера всех времен

Практически в любом руководстве по Neovim с нуля обсуждается ключ лидера. Что означает этот термин?

В Vim ведущий ключ — это ключ, который предоставляет пространство имен для любых настраиваемых ярлыков, которые мы хотим. Другими словами, после нажатия вашей ведущей клавиши Vim интерпретирует любые другие нажатые вами клавиши и выполняет команду (если она существует), связанную с этой раскладкой. Что действительно здорово в ведущем ключе Vim, так это то, что он дает вам совершенно пустое пространство имен для настройки ваших собственных раскладок. Вам не придется беспокоиться о создании каких-либо конфликтующих раскладок, поскольку по умолчанию их не существует.

Возможно, самый популярный ведущий ключ (даже в Emacs) — это <SPC>, который можно определить как таковой в Lua для Neovim:

vim.g.mapleader = ' '
vim.g.maplocalleader = ' '

Если вам интересно, в чем разница между первым и вторым вариантами, то она невелика. Локальный лидер, как следует из его названия, существует для определенных буферов, которыми вы можете воспользоваться для определенных типов файлов, просто в качестве примера. Сам лидер является глобальным для Vim, то есть он применим везде. В большинстве конфигураций, которые я видел, ключи локального лидера и лидера настроены на одно и то же, поэтому вам, вероятно, не нужно беспокоиться о различии между ними.

С набором клавиш лидера теперь вы можете настроить несколько довольно изящных раскладок, таких как следующие:

local keymap = vim.keymap
local opts = { noremap = true, silent = true }

keymap.set('n', '<leader>w', ':wa<CR>', opts)
keymap.set('n', '<leader>q', ':qa<CR>', opts)

Общая формула настройки раскладки клавиатуры в Neovim заключается в указании четырех параметров:

  1. Режим, к которому будет применяться раскладка клавиатуры
  2. Сама раскладка клавиатуры
  3. Что должна выполнять карта клавиш
  4. Любые параметры для раскладки (которые я объединил в локальную переменную с именем opts (установка noremap в true делает так, чтобы раскладки были нерекурсивными, а установка silent в true делает так, чтобы команды выполнялись без записи в командную строку Vim )

В двух приведенных выше примерах оба относятся к обычному режиму и выполняются с ключом-лидером, за которым следует w или q соответственно. Функционально они пишут во все буферы и выходят из всех буферов соответственно.

Это делает запись и выход из Neovim намного быстрее и, на мой взгляд, более приятной, чем запись команды :wqa и нажатие ENTER.

Однако расширяемость раскладок лидеров выходит далеко за рамки встроенных функций Vim, таких как запись или выход. Например, с некоторым типом плагина предварительного просмотра Markdown вы можете установить раскладку клавиатуры для быстрого запуска плагина следующим образом:

keymap.set('n', '<leader>m', ':MarkdownPreview<CR>', opts)

Но <SPC>, на мой взгляд, неоптимальный ведущий ключ. Конечно, пробел можно нажимать любой рукой, это довольно большая клавиша, и она не мешает другим раскладкам в обычном режиме, но она не идет ни в какое сравнение со всемогущей точкой с запятой.

Почему точка с запятой является таким хорошим ведущим ключом? В отличие от пробела, она находится в домашнем ряду, а это означает, что она укрепит хорошие привычки набора текста, гарантируя, что ваши пальцы всегда будут плавать над домашним рядом, чтобы иметь доступ к этой удивительной клавише.

Вдобавок ко всему, это клавиша того же размера, что и другие ваши буквенно-цифровые клавиши, поэтому нажатие «комбо» с ее помощью кажется гораздо более удовлетворительным и последовательным. Я обнаружил, что с пробелом обратная связь, которую я получаю от нажатия комбинации клавиш, кажется менее «четкой». Не поймите меня неправильно, пробел сам по себе может быть очень удобным, особенно на некоторых механических клавиатурах очень высокого класса, но в сочетании с другими клавишами во всей последовательности возникает что-то непоследовательное.

Теперь у точки с запятой почти нет конфликтов раскладок в обычном режиме, есть одно исключение, которое можно исправить с помощью очень простого плагина. В обычном режиме ; используется только для повторения перехода f. Другими словами, когда вы используете f для перехода к следующему экземпляру символа, вы используете ; для перехода к следующему экземпляру того же символа и , для перехода к предыдущему экземпляру. Когда точка с запятой установлена ​​на ключе-лидере, нажатие ; во время прыжка f не приводит к немедленному переходу курсора к следующему экземпляру этого символа. Вместо этого, из-за раскладки клавиатуры лидера, Vim будет ждать одну секунду для любых других входных данных, которые вы хотите связать вместе. Если вы ничего не делаете целую секунду, Vim перейдет к следующему символу.

И, конечно, это совершенно одиозно. Каждый раз, когда я не получаю немедленной обратной связи от ввода, будь то программирование, игра или просто набор текста, я чувствую, что меня тошнит. Но, как я уже говорил, исправить это очень просто. С подключаемым модулем Vim clever-f (который безупречно работает с Neovim) f и F становятся доступными вместо ; и ,. Таким образом, вместо того, чтобы использовать ; для перехода вперед, вы можете просто нажимать f снова и снова (то же самое можно применить к F для ,). Это также интуитивно понятно, особенно при сравнении n и N для перехода вперед и назад по / последовательностям поиска.

Плагин, который я решил добавить следующим (что я сделал сразу после того, как сказал своему другу, что мне больше не нужны плагины), был плагином для предварительного просмотра файлов Markdown. Когда я использовал VS Code в качестве своего ежедневного драйвера, я мог легко просматривать предварительные просмотры Markdown в самом VS Code с помощью простого ярлыка CTRL + SHIFT + V. Поскольку я склонен вкладывать свое сердце и душу в свои README, я решил найти плагин, который помог бы мне увидеть всю свою тяжелую работу.

уценка-превью

Плагин markdown-preview от iamcco очень прост. После установки вы вызываете :MarkdownPreview как команду Vim, и плагин открывает вкладку в вашем браузере по умолчанию с предварительным просмотром вашего файла Markdown. Когда вы прокручиваете свой файл Markdown, предварительный просмотр фактически следует за ним; его положение зависит от вашего курсора.

Некоторые другие функции этого плагина включают в себя:

  • Поддержка Русалка
  • Поддержка Chart.js
  • Синхронизированная, плавная прокрутка
  • смайлики

Я обнаружил, что набирать :MarkdownPreview каждый раз, когда я хотел посмотреть, как выглядит мой README, было несколько хлопотно, поэтому, используя мой новый ведущий ключ, я установил ;m для его запуска.

Для меня довольно круто иметь плагин предварительного просмотра Markdown, но я обнаружил, что большую часть времени при редактировании моих README я на самом деле не просматриваю отрендеренный Markdown — я просто использую его после внесения большого количества правок, чтобы увидеть, как он работает. изменился со временем. Но независимо от того, как вы можете использовать такой инструмент для предварительного просмотра Markdown, он определенно не так важен, как плагин, который следует за ним.

Комментарии

Как программисты, мы обязаны писать комментарии. То ли это бесполезная серия комментариев, как этот

/* 
This is a function, which has the name "Minion," which takes in a String
which is denoted by the character in the English alphabet referred to as 's,'
and then returns that same String (note that the String is still called 's.'
*/
public static String Minion(String s){  // function header, take in a single parameter, String s
  return s;  // this is the return statement, in which the String is returned
}  // this is a closing bracket
// this is the end of the function which we have referred to as Minion

или комментарии, которые на самом деле прагматично документируют код, комментарии являются основной функцией любого программиста. В отличие от VS Code, Vim не имеет встроенного способа переключения комментариев на основе выбранных строк.

В VS Code, если вы выделите 3 строки, а затем выполните CTRL + /, эти строки будут закомментированы, если они еще не были (и раскомментированы, если они были). Если вы ничего не выберете, VS Code изменит статус комментария текущей строки.

Чтобы эмулировать это поведение, мы будем использовать Comment.nvim. Comment.nvim — еще один простой плагин, который не требует дополнительной настройки. Установите его с вашим любимым менеджером плагинов и начните переключать комментарии в свое удовольствие с помощью gcc для отдельных строк и gc для выбора визуального режима.

Отступ и отступ кода

Будучи ранее пользователем VS Code, я уже привык к отступу моего кода с помощью TAB и отступу моего кода с помощью SHIFT + TAB. Когда я узнал, что Vim использует >> и << для отступа и отступа кода соответственно, я решил, что мне нужен более быстрый способ выполнения этих функций. Благодаря этим потрясающим переназначениям я теперь могу молниеносно быстро выполнять отступы и отступы в своем коде:

-- indent and outdent lines quickly
keymap.set('n', '<TAB>', '>>', opts)
keymap.set('n', '<S-TAB>', '<<', opts)

-- indent and outdent lines in visual mode
keymap.set('v', '<TAB>', '<S->>gv', opts)
keymap.set('v', '<S-TAB>', '<S-<>gv', opts)

Первые две раскладки довольно просты. В обычном режиме они просто делают так, что нажатие TAB делает отступ текущей строки, а выполнение SHIFT + TAB отступает от текущей строки. Самое интересное в отступах и выступах Vim заключается в том, что их можно выполнять независимо от того, где находится курсор.

В VS Code отступ строки должен выполняться, когда курсор находится перед кодом (или слева от него), в то время как отступ может выполняться независимо от того, где находится курсор. Хотя в этом есть смысл, это просто странное несоответствие, которое достигается за счет неудобств для пользователя. Когда в последний раз вы хотели сделать отступ, но только начиная с определенного символа? Гораздо разумнее делать отступ всей строки, независимо от положения курсора, для чего VS Code, как ни странно, имеет функциональные возможности, но только для отступа кода.

Раскладки клавиатуры визуального режима не совсем необходимы, и опытные пользователи Vim, вероятно, возразят, что такие раскладки — неправильный способ отступа или отступа кода. Рассмотрим следующий код:

public static void main(String[] args){
System.out.println("spaghetti");
System.out.println("and");
System.out.println("meatballs");
System.out.println("dunkey");
}

Ясно, что вкладки в этом коде неправильные. Все, начиная со строки 2 и заканчивая строкой 5, должно иметь отступ один раз, и этого можно добиться в Vim, поместив курсор на строку 2, добавив перед номером 4 (количество строк, которые нужно изменить при последующем действии), а затем выполнив >>, или в случае первой раскладки клавиатуры нормального режима, TAB. Хотя это, несомненно, быстрее, чем делать это с выбором визуального режима, я считаю, что выбор текста, который я хочу сделать отступом или выступом, делает весь процесс более понятным.

Таким образом, с раскладкой отступа/выступа в визуальном режиме я бы поместил курсор на строку 2, выполнил V (помните, что это означает SHIFT + V, поскольку клавиши Vim различают заглавные и строчные буквы), чтобы начать визуальный выбор строки, затем сделал 3j, чтобы перейти вниз на три строки, выбрав все операторы печати, а затем, наконец, нажмите TAB.

Есть два ключевых различия между раскладкой отступа/выступа в обычном режиме и версией визуального режима: Первое — это фактический процесс отступа/выступа. В обычном режиме отступ выполняется с помощью >>, но в визуальном режиме это достигается не с помощью >>, а с помощью <S->> или в не-Vim «синтаксисе», SHIFT + >.

Второе отличие состоит в том, что в раскладке нормального режима ничего не следует за самим процессом отступа. За раскладкой визуального режима следует gv. Что это делает?

В Vim gv выбирает ваш последний выбор, поэтому он включен в конец раскладки клавиатуры визуального режима. Без него код, который вы выделяете, просто будет иметь отступ/выступ, и вы выйдете из визуального режима. Но с ним, после того, как код будет отступом/выступом, тот же самый выбор, который вы только что сделали, будет выбран повторно (хотя этот процесс бесшовный, вы не заметите мерцание выделения или что-то в этом роде).

Автопары и автотеги:

В моей конфигурации Neovim по-прежнему отсутствовали некоторые основные функции, которые были у меня по умолчанию в VS Code, а именно автодополнение для пар и тегов.

Под «парами» рассмотрите сценарий, в котором вы вводите {, а VS Code автоматически вставляет за вас }. То же самое делается для скобок, квадратных скобок, одинарных и двойных кавычек.

Для тегов рассмотрите простой пустой HTML-файл. Если вы наберете это:

<html>

Вы ожидаете, что ваш редактор автоматически вставит конечный тег следующим образом:

<html></html>

И то, и другое может быть достигнуто с помощью двух плагинов наряду с уже существующей конфигурацией Treesitter:

Для пар есть плагин nvim-autopairs, а для тегов — плагин nvim-ts-autotag. Вот как вы можете установить и правильно настроить эти два плагина.

В вашем файле plugins.lua или там, где у вас есть загрузочный код упаковщика, включите это:

-- packer boostrapping code
  use {
    "windwp/nvim-autopairs",
      config = function() require("nvim-autopairs").setup {} end
  }
  use {
    "windwp/nvim-ts-autotag",
      config = function() require("nvim-ts-autotag").setup {} end
  }

И в файле конфигурации Treesitter обязательно включите эти параметры в функцию setup:

local status_ok, treesitter = pcall(require, 'nvim-treesitter.configs')
if not status_ok then
  return
end

treesitter.setup {
  ensure_installed = { "lua", "vim", "python" },

  sync_install = false,
  auto_install = true,
  highlight = {
    enable = true,
  },
  context_commentstring = {
    enable = true,
    autocmd = false
  },
-- these options
  autopairs = {
    enable = true
  },
  autotag = {
    enable = true
  }
-- these options
}

Как только вы это сделаете, Neovim автоматически подберет для вас пары и теги. Из того, что я могу сказать, параметры по умолчанию для обоих этих плагинов вполне разумны и в значительной степени отражают то, что достигают такие редакторы, как VS Code.

Альфа: лучший плагин для панели инструментов:

К этому моменту моя конфигурация Neovim стала достаточно надежной — в плане функциональности в ней не так уж много упущено. Так что было вполне логично, что я начал искать ненужные плагины, которые были просто крутыми.

Представляем alpha-nvim, плагин приветствия, который легко настраивается и включает стартовые шаблоны на основе vim-startify и dashboard-nvim.

Лично я предпочитаю тему панели инструментов, поскольку включение таких действий, как открытие проводника дерева файлов, создание нового файла или использование grep для поиска в каталоге, кажется мне более полезным, чем просто доступ к недавно использованным файлам. И, кроме того, если вы включите опцию для переключения встроенной функции последних файлов Telescope, тема панели инструментов может делать все, что может сделать startify, плюс некоторые.

Я провел довольно много времени, возясь с альфой, и текущая конфигурация, которая у меня есть, имеет несколько довольно отличных функций.

Во-первых, приборная панель генерирует довольно крутую ASCII-графику, которую она извлекает из другого файла с именем logos.lua. По сути, каждый раз, когда запускается Neovim, alpha выбирает случайный ASCII-арт и затем выводит его на экран:

Ниже ASCII-арта находится список полезных опций:

  1. Найти файлы — вызывает встроенные файлы поиска Telescope.
  2. Новый файл — просто создает новый пустой файл.
  3. Недавно использованные файлы — вызывает последние встроенные файлы Telescope (называемые Telescope «старыми файлами»).
  4. Найти текст — вызывает живой grep Telescope.
  5. Открыть файловое дерево — открывает и фокусируется на дереве nvim.
  6. Плагины — переход к моему файлу plugins.lua независимо от того, в каком каталоге изначально был открыт Neovim.
  7. Keymaps — делает то же самое, что и опция выше, но для keymaps.lua

Эти параметры можно использовать либо с помощью раскладки клавиатуры, указанной в альфа-версии (которая отличается от любых раскладок, которые могли быть установлены где-либо еще в конфигурации), но также и с помощью навигации по строкам с помощью клавиш j и k и нажатия клавиши ENTER.

Наконец, в нижнем колонтитуле панели alpha отображается запущенная версия Neovim, текущая дата и время, а также сколько плагинов было загружено и как быстро это произошло.

альфа + лолкот

Теперь тот факт, что альфа-версия может выбирать случайный ASCII-арт из заданного набора, довольно круто, но я думаю, что мы можем добиться большего. Идея состоит в том, чтобы альфа-версия использовала lolcat, инструмент командной строки, который окрашивает выходные данные в цвета радуги, а затем анимирует ASCII-графику, чтобы получился классный эффект радужной волны, который возникает постоянно:

Сделать этот удивительный эффект RGB на нашем ASCII-графике не так просто, как некоторые из предыдущих конфигураций плагина, но вот что для этого нужно:

Во-первых, альфа-конфигурация должна выполнять большую часть работы, вызывая сценарий bash, который фактически будет анимировать вывод из файлов .cat, содержащих само изображение ASCII:

Вы заметите некоторые несоответствия между кодом и параметрами панели инструментов — это потому, что выходные данные настолько велики, что на самом деле покрывают некоторые из них. В этом случае «найти текст», «недавно использованные файлы» и «новый файл» фактически скрыты под символом ASCII. Это всего лишь одна из ошибок, которую я все еще пытаюсь исправить с помощью этой альфа-конфигурации (поэтому она закомментирована в основной ветке).

Еще одна проблема с этой альфа-конфигурацией заключается в том, что при вызове альфа-версии в Neovim не удается отобразить ASCII-арт. Хотя не имеет особого смысла открывать панель инструментов, уже находясь в Neovim, это просто хорошо иметь для согласованности. Кроме того, эта альфа-конфигурация полностью функциональна. Все параметры приборной панели работают, и самое главное, эта анимированная гидра выглядит потрясающе. Вернемся к тому, как это на самом деле работает…

Наряду с альфа-конфигурацией вам понадобится bash-скрипт, который анимирует вывод, зацикливая вызовы на lolcat:

Наконец, вам понадобится сама графика ASCII, которая будет содержаться в файлах .cat, а не в представлениях необработанных строк, как показано ранее:

Не стесняйтесь найти свой собственный рисунок ASCII для этой RGB-анимации. Я обнаружил, что изображения, созданные точками (например, гидра), могут иметь гораздо больше деталей, чем традиционные рисунки ASCII, в которых используются только буквенно-цифровые символы и знаки препинания.

ленивый.nvim

В жизни каждого человека наступает момент, когда он понимает, что упаковщик — это устаревший и несовершенный менеджер плагинов для Neovim. Это неизбежно приводит к установке lazy.nvim (я называю его lazy.nvim, чтобы не путать с LazyVim, предварительно сконфигурированной установкой Neovim), современного менеджера плагинов, настолько мощного, что он даже заставил «создателя упаковщика переключиться над".

lazy.nvim — замечательный менеджер плагинов для Neovim, которым я едва потрогал поверхность в процессе собственного использования. Вот лишь некоторые из удивительных функций, которые он предлагает:

  • Управляйте всеми своими плагинами с помощью мощного и быстрого графического интерфейса.
  • Более быстрое время запуска, чем у упаковщика, благодаря кэшированию и ленивой загрузке плагинов, модулей Lua, раскладок, цветовых схем и т. д.
  • Нет необходимости вручную компилировать плагины (как с :source %)
  • Lockfile под названием lazy-lock.json, который отслеживает установленные плагины, а также их коммиты.

Я думаю, что одна из самых крутых частей lazy.nvim — это графический интерфейс, который появляется при выполнении :Lazy:

Этот графический интерфейс имеет массу опций, которые вы можете использовать, набрав соответствующую букву (они в нотации Vim, так что да, это заглавные буквы). Для получения дополнительной информации об этих параметрах я бы проверил репозиторий lazy.nvim на GitHub или просто запустил :Lazy help, чтобы вызвать меню справки непосредственно в Neovim.

Подобно тому, как :PackerSync выполняет :PackerUpdate, а затем :PackerCompile, наиболее мощной опцией в lazy.nvim является Sync (S), поскольку она выполняет операции установки, очистки и обновления одновременно.

Что действительно здорово в этом графическом интерфейсе, так это то, что он будет отдавать приоритет показу критических изменений при обновлении плагинов, например:

Это действительно полезно; если вы заметили какие-либо критические изменения при обновлении своих плагинов, просто запомните, какие коммиты вызвали это. Если критические изменения в конечном итоге повлияли на функциональность вашей конфигурации, вы можете начать отладку с очень надежной отправной точки: исходного кода, который вызвал поломку вашей конфигурации!

Конечно, этого можно вообще избежать, просто прикрепив свои плагины к определенному коммиту, чтобы любые будущие обновления не привели к их поломке. Это также можно сделать с помощью упаковщика, но файл lazy-lock.json от lazy.nvim упрощает отслеживание.

Но, пожалуй, самая крутая вещь в lazy.nvim — это функция отложенной загрузки. Может быть, поэтому он и называется lazy.nvim…

Ленивая загрузка — это процесс загрузки плагинов только тогда, когда они необходимы (или когда вы это укажете). Например, вы можете настроить lazy.nvim так, чтобы Neovim загружался только с теми плагинами, которые вы считаете необходимыми, а остальные загружались при определенных событиях, таких как запуск, появление определенных раскладок и т. д.

Делая это, вы можете значительно улучшить время запуска, заставив Neovim откладывать попытки загрузить каждый отдельный плагин перед запуском. Скорее всего, вам не нужно, чтобы все ваши плагины были готовы сразу, поэтому вы можете отложенно загружать те, которые в конечном итоге используете, в среднем через несколько секунд или даже через несколько минут после запуска Neovim.

Сравнительный анализ стартапа Neovim

Хотя редакторы для терминалов, такие как Neovim и Vim, уже имеют невероятно быстрое время запуска по сравнению с такими редакторами, как VS Code, мы всегда можем улучшить эти скорости. Если вам интересно, как вы можете сравнить время запуска Neovim, вот несколько способов сделать это:

(1) Используйте встроенный аргумент запуска --startuptime

Первый вариант сопряжен с наименьшими трудностями, но приводит к самым трудным для интерпретации данным. Просто запустите Neovim следующим образом:

nvim --startuptime medium.txt

Где medium.txt — это имя файла, в который вы хотите распечатать результаты. Выходной файл будет выглядеть примерно так:

times in msec
 clock   self+sourced   self:  sourced script
 clock   elapsed:              other lines

000.005  000.005: --- NVIM STARTING ---
000.054  000.050: event init
000.140  000.085: early init
000.186  000.046: locale set
000.214  000.028: init first window
000.407  000.193: inits 1
000.417  000.010: window checked
000.419  000.002: parsing arguments
000.738  000.035  000.035: require('vim.shared')
000.813  000.028  000.028: require('vim._meta')
000.814  000.074  000.046: require('vim._editor')
000.815  000.140  000.031: require('vim._init_packages')
000.818  000.258: init lua interpreter
000.868  000.050: expanding arguments
000.889  000.022: inits 2
001.128  000.239: init highlight
001.130  000.002: waiting for UI
001.802  000.672: done waiting for UI
001.812  000.011: clear screen
--
CUT OUT BECAUSE THIS FILE IS OVER 500 LINES LONG
--
101.896  000.030  000.030: require('noice.ui.popupmenu')
102.058  000.059  000.059: require('noice.text.block')
102.166  000.046  000.046: require('noice.message.filter')
102.168  000.236  000.131: require('noice.message')
102.182  000.284  000.048: require('noice.ui.cmdline')
102.364  003.462: VimEnter autocommands
102.903  000.539: UIEnter autocommands
102.942  000.040: before starting main loop
104.132  001.189: first screen update
104.134  000.003: --- NVIM STARTED ---

Хотя на первый взгляд это может показаться немного пугающим, эти выходные данные состоят всего из трех столбцов: часы (которые запускаются после выполнения команды nvim), прошедшее время (которое отслеживает, сколько времени занимает каждое событие) и событие, связанное с два вышеупомянутых столбца.

Все время указано в миллисекундах, и в идеале Neovim должен запускаться примерно через 100 мс. Все, что меньше 100 мс, очень хорошо, а все, что больше 250 мс или около того, становится заметно медленнее.

Конечно, возникает вопрос: насколько это важно? На самом деле это зависит от того, сколько раз вы запускаете Neovim каждый день или насколько вы заботитесь об эффективности, просто ради эффективности.

Что касается меня, у меня было невероятно медленное время запуска на моем рабочем столе, иногда доходящее до 600 мс, поэтому мой интерес к времени запуска Neovim возник с практической точки зрения.

(2) Используйте плагин vim-startuptime

Плагин vim-startuptime — еще один простой плагин, который не требует специальных параметров конфигурации. Просто установите его с помощью вашего любимого диспетчера плагинов (конечно, это должен быть lazy.nvim), а затем используйте его команду :StartupTime для создания визуального графического представления вашего запуска Neovim.

В отличие от аргумента --startuptime, передаваемого при запуске Neovim, этот метод позволяет вам увидеть визуализацию данных и экстраполировать основную причину потенциально неэффективного или медленного запуска.

На изображении выше вы можете очень быстро обнаружить, что общее время запуска моей конфигурации Neovim составляет чуть более 100 мс, причем большую часть этого времени занимает мой файл init.lua, который вызывает как v9.plugin_config/, v9.plugins, так и v9.keymaps. Как и ожидалось, v9.keymaps не отображается вверху этого списка, поскольку переназначение ключей требует гораздо меньше усилий, чем загрузка полных конфигураций LSP или элементов пользовательского интерфейса, таких как nvim-tree.

Если бы я хотел ускорить свои стартапы Neovim, я бы, наверное, сначала подумал об отключении плагина лаборатория, так как только он составляет ~20% запуска. Фактически, это единственный конфигурационный файл плагина, загрузка которого занимает более 10 мс; LSP загружается менее чем за 10 мс.

(3) Используйте инструмент сверхтонкий

hyperfine — это инструмент для сравнительного анализа командной строки, который может запускать Neovim несколько раз и показывать среднее время запуска, а также минимальные и максимальные значения. Установите его с помощью вашего любимого менеджера пакетов (у меня Ubuntu, поэтому я буду использовать apt):

sudo apt-get install hyperfine

После его установки вы можете запустить что-то вроде

hyperfine "nvim --headless +qa" --warmup 5 

иметь стартапы Neovim со сверхтонким эталонным тестом с 5 предварительными прогонами. Вывод будет выглядеть следующим образом:

Benchmark 1: nvim --headless +qa
  Time (mean ± σ):      80.3 ms ±   5.8 ms    [User: 52.7 ms, System: 15.8 ms]
  Range (min … max):    71.3 ms …  91.3 ms    32 runs

Если вы хотите сохранить эти результаты в файле, просто направьте вывод в файл по вашему выбору следующим образом:

hyperfine "nvim --headless +qa" --warmup 5 > hyperfineresults.txt

Подробнее о lazy.nvim

Одна из основных причин, по которой люди переходят с упаковщика на lazy.nvim, связана с медленным запуском. И хотя packer поддерживает отложенную загрузку, lazy.nvim определенно является золотым стандартом для отложенной загрузки.

Что касается меня, я замечал все больше и больше конфигураций с использованием lazy.nvim, и при изучении плагинов через GitHub присутствие lazy.nvim рядом с упаковщиком было чем-то, что я не мог игнорировать.

-- Example syntax of installing noice.nvim through lazy.nvim
{
  "folke/noice.nvim",
  event = "VeryLazy",
  opts = {
    -- add any options here
  },
  dependencies = {
    -- if you lazy-load any plugin below, make sure to add proper `module="..."` entries
    "MunifTanjim/nui.nvim",
    -- OPTIONAL:
    --   `nvim-notify` is only needed, if you want to use the notification view.
    --   If not available, we use `mini` as the fallback
    "rcarriga/nvim-notify",
    }
}

Так что lazy.nvim быстро заинтересовал меня, и я начал смотреть видео о переходе с упаковщика на lazy.nvim. Удивительно, но в этом процессе переключения нет ничего сложного — он просто включает в себя замену кода начальной загрузки упаковщика для lazy.nvim, изменение некоторого синтаксиса упаковщика на синтаксис lazy.nvim, а для собственного здоровья lazy.nvim — удаление файлов упаковщика, особенно packer_compiled.lua.

Я очень рекомендую видео typecraft на эту тему, если вы заинтересованы в этом переключении:

Процесс переключения с упаковщика на lazy.nvim очень прост, занимает мало времени, а различия в синтаксисе между двумя менеджерами плагинов минимальны. Из-за сочетания этих факторов Крис (автор вышеупомянутого видео) упомянул, что после того, как он переключил свой конфиг на lazy.nvim, он даже не был уверен, правильно ли он работает, и я честно с этим согласен. Процесс странно не впечатляет, но если это так, это хороший признак того, что все работает правильно.

Но причина, по которой я переключился на lazy.nvim, в первую очередь заключалась в том, что я заметил, что время запуска на моем рабочем столе было очень медленным (почти медленное VS Code).

У меня одинаковая настройка виртуальной машины на обоих моих устройствах (настольном компьютере и ноутбуке), а также одинаковая конфигурация Neovim. Зная, что мой рабочий стол, который я построил имеет гораздо лучшие характеристики, чем мой ноутбук (а также учитывая тот факт, что это настольный компьютер), я был очень удивлен, обнаружив, что мой рабочий стол запускает Neovim в 6 раз дольше.

Проведя несколько тестов во время настройки упаковщика, я обнаружил, что запуск Neovim на моем настольном компьютере занимает от 500 до 600 мс, в то время как на моем ноутбуке требуется немногим более 100 мс. Если вы не считаете, что есть заметная разница между 100 мс и 500 мс, то вы явно не тратили всю свою жизнь на настройку терминального текстового редактора раньше.

Как упоминалось ранее, время запуска около 100 мс кажется, что Neovim запускается «мгновенно», в то время как все, что превышает 250 мс, начинает ощущаться довольно вялым. Я бы даже сказал, что примерно через 180–200 мс я начинаю наблюдать заметную задержку. Возможно, это как-то связано с тем, что время моей реакции очень похоже.

Но не только Neovim был медленным. Я заметил, что виртуальная машина на моем рабочем столе в целом работала значительно медленнее. Самым очевидным отличием было взаимодействие с браузером. На моем ноутбуке все было так же, как если бы я использовал Google Chrome в основной ОС (Windows 10), но на моем рабочем столе все было прерывисто, и некоторые действия задерживались.

Еще одним заметным отличием было то, насколько быстрым был терминал. Когда я устанавливал пакеты с помощью apt на свой ноутбук, ввод команды и последующий процесс установки казались совершенно «нормальными». Не на что было жаловаться с точки зрения обратной связи и скорости. Однако на своем рабочем столе я заметил небольшую задержку между вводом символа и его отображением в терминале, и, кроме того, процесс установки был немного медленнее.

Таким образом, было очевидно, что что-то не так с тем, как мой рабочий стол виртуализирует ОС Ubuntu, и решение этой проблемы сократит время запуска намного больше, чем любые оптимизации плагинов.

К моему удивлению, после перехода на lazy.nvim время запуска стало медленнее, а не быстрее. Хотя это время запуска было не намного медленнее (около десятков мс), это все равно не было хорошим знаком. Поэтому я сразу же присмотрелся к плагинам с ленивой загрузкой.

Моим первым побуждением было лениво загрузить все и просто посмотреть, что произойдет. Поэтому, используя некоторые макросы Vim, я быстро добавил lazy = true в конец каждого плагина и перезапустил Neovim. Как я и ожидал, некоторые плагины сломались, но это почти не имело для меня значения, когда я увидел, насколько быстрее у меня было время запуска.

После запуска нескольких тестов мое время запуска сократилось до 250 мс (с 600 мс!), что, безусловно, является огромным улучшением после того, как раньше приходилось ждать более полсекунды для запуска Neovim. Но вскоре реальность оправдалась, и я начал чинить свои плагины.

Когда я начал тестировать функциональность своих плагинов один за другим, я был удивлен, обнаружив, что даже некоторые из самых простых плагинов не работают. Тот факт, что переключение комментариев не работает, меня весьма удивил, так как я заметил, что ни gcc, ни gc не работают.

Итак, я удалил lazy = true из всех плагинов, которые не работали, и снова обнаружил, что у меня… время запуска 500 мс?

Казалось, что все снова заработало, но почему время запуска стало таким медленным? После быстрой проверки журналов --startuptime я определил виновника: markdown-preview.

По какой-то причине markdown-preview загружался невероятно долго (что-то около 200 мс, если я правильно помню), затмевая все остальные плагины с точки зрения времени загрузки, и я не имею в виду это в хорошем смысле. .

Интересно, что markdown-preview был единственным плагином, для которого мне пришлось искать синтаксис установки lazy.nvim, поскольку метод установки вызывал vim-функцию.

В этой ветке Reddit (гиперссылка ведет прямо на комментарий) вы найдете комментарий с кодом, который выглядит так:

{
    "iamcco/markdown-preview.nvim",
    config = function()
      vim.fn["mkdp#util#install"]()
    end
}

И хотя этот код работает для установки markdown-preview на lazy.nvim, я обнаружил, что он делает мою конфигурацию чрезвычайно медленной — в конце концов, это было основной причиной моего времени запуска 500 мс! Поэтому не рассматривая другие варианты установки этого плагина, я решил поискать альтернативу.

заглянуть

peek — еще один плагин предварительного просмотра Markdown для Neovim, хотя он использует несколько иной подход по сравнению с markdown-preview от iamcco. Используя Deno, среду выполнения JavaScript, peek загружает предварительный просмотр текущего файла Markdown с большинством основных функций из markdown-preview, но не в вашем браузере. Вместо этого он создает новое окно, привязанное к Neovim (в заголовке окна даже написано nvim), и по умолчанию это окно стилизовано под форматированные GitHub файлы Markdown.

Самая крутая и самая фундаментальная функция, которую peek поддерживает по сравнению с markdown-preview, — это «прокрутка» на основе Vim в любом окне. Другими словами, если вы нажмете j в файле Markdown в Neovim, последует предварительный просмотр; markdown-preview также делает то же самое в появившемся окне браузера. Однако, если вы нажмете j, сосредоточившись на окне браузера, созданном предварительным просмотром уценки, ничего не произойдет. Но нажатие j во время предварительного просмотра заставляет Neovim выполнять синхронизированную прокрутку, что, на мой взгляд, довольно круто.

Итак, после отключения markdown-preview и установки peek я обнаружил, что время запуска составляет 300 мс, что все еще в три раза больше, чем у моего ноутбука. Как это могло произойти? Мой процессор, память, материнская плата — на самом деле все в моем настольном компьютере превосходило мой ноутбук. И это не было проблемой недораспределения ОЗУ для моей виртуальной машины Ubuntu, так как они обе получали по 4 ГБ (я пробовал выделять 8 ГБ, на самом деле это не имеет значения).

Запретный гипервизор

Гипервизор — это программное обеспечение, которое создает и запускает виртуальные машины, позволяя одному хост-компьютеру поддерживать несколько гостевых виртуальных машин, виртуально разделяя свои ресурсы. По сути, гипервизоры могут позволить системе использовать больше доступных ресурсов, а также повысить мобильность, поскольку виртуальные машины не зависят от аппаратного обеспечения хоста.

Как это связано с Neovim? Мой рабочий стол использовал гипервизор для виртуализации, что могло повлиять на производительность виртуальной машины и, следовательно, повлиять на производительность Neovim. И хотя существует несколько способов отключения гипервизора Microsoft, Hyper-V, ничто не повлияло на поведение виртуализации моего рабочего стола. Вот два способа отключения Hyper-V в Windows:

Отключение Hyper-V через панель управления:

  1. Открыть панель управления
  2. Выберите Программы и компоненты.
  3. Выберите Включает или отключает функции Windows.
  4. Разверните папку Hyper-V, затем разверните Платформа Hyper-V и отключите гипервизор Hyper-V.

Отключение Hyper-V через Powershell:

  1. Откройте окно Powershell в качестве администратора
  2. Запустите эту команду:
Disable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V-Hypervisor

Попробовав оба этих варианта, я был разочарован, обнаружив, что виртуальная машина моего рабочего стола по-прежнему работает плохо. Взаимодействие с браузером было вялым, терминал не работал быстро, и самое главное, Neovim не запускался «мгновенно», как это было на моем ноутбуке.

И вот тогда я наткнулся на этого спасителя видео:

Я знаю, что это выглядит как одно из тех стереотипных обучающих видео по решениям, которые предлагают только одно решение (и это решение никогда не работает), которое вызывает массу неприязни, но это видео на самом деле было другим. Он предлагал различные способы ускорения виртуальных машин, одним из которых было отключение гипервизора с помощью команды, которую я раньше не видел:

bcdedit /set hypervisorlaunchtype off

После запуска этой команды с повышенным экземпляром командной строки я снова запустил свою виртуальную машину Ubuntu. Когда я вошел в систему, я почувствовал, что все происходит немного быстрее — система стала более отзывчивой, но только чуть-чуть. Когда я попытался открыть терминал с CTRL + ALT + T, у меня не было сомнений, что гипервизор отключен. Экземпляр терминала GNOME сразу же открылся, и я запустил сверхтонкий тест времени запуска Neovim, чтобы найти смехотворное время запуска всего 73 мс!

Я был вне себя от восторга. Я открыл Google Chrome и обнаружил, что он также открывается невероятно быстро по сравнению с предыдущим. Я пошел что-то искать и…

Меня встретила игра про динозавров Chrome. Это было странно. У моего рабочего стола было подключение к сети Ethernet, которое, как я точно знал, использовалось виртуальной машиной.

«Должно быть, это какая-то ошибка», — подумал я про себя, но после нескольких минут ожидания и попытки пропинговать Google с помощью команды ping 8.8.8.8 я подтвердил, что интернет моей виртуальной машины не работает. Как говорится, исправление одной ошибки всегда порождает другую…

Сначала я думал, что это будет так же просто, как перезапустить виртуальную машину. Я выключил его, снова открыл VMWare Workstation и перезагрузил Ubuntu. Нет игральных костей. Я попробовал еще раз, чтобы убедиться. Ничего. Поэтому я сделал единственное, что умею делать как программист: обратился к Stack Overflow (или, по крайней мере, к его эквиваленту для компьютерных энтузиастов).



Используя один из первых результатов поиска, на который я наткнулся, я нашел гениальное и простое решение, требующее множества перезапусков. Это кажется довольно избыточным, но это сработало для меня:

  1. Выключить виртуальную машину
  2. Удалите сетевой адаптер из виртуальной машины
  3. Включите виртуальную машину, затем выключите ее.
  4. Откройте файл vmx виртуальной машины (это может быть странно найти в Windows, поскольку файловый менеджер явно не указывает расширение файла) с помощью текстового редактора и удалите все строки, начинающиеся с «ethernet0».
  5. Включите виртуальную машину, затем выключите ее.
  6. Добавьте новый сетевой адаптер к виртуальной машине
  7. Включите виртуальную машину, но на этот раз не выключайте ее.
  8. Откройте терминал и выполните эту команду: ip link
  9. Найдите сетевой интерфейс (для моей виртуальной машины Ubuntu это был ens33) и запустите эту команду sudo ip link set <INTERFACE> up, заменив <INTERFACE> фактическим сетевым интерфейсом.
  10. Наконец, заставьте сетевой интерфейс искать IP-адрес с помощью этой команды: sudo dhclient <INTERFACE> -v

Без повторного перезапуска в конце этих шагов моя виртуальная машина снова была подключена к Интернету! Neovim работал невероятно быстро, и все казалось очень быстрым и отзывчивым. Что еще я мог попросить?

Больше плагинов.

"прыгнуть"

Leap — это плагин движения для Neovim, который полностью заменяет функциональность мыши при навигации по тексту. Вы можете возразить, что Vim сам по себе не нуждается в мыши, но на самом деле он не делает этого из коробки.

Чтобы переместить курсор в нужное место в Vim, в зависимости от сценария необходимо выполнить несколько действий:

  1. Если текст виден, прыгайте вверх или вниз, используя относительные номера строк, чтобы сначала добраться до нужной строки. Затем используйте что-то вроде перехода через f символа или w слова, чтобы добраться до точной позиции в этой строке.
  2. Если текст в данный момент не виден, используйте CTRL + U или CTRL + D (у меня они переназначены на CTRL + K и CTRL + J соответственно), чтобы прыгать вверх и вниз по файлу, пока первый сценарий не станет актуальным; применять философию первого сценария.
  3. Используйте поиск /, чтобы найти точную последовательность символов, и используйте n и N, чтобы перейти к правильному экземпляру (для этого требуется больше знаний о коде или тексте, чем просто «охота» за ним, как в предыдущих двух сценариях).

Из этих трех сценариев Leap действительно обращается только к первому, поскольку это единственный сценарий, в котором вы должны использовать мышь, чтобы указать и щелкнуть туда, куда вы хотите, чтобы ваш курсор переместился в редакторе, таком как VS Code. Это может облегчить понимание:

Давайте представим, что вы используете стандартный редактор кода, такой как VS Code. Во втором сценарии вы на самом деле не щелкаете мышью в нужном месте курсора. Поскольку текст не виден на экране, вы меняете «представление» вашего редактора кода, прокручивая его вверх или вниз. Независимо от того, достигаете ли вы этого с помощью ввода с клавиатуры (клавиши со стрелками вверх и вниз, клавиши со стрелками страницы вверх и вниз и т. д.) или ввода с помощью мыши (колесико прокрутки вверх и колесо прокрутки вниз, щелчок и перетаскивание на панели навигации сбоку и т. д.) , это не меняет того факта, что вы не нажимаете на определенное место, куда должен перейти курсор.

В третьем сценарии вы вообще не пользуетесь мышью, поскольку выполняете что-то вроде CTRL + F, а затем просто ищете нужные символы.

Это только первый сценарий, в котором вы должны щелкнуть где-нибудь, чтобы начать редактирование текста. Так как же Leap достигает этого, не копируя уже существующие движения Vim?

По умолчанию, когда вы используете s, Leap инициирует простой поиск с фильтрацией по двум символам. Когда вы вводите первую букву последовательности фильтров, Leap ищет весь видимый текст на экране перед курсором и ставит маркеры при каждом совпадении. Чтобы выполнить поиск в обратном направлении, то есть найти что-либо за курсором, просто начните поиск с S.

Затем вы можете ввести следующий символ вашей последовательности фильтров, что приведет к трем вещам: (1) более конкретно отфильтровать маркеры (поскольку теперь Leap фильтрует по двум указанным символам, а не по одному, (2) перейти к первому экземпляру этого двухсимвольного фильтра и (3) включить переход через маркеры символов.Если вы хотите перейти к маркеру, просто введите показанную букву для этого.

Таким образом, Leap позволяет вам попасть в любое место на текущем экране всего двумя или тремя входами. В случае, если ваш двухсимвольный фильтр заставляет ваш курсор переходить к первому (или единственному) экземпляру, содержащему эти два символа, вам потребуется только два ввода. Если это не так, вам нужно будет указать, куда вы хотите перейти, с помощью одного из сгенерированных маркеров, так что это считается третьим входом. Я знаю, что это объяснение не совсем понятно, поэтому вот пример. Рассмотрим этот фрагмент кода:

Чтобы сделать этот пример более осмысленным, давайте попробуем отредактировать какой-нибудь код с помощью Leap, который действительно имел бы смысл делать это с помощью Leap, и не обязательно потому, что это имело бы логический смысл в контексте кода. Другими словами, мы должны попытаться переместить курсор в какое-то место в коде, что будет быстрее сделать с помощью Leap, а не с помощью встроенных движений Vim.

Плохой пример — отредактировать раскладку, которая заставляет CTRL + A выбирать весь файл (на 27 строк ниже текущей позиции курсора) следующим образом:

keymap.set(… to vim.keymap.set(...

Хотя это не имеет смысла делать с точки зрения логики кода, также не имеет особого смысла прыгать туда с помощью Leap, чего я и пытаюсь добиться. Вместо использования Leap мы можем просто выполнить 27j, чтобы перейти на 27 строк вниз, а затем ввести ivim., чтобы войти в режим вставки, и вставить vim., которое должно предшествовать слову keymap.

Вместо этого давайте попробуем отредактировать что-то, чего нет в первом столбце кода, например, удалить opts из раскладки клавиатуры на 18 строк ниже текущего местоположения курсора. Для этого нам нужно перейти к запятой перед opts, а затем удалить все до закрывающей скобки с de или dt). Этот второй вариант для его удаления может потребовать дополнительного нажатия клавиши, но может потребовать меньше умственных усилий в зависимости от того, как вы думаете в определенных сценариях (я бы сказал, что de — это тот, который требует меньше умственных усилий в этом случае).

Если бы мы следовали философии «движение по вертикали, затем движение по горизонтали», мы бы определенно сделали 18j для движения по вертикали, а что касается движения по горизонтали, у нас есть несколько вариантов. Две из них, которые приходят на ум, — либо использовать f символов, либо слов.

Для перехода на символ f простое выполнение f,;; переместит ваш курсор на , перед opts, поскольку f, переместит ваш курсор к первому , в строке, а ;; перейдет ко второму (и последнему) , в строке. С плагином smart-f это становится еще проще, так как вы можете просто выполнить f,ff. Затем просто выполните de или dt).

Хотя слово «прыгать» может звучать как довольно плохой вариант, вы должны иметь в виду, что возможно перескакивание слов назад. Так что даже если потребуется 19 w и два l, чтобы поставить курсор на запятую, это не имеет значения. Вместо этого мы можем сделать $bhh, так как $ перескакивает в конец строки, а b перескакивает через слова, но назад (hh настраивает курсор на запятую).

Примечание редактора. Вы также можете сделать что-нибудь причудливое, например $F,, но я не уверен, что это того стоит. Если вы так думаете, то вам больше силы.

Оба эти варианта не кажутся такими уж плохими. Один заключается в выполнении 18jf,;;, а другой включает в себя выполнение 18j$bhh. Ни то, ни другое не требует слишком больших умственных усилий, так как большая часть «обдумывания» уходит на проверку относительного числа перед выполнением 18j, хотя переход на f символов мог потребовать большего количества входных данных, если строка была длиннее и включала больше , символов (что не увеличивает умственную активность). накладные расходы вообще, это просто увеличивает количество необходимых входных данных).

Однако с помощью Leap мы можем устранить эту философию «вертикальное движение, затем горизонтальное движение», что особенно полезно, когда вы уже знаете, что хотите отредактировать. Не сводя глаз с того места, куда мы хотим прыгнуть, мы набираем s, чтобы начать поиск прыжка лицом вперед, затем набираем , в качестве нашего двухсимвольного фильтра (это запятая, за которой следует <SPC>, просто для ясности). Вот что мы увидим:

Для каждого места, где есть зеленая подсветка (цвет подсветки будет зависеть от вашей цветовой схемы), есть символ для обозначения маркера. Все они сдвинуты на два символа из отфильтрованной последовательности, чтобы вы могли видеть, куда вы переходите.

Поскольку мы следим за opts на 18 строк ниже текущей позиции курсора, мы увидим, какой символ связан с маркером, к которому мы хотим перейти — мы набираем c, и наш курсор прыгает туда! Затем мы просто выполняем вышеупомянутые de или dt).

Модульность lazy.nvim

Хотя я решил проблему низкой производительности моей виртуальной машины, отключив гипервизор, время запуска медленно увеличивалось снова и снова (что меня не удивило, учитывая количество плагинов, которые я объединил). Поэтому я начал изучать плагины с ленивой загрузкой немного дальше.

Однако я сразу же столкнулся с проблемой, что некоторые плагины просто не лениво загружались. Другими словами, попытка установить отложенную загрузку плагина с помощью параметра lazy = true lazy.nvim приведет к тому, что плагин вообще не будет работать. Но почему? Я понял, что для плагинов, написанных на Vimscript, таких как плагин smart-f, могут быть некоторые проблемы с совместимостью, но для всех плагинов, написанных на Lua (большинство из них), почему ленивая загрузка не работала?

Присмотревшись к тому, что отличало эти два набора плагинов (те, которые успешно загружались отложенной загрузкой, и те, которые не загружались), я заметил, что все те, которые не загрузились, использовали конфигурации по умолчанию или конфигурации, закодированные непосредственно в plugins.lua.

Теперь это имело такой смысл! Как плагин мог быть отложенно загружен, если у него не было другого файла, который можно было бы вызвать позже (позже это означает само событие отложенной загрузки)? По сути, правильный способ ленивой загрузки плагинов включает в себя модульную конфигурацию плагинов, в чем вы можете убедиться, взглянув на то, как я упорядочил свою собственную конфигурацию Neovim.

Конечно, есть и другие способы ленивой загрузки плагинов, например, загрузка их при нажатии определенных раскладок клавиш, но для меня время запуска достаточно быстрое благодаря времени, сэкономленному от слепой ленивой загрузки большинства плагинов — не то чтобы я бы рекомендуем сделать так.

Властелин Vims: Возвращение короля

Наконец-то мы подходим к третьей дуге моего конфига Neovim, где все сходит с ума из-за моего капризного характера. Будь то добавление подключаемых модулей, представляющих собой простые игры, или подключаемых модулей, которые постепенно превращают мой текстовый редактор все ближе и ближе к операционной системе, я полностью за это.

живи-будь-хорошим

vim-be-good — это плагин Neovim, разработанный, чтобы помочь вам улучшить работу с движениями Vim. Разработанная ThePrimeagen, vim-be-good — это простая игра, которая проверяет вашу способность выполнять движения Vim, измеряя вашу производительность в нескольких испытаниях. В игре есть несколько режимов:

Вы можете запустить vim-be-good с помощью его команды :VimBeGood, а затем выбрать режим игры и сложность игры. Убедитесь, что у вас включены относительные номера строк — они не только необходимы для режима относительной игры, но и более прагматичны, чем абсолютные номера строк.

После того, как вы запустили vim-be-good, вы можете выбрать параметры, удалив строки (или dd). Изменение параметра сложности путем удаления соответствующей строки не запустит игру, но удаление одной из строк игрового режима запустит. Как только вы это сделаете, начнется обратный отсчет с 3, и игра начнется.

В каждой игре будет отображаться количество раундов, инструкции о том, что вам нужно сделать, и фактический текст, который необходимо отредактировать. Как только вы успешно выполните задание (или невидимый таймер текущего раунда истечет), начнется следующий раунд.

В режиме игры «слова» вам просто нужно использовать w и dw, чтобы удалить слова, которые отличаются в текущей строке.

Как вы можете видеть в приведенном выше примере, другое слово — это то, которое читается как «зар» вместо «вар». Чтобы удалить его, все, что нам нужно сделать, это выполнить wwwdw (обратите внимание, что другое слово может быть прямо под вашим курсором, поэтому, если вы ищете это другое слово слишком долго), просто выполните dw, чтобы удалить текущее слово).

Когда вы пройдете все 10 раундов, вы увидите конечный экран:

Вы увидите, сколько раундов вы успешно завершили, а также среднее время, затраченное на завершение раунда. Затем вы можете вернуться в меню с помощью 2jdd, повторить ту же игру с помощью 3jdd или выйти с помощью 4jdd (или, что более эффективно, ZZ).

В игровом режиме ci{ вы должны заменить содержимое между внешними скобками (которые могут быть как квадратными, так и волнистыми) на «bar». Как следует из названия игрового режима, вы должны использовать ci[ или ci{, чтобы быстро заменить внутреннее содержимое крайних скобок на «bar», а не делать что-то медленное, например, вручную выбирать внутреннюю часть скобок, удалять их, а затем выполнять O для создайте новую строку над курсором, а затем введите bar.

Если вы не знаете о ci в Vim, это в значительной степени означает «изменение внутри». Таким образом, символ, который следует за ci, будет изменен (это означает, что он не только будет удален, но и Vim автоматически переведет вас в режим вставки). Очень полезная команда — ciw, которая удалит текущее слово и переведет вас в режим вставки.

Я не буду перечислять все игровые режимы, в которые можно играть в vim-be-good — это вам решать!

Тетрис

Это Тетрис. В Неовим. Вот и все. Запускайте игру командой :Tetris и очищайте линии сколько душе угодно!

"Блэк Джек"

Подобно плагину Tetris, это простая игра, но на этот раз это блэкджек. Начните игру с :BlackJackNewGame и играйте в свое удовольствие (хотя здесь вы не рискуете потерять деньги)!

Пока мы говорим об играх…

Vim-lichess

Это верно. Вы можете играть в шахматы онлайн с реальными людьми… в Neovim! Плагин vim-lichess выглядит именно так, как кажется: клиент, который использует вызовы Lichess API для поиска игр, взаимодействия с доской, отправки предложений об отставке/ничьи и даже для чата с вашим оппонентом.

Конфигурация vim-lichess может быть немного запутанной, хотя я нашел документацию на странице GitHub особенно полезной.

Вам нужно будет установить berserk, который является пакетом для python3. Просто выполните pip install berserk, чтобы выполнить это требование. Говоря об этом, вам также понадобится python3, что вы можете проверить, если у вас есть некоторые команды :checkhealth.

Вам также понадобится учетная запись Lichess, которая будет связана с vim-lichess через ваш токен Lichess API. На самом деле вам будут предложены инструкции для этого, когда вы впервые выполните :LichessFindGame в первый раз. Есть также некоторые другие настройки, которые вам нужно будет применить, прежде чем вы сможете начать играть:

vim.g.lichess_api_token = 'NOT FOR YOU TO SEE!!!'
vim.g.lichess_time = 10
vim.g.lichess_increment = 0
vim.g.lichess_rated = 0
vim.g.lichess_variant = 'standard'
vim.g.lichess_color = 'random'

vim.g.python_cmd = 'python3'
vim.g.lichess_debug_level = -1

Когда все настроено, повторите :LichessFindGame и примите силу Магнуса Карлсена! Перемещайте фигуры, сначала щелкая левой кнопкой мыши по их исходному местоположению, а затем щелкая правой кнопкой мыши по целевым клеткам. Вы также можете печатать свои ходы, как профессиональный шахматист, в формате UCI. :LichessMakeMoveUCI e2e4 это просто пример.

Зона

Zone — это плагин скринсейвера для Neovim, эмулирующий то, как операционные системы отображают скринсейвер. Существует множество параметров конфигурации, в том числе, какая анимация должна воспроизводиться, когда Neovim остается бездействующим, как долго определяется этот период бездействия (имеется в виду, как долго Zone должна проверять отсутствие пользовательских входов перед запуском своей заставки) и т. д.

С этой конфигурацией у меня есть Zone, использующая анимацию DVD — ту, где вы смотрите логотип DVD в трансе, пока он не попадает в угол — до тех пор, пока Neovim не получает никаких входных данных в течение 30 секунд.

local status_ok, zone = pcall(require, 'zone')
if not status_ok then
    return
end

zone.setup({
    style = 'dvd',
    after = 30, -- Idle timeout
    exclude_filetypes = { 'TelescopePrompt', 'NvimTree', 'neo-tree', 'dashboard', 'lazy' },
    -- More options to come later

    treadmill = {
        direction = 'left',
        headache = true,
        tick_time = 30, -- Lower, the faster
        -- Opts for Treadmill style
    },
    epilepsy = {
        stage = 'aura', -- "aura" or "ictal"
        tick_time = 100,
    },
    dvd = {
        -- text = {"line1", "line2", "line3", "etc"}
        tick_time = 100,
        -- Opts for Dvd style
    },
    -- etc
})

Вы также заметите, что вы можете исключить определенные типы файлов из зоны действия над ними. Это очень разумно, так как выглядит особенно прикольно, когда Zone решает анимировать логотип DVD, подпрыгивающий в вашем проводнике, который занимает лишь небольшую часть в левой части экрана.

Шум

Noice — сложный для определения плагин. Проще говоря, это делает многие меню и всплывающие окна в Neovim похожими на NOICE.

Используя довольно новый vim.ui_attach API, Noice заставляет многие устаревшие элементы пользовательского интерфейса Neovim выглядеть современно и изящно. Например, когда вы вводите двоеточие для входа в командный режим, вместо того, чтобы ваша команда отображалась в левом нижнем углу в очень обыденной и скучной форме, Noice отобразит вашу команду в плавающем окне в середине вашего экрана, даже обновив его название в зависимости от того, что вы печатаете. Вот пример.

Здесь я просто нажал клавишу двоеточия, создав красивое плавающее окно из Noice с надписью «Cmdline».

Посмотрите внимательно сюда. Текстовое поле больше не читается как «Cmdline», а вместо этого читается как «Справка». Noice реагирует на то, что я набираю :h (это двоеточие, за которым следует «h», а затем пробел) в команде, изменяя заголовок плавающего окна на «Справка» и изменяя значок на вопросительный знак.

Noice также может создавать эти удивительные всплывающие меню каждый раз, когда вы записываете файл.

которые появляются в правом верхнем углу вашего терминала по умолчанию.

Вы можете многое сделать с Noice, и мое резюме действительно оказывает плагину медвежью услугу в отношении того, насколько он настраиваемый — я бы порекомендовал проверить его репозиторий GitHub, чтобы увидеть все доступные параметры.

"Прозрачный"

Я уверен, что вы видели множество рабочих процессов кодирования, которые предполагают прозрачность в их редакторах кода. Будь то VS Code или Vim, возможность видеть свои обои — это всегда круто, чтобы повысить свой статус программиста. С этим плагином прозрачности вы можете добиться именно этого.

Просто установите плагин так же, как с вашим любимым менеджером плагинов, и убедитесь, что он не загружен лениво (это может привести к некоторым искаженным визуальным эффектам для Neovim). Время загрузки довольно быстрое, поэтому оно практически незначительно даже без ленивой загрузки.

После установки просто используйте :TransparentToggle для включения или выключения прозрачности. Важно отметить, что эта прозрачность основана на прозрачности вашего терминала. Ubuntu по умолчанию использует терминал GNOME, и вы можете легко изменить прозрачность через встроенный графический интерфейс на странице «Настройки».

  1. Щелкните правой кнопкой мыши в открытой области терминала и выберите «Настройки».
  2. Перейдите на вкладку «Цвета» и отрегулируйте ползунок «Использовать прозрачный фон», поставив галочку напротив него.

Я бы порекомендовал установить его на какое-то значение от 10% до 25%, хотя это легче сказать, чем сделать с ползунком, который даже не отображает значение, на которое он установлен. Чтобы настроить прозрачность терминала GNOME, сделайте следующее:

Сначала используйте эту команду

dconf dump /org/gnome/terminal/legacy/profiles:/

чтобы найти профиль вашего терминала. Вы получите вывод, который выглядит следующим образом:

[:b1dcc9dd-5262-4d8d-a863-c897e6d979b9]
background-color='rgb(33,33,33)'
background-transparency-percent=10
bold-color-same-as-fg=true
bold-is-bright=false
default-size-columns=80
font='Hack Nerd Font 12'
foreground-color='rgb(255,255,255)'
use-system-font=false
use-theme-colors=false
use-theme-transparency=false
use-transparent-background=true
visible-name='kevinfengcs88'

Первая часть — это то, что вам нужно, за исключением квадратных скобок. В моем случае это :b1dcc9dd-5262-4d8d-a863-c897e6d979b9 . Затем выполните эту команду, заменив <profile-id> идентификатором вашего профиля (который начинается с двоеточия, поэтому обязательно включите его) и <value> желаемым значением прозрачности (не включайте угловые скобки).

dconf write /org/gnome/terminal/legacy/profiles:/<profile-id>/background-transparency-percent <value>

Я обнаружил, что установка непрозрачности моего терминала на 10 приводит к хорошему балансу между возможностью видеть мои обои и сохранением читабельности моего кода. Установка непрозрачности на 25 действительно начинает подталкивать меня, но это действительно выделяет мои обои.

Благодаря силе аниме вайфус от ThePrimagen и такому инструменту, как Разнообразие, я настроил его так, чтобы мои обои менялись каждые 5 секунд из указанного каталога. Я отфильтровал репозиторий обоев ThePrimeagen для моего любимого аниме-вайфуса (и, возможно, даже несколько моих собственных бонусов), и вы можете найти эти изображения в папке вайфуса моей конфигурации Neovim.

Однако это не единственный способ сделать Neovim прозрачным. Как я узнал от великого ThePrimeagen, вы можете включить что-то вроде этого в свой конфиг:

vim.api.nvim_set_hl(0, "Normal", { bg = "none" })
vim.api.nvim_set_hl(0, "NormalFloat", { bg = "none" })

Хотя я по-прежнему предпочитаю прозрачный плагин, так как я могу включить раскладку клавиатуры, которая переключает прозрачность в зависимости от того, хочу я этого или нет:

local opts = { noremap = true, silent = true }
local keymap = vim.keymap

keymap.set('n', '<C-t>', ':TransparentToggle<CR>', opts)

"Гарпун"

Конечно, последний плагин, который мы рассмотрим в нашем приключении, — это самый лучший плагин из всех, созданный величайшим из когда-либо существовавших Vimmer, ThePrimeagen.

Harpoon — это навигационный плагин, который следует философии Vim, не заходя так далеко, как bufferline.nvim. Основная функциональность Harpoon заключается в закреплении нужных буферов в меню Harpoon, к которому затем можно получить доступ как к обычному буферу, удалить закрепленные буферы или переключиться на закрепленные буферы. Я знаю, что это звучит несколько запутанно, поэтому я бы порекомендовал посмотреть видео ThePrimeagen от 0 до LSP, начиная с этой отметки времени, где он обсуждает Harpoon.

В моей конфигурации Harpoon я использую значения по умолчанию и включаю несколько полезных раскладок:

local harpoon_status_ok, harpoon = pcall(require, 'harpoon')
if not harpoon_status_ok then
    return
end

local harpoon_mark_status_ok, harpoon_mark = pcall(require, 'harpoon.mark')
if not harpoon_mark_status_ok then
    return
end

local harpoon_ui_status_ok, harpoon_ui = pcall(require, 'harpoon.ui')
if not harpoon_ui_status_ok then
    return
end

local opts = { noremap = true, silent = true }
local keymap = vim.keymap

harpoon.setup({
    menu = {
        width = 60,
    },
})

keymap.set('n', '<leader>h', harpoon_mark.add_file, opts)
keymap.set('n', '<C-e>', harpoon_ui.toggle_quick_menu, opts)

keymap.set('n', '<leader>1', function() harpoon_ui.nav_file(1) end, opts)
keymap.set('n', '<leader>2', function() harpoon_ui.nav_file(2) end, opts)
keymap.set('n', '<leader>3', function() harpoon_ui.nav_file(3) end, opts)
keymap.set('n', '<leader>4', function() harpoon_ui.nav_file(4) end, opts)
keymap.set('n', '<leader>5', function() harpoon_ui.nav_file(5) end, opts)
keymap.set('n', '<leader>6', function() harpoon_ui.nav_file(6) end, opts)
keymap.set('n', '<leader>7', function() harpoon_ui.nav_file(7) end, opts)
keymap.set('n', '<leader>8', function() harpoon_ui.nav_file(8) end, opts)
keymap.set('n', '<leader>9', function() harpoon_ui.nav_file(9) end, opts)

Я использую <leader>h для закрепления текущего буфера, в котором я нахожусь, в Harpoon, <C-e> для переключения меню Harpoon (раньше это было C-h, пока я не зарезервировал эту раскладку для перемещения влево при разделении буфера), а также <leader>x для перехода к x-му буферу в Harpoon. меню, где x — любое число от 1 до 9.

Я считаю, что Harpoon особенно полезен для проектов, к которым я постоянно возвращаюсь, например, для моей конфигурации Neovim. Поскольку я знаю, что мой README — это первый пункт в меню Harpoon, я просто запускаю <leader>1 и перехожу к нему буквально без каких-либо умственных затрат, поскольку на данный момент это мышечная память.

Божественные раскладки

Пока мы говорим о нашем владыке и спасителе ThePrimeagen, я хочу упомянуть несколько удивительных раскладок, которые я узнал из его видео от 0 до LSP, а также некоторые раскладки, на которые я наткнулся сам. Вот то, что я считаю самыми мощными раскладками в моем файле keymaps.lua.

local opts = { noremap = true, silent = true }
local keymap = vim.keymap

-- search movement keeps cursor in middle
keymap.set('n', 'n', 'nzzzv', opts)
keymap.set('n', 'N', 'Nzzzv', opts)

-- vertical movement keeps cursor in middle
keymap.set('n', '<C-j>', '<C-d>zz', opts)
keymap.set('n', '<C-k>', '<C-u>zz', opts)

-- vertical movement keeps cursor in middle (visual mode)
keymap.set('v', '<C-j>', '<C-d>zz', opts)
keymap.set('v', '<C-k>', '<C-u>zz', opts)

-- copy into system clipboard with CTRL + C
keymap.set('v', '<C-c>', '"+y', opts)

-- copy into host system clipboard with <leader>y
keymap.set('v', '<leader>y', '"*y', opts)

-- move lines around
keymap.set('v', 'J', ":m '>+1<CR>gv=gv", opts)
keymap.set('v', 'K', ":m '<-2<CR>gv=gv", opts)

-- the greatest remap ever (Primeagen)
keymap.set('v', '<leader>p', '"_dP', opts)

Давайте начнем с первых трех раскладок, которые удерживают курсор в середине экрана:

-- search movement keeps cursor in middle
keymap.set('n', 'n', 'nzzzv', opts)
keymap.set('n', 'N', 'Nzzzv', opts)

Первая раскладка просто гарантирует, что ваш курсор останется в центре при нажатии n или N при поиске последовательности с / .

-- vertical movement keeps cursor in middle
keymap.set('n', '<C-j>', '<C-d>zz', opts)
keymap.set('n', '<C-k>', '<C-u>zz', opts)

Следующая раскладка позволяет достичь двух целей: во-первых, она переназначает неудобные <C-d> и <C-u> на <C-j> и <C-k> соответственно. В конце концов, j и k уже используются для перемещения вниз и вверх, так почему для перехода на полстраницы требуются разные клавиши? Во-вторых, он очень просто поддерживает ваш курсор в центре экрана с помощью zz.

-- vertical movement keeps cursor in middle (visual mode)
keymap.set('v', '<C-j>', '<C-d>zz', opts)
keymap.set('v', '<C-k>', '<C-u>zz', opts)

Эта последняя раскладка клавиатуры делает то же самое, что и предыдущая, но также в визуальном режиме. Вот и все.

После этого у нас есть несколько раскладок, которые немного портят системный буфер обмена — они могут не работать, если вы не используете виртуальную машину или если у вас не установлен wl-clipboard.

-- copy into system clipboard with CTRL + C
keymap.set('v', '<C-c>', '"+y', opts)

-- copy into host system clipboard with <leader>y
keymap.set('v', '<leader>y', '"*y', opts)

Первый делает так, что я могу легко скопировать выбор в систему (гостевая ОС или Ubuntu в моем случае) с помощью интуитивно понятного <C-c>. То же самое может быть достигнуто для основной ОС (для меня Windows 10) с <leader>y.

-- move lines around
keymap.set('v', 'J', ":m '>+1<CR>gv=gv", opts)
keymap.set('v', 'K', ":m '<-2<CR>gv=gv", opts)

Эта следующая раскладка также может быть очень полезной, хотя я бы поостерегся использовать K для перемещения строк вверх. Хотя он очень интуитивно понятен, он может конфликтовать с некоторыми раскладками LSP, в которых обычно используется заглавная буква K для перехода к определениям или описаниям функций. Конечно, это также маловероятно, учитывая, что эта раскладка клавиатуры является визуальным режимом, но эй, вы никогда не должны быть слишком осторожными.

Как следует из комментария, J перемещает строку вниз на строку, эффективно заменяя текущую строку, на которой находится курсор, на строку под ней, а K делает то же самое, но в направлении вверх.

-- the greatest remap ever (Primeagen)
keymap.set('v', '<leader>p', '"_dP', opts)

Самая лучшая раскладка идет последней. Вы когда-нибудь пытались заменить что-то, выделив это в визуальном режиме, заменив его своим регистром, только чтобы обнаружить, что ваш регистр был украдкой переопределен тем, что вы только что удалили?

Хорошо, я знаю, что это было ужасное объяснение. Вместо этого рассмотрим простой пример:

System.out.println("Hello world!");
System.out.println("foobar");

Давайте представим, что я хочу, чтобы эта программа распечатала «Hello world!» трижды вместо того, чтобы печатать «Hello world!» а затем «foobar». Так что же нам делать?

Во-первых, мы должны скопировать первую строку в наш регистр Vim с чем-то вроде yy или даже Vy. После этого мы выполняем j, чтобы перейти к строке, которая выводит «foobar». Поскольку мы хотим заменить всю строку, мы выбираем всю строку с V и заменяем ее на «Hello world!» строка с p .

Теперь наш код выглядит так:

System.out.println("Hello world!");
System.out.println("Hello world!");

Нам нужен еще один «Hello world!» оператор печати, так как мы хотим, чтобы он печатался три раза, верно? Таким образом, выполнение p может показаться самым простым способом сделать это, но на самом деле это приведет к следующему:

System.out.println("Hello world!");
System.out.println("Hello world!");
System.out.println("foobar");

Почему это? Что ж, у Vim есть неприятная (но весьма полезная) привычка сохранять все, что было только что удалено, в своем реестре, поэтому, когда мы удаляли строку, в которой напечатано «foobar», мы сохраняли это в нашем реестре (который вставляется, когда мы нажимаем p ). Чтобы обойти это, мы используем раскладку клавиатуры <leader>p, которая была определена ранее при вставке строки «foobar», сохраняя наш исходный регистр для использования при вставке с помощью p.

Bonus Terminal Fun Stuff (figlet + lolcat + neofetch)

Прежде чем мы закончим, я хотел бы включить несколько бонусных инструментов, которые я использую, чтобы сделать свой терминал еще круче:

Благодаря мощности figlet, lolcat и neofetch я могу сделать запуск своего терминала довольно элегантным. Установите все это с помощью вашего любимого менеджера пакетов (настройка не требуется).

Вы можете проверить figlet с помощью чего-то вроде

figlet "Neovim is cool"

который должен вывести это:

 _   _                 _             _                       _ 
| \ | | ___  _____   _(_)_ __ ___   (_)___    ___ ___   ___ | |
|  \| |/ _ \/ _ \ \ / / | '_ ` _ \  | / __|  / __/ _ \ / _ \| |
| |\  |  __/ (_) \ V /| | | | | | | | \__ \ | (_| (_) | (_) | |
|_| \_|\___|\___/ \_/ |_|_| |_| |_| |_|___/  \___\___/ \___/|_|

Затем вы можете передать этот вывод на lolcat вот так

figlet "Neovim is cool" | lolcat

который выведет этот действительно классный радужный текст ASCII:

Наконец, вы можете протестировать neofetch без параметров, чтобы получить некоторую информацию о вашей системе вместе с ASCII-изображением вашей операционной системы. Соедините все это вместе с некоторыми командами в верхней части вашего .bashrc или .zshrc, как это

figlet -f big "Kevin Feng" | lolcat
neofetch

позволяет нам получать это удивительное приветствие от нашего терминала каждый раз, когда мы его открываем:

Заключение

В заключение, я больше никогда не буду писать эту длинную статью о Neovim. Хотя это было весело, я выдохся на полпути и отложил доделку на целый месяц (просто посмотрите на разницу в датах между веткой репозитория GitHub, которую я упомянул в начале, и датой публикации).

Также могу с уверенностью заявить, что, наверное, до конца жизни не избавлюсь от конфигурации Neovim. Мне уже нужно поработать над Windows этим летом, так что я с нетерпением жду, чтобы снова заняться всем этим, но для Windows…

До следующего раза и счастливого Вимминга!

Источники

https://www.reddit.com/r/vim/comments/39jtib/what_is_the_difference_between_mapleader_and/

https://www.vmware.com/topics/glossary/content/hypervisor.html