Skip to content

Commit

Permalink
Increment/Decrement indentation of list items (#779)
Browse files Browse the repository at this point in the history
* feat: indent listitem - implement (failing) test

* feat: implement increase/decrease list item

---------

Co-authored-by: Sebastian Flügge <seflue@users.noreply.github.com>
  • Loading branch information
seflue and seflue authored Jul 22, 2024
1 parent c0584ec commit 947850a
Show file tree
Hide file tree
Showing 3 changed files with 157 additions and 2 deletions.
38 changes: 38 additions & 0 deletions lua/orgmode/files/elements/listitem.lua
Original file line number Diff line number Diff line change
Expand Up @@ -115,4 +115,42 @@ function Listitem:update_cookie(total_child_checkboxes, checked_child_checkboxes
end
end

---@param line string
---@return string
function Listitem._increase(line)
return ' ' .. line
end
---
---@param line string
---@return string
function Listitem._decrease(line)
local repl, _ = line:gsub('^ ', '', 1)
return repl
end

---@param adjust_fn function
---@param include_childs boolean
function Listitem:_adjust_lines(adjust_fn, include_childs)
local start_row, _, end_row, _ = self.listitem:range()
if not include_childs then
end_row = start_row + 1
end

local lines = vim.api.nvim_buf_get_lines(0, start_row, end_row, false)
for i, line in ipairs(lines) do
lines[i] = adjust_fn(line)
end
vim.api.nvim_buf_set_lines(0, start_row, end_row, false, lines)
end

---@param include_childs boolean
function Listitem:demote(include_childs)
self:_adjust_lines(self._increase, include_childs)
end

---@param include_childs boolean
function Listitem:promote(include_childs)
self:_adjust_lines(self._decrease, include_childs)
end

return Listitem
38 changes: 36 additions & 2 deletions lua/orgmode/org/mappings.lua
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ local Table = require('orgmode.files.elements.table')
local EventManager = require('orgmode.events')
local events = EventManager.event
local Babel = require('orgmode.babel')
local ListItem = require('orgmode.files.elements.listitem')

---@class OrgMappings
---@field capture OrgCapture
Expand Down Expand Up @@ -489,25 +490,58 @@ function OrgMappings:_todo_change_state(direction)
end

function OrgMappings:do_promote(whole_subtree)
local count = vim.v.count1
local win_view = vim.fn.winsaveview() or {}
-- move to the first non-blank character so the current treesitter node is the listitem
vim.cmd([[normal! _]])

local node = ts_utils.get_node_at_cursor()
if node and node:type() == 'bullet' then
local listitem = self.files:get_closest_listitem()
if listitem then
listitem:promote(whole_subtree)
vim.fn.winrestview(win_view)
return
end
end

local headline = self.files:get_closest_headline()
local old_level = headline:get_level()
local foldclosed = vim.fn.foldclosed('.')
headline:promote(vim.v.count1, whole_subtree)
headline:promote(count, whole_subtree)
if foldclosed > -1 and vim.fn.foldclosed('.') == -1 then
vim.cmd([[norm!zc]])
end
EventManager.dispatch(events.HeadlinePromoted:new(self.files:get_closest_headline(), old_level))
vim.fn.winrestview(win_view)
end

function OrgMappings:do_demote(whole_subtree)
local count = vim.v.count1
local win_view = vim.fn.winsaveview() or {}
-- move to the first non-blank character so the current treesitter node is the listitem
vim.cmd([[normal! _]])

local node = ts_utils.get_node_at_cursor()
if node and node:type() == 'bullet' then
local listitem = self.files:get_closest_listitem()
if listitem then
listitem:demote(whole_subtree)
vim.fn.winrestview(win_view)

return
end
end

local headline = self.files:get_closest_headline()
local old_level = headline:get_level()
local foldclosed = vim.fn.foldclosed('.')
headline:demote(vim.v.count1, whole_subtree)
headline:demote(count, whole_subtree)
if foldclosed > -1 and vim.fn.foldclosed('.') == -1 then
vim.cmd([[norm!zc]])
end
EventManager.dispatch(events.HeadlineDemoted:new(self.files:get_closest_headline(), old_level))
vim.fn.winrestview(win_view)
end

function OrgMappings:org_return()
Expand Down
83 changes: 83 additions & 0 deletions tests/plenary/ui/mappings/list_spec.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
local config = require('orgmode.config')
local helpers = require('tests.plenary.helpers')
local org = require('orgmode')

local feed = function(keys, mode)
vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes(keys, true, true, true), mode, true)
end

describe('with list item', function()
describe('increase indentation', function()
before_each(function()
helpers.create_file({
'* Some headline',
' - content 1',
' - content sub 1',
' - content sub 2',
' - content subsub 1',
' - content subsub 2',
' - content 2',
'',
})
end)

it('with subitems', function()
vim.fn.cursor(2, 1)
vim.cmd([[norm >s]])
assert.are.same('* Some headline', vim.fn.getline(1))
assert.are.same(' - content 1', vim.fn.getline(2))
assert.are.same(' - content sub 1', vim.fn.getline(3))
assert.are.same(' - content sub 2', vim.fn.getline(4))
assert.are.same(' - content subsub 1', vim.fn.getline(5))
assert.are.same(' - content subsub 2', vim.fn.getline(6))
assert.are.same(' - content 2', vim.fn.getline(7))
end)

it('without subitems', function()
vim.fn.cursor(2, 1)
vim.cmd([[norm >>]])
assert.are.same(' - content 1', vim.fn.getline(2))
assert.are.same(' - content sub 1', vim.fn.getline(3))
assert.are.same(' - content sub 2', vim.fn.getline(4))
assert.are.same(' - content subsub 1', vim.fn.getline(5))
assert.are.same(' - content subsub 2', vim.fn.getline(6))
assert.are.same(' - content 2', vim.fn.getline(7))
end)
end)
describe('decrease indentation', function()
before_each(function()
helpers.create_file({
'* Some headline',
' - parent',
' - content 1',
' - content sub 1',
' - content sub 2',
' - content subsub 1',
' - content subsub 2',
' - content 2',
})
end)
it('with subitems', function()
vim.fn.cursor(3, 1)
vim.cmd([[norm <s]])
assert.are.same(' - parent', vim.fn.getline(2))
assert.are.same(' - content 1', vim.fn.getline(3))
assert.are.same(' - content sub 1', vim.fn.getline(4))
assert.are.same(' - content sub 2', vim.fn.getline(5))
assert.are.same(' - content subsub 1', vim.fn.getline(6))
assert.are.same(' - content subsub 2', vim.fn.getline(7))
assert.are.same(' - content 2', vim.fn.getline(8))
end)
it('without subitems', function()
vim.fn.cursor(3, 1)
vim.cmd([[norm <<]])
assert.are.same(' - parent', vim.fn.getline(2))
assert.are.same(' - content 1', vim.fn.getline(3))
assert.are.same(' - content sub 1', vim.fn.getline(4))
assert.are.same(' - content sub 2', vim.fn.getline(5))
assert.are.same(' - content subsub 1', vim.fn.getline(6))
assert.are.same(' - content subsub 2', vim.fn.getline(7))
assert.are.same(' - content 2', vim.fn.getline(8))
end)
end)
end)

0 comments on commit 947850a

Please sign in to comment.