Skip to content

Commit 5875037

Browse files
fix: Use valid bufnr for all edits
1 parent 80fec6e commit 5875037

File tree

4 files changed

+46
-27
lines changed

4 files changed

+46
-27
lines changed

lua/orgmode/files/file.lua

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -408,10 +408,10 @@ end
408408
---@param front_trim boolean? If true,trim the text from the front by 1 character
409409
---@return boolean
410410
function OrgFile:set_node_text(node, text, front_trim)
411-
local bufnr = self:bufnr()
412-
if not node or bufnr < 0 then
411+
if not node then
413412
return false
414413
end
414+
local bufnr = self:get_valid_bufnr()
415415
local start_row, start_col, end_row, end_col = node:range()
416416
local replacement = vim.split(text, '\n', { plain = true })
417417
if string.len(text) == 0 then
@@ -427,10 +427,10 @@ function OrgFile:set_node_text(node, text, front_trim)
427427
-- (section: 10, 0, 11, 0) instead of (section: 10, 0, 10, 10)
428428
-- If we are setting text at the end of the file it will throw an out of range error
429429
-- To avoid that,get the last line number and it's last column
430-
local last_line = vim.fn.line('$') - 1
430+
local last_line = vim.api.nvim_buf_line_count(bufnr) - 1
431431
if end_row > last_line then
432432
end_row = last_line
433-
end_col = vim.fn.col({ end_row, '$' }) - 2
433+
end_col = vim.api.nvim_buf_get_lines(bufnr, end_row, end_row + 1, false)[1]:len()
434434
end
435435
local ok = pcall(vim.api.nvim_buf_set_text, bufnr, start_row, start_col, end_row, end_col, replacement)
436436
return ok
@@ -440,12 +440,12 @@ end
440440
---@param lines string[]
441441
---@return boolean
442442
function OrgFile:set_node_lines(node, lines)
443-
local bufnr = self:bufnr()
444-
if not node or bufnr < 0 then
443+
if not node then
445444
return false
446445
end
446+
local bufnr = self:get_valid_bufnr()
447447
local start_row, _, end_row, _ = node:range()
448-
vim.api.nvim_buf_set_lines(0, start_row, end_row, false, lines)
448+
vim.api.nvim_buf_set_lines(bufnr, start_row, end_row, false, lines)
449449
return true
450450
end
451451

@@ -460,6 +460,21 @@ function OrgFile:bufnr()
460460
return -1
461461
end
462462

463+
---Return valid buffer handle or throw an error if it's not valid
464+
---@return number
465+
function OrgFile:get_valid_bufnr()
466+
local bufnr = vim.fn.bufnr(self.filename) or -1
467+
if bufnr < 0 then
468+
error('[orgmode] No valid buffer for file ' .. self.filename .. ' to edit')
469+
end
470+
-- Do not consider unloaded buffers as valid
471+
-- Treesitter is not working in them
472+
if not vim.api.nvim_buf_is_loaded(bufnr) then
473+
error('[orgmode] Cannot edit buffer ' .. tostring(bufnr) .. ' for file ' .. self.filename .. ', it is not loaded')
474+
end
475+
return bufnr
476+
end
477+
463478
memoize('get_filetags')
464479
--- Get tags list applied on file level via #+FILETAGS
465480
--- @return string[]
@@ -584,10 +599,7 @@ end
584599
---@param value? string
585600
---@return OrgFile
586601
function OrgFile:set_property(name, value)
587-
local bufnr = self:bufnr()
588-
if bufnr < 0 then
589-
return self
590-
end
602+
local bufnr = self:get_valid_bufnr()
591603

592604
if not value then
593605
local existing_property, property_range = self:get_property(name)

lua/orgmode/files/headline.lua

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -240,9 +240,10 @@ function Headline:set_tags(tags)
240240
return nil
241241
end
242242

243+
local bufnr = self.file:get_valid_bufnr()
243244
local txt = self.file:get_node_text(predecessor)
244245
local pred_end_row, pred_end_col, _ = predecessor:end_()
245-
local line = vim.fn.getline(pred_end_row + 1)
246+
local line = vim.api.nvim_buf_get_lines(bufnr, pred_end_row, pred_end_row + 1, false)[1]
246247
local stars = line:match('^%*+%s*')
247248
local end_col = line:len()
248249

@@ -261,7 +262,7 @@ function Headline:set_tags(tags)
261262
text = string.rep(' ', spaces) .. tags
262263
end
263264

264-
vim.api.nvim_buf_set_text(0, pred_end_row, pred_end_col, pred_end_row, end_col, { text })
265+
vim.api.nvim_buf_set_text(bufnr, pred_end_row, pred_end_col, pred_end_row, end_col, { text })
265266
end
266267

