Skip to content

Commit 5c6c9b6

Browse files
feat(highlights): Add highlights for priorities (nvim-orgmode#687)
1 parent ac6cf5d commit 5c6c9b6

File tree

9 files changed

+124
-16
lines changed

9 files changed

+124
-16
lines changed

DOCS.md

+11-8
Original file line numberDiff line numberDiff line change
@@ -1329,14 +1329,17 @@ Most of the highlight groups are linked to treesitter highlights where applicabl
13291329

13301330
The following highlight groups are used:
13311331

1332-
* `@org.headline.level1`: Headline at level 1 - `linked to Title`
1333-
* `@org.headline.level2`: Headline at level 2 - `linked to Constant`
1334-
* `@org.headline.level3`: Headline at level 3 - `linked to Identifier`
1335-
* `@org.headline.level4`: Headline at level 4 - `linked to Statement`
1336-
* `@org.headline.level5`: Headline at level 5 - `linked to PreProc`
1337-
* `@org.headline.level6`: Headline at level 6 - `linked to Type`
1338-
* `@org.headline.level7`: Headline at level 7 - `linked to Special`
1339-
* `@org.headline.level8`: Headline at level 8 - `linked to String`
1332+
* `@org.headline.level1`: Headline at level 1 - linked to `Title`
1333+
* `@org.headline.level2`: Headline at level 2 - linked to `Constant`
1334+
* `@org.headline.level3`: Headline at level 3 - linked to `Identifier`
1335+
* `@org.headline.level4`: Headline at level 4 - linked to `Statement`
1336+
* `@org.headline.level5`: Headline at level 5 - linked to `PreProc`
1337+
* `@org.headline.level6`: Headline at level 6 - linked to `Type`
1338+
* `@org.headline.level7`: Headline at level 7 - linked to `Special`
1339+
* `@org.headline.level8`: Headline at level 8 - linked to `String`
1340+
* `@org.priority.highest`: Highest priority marker - linked to `@comment.error`
1341+
* `@org.priority.default`: Default priority marker - Not linked to anything, defaults to normal text
1342+
* `@org.priority.lowest`: Lowest priority marker - Not linked to anything, defaults to normal text
13401343
* `@org.timestamp.active`: An active timestamp - linked to `@keyword`
13411344
* `@org.timestamp.inactive`: An inactive timestamp - linked to `@comment`
13421345
* `@org.keyword.todo`: TODO keywords color - Parsed from `Error` (see note below)

lua/orgmode/agenda/agenda_item.lua

+19
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ function AgendaItem:_generate_data()
8383
table.insert(self.highlights, highlight)
8484
end
8585
self:_add_keyword_highlight()
86+
self:_add_priority_highlight()
8687
end
8788

8889
function AgendaItem:_is_valid_for_today()
@@ -260,4 +261,22 @@ function AgendaItem:_add_keyword_highlight()
260261
end
261262
end
262263

264+
function AgendaItem:_add_priority_highlight()
265+
local priority, priority_node = self.headline:get_priority()
266+
if not priority_node then
267+
return
268+
end
269+
local hlgroup = hl_map.priority[priority].hl_group
270+
local last_hl = self.highlights[#self.highlights]
271+
local start_col = 2
272+
if last_hl and last_hl.todo_keyword then
273+
start_col = start_col + last_hl.todo_keyword:len()
274+
end
275+
table.insert(self.highlights, {
276+
hlgroup = hlgroup,
277+
priority = priority,
278+
start_col = start_col,
279+
})
280+
end
281+
263282
return AgendaItem

lua/orgmode/agenda/views/agenda.lua

+5-1
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,10 @@ function AgendaView.build_agenda_item_content(agenda_item, longest_category, lon
309309
hl.range.start_col = todo_keyword_pos + 1
310310
hl.range.end_col = todo_keyword_pos + hl.todo_keyword:len() + 1
311311
end
312+
if hl.priority then
313+
hl.range.start_col = todo_keyword_pos + hl.start_col
314+
hl.range.end_col = todo_keyword_pos + hl.start_col + 4
315+
end
312316
return hl
313317
end, agenda_item.highlights)
314318
end
@@ -321,7 +325,7 @@ function AgendaView.build_agenda_item_content(agenda_item, longest_category, lon
321325
start_col = 1,
322326
end_col = 0,
323327
}),
324-
hl_group = 'Visual',
328+
hlgroup = 'Visual',
325329
whole_line = true,
326330
})
327331
end

