更新 2023.3
突然发现之前的配置好像没有正确使用 lazy.nvim
,
准备从 NvChad 那里再抄一些新东西过来,
最新版的配置可以在 这里 找到。
引言
本周,我总计第三次折腾了自己的 neovim 配置,目前感觉还可以。 之后这段时间计划尝试长期使用,不知道能坚持多久。
第一次用 neovim 是在刚加入浮动窗口那段时间,我抄了大部分之前的 vim 配置, 然后尝试用
coc.nvim
做补全,一段时间后还是回去用 VSCode 了。第二次用是听说 neovim 加入了内置的 LSP 支持,再次尝试折腾,但是 懒得学了,于是用了现成的
lunarvim
项目,自己基本没做配置。 这个项目用了大量 lua 写的新一代插件,感觉体验是比之前好多了, 但不是自己配置还是有些不顺手,一段时间后发现还是 VSCode 用得更多。这次是因为看到了
kickstart.nvim
这个项目,感觉自己配置好像也并不复杂, 于是简单学了下 lua 相关的配置方式,在这基础上修改成现在的配置。
此外,最近我 Windows 用得比较多, 这次配置的最终目标不仅是配好服务器, 还包括改进我在 Windows 下的使用体验,使其能够作为日常编辑器使用。
最终,除了 Windows 上面编译 tree-sitter 的语言支持稍微麻烦了一点, 由于 LSP 的存在,感觉一套配置跨平台的使用体验基本上是一致的。
下图是在 Windows 用 fvim 连接服务端编辑远程文件的截图:
基本配置
基本是照抄 kickstart.nvim
, 也加了一些自己的配置,比如折行,相对行号.
-- [[ Basic Settings ]]
-- Set highlight on search
vim.o.hlsearch = false
-- Make line numbers default
vim.wo.number = true
-- Enable mouse mode
vim.o.mouse = 'a'
-- Enable break indent
vim.o.breakindent = true
-- Save undo history
vim.o.undofile = true
-- Case insensitive searching UNLESS /C or capital in search
vim.o.ignorecase = true
vim.o.smartcase = true
-- Decrease update time
vim.o.updatetime = 250
vim.wo.signcolumn = 'yes'
-- Set color
vim.o.termguicolors = true
-- Set completeopt to have a better completion experience
vim.o.completeopt = 'menuone,noselect'
-- my custom setting
vim.opt.cmdheight = 1
vim.opt.spelllang = "cjk"
vim.opt.relativenumber = true
vim.wo.cursorline = true
vim.wo.wrap = false
-- my default tabwidth
local TABWIDTH = 4
vim.opt.tabstop = TABWIDTH
vim.opt.shiftwidth = TABWIDTH
vim.opt.expandtab = true
-- [[ Basic Keymaps ]]
-- Set <space> as the leader key
-- NOTE: Must happen before plugins are required (otherwise wrong leader will be used)
vim.g.mapleader = ' '
vim.g.maplocalleader = ' '
-- Keymaps for better default experience
vim.keymap.set({ 'n', 'v' }, '<Space>', '<Nop>', { silent = true })
-- Remap for dealing with word wrap
vim.keymap.set('n', 'k', "v:count == 0 ? 'gk' : 'k'", { expr = true, silent = true })
vim.keymap.set('n', 'j', "v:count == 0 ? 'gj' : 'j'", { expr = true, silent = true })
-- use Alt-hjkl to move between windows
vim.keymap.set('n', '<A-h>', '<C-w>h')
vim.keymap.set('n', '<A-j>', '<C-w>j')
vim.keymap.set('n', '<A-k>', '<C-w>k')
vim.keymap.set('n', '<A-l>', '<C-w>l')
-- keymap for toggle some plugin
vim.keymap.set('n', '<leader>t', '<cmd>exe v:count1 . "ToggleTerm"<cr>')
vim.keymap.set('n', '<leader>T', '<cmd>exe v:count1 . "ToggleTerm direction=vertical"<cr>')
vim.keymap.set('n', '<C-t>', '<cmd>exe v:count1 . "ToggleTerm direction=float"<cr>')
vim.keymap.set('n', '<leader>e', '<cmd>NvimTreeToggle<cr>')
-- Highlight on yank
local highlight_group = vim.api.nvim_create_augroup('YankHighlight', { clear = true })
vim.api.nvim_create_autocmd('TextYankPost', {
callback = function()
vim.highlight.on_yank()
end,
group = highlight_group,
pattern = '*',
})
插件配置
插件方面,我基本没有修改 LSP, tree-sitter 和补全相关的插件配置, 其他一部分常用插件稍微研究了一下做了些增减和配置。
此外,我把插件管理从 Packer
迁移到了比较新的 lazy.nvim
,
并稍微配了一下懒加载,
将 Windows 下的启动速度提高了不少(300ms -> 70ms)。
我还是更习惯所有配置写到一个文件里, 所以没有用推荐的更模块化的写法,仅用注释将不同插件配置简单隔开。 由于插件不算多,配置总行数在 600 左右,多数配置不用动,目前维护还不算麻烦。
-- [[ Plugin Settings ]]
-- Install lazy.nvim
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)
-- Config Catppuccin
local catppuccin = {
'catppuccin/nvim',
name = 'catppuccin',
lazy = false,
priority = 1000,
config = function()
require('catppuccin').setup({
flavour = 'mocha', -- latte, frappe, macchiato, mocha
transparent_background = true,
})
vim.cmd.colorscheme 'catppuccin'
end
}
-- Config lualine
local lualine = {
'nvim-lualine/lualine.nvim', -- Fancier statusline
dependencies = { 'catppuccin/nvim' },
event = "VeryLazy",
config = function()
require('lualine').setup {
options = {
icons_enabled = false,
theme = 'catppuccin',
component_separators = '|',
section_separators = '',
},
}
end
}
-- Config indent_blankline
local indent_blankline = {
'lukas-reineke/indent-blankline.nvim', -- Add indentation guides even on blank lines
event = { "BufReadPre", "BufNewFile" },
config = function()
require('indent_blankline').setup {
char = '┊',
show_trailing_blankline_indent = false,
}
end
}
-- Config gitsigns
local gitsigns = {
'lewis6991/gitsigns.nvim',
event = { "BufReadPre", "BufNewFile" },
config = function()
require('gitsigns').setup {
signs = {
add = { text = '+' },
change = { text = '~' },
delete = { text = '_' },
topdelete = { text = '‾' },
changedelete = { text = '~' },
},
}
-- keymap for previewing hunks
vim.keymap.set('n', '<leader>gh', '<cmd>Gitsigns preview_hunk<cr>', { desc = '[G]itsigns preview [H]unks' })
vim.keymap.set('n', '<leader>gp', '<cmd>Gitsigns prev_hunk<cr>', { desc = '[G]itsigns [P]revious hunk' })
vim.keymap.set('n', '<leader>gn', '<cmd>Gitsigns next_hunk<cr>', { desc = '[G]itsigns [N]ext hunk' })
end
}
-- Config barbar
local barbar = {
'romgrk/barbar.nvim',
dependencies = 'nvim-tree/nvim-web-devicons',
event = "BufAdd",
config = function()
-- use shift-hl to move between tabs, <leader>cb to close buffer
vim.keymap.set('n', '<S-h>', '<cmd>BufferPrevious<cr>')
vim.keymap.set('n', '<S-l>', '<cmd>BufferNext<cr>')
vim.keymap.set('n', '<leader>cb', '<cmd>BufferClose<cr>')
vim.keymap.set('n', '<leader>cp', '<cmd>BufferPickDelete<cr>')
-- set nvimtree sidebar offset (FIXME: resize not follow mouse click issue #1545)
local nvim_tree_events = require('nvim-tree.events')
local bufferline_api = require('bufferline.api')
local function get_tree_size()
return require('nvim-tree.view').View.width
end
-- subscribe nvim-tree events
nvim_tree_events.subscribe("TreeOpen", function()
bufferline_api.set_offset(get_tree_size(), 'File Explorer')
end)
nvim_tree_events.subscribe("Resize", function()
bufferline_api.set_offset(get_tree_size(), 'File Explorer')
end)
nvim_tree_events.subscribe("TreeClose", function()
bufferline_api.set_offset(0)
end)
-- better Resize event for nvim-tree (with mouse and `<C-w><>` support)
if vim.fn.has('nvim-0.9') == 1 then
local group = vim.api.nvim_create_augroup("nvim_tree_resize", { clear = true })
vim.api.nvim_create_autocmd('WinResized', {
group = group,
pattern = { "*" },
callback = function()
local windows = vim.v.event.windows
for _, win_id in ipairs(windows) do
local buf = vim.api.nvim_win_get_buf(win_id)
if buf and vim.bo[buf].filetype == "NvimTree" then
local width = vim.api.nvim_win_get_width(win_id)
require('nvim-tree.view').resize(width)
break
end
end
end,
})
end
end
}
-- Config toggleterm
local toggleterm = {
'akinsho/toggleterm.nvim',
version = '*', -- Terminal
cmd = { 'ToggleTerm' },
config = function()
require('toggleterm').setup({
size = function(term)
if term.direction == 'horizontal' then
return 15
elseif term.direction == 'vertical' then
return vim.o.columns * 0.4
end
end
})
-- set keymaps to easily move between buffers and terminal
function _G.set_terminal_keymaps()
local opts = { buffer = 0 }
vim.keymap.set('t', '<esc>', [[<C-\><C-n>]], opts)
vim.keymap.set('t', 'jk', [[<C-\><C-n><Cmd>ToggleTerm<CR>]], opts)
end
vim.cmd('autocmd! TermOpen term://* lua set_terminal_keymaps()')
end
}
-- Config nvim-tree
local nvimtree = {
'nvim-tree/nvim-tree.lua',
dependencies = 'nvim-tree/nvim-web-devicons',
cmd = { 'NvimTreeToggle', 'NvimTreeFocus' },
config = function()
require('nvim-tree').setup({
actions = {
change_dir = {
enable = true,
global = true
}
},
renderer = {
indent_markers = {
enable = true
}
}
})
end
}
-- Config treesitter
local treesitter = {
'nvim-treesitter/nvim-treesitter',
event = "BufReadPost",
build = function()
pcall(require('nvim-treesitter.install').update { with_sync = true })
end,
config = function()
require('nvim-treesitter.configs').setup {
-- Add languages to be installed here that you want installed for treesitter
ensure_installed = { 'c', 'cpp', 'go', 'lua', 'python', 'rust', 'help' },
highlight = { enable = true },
indent = { enable = true, disable = { 'python' } },
incremental_selection = {
enable = true,
keymaps = {
init_selection = '<c-space>',
node_incremental = '<c-space>',
scope_incremental = '<c-s>',
node_decremental = '<c-backspace>',
},
},
textobjects = {
select = {
enable = true,
lookahead = true, -- Automatically jump forward to textobj, similar to targets.vim
keymaps = {
-- You can use the capture groups defined in textobjects.scm
['aa'] = '@parameter.outer',
['ia'] = '@parameter.inner',
['af'] = '@function.outer',
['if'] = '@function.inner',
['ac'] = '@class.outer',
['ic'] = '@class.inner',
},
},
move = {
enable = true,
set_jumps = true, -- whether to set jumps in the jumplist
goto_next_start = {
[']m'] = '@function.outer',
[']c'] = '@class.outer',
},
goto_next_end = {
[']M'] = '@function.outer',
[']C'] = '@class.outer',
},
goto_previous_start = {
['[m'] = '@function.outer',
['[c'] = '@class.outer',
},
goto_previous_end = {
['[M'] = '@function.outer',
['[C'] = '@class.outer',
},
},
swap = {
enable = true,
swap_next = {
['<leader>a'] = '@parameter.inner',
},
swap_previous = {
['<leader>A'] = '@parameter.inner',
},
},
},
}
-- Diagnostic keymaps
vim.keymap.set('n', '[d', vim.diagnostic.goto_prev)
vim.keymap.set('n', ']d', vim.diagnostic.goto_next)
vim.keymap.set('n', '<leader>df', vim.diagnostic.open_float) -- diagnostic float
vim.keymap.set('n', '<leader>dq', vim.diagnostic.setloclist) -- diagnostic quickfix
end
}
-- Config luasnip
local lua_snip = {
'L3MON4D3/LuaSnip',
event = "InsertEnter",
dependencies = {
'rafamadriz/friendly-snippets',
config = function()
require('luasnip.loaders.from_vscode').lazy_load()
end,
},
}
-- Config nvim-cmp
local cmp = {
'hrsh7th/nvim-cmp',
event = "InsertEnter",
dependencies = { 'hrsh7th/cmp-buffer', 'hrsh7th/cmp-path', 'hrsh7th/cmp-nvim-lsp',
'hrsh7th/cmp-nvim-lsp-signature-help',
'L3MON4D3/LuaSnip', 'saadparwaiz1/cmp_luasnip',
},
config = function()
local cmp = require 'cmp'
local luasnip = require 'luasnip'
cmp.setup {
snippet = {
expand = function(args)
luasnip.lsp_expand(args.body)
end,
},
mapping = cmp.mapping.preset.insert {
['<C-d>'] = cmp.mapping.scroll_docs(-4),
['<C-f>'] = cmp.mapping.scroll_docs(4),
['<C-Space>'] = cmp.mapping.complete(),
['<CR>'] = cmp.mapping.confirm {
behavior = cmp.ConfirmBehavior.Replace,
select = true,
},
['<Tab>'] = cmp.mapping(function(fallback)
if cmp.visible() then
cmp.select_next_item()
elseif luasnip.expand_or_jumpable() then
luasnip.expand_or_jump()
else
fallback()
end
end, { 'i', 's' }),
['<S-Tab>'] = cmp.mapping(function(fallback)
if cmp.visible() then
cmp.select_prev_item()
elseif luasnip.jumpable(-1) then
luasnip.jump(-1)
else
fallback()
end
end, { 'i', 's' }),
},
sources = {
{ name = 'nvim_lsp' },
{ name = 'luasnip' },
{ name = 'buffer' },
{ name = 'path' },
{ name = 'nvim_lsp_signature_help' }
},
}
end
}
-- Config LSP
local lspconfig = {
'neovim/nvim-lspconfig',
event = { "BufReadPre", "BufNewFile" },
dependencies = {
-- Automatically install LSPs to stdpath for neovim
{ 'williamboman/mason.nvim', config = true, cmd = "Mason" },
'williamboman/mason-lspconfig.nvim',
-- Useful status updates for LSP
{ 'j-hui/fidget.nvim', config = true },
-- Additional lua configuration, makes nvim stuff amazing
{ 'folke/neodev.nvim', config = true },
'hrsh7th/cmp-nvim-lsp',
},
config = function()
-- LSP settings.
-- This function gets run when an LSP connects to a particular buffer.
local on_attach = function(_, bufnr)
-- In this case, we create a function that lets us more easily define mappings specific
-- for LSP related items. It sets the mode, buffer and description for us each time.
local nmap = function(keys, func, desc)
if desc then
desc = 'LSP: ' .. desc
end
vim.keymap.set('n', keys, func, { buffer = bufnr, desc = desc })
end
nmap('<leader>rn', vim.lsp.buf.rename, '[R]e[n]ame')
nmap('<leader>ca', vim.lsp.buf.code_action, '[C]ode [A]ction')
nmap('gd', vim.lsp.buf.definition, '[G]oto [D]efinition')
nmap('gr', require('telescope.builtin').lsp_references, '[G]oto [R]eferences')
nmap('gI', vim.lsp.buf.implementation, '[G]oto [I]mplementation')
nmap('<leader>D', vim.lsp.buf.type_definition, 'Type [D]efinition')
nmap('<leader>ds', require('telescope.builtin').lsp_document_symbols, '[D]ocument [S]ymbols')
nmap('<leader>ws', require('telescope.builtin').lsp_dynamic_workspace_symbols, '[W]orkspace [S]ymbols')
-- See `:help K` for why this keymap
nmap('K', vim.lsp.buf.hover, 'Hover Documentation')
nmap('<C-k>', vim.lsp.buf.signature_help, 'Signature Documentation')
-- Lesser used LSP functionality
nmap('gD', vim.lsp.buf.declaration, '[G]oto [D]eclaration')
nmap('<leader>wa', vim.lsp.buf.add_workspace_folder, '[W]orkspace [A]dd Folder')
nmap('<leader>wr', vim.lsp.buf.remove_workspace_folder, '[W]orkspace [R]emove Folder')
nmap('<leader>wl', function()
print(vim.inspect(vim.lsp.buf.list_workspace_folders()))
end, '[W]orkspace [L]ist Folders')
-- Create a command `:Format` local to the LSP buffer
vim.api.nvim_buf_create_user_command(bufnr, 'Format', function(_)
vim.lsp.buf.format()
end, { desc = 'Format current buffer with LSP' })
vim.keymap.set('n', '<Leader>f', ":Format<cr>")
end
-- Enable the following language servers
local servers = {
-- clangd = {},
-- gopls = {},
-- pyright = {},
-- rust_analyzer = {},
-- pylsp = {
-- configurationSources = { "flake8" },
-- plugins = {
-- jedi_completion = {
-- include_params = true -- this line enables snippets
-- },
-- },
-- },
sumneko_lua = {
Lua = {
workspace = { checkThirdParty = false },
telemetry = { enable = false },
},
},
}
-- nvim-cmp supports additional completion capabilities, so broadcast that to servers
local capabilities = vim.lsp.protocol.make_client_capabilities()
capabilities = require('cmp_nvim_lsp').default_capabilities(capabilities)
-- Ensure the servers above are installed
local mason_lspconfig = require 'mason-lspconfig'
mason_lspconfig.setup {
ensure_installed = vim.tbl_keys(servers),
}
mason_lspconfig.setup_handlers {
function(server_name)
require('lspconfig')[server_name].setup {
capabilities = capabilities,
on_attach = on_attach,
settings = servers[server_name],
}
end,
}
end
}
-- Config autopairs
local autopairs = {
"windwp/nvim-autopairs",
event = "InsertEnter",
config = function()
require("nvim-autopairs").setup {}
-- config autopairs
local cmp_autopairs = require('nvim-autopairs.completion.cmp')
local nvim_cmp = require('cmp')
nvim_cmp.event:on(
'confirm_done',
cmp_autopairs.on_confirm_done()
)
end
}
-- Config illuminate
local illuminate = {
'RRethy/vim-illuminate',
event = "BufReadPost",
config = function()
require("illuminate").configure({
delay = 200,
filetypes_denylist = {
"NvimTree",
"toggleterm",
"TelescopePrompt",
},
})
end,
keys = {
{
"]r",
function()
require("illuminate").goto_next_reference(false)
end,
desc = "illuminate Next Reference",
},
{
"[r",
function()
require("illuminate").goto_prev_reference(false)
end,
desc = "illuminate Prev Reference",
},
},
}
-- Config telescope
local telescope = {
'nvim-telescope/telescope.nvim',
version = '0.1.x',
dependencies = { 'nvim-lua/plenary.nvim' },
config = function()
require('telescope').setup {
defaults = {
mappings = {
i = {
['<C-u>'] = false,
['<C-d>'] = false,
},
},
},
}
-- Enable telescope fzf native, if installed
pcall(require('telescope').load_extension, 'fzf')
-- Keymap for toggling telescope
vim.keymap.set('n', '<leader>?', require('telescope.builtin').oldfiles, { desc = '[?] Find recently opened files' })
vim.keymap.set('n', '<leader><space>', require('telescope.builtin').buffers, { desc = '[ ] Find existing buffers' })
vim.keymap.set('n', '<leader>sb', function()
-- You can pass additional configuration to telescope to change theme, layout, etc.
require('telescope.builtin').current_buffer_fuzzy_find(require('telescope.themes').get_dropdown {
winblend = 10,
previewer = false,
})
end, { desc = '[S]earch [B]uffer' })
vim.keymap.set('n', '<leader>p', require('telescope.builtin').find_files,
{ desc = 'Ctrl-P: Search file in current directory' })
vim.keymap.set('n', '<leader>sh', require('telescope.builtin').help_tags, { desc = '[S]earch [H]elp' })
vim.keymap.set('n', '<leader>sw', require('telescope.builtin').grep_string, { desc = '[S]earch current [W]ord' })
vim.keymap.set('n', '<leader>sg', require('telescope.builtin').live_grep, { desc = '[S]earch by [G]rep' })
vim.keymap.set('n', '<leader>sd', require('telescope.builtin').diagnostics, { desc = '[S]earch [D]iagnostics' })
end
}
-- Config Lazy
require('lazy').setup({
-- Theme
catppuccin,
-- UI related
lualine,
indent_blankline,
gitsigns,
barbar,
toggleterm,
nvimtree,
-- Coding
treesitter,
{ 'nvim-treesitter/nvim-treesitter-textobjects', event = "BufReadPost", dependencies = { 'nvim-treesitter' } },
lua_snip,
cmp,
lspconfig,
autopairs,
illuminate,
{ 'numToStr/Comment.nvim', config = true }, -- "gc" to comment visual regions/lines}
'tpope/vim-sleuth', -- Detect tabstop and shiftwidth automatically
-- Fuzzy Finder (files, lsp, etc)
telescope,
-- Fuzzy Finder Algorithm which requires local dependencies to be built. Only load if `make` is available
{ 'nvim-telescope/telescope-fzf-native.nvim', build = 'make', cond = vim.fn.executable 'make' == 1 },
})
-- The line beneath this is called `modeline`. See `:help modeline`
-- vim: ts=2 sts=2 sw=2 et
图形界面
虽然在 Windows Terminal 里用 TUI 的体验已经挺不错了, 但单独的 GUI 程序还是有必要的。
之前用图形界面主要尝试过 neovide,buffer 的平滑滚动很舒服, 这次发现在 Windows 下用问题还是有点多。
后来我找到了 fvim 这个项目, 解决了很多痛点,可配置项很多,配置也很方便,输入法界面也正常。 可惜看起来最近维护不是很活跃,希望这个项目能继续长久发展下去。
我的 ginit.vim
文件:
lua << EOF
-- config neovide
if vim.fn.exists("g:neovide") == 1 then
vim.g.neovide_transparency = 0.98
vim.g.neovide_floating_blur_amount_x = 2.0
vim.g.neovide_floating_blur_amount_y = 2.0
vim.opt.guifont = { "JetBrainsMono NF", ":h11" }
end
-- config fvim
if vim.fn.exists('g:fvim_loaded') == 1 then
vim.opt.guifont = { "JetBrains Mono", ":h15" } -- with embedded NF font
vim.keymap.set('n', '<C-ScrollWheelUp>', '<cmd>set guifont=+<cr>', { silent = true })
vim.keymap.set('n', '<C-ScrollWheelDown>', '<cmd>set guifont=-<cr>', { silent = true })
vim.keymap.set('n', '<A-CR>', '<cmd>FVimToggleFullScreen<cr>', { silent = true })
vim.cmd [[ FVimCursorSmoothMove v:true ]]
vim.cmd [[ FVimCursorSmoothBlink v:true ]]
vim.cmd [[ FVimBackgroundComposition 'blur' ]]
vim.cmd [[ FVimBackgroundOpacity 0.9 ]]
vim.cmd [[ FVimBackgroundAltOpacity 0.9 ]]
vim.cmd [[ FVimCustomTitleBar v:true ]]
vim.cmd [[ FVimUIPopupMenu v:true ]]
end
require('catppuccin').setup({
flavour = 'mocha', -- latte, frappe, macchiato, mocha
transparent_background = false,
term_colors = true,
})
vim.cmd.colorscheme 'catppuccin'
EOF
由于 fvim 发布的只是个压缩包,
为了方便图形界面使用,还需要配置下注册表。
自带的注册功能有些毛病,
现在也还没修,我也不想自己编译,就在注册表的HKEY_CLASSES_ROOT\*\shell
下仿照 VSCode 新建了一项,这样就有右键菜单打开了。不够完善但勉强能用。
我给 command 设置的值是"C:\Program Files\fvim\FVim.exe" "-c" "cd %%:p:h" "%1"
,
这样写可以右键菜单打开文件的同时同步当前工作目录,与文件管理器的集成更友好。
远程编辑
我一开始觉得 neovim 的远程编辑功能不太有必要,直接 ssh 上去写就可以了, 这次又研究了下觉得还是有用的。
在服务器 nvim --listen <TCP addr> --headless
,然后用 TUI / GUI 客户端远程连,
对我来说主要的好处是服务端不退出可以一直保持着这次编辑会话的现场,
跟 VSCode 的远程编辑的体验很像。
fvim 甚至还直接提供了 --ssh
选项直接连 ssh 配置里的机器,更加方便。
当然整体上还是不如 VSCode,现在只有基础的编辑,感觉还缺少一些高级功能。
总结
在编辑器上的折腾肯定是无止境的,一些自以为能增加生产力的想法实际上可能并不行, 更重要的是要去实践。希望这次折腾的成果能持续得长一些。