Skip to content

Commit 43f6fe0

Browse files
Merge remote-tracking branch 'origin/ts-org-1.0.0'
2 parents 4d2b47b + d053f86 commit 43f6fe0

File tree

16 files changed

+333
-209
lines changed

16 files changed

+333
-209
lines changed

.github/workflows/tests.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ jobs:
1717
- v0.5.0
1818
- v0.5.1
1919
- v0.6.0
20+
- v0.6.1
2021
- nightly
2122
runs-on: ubuntu-latest
2223
steps:

DOCS.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ Available options:
8686
* underline - `:underline on`
8787
* italic - `:slant italic`
8888

89+
---
90+
8991
Full configuration example with additional todo keywords and their colors:
9092
```lua
9193
require('orgmode').setup({
@@ -1183,6 +1185,7 @@ set statusline=%{v:lua.orgmode.statusline()}
11831185
```
11841186

11851187
## Changelog
1188+
To track breaking changes, subscribe to [Notice of breaking changes](https://github.com/nvim-orgmode/orgmode/issues/217) issue where those are announced.
11861189

11871190
#### 24 October 2021
11881191
* Help mapping was changed from `?` to `g?` to avoid conflict with built in backward search. See issue [#106](https://github.com/nvim-orgmode/orgmode/issues/106).

README.md

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -71,16 +71,10 @@ call dein#add('nvim-orgmode/orgmode')
7171
```lua
7272
-- init.lua
7373

74-
local parser_config = require "nvim-treesitter.parsers".get_parser_configs()
75-
parser_config.org = {
76-
install_info = {
77-
url = 'https://github.com/milisims/tree-sitter-org',
78-
revision = 'f110024d539e676f25b72b7c80b0fd43c34264ef',
79-
files = {'src/parser.c', 'src/scanner.cc'},
80-
},
81-
filetype = 'org',
82-
}
74+
-- Load custom tree-sitter grammar for org filetype
75+
require('orgmode').setup_ts_grammar()
8376

77+
-- Tree-sitter configuration
8478
require'nvim-treesitter.configs'.setup {
8579
-- If TS highlights are not enabled at all, or disabled via `disable` prop, highlighting will fallback to default Vim syntax highlighting
8680
highlight = {
@@ -101,16 +95,11 @@ Or if you are using `init.vim`:
10195
```vim
10296
" init.vim
10397
lua << EOF
104-
local parser_config = require "nvim-treesitter.parsers".get_parser_configs()
105-
parser_config.org = {
106-
install_info = {
107-
url = 'https://github.com/milisims/tree-sitter-org',
108-
revision = 'f110024d539e676f25b72b7c80b0fd43c34264ef',
109-
files = {'src/parser.c', 'src/scanner.cc'},
110-
},
111-
filetype = 'org',
112-
}
11398
99+
-- Load custom tree-sitter grammar for org filetype
100+
require('orgmode').setup_ts_grammar()
101+
102+
-- Tree-sitter configuration
114103
require'nvim-treesitter.configs'.setup {
115104
-- If TS highlights are not enabled at all, or disabled via `disable` prop, highlighting will fallback to default Vim syntax highlighting
116105
highlight = {

doc/orgmode.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,7 @@ Available options:
261261
* underline - `:underline on`
262262
* italic - `:slant italic`
263263

264+
--------------------------------------------------------------------------------
264265
Full configuration example with additional todo keywords and their colors:
265266
>
266267
require('orgmode').setup({
@@ -1572,6 +1573,8 @@ Show the currently clocked in headline (if any), with total clocked time / effor
15721573
--------------------------------------------------------------------------------
15731574
CHANGELOG *orgmode-changelog*
15741575

1576+
To track breaking changes, subscribe to Notice of breaking changes (https://github.com/nvim-orgmode/orgmode/issues/217) issue where those are announced.
1577+
15751578
24 OCTOBER 2021 *orgmode-24_october_2021*
15761579

15771580
* Help mapping was changed from `?` to `g?` to avoid conflict with built in backward search. See issue #106 (https://github.com/nvim-orgmode/orgmode/issues/106).

lua/orgmode/colors/todo_highlighter.lua

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,10 @@ local function add_todo_keyword_highlights()
3131
end, todo_keywords.DONE),
3232
' '
3333
)
34-
table.insert(lines, string.format([[(item "keyword?" @OrgTODO (#any-of? @OrgTODO %s))]], todo_type))
35-
table.insert(lines, string.format([[(item "keyword?" @OrgDONE (#any-of? @OrgDONE %s))]], done_type))
34+
table.insert(lines, string.format([[(item . (expr) @OrgTODO (#any-of? @OrgTODO %s))]], todo_type))
35+
table.insert(lines, string.format([[(item . (expr) @OrgDONE (#any-of? @OrgDONE %s))]], done_type))
3636
for face_name, face_hl in pairs(faces) do
37-
table.insert(lines, string.format([[(item "keyword?" @%s (#eq? @%s %s))]], face_hl, face_hl, face_name))
37+
table.insert(lines, string.format([[(item . (expr) @%s (#eq? @%s %s))]], face_hl, face_hl, face_name))
3838
end
3939
vim.treesitter.set_query('org', 'highlights', table.concat(lines, '\n'))
4040
if vim.bo.filetype == 'org' then

lua/orgmode/init.lua

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
_G.orgmode = _G.orgmode or {}
1+
_G.orgmode = _G.orgmode or {
2+
ts_revision = '1c3eb533a9cf6800067357b59e03ac3f91fc3a54',
3+
}
4+
local setup_ts_grammar_used = false
25
local instance = nil
36

47
---@class Org
@@ -58,10 +61,42 @@ function Org:setup_autocmds()
5861
vim.cmd([[augroup END]])
5962
end
6063

64+
--- @param revision string?
65+
local function setup_ts_grammar(revision)
66+
setup_ts_grammar_used = true
67+
local parser_config = require('nvim-treesitter.parsers').get_parser_configs()
68+
parser_config.org = {
69+
install_info = {
70+
url = 'https://github.com/milisims/tree-sitter-org',
71+
revision = revision or _G.orgmode.ts_revision,
72+
files = { 'src/parser.c', 'src/scanner.cc' },
73+
},
74+
filetype = 'org',
75+
}
76+
end
77+
78+
local function check_ts_grammar()
79+
if setup_ts_grammar_used then
80+
return
81+
end
82+
vim.defer_fn(function()
83+
local parser_config = require('nvim-treesitter.parsers').get_parser_configs()
84+
if parser_config and parser_config.org and parser_config.org.install_info.revision ~= _G.orgmode.ts_revision then
85+
require('orgmode.utils').echo_error({
86+
'You are using outdated version of tree-sitter grammar for Orgmode.',
87+
'To use latest version, replace current grammar installation with "require(\'orgmode\').setup_ts_grammar()" and run :TSUpdate org.',
88+
'More info in setup section of readme: https://github.com/nvim-orgmode/orgmode#setup',
89+
})
90+
end
91+
end, 200)
92+
end
93+
6194
---@param opts? table
6295
---@return Org
6396
local function setup(opts)
97+
opts = opts or {}
6498
instance = Org:new()
99+
check_ts_grammar()
65100
local config = require('orgmode.config'):extend(opts)
66101
vim.defer_fn(function()
67102
if config.notifications.enabled and #vim.api.nvim_list_uis() > 0 then
@@ -140,6 +175,7 @@ function _G.orgmode.statusline()
140175
end
141176

142177
return {
178+
setup_ts_grammar = setup_ts_grammar,
143179
setup = setup,
144180
reload = reload,
145181
action = action,

lua/orgmode/objects/date.lua

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,35 @@ local function from_string(datestr, opts)
213213
return parse_date(date, dayname, adjustments, opts)
214214
end
215215

216+
--- @param datestr string
217+
--- @return table[]
218+
local function parse_parts(datestr)
219+
local result = {}
220+
local counter = 1
221+
local patterns = {
222+
{ type = 'date', rgx = '^%d%d%d%d%-%d%d%-%d%d$' },
223+
{ type = 'dayname', rgx = '^%a%a%a$' },
224+
{ type = 'time', rgx = '^%d?%d:%d%d$' },
225+
{ type = 'time_range', rgx = '^%d?%d:%d%d%-%d?%d:%d%d$' },
226+
{ type = 'adjustment', rgx = '^[%.%+%-]+%d+[hdwmy]?$' },
227+
}
228+
for space, item in string.gmatch(datestr, '(%s*)(%S+)') do
229+
local from = counter + space:len()
230+
for _, dt_pattern in ipairs(patterns) do
231+
if item:match(dt_pattern.rgx) then
232+
table.insert(result, {
233+
type = dt_pattern.type,
234+
value = item,
235+
from = from,
236+
to = from + item:len() - 1,
237+
})
238+
counter = counter + item:len() + space:len()
239+
end
240+
end
241+
end
242+
return result
243+
end
244+
216245
local function from_org_date(datestr, opts)
217246
local from_open, from, from_close, delimiter, to_open, to, to_close = datestr:match(pattern .. '(%-%-)' .. pattern)
218247
if not delimiter then
@@ -858,6 +887,7 @@ local function parse_all_from_line(line, lnum)
858887
end
859888

860889
return {
890+
parse_parts = parse_parts,
861891
from_org_date = from_org_date,
862892
from_string = from_string,
863893
now = now,

lua/orgmode/objects/edit_special/init.lua

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,7 @@ function EditSpecial:new()
2121
end
2222

2323
function EditSpecial:_parse_position()
24-
local nearest_block_node_info = utils.get_nearest_block_node(
25-
self.file,
26-
{ 'name', 'contents', 'parameters' },
27-
self.org_pos,
28-
true
29-
)
24+
local nearest_block_node_info = utils.get_nearest_block_node(self.file, self.org_pos, true)
3025

3126
if not nearest_block_node_info then
3227
utils.echo_warning('No block node found near cursor')

lua/orgmode/org/mappings.lua

Lines changed: 49 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -187,38 +187,70 @@ function OrgMappings:_adjust_date_part(direction, amount, fallback)
187187
local do_replacement = function(date)
188188
local col = vim.fn.col('.')
189189
local char = vim.fn.getline('.'):sub(col, col)
190+
local raw_date_value = vim.fn.getline('.'):sub(date.range.start_col + 1, date.range.end_col - 1)
190191
if col == date.range.start_col or col == date.range.end_col then
191192
date.active = not date.active
192193
return self:_replace_date(date)
193194
end
194-
local node = Files.get_node_at_cursor()
195195
local col_from_start = col - date.range.start_col
196-
local modify_end_time = false
196+
local parts = Date.parse_parts(raw_date_value)
197197
local adj = nil
198-
if node:type() == 'date' then
199-
if col_from_start <= 5 then
198+
local modify_end_time = false
199+
local part = nil
200+
for _, p in ipairs(parts) do
201+
if col_from_start >= p.from and col_from_start <= p.to then
202+
part = p
203+
break
204+
end
205+
end
206+
207+
if not part then
208+
return
209+
end
210+
211+
local offset = col_from_start - part.from
212+
213+
if part.type == 'date' then
214+
if offset <= 4 then
200215
adj = get_adj('y')
201-
elseif col_from_start <= 8 then
216+
elseif offset <= 7 then
202217
adj = get_adj('m')
203-
elseif col_from_start <= 15 then
218+
else
204219
adj = get_adj('d')
205220
end
206-
elseif node:type() == 'time' then
207-
local has_end_time = node:parent() and node:parent():type() == 'timerange'
208-
if col_from_start <= 17 then
221+
end
222+
223+
if part.type == 'dayname' then
224+
adj = get_adj('d')
225+
end
226+
227+
if part.type == 'time' then
228+
if offset <= 2 then
229+
adj = get_adj('h')
230+
else
231+
adj = minute_adj
232+
end
233+
end
234+
235+
if part.type == 'time_range' then
236+
if offset <= 2 then
209237
adj = get_adj('h')
210-
elseif col_from_start <= 20 then
238+
elseif offset <= 5 then
211239
adj = minute_adj
212-
elseif has_end_time and col_from_start <= 23 then
240+
elseif offset <= 8 then
213241
adj = get_adj('h')
214242
modify_end_time = true
215-
elseif has_end_time and col_from_start <= 26 then
243+
else
216244
adj = minute_adj
217245
modify_end_time = true
218246
end
219-
elseif (node:type() == 'repeater' or node:type() == 'delay') and char:match('[hdwmy]') ~= nil then
247+
end
248+
249+
if part.type == 'adjustment' then
220250
local map = { h = 'd', d = 'w', w = 'm', m = 'y', y = 'h' }
221-
vim.cmd(string.format('norm!r%s', map[char]))
251+
if map[char] then
252+
vim.cmd(string.format('norm!r%s', map[char]))
253+
end
222254
return true
223255
end
224256

@@ -401,6 +433,9 @@ function OrgMappings:handle_return(suffix)
401433
suffix = suffix or ''
402434
local current_file = Files.get_current_file()
403435
local item = current_file:get_current_node()
436+
if item.type == 'expr' then
437+
item = current_file:convert_to_file_node(item.node:parent())
438+
end
404439

405440
if item.node:parent() and item.node:parent():type() == 'headline' then
406441
item = current_file:convert_to_file_node(item.node:parent())

lua/orgmode/parser/file.lua

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ local utils = require('orgmode.utils')
1616
---@field sections_by_line table<number, Section>
1717
---@field source_code_filetypes string[]
1818
---@field is_archive_file boolean
19+
---@field archive_location string
1920
---@field clocked_headline Section
2021
---@field tags string[]
2122
local File = {}
@@ -43,7 +44,8 @@ end
4344

4445
function File:_parse()
4546
self:_parse_source_code_filetypes()
46-
self:_parse_sections_and_root_directives()
47+
self:_parse_directives()
48+
self:_parse_sections()
4749
end
4850

4951
function File:get_errors()
@@ -321,9 +323,8 @@ end
321323

322324
---@return string
323325
function File:get_archive_file_location()
324-
local matches = self:get_ts_matches('(document (directive (name) @name (value) @value (#eq? @name "ARCHIVE")))')
325-
if #matches > 0 then
326-
return config:parse_archive_location(self.filename, matches[1].value.text)
326+
if self.archive_location then
327+
return self.archive_location
327328
end
328329
return config:parse_archive_location(self.filename)
329330
end
@@ -335,11 +336,8 @@ function File:get_section(index)
335336
end
336337

337338
---@private
338-
function File:_parse_sections_and_root_directives()
339+
function File:_parse_sections()
339340
for child in self.tree:root():iter_children() do
340-
if child:type() == 'directive' then
341-
self:_parse_directive(child)
342-
end
343341
if child:type() == 'section' then
344342
local section = Section.from_node(child, self)
345343
table.insert(self.sections, section)
@@ -366,11 +364,10 @@ end
366364

367365
---@private
368366
function File:_parse_source_code_filetypes()
369-
local blocks = self:get_ts_matches('(block (name) @name (parameters) @parameters (#eq? @name "SRC"))')
367+
local blocks = self:get_ts_matches('(block name: (expr) @name parameter: (expr) @parameters (#eq? @name "SRC"))')
370368
local source_code_filetypes = {}
371369
for _, item in ipairs(blocks) do
372-
local params = vim.split(item.parameters.text, '%s+')
373-
local ft = params[1]
370+
local ft = item.parameters and item.parameters.text
374371
if
375372
ft
376373
and ft ~= ''
@@ -383,18 +380,19 @@ function File:_parse_source_code_filetypes()
383380
self.source_code_filetypes = source_code_filetypes
384381
end
385382

386-
function File:_parse_directive(node)
387-
local name = node:named_child(0)
388-
local value = node:named_child(1)
389-
if not name or not value then
390-
return
391-
end
392-
393-
local name_text = self:get_node_text(name)
394-
if name_text:upper() == 'FILETAGS' then
395-
local value_text = self:get_node_text(value)
396-
self.tags = utils.parse_tags_string(value_text)
383+
function File:_parse_directives()
384+
local directives = self:get_ts_matches([[(directive name: (expr) @name value: (value) @value)]])
385+
local tags = {}
386+
for _, directive in ipairs(directives) do
387+
local directive_name = directive.name.text:lower()
388+
if directive_name == 'filetags' then
389+
utils.concat(tags, utils.parse_tags_string(directive.value.text), true)
390+
end
391+
if directive_name == 'archive' then
392+
self.archive_location = config:parse_archive_location(self.filename, directive.value.text)
393+
end
397394
end
395+
self.tags = tags
398396
end
399397

400398
return File

0 commit comments

Comments
 (0)