NixDaemon

NixOS pentest workstation as one flake — IceBreaker's successor
git clone https://git.daemon-sec.xyz/NixDaemon.git
Log | Files | Refs | README

scrollback.lua (2612B)


      1 -- scrollback.lua — kitty's copy mode (ctrl+a>[) as a Neovim buffer.
      2 -- Started by home/modules/terminal.nix as
      3 --   bash -c 'exec nvim 63<&0 0</dev/null -u <this file> -c "let g:kitty_input_line=INPUT_LINE_NUMBER" …'
      4 -- kitty hands the scrollback (with colours) on fd 63; it is rendered through a
      5 -- :terminal so the ANSI colours survive, then the buffer is left in normal
      6 -- mode at the line that was under the cursor. Vi motions and search work as
      7 -- usual; / ? n N, v V ctrl-v select, y copies to the clipboard (wl-copy),
      8 -- Enter copies and leaves, q or Esc leave. Nothing from the AstroNvim config
      9 -- is loaded (-u), so this starts instantly.
     10 
     11 local o = vim.opt
     12 o.number = false
     13 o.relativenumber = false
     14 o.list = false
     15 o.showtabline = 0
     16 o.foldcolumn = "0"
     17 o.laststatus = 0
     18 o.signcolumn = "no"
     19 o.ruler = false
     20 o.showmode = false
     21 o.cmdheight = 1
     22 o.scrollback = 100000
     23 o.termguicolors = true
     24 o.background = "dark"
     25 o.clipboard = "unnamedplus" -- y → system clipboard
     26 o.ignorecase = true
     27 o.smartcase = true
     28 o.incsearch = true
     29 o.hlsearch = true
     30 o.shell = "bash"
     31 
     32 local function quit()
     33   vim.cmd("qa!")
     34 end
     35 local map = vim.keymap.set
     36 map({ "n", "v" }, "q", quit, { silent = true, desc = "leave copy mode" })
     37 map("n", "<Esc>", quit, { silent = true, desc = "leave copy mode" })
     38 map("n", "i", "<Nop>") -- no insert in a dead terminal
     39 map("n", "a", "<Nop>")
     40 map("v", "y", '"+y', { silent = true, desc = "copy selection" })
     41 map("v", "<CR>", '"+y<cmd>qa!<CR>', { silent = true, desc = "copy selection and leave (tmux)" })
     42 map("n", "<CR>", "<Nop>")
     43 
     44 vim.schedule(function()
     45   -- the -c flags have run by now, so the kitty positions are in vim.g
     46   local input_line = tonumber(vim.g.kitty_input_line) or 0
     47   local cursor_line = tonumber(vim.g.kitty_cursor_line) or 1
     48   local cursor_col = tonumber(vim.g.kitty_cursor_col) or 1
     49 
     50   vim.api.nvim_create_autocmd("TermEnter", { callback = function() vim.cmd("stopinsert") end })
     51   vim.api.nvim_create_autocmd("TermClose", {
     52     once = true,
     53     callback = function()
     54       vim.cmd("stopinsert")
     55       local target = math.max(0, input_line - 1) + cursor_line
     56       pcall(vim.fn.cursor, target, cursor_col)
     57       vim.cmd("normal! zz")
     58       if vim.env.KITTY_SCROLLBACK_TEST then
     59         -- smoke test (terminal.nix build check): print the text and leave
     60         io.stdout:write(table.concat(vim.api.nvim_buf_get_lines(0, 0, -1, false), "\n"), "\n")
     61         quit()
     62       end
     63     end,
     64   })
     65   -- strip kitty's OSC 8 file:// hyperlinks, which would print as noise
     66   vim.cmd([[terminal sed </dev/fd/63 -e 's/\x1b]8;;file:[^\\]*\\//g' && sleep 0.01 && printf '\x1b]2;\a']])
     67 end)