浏览代码

nixpkgs/neovim: make GLg async

Thomas Dy 2 周之前
父节点
当前提交
e1048bef17

+ 174 - 0
.config/nixpkgs/neovim/commands.lua

@@ -0,0 +1,174 @@
+local Job = require('plenary.job')
+
+function make(opts)
+  local makeprg = vim.bo.makeprg
+  local errorformat = vim.bo.errorformat
+  if makeprg == '' then
+    return
+  end
+
+  -- escape special characters in args
+  args = string.gsub(opts.args or '', '%%', '%%%%')
+  -- substitute $*
+  makeprg, _ = string.gsub(makeprg, '%$%*', args);
+  -- expand
+  makeprg = vim.fn.expandcmd(makeprg)
+
+  local function on_exit(job, retval)
+    local result = {}
+    vim.list_extend(result, job:result())
+    vim.list_extend(result, job:stderr_result())
+    vim.notify(string.format(
+      ':!%s\n%s\n\nshell returned %d',
+      makeprg,
+      table.concat(result, '\n'),
+      retval
+    ))
+    vim.fn.setqflist({}, ' ', {
+      title = makeprg,
+      lines = result,
+      efm = errorformat,
+    })
+    vim.api.nvim_exec_autocmds('QuickFixCmdPost', {})
+
+    if #result > 0 then
+      vim.cmd('copen')
+    end
+  end
+
+  Job:new({
+    command = 'sh',
+    args = { '-c', makeprg },
+    on_exit = vim.schedule_wrap(on_exit),
+  }):start()
+end
+
+vim.api.nvim_create_user_command('Make', make, {
+  nargs = '*',
+  complete = 'file',
+})
+
+function ensure_log_buffer(bufname)
+  for _, buf in ipairs(vim.api.nvim_list_bufs()) do
+    if vim.api.nvim_buf_is_loaded(buf) and vim.api.nvim_buf_get_name(buf) == bufname then
+      vim.bo[buf].modifiable = true
+      vim.api.nvim_buf_set_lines(buf, 0, -1, true, {})
+      vim.bo[buf].modifiable = false
+      return buf
+    end
+  end
+
+  local bufnr = vim.api.nvim_create_buf(true, true)
+  vim.api.nvim_buf_set_name(bufnr, bufname)
+  vim.bo[bufnr].filetype = 'git'
+  vim.bo[bufnr].buftype = 'nofile'
+  vim.bo[bufnr].bufhidden = 'hide'
+  vim.bo[bufnr].swapfile = false
+  vim.bo[bufnr].modifiable = false
+  vim.api.nvim_win_set_buf(0, bufnr)
+
+  -- avoid ui thrashing
+  vim.opt_local.number = false
+  vim.opt_local.relativenumber = false
+
+  -- add fugitive mappings
+  vim.fn['fugitive#MapJumps']()
+
+  return bufnr
+end
+
+function git_lg(opts)
+  local argstr = ''
+  if #opts.args > 0 then
+    argstr = ' ' .. opts.args
+  end
+
+  -- we want a pseudo fqdn so that it's not considered relative to the current
+  -- directory
+  local bufname = 'cmd://git//lg' .. argstr
+  local bufnr = ensure_log_buffer(bufname)
+
+  local job
+  -- there are custom syntax highlights for --graph and --pretty
+  local args = {
+    'log',
+    '--abbrev-commit',
+    '--graph',
+    '--pretty=%h %d %s (%cr) <%an>',
+  }
+  vim.list_extend(args, opts.fargs)
+
+  local stdout_lines = {}
+  local stderr_lines = {}
+  local first = true
+
+  local append_to_buf = vim.schedule_wrap(function(lines)
+    -- stop appending and terminate the job if the buffer is closed
+    if not vim.api.nvim_buf_is_loaded(bufnr) then
+      job:shutdown(0, 0)
+      return
+    end
+
+    -- the first append should replace the first line, succeeding appends
+    -- should append to the end
+    local start = -1
+    if first then
+      start = 0
+      first = false
+    end
+
+    vim.bo[bufnr].modifiable = true
+    vim.api.nvim_buf_set_lines(bufnr, start, -1, true, lines)
+    vim.bo[bufnr].modifiable = false
+  end)
+
+  local function on_stdout(error, data)
+    if data == nil then
+      return
+    end
+
+    -- we get called for every line of output so buffer the lines to avoid too
+    -- much overhead
+    table.insert(stdout_lines, data)
+    if #stdout_lines > 100 then
+      local done = stdout_lines
+      stdout_lines = {}
+      append_to_buf(done)
+    end
+  end
+
+  local function on_exit(job, retval)
+    append_to_buf(stdout_lines)
+    if retval ~= 0 then
+      vim.schedule(function()
+        vim.notify(string.format(
+          ':%s\n%s\n\nreturned %d',
+          'GLg' .. argstr,
+          table.concat(stderr_lines, '\n'),
+          retval
+        ))
+      end)
+    end
+  end
+
+  job = Job:new({
+    command = 'git',
+    args = args,
+    enable_recording = false,
+    on_stdout = on_stdout,
+    on_stderr = function(error, data)
+      if data == nil then
+        return
+      end
+      table.insert(stderr_lines, data)
+    end,
+    on_exit = on_exit,
+  })
+
+  job:start()
+end
+
+vim.api.nvim_create_user_command('GLg', git_lg, {
+  nargs = '*',
+  complete = vim.fn['fugitive#LogComplete'],
+})

