neovim

Personal neovim configuration files
git clone git://gtms.dev/neovim
Log | Files | Refs

terminal.lua (2795B)


      1 --- Dispatchers for LSP message types.
      2 --- @class (private) State
      3 --- @field win integer?
      4 --- @field buf integer
      5 --- @field chan integer
      6 --- @field last_command string?
      7 local State = {
      8 }
      9 
     10 function State:is_open()
     11   return self.win and vim.api.nvim_win_is_valid(self.win)
     12 end
     13 
     14 function State:is_valid()
     15   return self.buf and vim.api.nvim_buf_is_valid(self.buf) and self.chan
     16 end
     17 
     18 local M = {}
     19 
     20 M.toggle = function()
     21   if State:is_open() then
     22     vim.api.nvim_win_close(State.win, true)
     23     State.win = nil
     24     return
     25   end
     26 
     27   if State:is_valid() then
     28     State.win = vim.api.nvim_open_win(State.buf, false, { split = 'below', height = 12 })
     29 
     30     vim.api.nvim_set_current_win(State.win)
     31 
     32     vim.cmd.normal('G')
     33     vim.cmd.wincmd('p')
     34   else
     35     State.buf = vim.api.nvim_create_buf(false, true)
     36     State.win = vim.api.nvim_open_win(State.buf, false, { split = 'below', height = 12 })
     37 
     38     vim.api.nvim_set_current_win(State.win)
     39     vim.cmd.term()
     40     State.chan = vim.opt.channel:get()
     41     vim.api.nvim_buf_set_name(State.buf, 'terminal')
     42 
     43     vim.cmd.normal('G')
     44     vim.cmd.wincmd('p')
     45   end
     46 end
     47 
     48 -- Closes the window and deletes the buffer. This entirely resets the term state
     49 M.exit = function()
     50   if State:is_open() then
     51     vim.api.nvim_win_close(State.win, true)
     52     State.win = nil
     53   end
     54 
     55   if State:is_valid() then
     56     vim.api.nvim_buf_delete(State.buf, { force = true })
     57   end
     58 
     59   State.buf = nil
     60   State.chan = nil
     61 end
     62 
     63 -- Takes a command as a string and runs it in the terminal buffer. If the window is closed, it will be toggled
     64 ---@param cmd string
     65 M.run = function(cmd)
     66   if not State:is_open() and not State:is_valid() then
     67     M.toggle()
     68   elseif State.last_command then
     69     -- Send <C-c> to make sure any on-going commands like log tails are stopped before running the new command
     70     vim.api.nvim_chan_send(State.chan, '\003')
     71   end
     72 
     73   State.last_command = cmd
     74   vim.api.nvim_chan_send(State.chan, ' ' .. cmd .. '\r')
     75 end
     76 
     77 -- Runs the last command again
     78 M.rerun = function()
     79   if not State.last_command then
     80     print('Last command empty')
     81     return
     82   end
     83   M.run(State.last_command)
     84   M.catchup()
     85   return true
     86 end
     87 
     88 -- Jumps to the terminal window and enters insert mode. If called from the terminal window, it will jump back to the
     89 -- previous window
     90 M.interactive = function()
     91   if not State:is_open() then
     92     M.toggle()
     93   end
     94 
     95   if vim.api.nvim_get_current_win() == State.win then
     96     vim.cmd.wincmd('p')
     97   else
     98     vim.api.nvim_set_current_win(State.win)
     99     vim.cmd.startinsert()
    100   end
    101 end
    102 
    103 -- Jump to the end of terminal buffer without moving from actual buffer
    104 M.catchup = function()
    105   if not State:is_open() then
    106     M.toggle()
    107   end
    108 
    109   if State:is_valid() then
    110     vim.api.nvim_buf_call(State.buf, function()
    111       vim.cmd.normal('G')
    112     end)
    113   end
    114 end
    115 
    116 return M