aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGabriel Holodak <gthepiper@gmail.com>2017-11-20 00:19:08 -0500
committerGabriel Holodak <gthepiper@gmail.com>2017-12-27 23:27:14 -0500
commitc28ce5f6191d233228d1688de300727e1ae42831 (patch)
tree409b1488d3f50369a0dd861ec97a20459d2ba604
parent0446d4d6916d27041de5ac24ba0c741ae4ad5a39 (diff)
downloadrneovim-c28ce5f6191d233228d1688de300727e1ae42831.tar.gz
rneovim-c28ce5f6191d233228d1688de300727e1ae42831.tar.bz2
rneovim-c28ce5f6191d233228d1688de300727e1ae42831.zip
Switch to processing in Lua
-rw-r--r--runtime/autoload/man.vim42
-rw-r--r--runtime/lua/man.lua75
2 files changed, 77 insertions, 40 deletions
diff --git a/runtime/autoload/man.vim b/runtime/autoload/man.vim
index 3ea0b734c0..12c1bf3c86 100644
--- a/runtime/autoload/man.vim
+++ b/runtime/autoload/man.vim
@@ -391,48 +391,10 @@ function! man#highlight_backspaced_text() abort
let l:modifiable = &modifiable
set modifiable
- let l:lines = getline(1, line('$'))
- call map(l:lines, function('s:highlight_backspaced_line'))
- call setline(1, l:lines)
+ lua man = require("man")
+ luado return man.highlight_backspaced(line, linenr)
let &modifiable = l:modifiable
endfunction
-" This pattern is for "overstruck" text containing backspaces. It matches bold
-" text first, so a word beginning with "_^H_" is bold and text such as
-" "_^Hf_^Ho_^Ho_^H__^Hb_^Ha_^Hr" is entirely underlined.
-"
-" Bolded text can also be mixed with whitespace as a performance tweak, since
-" it's visually identical.
-let s:backspace_pattern = '\v%((.)\b\1\s*)+|%(_\b.)+'
-
-function! s:highlight_backspaced_line(index, val) abort
- let l:line = a:val
- let l:search_pos = 0
-
- while 1
- " Scanning for the next backspace without matching the entire pattern is
- " slightly faster
- let l:match_start = stridx(l:line, "\b", l:search_pos)
- if l:match_start == -1
- break
- endif
-
- let l:match = matchstrpos(l:line, s:backspace_pattern, l:match_start - 1)
- if l:match[0] =~# '^_\b[^_]'
- let l:hlgroup = 'manUnderline'
- else
- let l:hlgroup = 'manBold'
- endif
-
- let l:stripped = substitute(l:match[0], '.\b', '', 'g')
- let l:search_pos = l:match[1] + len(l:stripped)
- let l:line = strpart(l:line, 0, l:match[1]) . l:stripped . strpart(l:line, l:match[2])
-
- call nvim_buf_add_highlight(0, -1, l:hlgroup, a:index, l:match[1], l:search_pos)
- endwhile
-
- return l:line
-endfunction
-
call s:init()
diff --git a/runtime/lua/man.lua b/runtime/lua/man.lua
new file mode 100644
index 0000000000..63c2c14480
--- /dev/null
+++ b/runtime/lua/man.lua
@@ -0,0 +1,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 }