aboutsummaryrefslogtreecommitdiff
path: root/runtime/lua/man.lua
blob: 63c2c144803673435e973d0c7c0fb29770f6925e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
local function highlight_backspaced(line, linenr)
  local chars = {}
  local prev_char = ''
  local overstrike = false
  local hls = {} -- Store highlight groups as { attr, start, end }
  local NONE, BOLD, UNDERLINE = 0, 1, 2
  local attr = NONE
  local byte = 0 -- byte offset

  -- Break input into UTF8 characters
  for char in line:gmatch("[^\128-\191][\128-\191]*") do
    if overstrike then
      local last_hl = hls[#hls]
      if char == prev_char then
        if char == '_' and attr == UNDERLINE and last_hl and last_hl[3] == byte then
          -- This underscore is in the middle of an underlined word
          attr = UNDERLINE
        else
          attr = BOLD
        end
      elseif prev_char == '_' then
        -- char is underlined
        attr = UNDERLINE
      elseif prev_char == '+' and char == 'o' then
        -- bullet (overstrike text '+^Ho')
        attr = BOLD
        char = [[·]]
      elseif prev_char == [[·]] and char == 'o' then
        -- bullet (additional handling for '+^H+^Ho^Ho')
        attr = BOLD
        char = [[·]]
      else
        -- use plain char
        attr = NONE
      end

      -- Grow the previous highlight group if possible
      if last_hl and last_hl[1] == attr and last_hl[3] == byte then
        last_hl[3] = byte + #char
      else
        hls[#hls + 1] = {attr, byte, byte + #char}
      end

      overstrike = false
      prev_char = ''
      byte = byte + #char
      chars[#chars + 1] = char
    elseif char == "\b" then
      overstrike = true
      prev_char = chars[#chars]
      byte = byte - #prev_char
      chars[#chars] = nil
    else
      byte = byte + #char
      chars[#chars + 1] = char
    end
  end

  for i, hl in ipairs(hls) do
    if hl[1] ~= NONE then
      vim.api.nvim_buf_add_highlight(
        0,
        -1,
        hl[1] == BOLD and "manBold" or "manUnderline",
        linenr - 1,
        hl[2],
        hl[3]
      )
    end
  end

  return table.concat(chars, '')
end

return { highlight_backspaced = highlight_backspaced }