Skip to content

Commit

Permalink
feat: Add global :Org command and global Org lua variable
Browse files Browse the repository at this point in the history
These allow interacting with orgmode in a more user friendly way
  • Loading branch information
kristijanhusak committed Jan 20, 2025
1 parent 8db7711 commit cac776b
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 2 deletions.
22 changes: 22 additions & 0 deletions docs/index.org
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
Nvim orgmode is a clone of Emacs Orgmode for Neovim 0.10.0+.
It aims to be a feature-complete implementation of Orgmode features in Neovim.

💡 TIP: To view this documentation offline in Neovim, run =:Org help=. More info in [[#globals-commands][Globals and commands]] section.


** Quick start
:PROPERTIES:
:CUSTOM_ID: quick-start
Expand Down Expand Up @@ -45,3 +48,22 @@ that demonstrates how the similar Orgmode clone [[https://github.com/dhruvasagar
:END:
Nvim-orgmode exoses a Lua API that can be used to interact with the orgmode. To view it, check [[file:../docs/orgmode-api.txt][orgmode-api.txt]]
or do =:h OrgApi= in Neovim.

** Globals and commands
:PROPERTIES:
:CUSTOM_ID: globals-commands
:END:
There are 2 additional ways to interact with Orgmode:
1. Through the =:Org= command
2. Through =Org= Lua global variable

List of available actions:
- =:Org help= - Open this documentation in new tab, set working directory to the docs folder for the tab to allow browsing
- =:Org helpgrep= - Open search agenda view that allows searching through the documentation
- =:Org agenda {type?}= - Open agenda view by the shortcut, for example =:Org agenda M= will open =tags_todo= view. When =type= is omitted, it opens up Agenda view.

All of the commands above can be executed through the global Lua =Org= variable. Examples:
- =Org.help()=
- =Org.helpgrep()=
- =Org.open()= - Opens =agenda= view
- =Org.open.m()= - Opens =tags= view
1 change: 1 addition & 0 deletions lua/orgmode/agenda/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ local AgendaTypes = require('orgmode.agenda.types')
local Agenda = {}

---@param opts? { highlighter: OrgHighlighter, files: OrgFiles }
---@return OrgAgenda
function Agenda:new(opts)
opts = opts or {}
local data = {
Expand Down
2 changes: 2 additions & 0 deletions lua/orgmode/init.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
_G.orgmode = _G.orgmode or {}
_G.Org = _G.Org or {}
---@type Org | nil
local instance = nil

Expand Down Expand Up @@ -35,6 +36,7 @@ setmetatable(Org, {
})

function Org:new()
require('orgmode.org.global')(self)
self.initialized = false
self:setup_autocmds()
require('orgmode.config'):setup_ts_predicates()
Expand Down
91 changes: 91 additions & 0 deletions lua/orgmode/org/global.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
local current_file_path = string.sub(debug.getinfo(1, 'S').source, 2)
local docs_dir = vim.fn.fnamemodify(current_file_path, ':p:h:h:h:h') .. '/docs'

---@param orgmode Org
local build = function(orgmode)
local Open = setmetatable({}, {
__call = function(t, ...)
t.a(...)
end,
__index = function(t, k)
local existing = rawget(t, k)
if existing then
return existing
end

---@diagnostic disable-next-line: invisible
local keys = orgmode.agenda:_build_menu():get_valid_keys()

for key, item in pairs(keys) do
t[key] = item.action
end

return rawget(t, k)
end,
})

for _, shortcut in ipairs({ 'a', 't', 'm', 'M', 's' }) do
Open[shortcut] = function()
return orgmode.agenda:open_by_key(shortcut)
end
end

local OrgGlobal = {
help = function()
vim.cmd(('tabnew %s'):format(('%s/%s'):format(docs_dir, 'index.org')))
vim.cmd(('tcd %s'):format(docs_dir))
end,

helpgrep = function()
orgmode.agenda:open_view('search', {
agenda_files = ('%s/**/*'):format(docs_dir),
})
end,

open = Open,
}

_G.Org = OrgGlobal
end

---@param opts string[]
---@return table
local function resolve_item(opts)
---@type table
local obj = _G.Org
for _, opt in ipairs(opts) do
if type(obj) ~= 'table' then
return obj
end
if obj[opt] then
obj = obj[opt]
end
end

return obj
end

vim.api.nvim_create_user_command('Org', function(opts)
local item = resolve_item(opts.fargs)
if item and type(item) == 'function' then
return item()
end
require('orgmode.utils').echo_error(('Invalid command "Org %s"'):format(opts.args))
end, {
nargs = '*',
complete = function(arg_lead, cmd_line)
local opts = vim.split(cmd_line:sub(5), '%s+')
local item = resolve_item(opts)
if type(item) ~= 'table' then
return {}
end
local list = vim.tbl_keys(item)

if arg_lead == '' then
return list
end
return vim.fn.matchfuzzy(list, arg_lead)
end,
})

return build
9 changes: 7 additions & 2 deletions lua/orgmode/ui/menu.lua
Original file line number Diff line number Diff line change
Expand Up @@ -135,14 +135,19 @@ function Menu._default_menu(data)
return entry.action()
end

function Menu:get_entry_by_key(key)
---@return table<string, OrgMenuOption | OrgMenuSeparator>
function Menu:get_valid_keys()
local valid_keys = {}
for _, item in ipairs(self.items) do
if item.key then
valid_keys[item.key] = item
end
end
return valid_keys[key]
return valid_keys
end

function Menu:get_entry_by_key(key)
return self:get_valid_keys()[key]
end

function Menu:open()
Expand Down

0 comments on commit cac776b

Please sign in to comment.