lua/orgmode/agenda/views/todos.lua

+18-4
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,9 @@ function AgendaTodosView.generate_todo_item(headline, longest_category, line_nr)
8282
local todo_keyword, _, todo_type = headline:get_todo()
8383
todo_keyword = todo_keyword or ''
8484
local todo_keyword_padding = todo_keyword ~= '' and ' ' or ''
85-
local line =
86-
string.format(' %s%s%s %s', category, todo_keyword_padding, todo_keyword, headline:get_title_with_priority())
85+
local title_with_priority = headline:get_title_with_priority()
86+
local todo_keyword_len = todo_keyword:len()
87+
local line = string.format(' %s%s%s %s', category, todo_keyword_padding, todo_keyword, title_with_priority)
8788
if #headline:get_tags() > 0 then
8889
local tags_string = headline:tags_to_string()
8990
local padding_length =
@@ -100,7 +101,20 @@ function AgendaTodosView.generate_todo_item(headline, longest_category, line_nr)
100101
start_line = line_nr,
101102
end_line = line_nr,
102103
start_col = todo_keyword_pos,
103-
end_col = todo_keyword_pos + todo_keyword:len(),
104+
end_col = todo_keyword_pos + todo_keyword_len,
105+
}),
106+
})
107+
end
108+
local priority = headline:get_priority()
109+
if priority and hl_map.priority[priority] then
110+
local col_start = todo_keyword_pos + (todo_keyword_len > 0 and todo_keyword_len + 1 or 0)
111+
table.insert(highlights, {
112+
hlgroup = hl_map.priority[priority].hl_group,
113+
range = Range:new({
114+
start_line = line_nr,
115+
end_line = line_nr,
116+
start_col = col_start,
117+
end_col = col_start + 4,
104118
}),
105119
})
106120
end
@@ -112,7 +126,7 @@ function AgendaTodosView.generate_todo_item(headline, longest_category, line_nr)
112126
start_col = 1,
113127
end_col = 0,
114128
}),
115-
hl_group = 'Visual',
129+
hlgroup = 'Visual',
116130
whole_line = true,
117131
})
118132
end

lua/orgmode/colors/highlights.lua

+3
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ function M.link_highlights()
2121
['@org.headline.level7'] = 'Special',
2222
['@org.headline.level8'] = 'String',
2323

24+
['@org.priority.highest'] = '@comment.error',
25+
2426
-- Headline tags
2527
['@org.tag'] = '@tag.attribute',
2628

@@ -172,6 +174,7 @@ function M.get_agenda_hl_map()
172174
deadline = '@org.agenda.deadline',
173175
ok = '@org.agenda.scheduled',
174176
warning = '@org.agenda.scheduled_past',
177+
priority = config:get_priorities(),
175178
}, faces)
176179
end
177180

lua/orgmode/colors/init.lua

+1-1
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ M.highlight = function(highlights, clear)
8080
for _, hl in ipairs(highlights) do
8181
if hl.whole_line then
8282
vim.api.nvim_buf_set_extmark(0, namespace, hl.range.start_line - 1, hl.range.start_col - 1, {
83-
hl_group = hl.hl_group,
83+
hl_group = hl.hlgroup,
8484
end_line = hl.range.start_line,
8585
hl_eol = true,
8686
})

lua/orgmode/config/init.lua

+44
Original file line numberDiff line numberDiff line change
@@ -345,8 +345,17 @@ function Config:get_inheritable_tags(headline)
345345
end, headline.tags)
346346
end
347347