267268
function Headline:align_tags()
@@ -389,10 +390,11 @@ end
389390
---@param value? string
390391
---@return OrgHeadline
391392
function Headline:set_property(name, value)
393+
local bufnr = self.file:get_valid_bufnr()
392394
if not value then
393395
local existing_property, property_node = self:get_property(name)
394396
if existing_property and property_node then
395-
vim.fn.deletebufline(vim.api.nvim_get_current_buf(), property_node:start() + 1)
397+
vim.fn.deletebufline(bufnr, property_node:start() + 1)
396398
end
397399
self:refresh()
398400
local properties_node, properties = self:get_properties()
@@ -406,7 +408,7 @@ function Headline:set_property(name, value)
406408
if not properties then
407409
local append_line = self:get_append_line()
408410
local property_drawer = self:_apply_indent({ ':PROPERTIES:', ':END:' }) --[[ @as string[] ]]
409-
vim.api.nvim_buf_set_lines(0, append_line, append_line, false, property_drawer)
411+
vim.api.nvim_buf_set_lines(bufnr, append_line, append_line, false, property_drawer)
410412
properties = self:refresh():get_properties()
411413
end
412414

@@ -418,7 +420,7 @@ function Headline:set_property(name, value)
418420
local property_end = properties and properties:end_()
419421

420422
local new_line = self:_apply_indent(property) --[[@as string]]
421-
vim.api.nvim_buf_set_lines(0, property_end - 1, property_end - 1, false, { new_line })
423+
vim.api.nvim_buf_set_lines(bufnr, property_end - 1, property_end - 1, false, { new_line })
422424
return self:refresh()
423425
end
424426

@@ -824,9 +826,10 @@ function Headline:get_drawer_append_line(name)
824826
local drawer = self:get_drawer(name)
825827

826828
if not drawer then
829+
local bufnr = self.file:get_valid_bufnr()
827830
local append_line = self:get_append_line()
828831
local new_drawer = self:_apply_indent({ ':' .. name .. ':', ':END:' }) --[[ @as string[] ]]
829-
vim.api.nvim_buf_set_lines(0, append_line, append_line, false, new_drawer)
832+
vim.api.nvim_buf_set_lines(bufnr, append_line, append_line, false, new_drawer)
830833
drawer = self:get_drawer(name)
831834
end
832835
local name_row = drawer and drawer:field('name')[1]:end_() or 0
@@ -880,7 +883,7 @@ function Headline:_add_date(type, date, active)
880883
local text = type .. ': ' .. date:to_wrapped_string(active)
881884
if not has_plan_dates then
882885
local start_line = self:node():start()
883-
vim.fn.append(start_line + 1, self:_apply_indent(text))
886+
vim.fn.appendbufline(self.file:get_valid_bufnr(), start_line + 1, self:_apply_indent(text) --[[@as string]])
884887
return self:refresh()
885888
end
886889
if date_nodes[type] then
@@ -909,10 +912,12 @@ function Headline:_remove_date(type)
909912
if vim.tbl_count(date_nodes) == 0 or not date_nodes[type] then
910913
return
911914
end
912-
local line_nr = date_nodes[type]:start() + 1
915+
local line_nr = date_nodes[type]:start()
913916
self.file:set_node_text(date_nodes[type], '', true)
914-
if vim.trim(vim.fn.getline(line_nr)) == '' then
915-
vim.fn.deletebufline(vim.api.nvim_get_current_buf(), line_nr)
917+
local bufnr = self.file:get_valid_bufnr()
918+
local cur_line = vim.api.nvim_buf_get_lines(bufnr, line_nr, line_nr + 1, false)[1]
919+
if vim.trim(cur_line) == '' then
920+
vim.fn.deletebufline(bufnr, line_nr + 1)
916921
end
917922
return self:refresh()
918923
end
@@ -1005,11 +1010,12 @@ function Headline:_handle_promote_demote(recursive, modifier, dryRun)
10051010

10061011
local start = self:node():start()
10071012
local end_line = first_child_section:start()
1008-
local lines = modifier(start, vim.api.nvim_buf_get_lines(0, start, end_line, false))
1013+
local bufnr = self.file:get_valid_bufnr()
1014+
local lines = modifier(start, vim.api.nvim_buf_get_lines(bufnr, start, end_line, false))
10091015
if dryRun then
10101016
return lines
10111017
end
1012-
vim.api.nvim_buf_set_lines(0, start, end_line, false, lines)
1018+
vim.api.nvim_buf_set_lines(bufnr, start, end_line, false, lines)
10131019
return self:refresh()
10141020
end
10151021

lua/orgmode/files/init.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ function OrgFiles:new(opts)
2424
load_state = nil,
2525
}
2626
setmetatable(data, self)
27-
self.paths = self:_setup_paths(opts.paths)
27+
data.paths = self:_setup_paths(opts.paths)
2828
return data
2929
end
3030

tests/plenary/files/file_spec.lua

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -466,15 +466,16 @@ describe('OrgFile', function()
466466
end)
467467

468468
describe('set_node_text', function()
469-
it('should not do anything if file is not loaded in buffer', function()
469+
it('should throw an error if file is not loaded in buffer', function()
470470
local file = load_file_sync({
471471
'* Headline 1 :TAG:',
472472
' The content',
473473
' Multi line',
474474
})
475475
local paragraph_node = file:get_node_at_cursor():parent()
476-
local result = file:set_node_text(paragraph_node, 'New Text')
477-
assert.is.False(result)
476+
assert.is.error_matches(function()
477+
return file:set_node_text(paragraph_node, 'New Text')
478+
end, '%[orgmode%] No valid buffer for file ' .. file.filename .. ' to edit')
478479
end)
479480

480481
it('should set node text', function()

0 commit comments

Comments
 (0)