+ 0 - 49
.config/nixpkgs/neovim/make.lua

@@ -1,49 +0,0 @@
-local Job = require('plenary.job')
-
-function make(opts)
-  local makeprg = vim.bo.makeprg
-  local errorformat = vim.bo.errorformat
-  if makeprg == '' then
-    return
-  end
-
-  -- escape special characters in args
-  args = string.gsub(opts.args or '', '%%', '%%%%')
-  -- substitute $*
-  makeprg, _ = string.gsub(makeprg, '%$%*', args);
-  -- expand
-  makeprg = vim.fn.expandcmd(makeprg)
-
-  local function on_exit(job, retval)
-    local result = {}
-    vim.list_extend(result, job:result())
-    vim.list_extend(result, job:stderr_result())
-    vim.notify(string.format(
-      ':!%s\n%s\n\nshell returned %d',
-      makeprg,
-      table.concat(result, '\n'),
-      retval
-    ))
-    vim.fn.setqflist({}, ' ', {
-      title = makeprg,
-      lines = result,
-      efm = errorformat,
-    })
-    vim.api.nvim_exec_autocmds('QuickFixCmdPost', {})
-
-    if #result > 0 then
-      vim.cmd('copen')
-    end
-  end
-
-  Job:new({
-    command = 'sh',
-    args = { '-c', makeprg },
-    on_exit = vim.schedule_wrap(on_exit),
-  }):start()
-end
-
-vim.api.nvim_create_user_command('Make', make, {
-  nargs = '*',
-  complete = 'file',
-})

+ 1 - 1
.config/nixpkgs/neovim/neovim.nix

@@ -151,7 +151,7 @@ generic {
     source ${./mappings.lua}
     source ${./autocmd.lua}
     source ${./lsp.lua}
-    source ${./make.lua}
+    source ${./commands.lua}
     source ${./theme.lua}
   '' + lib.optionalString withLuadev ''
     source ${./luadev.lua}

+ 0 - 5
.config/nixpkgs/neovim/plugins.lua

@@ -425,8 +425,3 @@ _G.toggle_end_char = function(char)
     vim.api.nvim_buf_set_text(0, row, -1, row, -1, { char })
   end
 end
-
--- prettier git log, relies on additional syntax highlights
-vim.api.nvim_create_user_command('GLg', function(opts)
-  vim.cmd("Git ++curwin log --abbrev-commit --graph --pretty='%h %d %s (%cr) <%an>' " .. opts.args)
-end, { nargs = '?', complete = vim.fn['fugitive#LogComplete'] })

+ 3 - 0
.config/nixpkgs/neovim/settings.lua

@@ -34,6 +34,9 @@ vim.o.hlsearch = false
 -- always show sign column to avoid layout shift when staging
 vim.o.signcolumn = 'yes'
 
+-- have preview window be a bit taller
+vim.o.previewheight = 20
+
 -- make a new copy of the file for backup
 -- setting to no or auto messes with filewatchers
 vim.o.backupcopy = 'yes'