348+
function Config:get_priorities()
349+
return {
350+
[self.opts.org_priority_highest] = { type = 'highest', hl_group = '@org.priority.highest' },
351+
[self.opts.org_priority_default] = { type = 'default', hl_group = '@org.priority.default' },
352+
[self.opts.org_priority_lowest] = { type = 'lowest', hl_group = '@org.priority.lowest' },
353+
}
354+
end
355+
348356
function Config:setup_ts_predicates()
349357
local todo_keywords = self:get_todo_keywords().KEYS
358+
local valid_priorities = self:get_priorities()
350359

351360
vim.treesitter.query.add_predicate('org-is-todo-keyword?', function(match, _, source, predicate)
352361
local node = match[predicate[2]]
@@ -358,6 +367,41 @@ function Config:setup_ts_predicates()
358367
return false
359368
end, true)
360369

370+
vim.treesitter.query.add_predicate('org-is-valid-priority?', function(match, _, source, predicate)
371+
local node = match[predicate[2]]
372+
local type = predicate[3]
373+
if not node then
374+
return false
375+
end
376+
377+
local text = vim.treesitter.get_node_text(node, source)
378+
local is_valid = valid_priorities[text] and valid_priorities[text].type == type
379+
if not is_valid then
380+
return false
381+
end
382+
local priority_text = '[#' .. text .. ']'
383+
local full_node_text = vim.treesitter.get_node_text(node:parent(), source)
384+
if priority_text ~= full_node_text then
385+
return false
386+
end
387+
388+
local prev_sibling = node:parent():prev_sibling()
389+
-- If first child, consider it valid
390+
if not prev_sibling then
391+
return true
392+
end
393+
394+
-- If prev sibling has more prev siblings, it means that the prev_sibling is not a todo keyword
395+
-- so this priority is not valid
396+
if prev_sibling:prev_sibling() then
397+
return false
398+
end
399+
400+
local todo_text = vim.treesitter.get_node_text(prev_sibling, source)
401+
local is_prev_sibling_todo_keyword = todo_keywords[todo_text] and true or false
402+
return is_prev_sibling_todo_keyword
403+
end, true)
404+
361405
vim.treesitter.query.add_directive('org-set-block-language!', function(match, _, bufnr, pred, metadata)
362406
local lang_node = match[pred[2]]
363407
if not lang_node then

lua/orgmode/files/headline.lua

+20-2
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,26 @@ end
6666
memoize('get_priority')
6767
---@return string, TSNode | nil
6868
function Headline:get_priority()
69-
local node, priority = self:_parse_title_part('%[#(%w+)%]')
70-
return priority, node
69+
local _, todo_node = self:get_todo()
70+
local item = self:_get_child_node('item')
71+
72+
local priority_node = item and item:named_child(1)
73+
74+
if not todo_node then
75+
priority_node = item and item:named_child(0)
76+
end
77+
78+
if priority_node then
79+
local text = self.file:get_node_text(priority_node)
80+
local priority = text:match('%[#(%w+)%]')
81+
if priority then
82+
local priorities = config:get_priorities()
83+
if priorities[priority] then
84+
return priority, priority_node
85+
end
86+
end
87+
end
88+
return '', nil
7189
end
7290

7391
---@param amount number

queries/org/highlights.scm

+3
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
(headline (item) @spell)
1212
(item . (expr) @org.keyword.todo @nospell (#org-is-todo-keyword? @org.keyword.todo "TODO"))
1313
(item . (expr) @org.keyword.done @nospell (#org-is-todo-keyword? @org.keyword.done "DONE"))
14+
(item (expr "[" "#" "str" @_priority "]") @org.priority.highest (#org-is-valid-priority? @_priority "highest"))
15+
(item (expr "[" "#" "str" @_priority "]") @org.priority.default (#org-is-valid-priority? @_priority "default"))
16+
(item (expr "[" "#" "str" @_priority "]") @org.priority.lowest (#org-is-valid-priority? @_priority "lowest"))
1417
(list (listitem (paragraph) @spell))
1518
(body (paragraph) @spell)
1619
(bullet) @org.bullet

0 commit comments

Comments
 (0)