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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
|
-- mod-version:3
local core = require "core"
local style = require "core.style"
local StatusView = require "core.statusview"
local CommandView = require "core.commandview"
local DocView = require "core.docview"
local Doc = require "core.doc"
local keymap = require "core.keymap"
local words = setmetatable({}, { __mode = "k" })
local function compute_line_words(line)
local s, total_words = 1, 0
while true do
local ns, e = line:find("%s+", s)
if ns == 1 and e == #line then break end
if not e then total_words = math.max(total_words, 1) break end
total_words = total_words + 1
s = e + 1
end
return total_words
end
local function compute_words(doc, start_line, end_line)
local total_words = 0
for i = start_line or 1, end_line or #doc.lines do
total_words = total_words + compute_line_words(doc.lines[i])
end
return total_words
end
local old_raw_insert = Doc.raw_insert
function Doc:raw_insert(line, col, text, undo_stack, time)
if words[self] then
local old_count = compute_words(self, line, line)
old_raw_insert(self, line, col, text, undo_stack, time)
local total_lines, s = 0, 0
while true do
s = text:find("\n", s + 1, true)
if not s then break end
total_lines = total_lines + 1
end
words[self] = words[self] + compute_words(self, line, line + total_lines) - old_count
else
old_raw_insert(self, line, col, text, undo_stack, time)
end
end
local old_raw_remove = Doc.raw_remove
function Doc:raw_remove(line1, col1, line2, col2, undo_stack, time)
if words[self] then
local old_count = compute_words(self, line1, line2)
old_raw_remove(self, line1, col1, line2, col2, undo_stack, time)
words[self] = words[self] + compute_words(self, line1, line1) - old_count
else
old_raw_remove(self, line1, col1, line2, col2, undo_stack, time)
end
end
local old_doc_new = Doc.new
function Doc:new(...)
old_doc_new(self, ...)
words[self] = compute_words(self)
end
local cached_word_length, cached_word_count
core.status_view:add_item({
predicate = function() return core.active_view:is(DocView) and not core.active_view:is(CommandView) and words[core.active_view.doc] end,
name = "status:word-count",
alignment = StatusView.Item.RIGHT,
get_item = function()
local selection_text = core.active_view.doc:get_selection_text()
if #selection_text ~= cached_word_length then
cached_word_count = compute_line_words(selection_text)
cached_word_length = #selection_text
end
if #selection_text > 0 then
return { style.text, cached_word_count .. " words" }
else
return { style.text, words[core.active_view.doc] .. " words" }
end
end
})
|