Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions lua/orgmode/config/defaults.lua
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,8 @@ local DefaultConfig = {
org_time_stamp = '<prefix>i.',
org_time_stamp_inactive = '<prefix>i!',
org_toggle_timestamp_type = '<prefix>d!',
org_insert_drawer = '<prefix>iD',
org_insert_properties_drawer = '<prefix>ip',
org_insert_link = '<prefix>li',
org_store_link = '<prefix>ls',
org_clock_in = '<prefix>xi',
Expand Down
8 changes: 8 additions & 0 deletions lua/orgmode/config/mappings/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,14 @@ return {
args = { true },
opts = { desc = 'org timestamp (inactive)', help_desc = 'Insert/Update inactive date under cursor' },
}),
org_insert_drawer = m.action(
'org_mappings.insert_drawer',
{ opts = { desc = 'org insert drawer', help_desc = 'Insert drawer' } }
),
org_insert_properties_drawer = m.action(
'org_mappings.insert_properties_drawer',
{ opts = { desc = 'org insert properties drawer', help_desc = 'Insert Properties drawer' } }
),
org_insert_link = m.action('org_mappings.insert_link', {
modes = { 'n', 'x' },
opts = {
Expand Down
43 changes: 43 additions & 0 deletions lua/orgmode/org/mappings.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1057,6 +1057,49 @@ function OrgMappings:org_toggle_timestamp_type()
self:_replace_date(date)
end

-- Inserts a new drawer after the cursor position with custom name
function OrgMappings:insert_drawer()
local indent = vim.fn.matchstr(vim.fn.getline('.'), '^%s*')

return Input.open('Drawer name: '):next(function(drawer_name)
if not drawer_name or vim.trim(drawer_name) == '' then
return utils.echo_warning('Drawer name cannot be empty')
end
local insert_line = vim.fn.line('.')
local drawer_lines = {
string.format('%s:%s:', indent, drawer_name),
indent,
string.format('%s:END:', indent),
}
vim.fn.append(insert_line, drawer_lines)
vim.fn.cursor(insert_line + 2, #indent + 1)
return vim.cmd([[startinsert!]])
end)
end

-- Inserts a PROPERTIES drawer under the current headline
function OrgMappings:insert_properties_drawer()
local headline = self.files:get_closest_headline_or_nil()
if not headline then
return utils.echo_warning('No headline found to insert a drawer under')
end

local indent = headline:get_indent()
local existing = headline:get_drawer('PROPERTIES')

if existing then
local start_row = existing:start() + 1 -- 1-based
vim.fn.cursor(start_row + 1, #indent + 1)
return vim.cmd([[startinsert!]])
end

local drawer_lines = headline:_apply_indent({ ':PROPERTIES:', '', ':END:' }) --[[ @as string[] ]]
local insert_line = headline:get_range().start_line
vim.fn.append(insert_line, drawer_lines)
vim.fn.cursor(insert_line + 2, #indent + 1)
return vim.cmd([[startinsert!]])
end

---@param direction string
---@param use_fast_access? boolean
---@return boolean
Expand Down
63 changes: 63 additions & 0 deletions tests/plenary/ui/mappings/insert_drawer_spec.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
local helpers = require('tests.plenary.helpers')
local Input = require('orgmode.ui.input')
local Promise = require('orgmode.utils.promise')
local orgmode = require('orgmode')

local function with_mock_input(value, fn)
local original = Input.open
Input.open = function()
return Promise.resolve(value)
end
fn()
Input.open = original
end

describe('Insert drawer mappings', function()
after_each(function()
vim.cmd([[silent! %bw!]])
end)

it('inserts custom drawer at cursor (org_insert_drawer)', function()
helpers.create_file({
'* TODO heading',
'content line',
})

vim.fn.cursor(2, 1)
with_mock_input('NOTES', function()
orgmode.action('org_mappings.insert_drawer')
vim.wait(50, function()
return false
end)
end)

assert.are.same({
'* TODO heading',
'content line',
':NOTES:',
'',
':END:',
}, vim.api.nvim_buf_get_lines(0, 0, -1, false))
end)

it('inserts PROPERTIES drawer under headline', function()
helpers.create_file({
'* TODO heading',
'content line',
})

vim.fn.cursor(1, 1)
orgmode.action('org_mappings.insert_properties_drawer')
vim.wait(50, function()
return false
end)

assert.are.same({
'* TODO heading',
' :PROPERTIES:',
' ',
' :END:',
'content line',
}, vim.api.nvim_buf_get_lines(0, 0, -1, false))
end)
end)