From 133a928d2f9795e81b7c44924f80549f7417ecfe Mon Sep 17 00:00:00 2001 From: Kristijan Husak Date: Wed, 15 Jan 2025 18:52:34 +0100 Subject: [PATCH] feat(docs): Add orgmode docs feat(docs): Add orgmode docs --- .github/workflows/docgen.yml | 38 +- CONTRIBUTING.md | 52 - CONTRIBUTING.org | 1 + Makefile | 4 +- README.org | 263 +--- docs/configuration.org | 2831 ++++++++++++++++++++++++++++++++++ docs/contributing.org | 81 + docs/index.org | 46 + docs/installation.org | 58 + docs/plugins.org | 173 +++ docs/troubleshoot.org | 39 + docs/tutorial.org | 248 +++ lua/orgmode/org/mappings.lua | 4 +- scripts/build_docs.sh | 21 + scripts/panvimdoc.lua | 611 ++++++++ 15 files changed, 4144 insertions(+), 326 deletions(-) delete mode 100644 CONTRIBUTING.md create mode 100644 CONTRIBUTING.org create mode 100644 docs/configuration.org create mode 100644 docs/contributing.org create mode 100644 docs/index.org create mode 100644 docs/installation.org create mode 100644 docs/plugins.org create mode 100644 docs/troubleshoot.org create mode 100644 docs/tutorial.org create mode 100755 scripts/build_docs.sh create mode 100644 scripts/panvimdoc.lua diff --git a/.github/workflows/docgen.yml b/.github/workflows/docgen.yml index c5fa553e0..35fea4a8a 100644 --- a/.github/workflows/docgen.yml +++ b/.github/workflows/docgen.yml @@ -4,6 +4,7 @@ on: push: branches: - master + - feat/docs jobs: docgen: @@ -12,11 +13,10 @@ jobs: - uses: actions/checkout@v4 with: token: ${{ secrets.GH_TOKEN }} - - uses: actions/setup-go@v5 + - name: Install pandoc + uses: pandoc/actions/setup@v1 with: - go-version: '^1.17.1' - - name: Install md2vim - run: go install git.foosoft.net/alex/md2vim@latest + version: 3.5 - name: Install Neovim uses: rhysd/action-setup-vim@v1 id: neovim @@ -30,17 +30,19 @@ jobs: - name: Generate api docs run: make api_docs - name: Generate vim docs - run: make docs - - name: Commit changes - env: - GH_TOKEN: ${{ secrets.GH_TOKEN }} - COMMIT_MSG: | - [docgen] Update docs - run: | - rm lemmy-help - git config user.name github-actions - git config user.email github-actions@github.com - git add doc/orgmode.txt - git add doc/orgmode_api.txt - # Only commit and push if we have changes - git diff --quiet && git diff --staged --quiet || (git commit -m "${COMMIT_MSG}"; git push) + run: make vim_docs + - name: Print vim docs + run: cat doc/orgmode.txt + # - name: Commit changes + # env: + # GH_TOKEN: ${{ secrets.GH_TOKEN }} + # COMMIT_MSG: | + # [docgen] Update docs + # run: | + # rm lemmy-help + # git config user.name github-actions + # git config user.email github-actions@github.com + # git add doc/orgmode.txt + # git add doc/orgmode_api.txt + # # Only commit and push if we have changes + # git diff --quiet && git diff --staged --quiet || (git commit -m "${COMMIT_MSG}"; git push) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index d3f9cd1de..000000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,52 +0,0 @@ -# Contributing Guide - -Thanks for wanting to help out with nvim-orgmode, we appreciate the effort! - -## Reporting Bugs/Features - -> :mega: Please always make a quick search in our [issue-tracker](https://github.com/nvim-orgmode/orgmode/issues) before reporting anything. If the bug/feature has already been reported, continue the conversation on the existing issue. - -We distinguish between `core` (part of [orgmode](https://orgmode.org/)) and `non-core` features. -The former will be prioritized. Bugs get the highest priority. - -If you're reporting a `core` feature, please be sure to provide a link that describes it. There are several places where features could be documented, have a look at these [resources](https://orgmode.org/worg/#resources). The more info you provide the better! - -## Documentation - -If you spot something missing in our [docs](DOCS.md), don't hesitate making a PR. The [wiki](https://github.com/nvim-orgmode/orgmode/wiki) can be edited freely. - -## Local dev - -Requirements: - -- [StyLua](https://github.com/JohnnyMorganz/StyLua) - For formatting - -To set up local development, run `make setup_dev`. This will add a pre-commit hook that will auto format all files before committing them. -You can always manually format all files with `make format` command - -## Code - -You can take a look at our [feature completeness](https://github.com/nvim-orgmode/orgmode/wiki/Feature-Completeness) list and see if any of the missing features catch your interest. - -If you prefer working on an issue that has been reported, please leave a comment voicing your interest. - -Please document any new code you add with [emmylua annotations](https://emmylua.github.io/annotation.html). Feel free to add annotations/docs to any existing functions integral to your PR that are missing them. - -### Tests - -To run tests run `make test` in the nvim-orgmode directory: - -``` -make test -``` - -To run a specific test you can set a `FILE` environment variable to a specific -spec you want to test. Example: - -``` -make test FILE=./tests/plenary/api/api_spec.lua -``` - -### Parser - -Parsing is done via builtin treesitter parser and the [tree-sitter-org](https://github.com/milisims/tree-sitter-org) grammar. diff --git a/CONTRIBUTING.org b/CONTRIBUTING.org new file mode 100644 index 000000000..194363e91 --- /dev/null +++ b/CONTRIBUTING.org @@ -0,0 +1 @@ +* Check [[file:./docs/contributing.org][contributing]] for more information diff --git a/Makefile b/Makefile index bb100fd8a..5b0dfc4ae 100644 --- a/Makefile +++ b/Makefile @@ -2,8 +2,8 @@ clean: nvim --headless --clean -n -c "lua vim.fn.delete('./tests/.deps', 'rf')" +q test: nvim --headless --clean -u tests/test.lua "$(FILE)" -docs: - md2vim -desc "*orgmode* *orgmode.nvim*\n* NOTE: This file is autogenerated from DOCS.md file" DOCS.md doc/orgmode.txt +vim_docs: + ./scripts/build_docs.sh api_docs: nvim --headless --clean -u ./scripts/gendoc.lua setup_dev: diff --git a/README.org b/README.org index 58884725e..4a95443a2 100644 --- a/README.org +++ b/README.org @@ -8,13 +8,12 @@ #+HTML:Kofi #+HTML:Chat -Orgmode clone written in Lua for Neovim 0.10.0+ +Orgmode clone written in Lua for Neovim -[[#setup][Setup]] • [[file:./DOCS.md][Docs]] • [[#showcase][Showcase]] • [[#treesitter-info][Treesitter]] • [[#troubleshoot][Troubleshoot]] • [[#plugins][Plugins]] • [[file:./CONTRIBUTING.md][Contributing]] • [[#thanks-to][Kudos]] +[[#installation][Installation]] • [[file:./docs/index.org][Docs]] • [[#showcase][Showcase]] • [[file:./docs/troubleshoot.org][Troubleshoot]] • [[#plugins][Plugins]] • [[file:./docs/contributing.org][Contributing]] • [[#thanks-to][Kudos]] #+HTML: - ** Quickstart *** Requirements @@ -22,11 +21,11 @@ Orgmode clone written in Lua for Neovim 0.10.0+ - Neovim 0.10.0 or later *** Installation +:PROPERTIES: +:CUSTOM_ID: installation +:END: -Use your favourite package manager: - -#+HTML:
lazy.nvim (recommended)
- +Use your favourite package manager. We recommend [[https://github.com/folke/lazy.nvim][lazy.nvim]]: #+BEGIN_SRC lua { 'nvim-orgmode/orgmode', @@ -49,134 +48,14 @@ Use your favourite package manager: } #+END_SRC -#+HTML:
- -#+HTML:
packer.nvim
- -#+BEGIN_SRC lua -use {'nvim-orgmode/orgmode', config = function() - require('orgmode').setup{} -end -} -#+END_SRC - -#+HTML:
- -#+HTML:
vim-plug
- -#+BEGIN_SRC vim -Plug 'nvim-orgmode/orgmode' -#+END_SRC - -#+HTML:
- -#+HTML:
dein.vim
- -#+BEGIN_SRC vim -call dein#add('nvim-orgmode/orgmode') -#+END_SRC - -#+HTML:
- -*** Setup -:PROPERTIES: -:CUSTOM_ID: setup -:END: - -Note that this setup is not needed for [[https://github.com/folke/lazy.nvim][lazy.nvim]] -since instructions above covers full setup - -#+BEGIN_SRC lua --- init.lua - -require('orgmode').setup({ - org_agenda_files = {'~/Dropbox/org/*', '~/my-orgs/**/*'}, - org_default_notes_file = '~/Dropbox/org/refile.org', -}) - --- NOTE: If you are using nvim-treesitter with ~ensure_installed = "all"~ option --- add ~org~ to ignore_install --- require('nvim-treesitter.configs').setup({ --- ensure_installed = 'all', --- ignore_install = { 'org' }, --- }) - -Or if you are using ~init.vim~, wrap the above snippet like so: -#+BEGIN_SRC vim -" init.vim -lua << EOF - -require('orgmode').setup({ - org_agenda_files = {'~/Dropbox/org/*', '~/my-orgs/**/*'}, - org_default_notes_file = '~/Dropbox/org/refile.org', -}) - -EOF -#+END_SRC - -**** Completion - -#+HTML:
nvim-cmp
-#+BEGIN_SRC lua -require('cmp').setup({ - sources = { - { name = 'orgmode' } - } -}) -#+END_SRC - -#+HTML:
- -#+HTML:
blink.cmp
-#+BEGIN_SRC lua -require('blink.cmp').setup({ - sources = { - completion = { - enabled_providers = { 'lsp', 'path', 'snippets', 'buffer', 'orgmode' } - -- Or if you want to use only this provider in org files - -- enabled_providers = function() - -- if vim.bo.filetype == 'org' then - -- return { 'orgmode' } - -- end - -- return { 'lsp', 'path', 'snippets', 'buffer' } - -- end - }, - providers = { - orgmode = { - name = 'Orgmode', - module = 'orgmode.org.autocompletion.blink', - }, - }, - }, -}) -#+END_SRC - -#+HTML:
- -#+HTML:
completion-nvim
- -#+BEGIN_SRC lua -vim.g.completion_chain_complete_list = { - org = { - { mode = 'omni'}, - }, -} --- add additional keyword chars -vim.cmd[[autocmd FileType org setlocal iskeyword+=:,#,+]] -#+END_SRC - -#+HTML:
- -Or just use ~omnifunc~ via == - +For more installation options see [[file:./docs/installation.org][Installation]] page. *** Usage - *Open agenda prompt*: =oa= - *Open capture prompt*: =oc= - In any orgmode buffer press =g?= for help -If you are new to Orgmode, see [[/DOCS.md#getting-started-with-orgmode][Getting started]] section in the Docs -or a hands-on [[https://github.com/nvim-orgmode/orgmode/wiki/Getting-Started][tutorial]] in our wiki. +If you are new to Orgmode, see [[file:./docs/index.org#getting-started][Getting started]] section in the Docs. ** Showcase :PROPERTIES: @@ -207,84 +86,6 @@ or a hands-on [[https://github.com/nvim-orgmode/orgmode/wiki/Getting-Started][tu #+NAME: autocomplete [[https://user-images.githubusercontent.com/1782860/123550227-e8605800-d76c-11eb-96f6-c0a677d562d4.gif]] -** Treesitter Info -:PROPERTIES: -:CUSTOM_ID: treesitter-info -:END: - -The built-in treesitter parser is used for parsing the org files. - -*** Known highlighting issues and limitations - -- LaTex is still highlighted through syntax file - -** Troubleshoot -:PROPERTIES: -:CUSTOM_ID: troubleshoot -:END: - -*** Indentation is not working - -Make sure you are not overriding indentexpr in Org buffers with [[https://github.com/nvim-treesitter/nvim-treesitter#indentation][nvim-treesitter indentation]] - -*** I get ~treesitter/query.lua~ errors when opening agenda/capture prompt or org files - -Tree-sitter parser might not be installed. -Try running ~:lua require('orgmode.config'):reinstall_grammar()~ to reinstall it. - -*** Dates are not in English - -Dates are generated with Lua native date support, and it reads your current locale when creating them. -#+HTML:
-To use different locale you can add this to your ~init.lua~: - -#+BEGIN_SRC lua -vim.cmd('language en_US.utf8') -#+END_SRC - -or ~init.vim~ - -#+BEGIN_SRC vim -language en_US.utf8 -#+END_SRC - -Just make sure you have ~en_US~ locale installed on your system. To see what you have available on the system you can -start the command ~:language~ and press ~~ to autocomplete possible options. - -*** Links are not concealed - -Links are concealed with Vim's conceal feature (see ~:help conceal~). To enable concealing, add this to your ~init.lua~: - -#+BEGIN_SRC lua -vim.opt.conceallevel = 2 -vim.opt.concealcursor = 'nc' -#+END_SRC - -Or if you are using ~init.vim~: - -#+BEGIN_SRC vim -set conceallevel=2 -set concealcursor=nc -#+END_SRC - -*** Jumping to file path is not working for paths with forward slash - -If you are using Windows, paths are by default written with backslashes. -To use forward slashes, you must enable ~shellslash~ option -(see ~:help shellslash~). - -#+BEGIN_SRC lua -vim.opt.shellslash = true -#+END_SRC - -Or if you are using ~init.vim~: - -#+BEGIN_SRC vim -set shellslash -#+END_SRC - -More info on issue [[https://github.com/nvim-orgmode/orgmode/issues/281#issuecomment-1120200775][#281]] - ** Features *** TL;DR @@ -329,7 +130,7 @@ More info on issue [[https://github.com/nvim-orgmode/orgmode/issues/281#issuecom - List tasks that have "TODO" state (=t=): - Find headlines matching tag(s) (=m=): - Search for headlines (and it's content) for a query (=s=): - - [[DOCS.md#advanced-search][Advanced search]] for tags/todo kewords/properties + - [[file:./docs/configuration.org#advanced-search][Advanced search]] for tags/todo kewords/properties - Notifications (experimental, see issue [[https://github.com/nvim-orgmode/orgmode/issues/49][#49]]) - Clocking time - Capture: @@ -364,23 +165,10 @@ More info on issue [[https://github.com/nvim-orgmode/orgmode/issues/281#issuecom - Highlighted code blocks (~#+BEGIN_SRC filetype~) Exporting (via ~emacs~, ~pandoc~ and custom export options) -Link to detailed documentation: [[DOCS.md][DOCS]] +Link to detailed documentation: [[./docs/index.org][DOCS]] ** Plugins -:PROPERTIES: -:CUSTOM_ID: plugins -:END: - -- [[https://github.com/chipsenkbeil/org-roam.nvim][org-roam.nvim]] - Implementation of [[https://orgroam.com][Org-roam]] knowledge management system -- [[https://github.com/nvim-orgmode/telescope-orgmode.nvim][telescope-orgmode.nvim]] - Telescope extension to find headlines, refile and insert links -- [[https://github.com/akinsho/org-bullets.nvim][org-bullets.nvim]] - Show org mode bullets as UTF-8 characters -- [[https://github.com/lukas-reineke/headlines.nvim][headlines.nvim]] - Add few highlight options for code blocks and headlines -- [[https://github.com/michaelb/sniprun][sniprun]] - For code evaluation in blocks -- [[https://github.com/dhruvasagar/vim-table-mode][vim-table-mode]] - For table support - -See all available plugins on [[https://github.com/topics/orgmode-nvim][orgmode-nvim]] - -*If you built a plugin please add "orgmode-nvim" topic to it.* +Check [[file:./docs/plugins.org][Plugins]] page for list of plugins. #+BEGIN_QUOTE *NOTE*: None of the Emacs Orgmode plugins will be built into nvim-orgmode. @@ -392,35 +180,6 @@ and a good foundation for external plugins. If you want to build a plugin, post suggestions and improvements on [[https://github.com/nvim-orgmode/orgmode/issues/26][Plugins infrastructure]] issue. -*** :wrench: API - -Documentation for our work-in-progress API can be found [[doc/orgmode_api.txt][here]] - -** Contributing - -See [[CONTRIBUTING.md][CONTRIBUTING.md]] - -** Documentation - -If you are just starting out with orgmode, have a look at the [[https://github.com/nvim-orgmode/orgmode/wiki/Getting-Started][Getting Started]] section in our wiki. - -Vim documentation is auto generated from [[DOCS.md][DOCS.md]] file with [[https://github.com/FooSoft/md2vim][md2vim]]. - -Hosted documentation is on: [[https://nvim-orgmode.github.io/][https://nvim-orgmode.github.io/]] - -** Roadmap - -- :white_check_mark: Support searching by properties -- :white_square_button: Improve checkbox hierarchy -- :white_check_mark: Support todo keyword faces -- :white_check_mark: Support clocking work time -- :white_check_mark: Improve folding -- :white_check_mark: Support exporting (via existing emacs tools) -- :white_square_button: Support archiving to specific headline -- :white_check_mark: Support tables -- :white_square_button: Support diary format dates -- :white_square_button: Support evaluating code blocks - ** Thanks to :PROPERTIES: :CUSTOM_ID: thanks-to diff --git a/docs/configuration.org b/docs/configuration.org new file mode 100644 index 000000000..d56313bf7 --- /dev/null +++ b/docs/configuration.org @@ -0,0 +1,2831 @@ +#+OPTIONS: H:9 +* Configuration + +This page contains information about all configuration that can be provided to the plugin. + +- [[#global-settings][Global setting]] +- [[#agenda-settings][Agenda settings]] +- [[#calendar-settings][Calendar settings]] +- [[#tags-settings][Tags settings]] +- [[#mappings][Mappings]] +- [[#features][Features]] +- [[#user-interface][User interface]] + +** Global setting +:PROPERTIES: +:CUSTOM_ID: global-settings +:END: +**** =org_agenda_files= +:PROPERTIES: +:CUSTOM_ID: org_agenda_files +:END: +- Type: =string | string[]= +- Default: =''= +Single or multiple paths from where the org files are being read. +# TODO: Add link to custom agenda commands + +Examples: +- =~/org/*= +- ={'~/Dropbox/org/**/*', '~/orgfiles/*'}= +*** =org_default_notes_file= +:PROPERTIES: +:CUSTOM_ID: org_default_notes_file +:END: +- Type: =string= +- Default: =''= +Path to a file that will be used as a default target file when refiling. + +Example: =~/orgfiles/refile.org= +*** =org_todo_keywords= +:PROPERTIES: +:CUSTOM_ID: org_todo_keywords +:END: +- Type: =string[]= +- Default: ={'TODO', '|', 'DONE'}= +List of unfinished (/"TODO"/) and finished (/"DONE"/) keywords. \\ +=|= is used as a separator between the two groups. + +if =|= is omitted, only the last entry in array is considered a /"DONE"/ state. + +To use [[https://orgmode.org/manual/Fast-access-to-TODO-states.html#Fast-access-to-TODO-states][Fast access to TODO States]], set a fast access key to at least one of the entries. + +For entries where a fast access key is not set, the first character of the keyword is used as the fast access key. + +Examples (Without fast access): +- ={'TODO', 'NEXT', '|', 'DONE'}= +- ={'TODO', 'WAITING', '|', 'DONE', 'DELEGATED'}= + +Examples (With fast access): +- ={'TODO(t)', 'NEXT(n)', '|', 'DONE(d)'}= +- ={'TODO(t)', 'NEXT', '|', 'DONE'}= - Same as above. Fast key is derived from first char. + +NOTE: Make sure fast access keys do not overlap. If that happens, first entry in list gets it. +*** =org_todo_repeat_to_state= +:PROPERTIES: +:CUSTOM_ID: org_todo_repeat_to_state +:END: +- Type: =string | nil= +- Default: =nil= +Path to a file that will be used as a default target file when refiling. + +Set an entry from [[#org_todo_keywords][org_todo_keywords]] to use as the "starting" state for repeatable todos. + +If provided value does not exist in [[#org_todo_keywords][org_todo_keywords]], first entry from that list is used. +*** =win_split_mode= +:PROPERTIES: +:CUSTOM_ID: win_split_mode +:END: +- Type: =string | function | [string, number]= +- Default: ='horizontal'= +This option determines how to open agenda and capture window. + +Available =string= values: +- =horizontal= - Always split horizontally +- =vertical= - Always split vertically +- =auto= - Determine between horizontal and vertical split depending on the current window size +- =float= - Open in float window that has width of 70% of the screen centered +- ={'float', 0.9}= - Open in float window and provide custom scale (in this case it's 90% of screen size), must be value between =0= and =1= + +If none of the options above suit your needs, there are 2 other ways to customize this: +1. Provide a custom command string (see =:help =). Few examples: + - Always open in tab: =tabnew= + - Always open vertically: =vsplit= + - Always open horizontally with specific height of 20 lines: =20split= +2. Custom function + #+begin_src lua + win_split_mode = function(name) + -- Make sure it's not a scratch buffer by passing false as 2nd argument + local bufnr = vim.api.nvim_create_buf(false, false) + --- Setting buffer name is required + vim.api.nvim_buf_set_name(bufnr, name) + + local fill = 0.8 + local width = math.floor((vim.o.columns * fill)) + local height = math.floor((vim.o.lines * fill)) + local row = math.floor((((vim.o.lines - height) / 2) - 1)) + local col = math.floor(((vim.o.columns - width) / 2)) + + vim.api.nvim_open_win(bufnr, true, { + relative = "editor", + width = width, + height = height, + row = row, + col = col, + style = "minimal", + border = "rounded" + }) + end + #+end_src + +*** =win_border= +:PROPERTIES: +:CUSTOM_ID: win_border +:END: +- Type: =string | string[]= +- Default: ='single'= +Border style for floating windows. +Available options: +- =none= - No border (default) +- =single= - A single line box +- =double= - A double line box +- =rounded= - Like "single", but with rounded corners ("╭" etc.) +- =solid= - Adds padding by a single whitespace cell +- =shadow= - A drop shadow effect by blending with the background +- ={'╔', '═' ,'╗', '║', '╝', '═', '╚', '║' }= - Specify border characters in a clock-wise fashion +- ={'/', '-', '\\', '|' }= - If less than eight chars the chars will start repeating + +See =:help nvim_open_win()= + +Applies to: +- always - calendar pop-up, help pop-up, notification pop-up +- =win_split_mode= is set to =float= - agenda window , capture window + +*** =org_startup_folded= +:PROPERTIES: +:CUSTOM_ID: org_startup_folded +:END: +- Type: =string= +- Default: ='overview'= +How many headings and other foldable items should be shown when an org file is opened. +Available options: +- =overview= - Only show top level elements (default) +- =content= - Only show the first two levels +- =showeverything= - Show all elements +- =inherit= - Use the fold level set in Neovim's global =foldlevel= option + +*** =org_todo_keyword_faces= +:PROPERTIES: +:CUSTOM_ID: org_todo_keyword_faces +:END: +- Type: =table= +- Default: ={}= +Custom colors for todo keywords. +Available options: + +- foreground - =:foreground hex/colorname=. Examples: =:foreground #FF0000=, =:foreground blue= +- background - =:background hex/colorname=. Examples: =:background #FF0000=, =:background blue= +- weight - =:weight bold= +- underline - =:underline on= +- italic - =:slant italic= + +Full configuration example with additional todo keywords and their colors: + +#+begin_src lua +require('orgmode').setup({ + org_todo_keywords = {'TODO', 'WAITING', '|', 'DONE', 'DELEGATED'}, + org_todo_keyword_faces = { + WAITING = ':foreground blue :weight bold', + DELEGATED = ':background #FFFFFF :slant italic :underline on', + TODO = ':background #000000 :foreground red', -- overrides builtin color for `TODO` keyword + } +}) +#+end_src +*** +*** =org_archive_location= +:PROPERTIES: +:CUSTOM_ID: org_archive_location +:END: +- Type: =string= +- Default: ='%s_archive::'= +Destination file for archiving. =%s= indicates the current file. =::= is used as a separator for archiving to headline +which is currently not supported. +This means that if you do a refile from a file =~/my-orgs/todos.org=, your task +will be archived in =~/my-orgs/todos.org_archive=. + +Example value: ='~/my-orgs/default-archive-file.org::'= + +📝 NOTE: This value can be overridden per file basis with a org special keyword =#+ARCHIVE=. + + + +*** =org_hide_leading_stars= +:PROPERTIES: +:CUSTOM_ID: org_hide_leading_stars +:END: +- Type: =boolean= +- Default: =false= +Hide leading stars for headings. +Example: + +Disabled (default): +#+begin_src org +* TODO First item +** TODO Second Item +*** TODO Third item +#+end_src + +Enabled: +#+begin_src org +* TODO First item + * TODO Second Item + * TODO Third item +#+end_src + +📝 NOTE: Stars are hidden by applying highlight group that masks them with color that's same as background color. +If this highlight group does not suit you, you can apply different highlight group to it: +#+begin_src lua +vim.cmd[[autocmd ColorScheme * hi link @org.leading.stars MyCustomHlGroup]] +#+end_src + +To set specific characters instead of using asterisk, check [[file:./plugins.org::#org-bulletsnvim][org-bullets.nvim]] plugin plugin. + + +*** =org_hide_emphasis_markers= +:PROPERTIES: +:CUSTOM_ID: org_hide_emphasis_markers +:END: +- Type: =boolean= +- Default: =false= +Conceal bold/italic/underline/code/verbatim markers. + +Ensure your =:h conceallevel= is set properly in order for this to function. + +*** =org_ellipsis= +:PROPERTIES: +:CUSTOM_ID: org_ellipsis +:END: +- Type: =string= +- Default: ='...'= +Marker used to indicate a folded headline. + +*** =org_log_done= +:PROPERTIES: +:CUSTOM_ID: org_log_done +:END: +- Type: =string|false= +- Default: =time= +Possible values: +- =time= - adds =CLOSED= date when marking headline as done +- =note= - adds =CLOSED= date as above, and prompts for closing note via capture window. + Confirm note with =org_note_finalize= (Default ==), or ignore providing note via =org_note_kill= (Default =ok=) +- =false= - Disable any logging + +*** =org_log_repeat= +:PROPERTIES: +:CUSTOM_ID: org_log_repeat +:END: +- Type: =string|false= +- Default: =time= +Possible values: + +- =time= - adds =LAST_REPEAT= date to properties when marking headline with a repeater date as done +- =note= - adds =LAST_REPEAT= date as above, and prompts for closing note via capture window. + Confirm note with =org_note_finalize= (Default ==), or ignore providing note via =org_note_kill= (Default =ok=) +- =false= - Disable logging the =LAST_REPEAT= date + +*** =org_log_into_drawer= +:PROPERTIES: +:CUSTOM_ID: org_log_into_drawer +:END: +- Type: =string|nil= +- Default: =nil= +Log TODO state changes into a drawer with the given name. The recommended value is =LOGBOOK=. +If =nil=, log into the section body. + +*** =org_highlight_latex_and_related= +:PROPERTIES: +:CUSTOM_ID: org_highlight_latex_and_related +:END: +- Type: =string|nil= +- Default: =nil= + +📝 NOTE: This option is experimental + +Possible values: +- =native= - Includes whole latex syntax file into the org syntax. It can potentially cause some highlighting issues and slowness. +- =entities= - Highlight latex only in these situations (see [[https://orgmode.org/manual/LaTeX-fragments.html#LaTeX-fragments][Orgmode latex fragments]]): + - between ~\begin~ and ~\end~ delimiters + - between ~$~ and ~$~ delimiters - example: ~$a^2=b$~ + - between ~$$~ and ~$$~ delimiters - example: ~$$ a=+\sqrt{2} $$~ + - between ~\[~ and ~\]~ delimiters - example: ~\[ a=-\sqrt{2} \]~ + - between ~\(~ and ~\)~ delimiters - example: ~\( b=2 \)~ + +*** =org_startup_indented= +:PROPERTIES: +:CUSTOM_ID: org_startup_indented +:END: +- Type: =boolean= +- Default: =false= +Possible values: +- =true= - Uses /Virtual/ indents to align content visually. The indents are only visual, they are not saved to the file. +- =false= - Do not add any /Virtual/ indentation. + +You can toggle Virtual indents on the fly by setting =vim.b.org_indent_mode= to either =true= or =false= when in a org +buffer. For example, if virtual indents were enabled in the current buffer then you could disable them immediately by +setting ~vim.b.org_indent_mode = false~. + +*** =org_adapt_indentation= +:PROPERTIES: +:CUSTOM_ID: org_adapt_indentation +:END: +- Type: =boolean= +- Default: =true= +Possible values: +- =true= - Use /hard/ indents for content under headlines. Files will save with indents relative to headlines. +- =false= - Do not add any /hard/ indents. Files will save without indentation relative to headlines. + +*** =org_indent_mode_turns_off_org_adapt_indentation= +:PROPERTIES: +:CUSTOM_ID: org_indent_mode_turns_off_org_adapt_indentation +:END: +- Type: =boolean= +- Defaul: =true= +Possible values: +- =true= - Disable [[#org_adapt_indentation][org_adapt_indentation]] by default when [[#org_startup_indented][org_startup_indented]] is enabled. +- =false= - Do not disable [[#org_adapt_indentation][org_adapt_indentation]] by default when [[#org_startup_indented][org_startup_indented]] is enabled. + +*** =org_indent_mode_turns_on_hiding_stars= +:PROPERTIES: +:CUSTOM_ID: org_indent_mode_turns_on_hiding_stars +:END: +- Type: =boolean= +- Defaul: =true= +Possible values: +- =true= - Enable [[#org_hide_leading_stars][org_hide_leading_stars]] by default when [[#org_startup_indented][org_indent_mode]] is enabled for buffer (~vim.b.org_indent_mode = true~). +- =false= - Do not modify the value in [[#org_hide_leading_stars][org_hide_leading_stars]] by default when [[#org_startup_indented][org_indent_mode]] is enabled for buffer (~vim.b.org_indent_mode = true~). + +*** =org_src_window_setup= +:PROPERTIES: +:CUSTOM_ID: org_src_window_setup +:END: +- Type: =string | function= +- Default: ='top 16new'= +If the value is a string, it will be run directly as input to +=:h vim.cmd=, otherwise if the value is a function it will be called. +Both values have the responsibility of opening a buffer (within a +window) to show the special edit buffer. The content of the buffer will +be set automatically, so this option only needs to handle opening an +empty buffer. + +*** =org_edit_src_content_indentation= +:PROPERTIES: +:CUSTOM_ID: org_edit_src_content_indentation +:END: +- Type: =number= +- Default: =0= +The indent value for content within =SRC= block types beyond the +existing indent of the block itself. Only applied when exiting from an +=org_edit_special= action on a =SRC= block. + +*** =org_custom_exports= +:PROPERTIES: +:CUSTOM_ID: org_custom_exports +:END: +- Type: =table= +- Default: ={}= +Add custom export options to the export prompt. +Structure: + +#+begin_example +[shortcut:string] = { + [label:string] = 'Label in export prompt', + [action:function] = function(exporter) + return exporter(command:table, target:string, on_success?:function, on_error?:function) + end +} +#+end_example + +Breakdown: + +- =shortcut= - single char that will be used to select the export. Make + sure it doesn't conflict with existing options +- =action= - function that provides =exporter= function for generating + the exports +- =exporter= - function that calls the command provided via =job= + - =command= - table (array like) that contains command how to generate + the export + - =target= - target file name that will be generated + - =on_success?= - function that is triggered when export succeeds + (command exit status is 0). Provides table parameter with command + output. Optional, defaults to prompt to open target file. + - =on_error?= - function that is triggered when export fails (command + exit status is not 0). Provides table parameter with command output. + Optional, defaults to printing output as error. + +For example, lets add option to export to =rtf= format via =pandoc=: + +#+begin_src lua +require('orgmode').setup({ + org_custom_exports = { + f = { + label = 'Export to RTF format', + action = function(exporter) + local current_file = vim.api.nvim_buf_get_name(0) + local target = vim.fn.fnamemodify(current_file, ':p:r')..'.rtf' + local command = {'pandoc', current_file, '-o', target} + local on_success = function(output) + print('Success!') + vim.api.nvim_echo({{ table.concat(output, '\n') }}, true, {}) + end + local on_error = function(err) + print('Error!') + vim.api.nvim_echo({{ table.concat(err, '\n'), 'ErrorMsg' }}, true, {}) + end + return exporter(command , target, on_success, on_error) + end + } + } +}) +#+end_src + +*** =org_time_stamp_rounding_minutes= +:PROPERTIES: +:CUSTOM_ID: org_time_stamp_rounding_minutes +:END: +- Type: =number= +- Default: =5= +Number of minutes to increase/decrease when using +[[#org_timestamp_up][org_timestamp_up]]/[[#org_timestamp_down][org_timestamp_down]] + +*** =org_blank_before_new_entry= +:PROPERTIES: +:CUSTOM_ID: org_blank_before_new_entry +:END: +- Type: =table= +- Default: ~{ heading = true, plain_list_item = false }~ +Determine if blank line should be prepended when: + +- Adding heading via =org_meta_return= and =org_insert_*= mappings +- Adding a list item via =org_meta_return= + +*** =org_id_uuid_program= +:PROPERTIES: +:CUSTOM_ID: org_id_uuid_program +:END: +- Type: =string= +- Default: =uuidgen= +External program used to generate uuid's for id module + +*** =org_id_ts_format= +:PROPERTIES: +:CUSTOM_ID: org_id_ts_format +:END: +- Type: =string= +- Default: =%Y%m%d%H%M%S= +Format of the id generated when [[#org_id_method][org_id_method]] is set +to =ts=. + +*** =org_id_method= +:PROPERTIES: +:CUSTOM_ID: org_id_method +:END: +- Type: ='uuid' | 'ts' | 'org'= +- Default: =uuid= +What method to use to generate ids via org id module. + +- =uuid= - Use [[#org_id_uuid_program][org_id_uuid_program]] to generate + the id +- =ts= - Generate id from current timestamp using format [[#org_id_ts_format][org_id_ts_format]] +- =org= - Generate a random 12 digit number and prepend [[#org_id_prefix][org_id_prefix]] + +*** =org_id_prefix= +:PROPERTIES: +:CUSTOM_ID: org_id_prefix +:END: +- Type: =string | nil= +- Default: =nil= +Prefix added to the generated id when [[#org_id_method][org_id_method]] is set to =org=. + +*** =org_id_link_to_org_use_id= +:PROPERTIES: +:CUSTOM_ID: org_id_link_to_org_use_id +:END: +- Type: =boolean= +- Default: =false= +If =true=, generate ID with the Org ID module and append it to the +headline as property. More info on [[#org_store_link][org_store_link]] + +*** =org_babel_default_header_args= +:PROPERTIES: +:CUSTOM_ID: org_babel_default_header_args +:END: +- Type: =table= +- Default: ~{ [':tangle'] = 'no', [':noweb'] = no }~ +Default header args for extracting source code. See [[#extract-source-code-tangle][Extract source code (tangle)]] for more details. + +*** =calendar_week_start_day= +:PROPERTIES: +:CUSTOM_ID: calendar_week_start_day +:END: +- Type: =number= +- Default: =1= +Available options: + +- =0= - start week on Sunday +- =1= - start week on Monday + +Determine on which day the week will start in calendar modal (ex:[[#org_change_date][changing the date under cursor]]) + +*** =emacs_config= +:PROPERTIES: +:CUSTOM_ID: emacs_config +:END: +- Type: =table= +- Default: ={ executable_path = 'emacs', config_path=nil }= +Set configuration for your emacs. This is useful for having the emacs +export properly pickup your emacs config and plugins. If =config_path= +is not provided, exporter tries to find a configuration file from these +locations: + +1. =~/.config/emacs/init.el= +2. =~/.emacs.d/init.el= +3. =~/.emacs.el= + +If there is no configuration found, it will still process the export. + +If it finds a configuration and export attempt fails because of the +configuration issue, there will be a prompt to attempt the same export +without the configuration file. + +** Agenda settings +:PROPERTIES: +:CUSTOM_ID: agenda-settings +:END: +*** =org_deadline_warning_days= +:PROPERTIES: +:CUSTOM_ID: org_deadline_warning_days +:END: +- Type: =number= +- Default: =14= +Number of days during which deadline becomes visible in today's +agenda. +Example: If Today is =2021-06-10=, and we have these tasks: +- =Task 1= has a deadline date =2021-06-15= +- =Task 2= has a deadline date =2021-06-30= + +- =Task 1= is visible in today's agenda +- =Task 2= is not visible in today's agenda until =2021-06-16= + +*** =org_agenda_span= +:PROPERTIES: +:CUSTOM_ID: org_agenda_span +:END: +- Type: =string|number= +- Default: ='week'= +/possible string values/: =day=, =week=, =month=, =year= +Default time span shown when agenda is opened. + +*** =org_agenda_start_on_weekday= +:PROPERTIES: +:CUSTOM_ID: org_agenda_start_on_weekday +:END: +- Type: =number= +- Default: =1= +From which day in week (ISO weekday, 1 is Monday) to show the agenda. +Applies only to =week= and number span. +If set to =false=, starts from today + +*** =org_agenda_start_day= +:PROPERTIES: +:CUSTOM_ID: org_agenda_start_day +:END: +- Type: =string= +- Default: =nil= +/example values/: =+2d=, =-1d= +offset to apply to the agenda start date. +Example: +If =org_agenda_start_on_weekday= is =false=, and =org_agenda_start_day= +is =-2d=, +agenda will always show current week from today - 2 days + +*** =org_agenda_custom_commands= +:PROPERTIES: +:CUSTOM_ID: org_agenda_custom_commands +:END: +- Type: =table= +- Default: ={}= + +Define custom agenda views that are available through the +(org_agenda)[#org_agenda] mapping. It is possible to combine multiple +agenda types into single view. An example: + +#+begin_src lua +require('orgmode').setup({ + org_agenda_files = {'~/org/**/*'}, + org_agenda_custom_commands = { + -- "c" is the shortcut that will be used in the prompt + c = { + description = 'Combined view', -- Description shown in the prompt for the shortcut + types = { + { + type = 'tags_todo', -- Type can be agenda | tags | tags_todo + match = '+PRIORITY="A"', --Same as providing a "Match:" for tags view oa + m, See: https://orgmode.org/manual/Matching-tags-and-properties.html + org_agenda_overriding_header = 'High priority todos', + org_agenda_todo_ignore_deadlines = 'far', -- Ignore all deadlines that are too far in future (over org_deadline_warning_days). Possible values: all | near | far | past | future + }, + { + type = 'agenda', + org_agenda_overriding_header = 'My daily agenda', + org_agenda_span = 'day' -- can be any value as org_agenda_span + }, + { + type = 'tags', + match = 'WORK', --Same as providing a "Match:" for tags view oa + m, See: https://orgmode.org/manual/Matching-tags-and-properties.html + org_agenda_overriding_header = 'My work todos', + org_agenda_todo_ignore_scheduled = 'all', -- Ignore all headlines that are scheduled. Possible values: past | future | all + }, + { + type = 'agenda', + org_agenda_overriding_header = 'Whole week overview', + org_agenda_span = 'week', -- 'week' is default, so it's not necessary here, just an example + org_agenda_start_on_weekday = 1 -- Start on Monday + org_agenda_remove_tags = true -- Do not show tags only for this view + }, + } + }, + p = { + description = 'Personal agenda', + types = { + { + type = 'tags_todo', + org_agenda_overriding_header = 'My personal todos', + org_agenda_category_filter_preset = 'todos', -- Show only headlines from `todos` category. Same value providad as when pressing `/` in the Agenda view + org_agenda_sorting_strategy = {'todo-state-up', 'priority-down'} -- See all options available on org_agenda_sorting_strategy + }, + { + type = 'agenda', + org_agenda_overriding_header = 'Personal projects agenda', + org_agenda_files = {'~/my-projects/**/*'}, -- Can define files outside of the default org_agenda_files + }, + { + type = 'tags', + org_agenda_overriding_header = 'Personal projects notes', + org_agenda_files = {'~/my-projects/**/*'}, + org_agenda_tag_filter_preset = 'NOTES-REFACTOR' -- Show only headlines with NOTES tag that does not have a REFACTOR tag. Same value providad as when pressing `/` in the Agenda view + }, + } + } + } +}) +#+end_src + +*** =org_agenda_sorting_strategy= +:PROPERTIES: +:CUSTOM_ID: org_agenda_sorting_strategy +:END: +- Type: +=table<'agenda' | 'todo' | 'tags', OrgAgendaSortingStrategy[]><= +- Default: +~{ agenda = {'time-up', 'priority-down', 'category-keep'}, todo = {'priority-down', 'category-keep'}, tags = {'priority-down', 'category-keep'}}~ +List of sorting strategies to apply to a given view. Available +strategies: + +- =time-up= - Sort entries by time of day. Applicable only in =agenda= + view +- =time-down= - Opposite of =time-up= +- =priority-down= - Sort by priority, from highest to lowest +- =priority-up= - Sort by priority, from lowest to highest +- =tag-up= - Sort by sorted tags string, ascending +- =tag-down= - Sort by sorted tags string, descending +- =todo-state-up= - Sort by todo keyword by position (example: 'TODO, + PROGRESS, DONE' has a sort value of 1, 2 and 3), ascending +- =todo-state-down= - Sort by todo keyword, descending +- =clocked-up= - Show clocked in headlines first +- =clocked-down= - Show clocked in headines last +- =category-up= - Sort by category name, ascending +- =category-down= - Sort by category name, descending +- =category-keep= - Keep default category sorting, as it appears in + org-agenda-files + +*** =org_agenda_block_separator= +:PROPERTIES: +:CUSTOM_ID: org_agenda_block_separator +:END: +- Type: =string= +- Default: =-= +Separator used to separate multiple agenda views generated by +org_agenda_custom_commands. +To change the highlight, override =@org.agenda.separator= hl group. + +*** =org_agenda_remove_tags= +:PROPERTIES: +:CUSTOM_ID: org_agenda_remove_tags +:END: +- Type: =boolean= +- Default: =false= +Should tags be hidden from all agenda views. + +*** =org_capture_templates= +:PROPERTIES: +:CUSTOM_ID: org_capture_templates +:END: +- Type: =table= +- Default: +={ t = { description = 'Task', template = '* TODO %?\n %u' } }= +Templates for capture/refile prompt. +Variables: + +- =%f=: Prints the file of the buffer capture was called from +- =%F=: Like =%f= but inserts the full path +- =%n=: Inserts the current =$USER= +- =%t=: Prints current date (Example: =<2021-06-10 Thu>=) +- =%^t=: Prompt for current date (Example: =<2021-06-10 Thu>=) +- =%^{Name}t=: Prompt for current date for given =Name= (visible in + calendar title) (Example: =<2021-06-10 Thu>=) +- =%T=: Prints current date and time (Example: =<2021-06-10 Thu 12:30>=) +- =%^T=: Prompt for current date and time (Example: + =<2021-06-10 Thu 12:30>=) +- =%^{Name}T=: Prompt for current date and time for given =Name= + (visible in calendar title) (Example: =<2021-06-10 Thu 12:30>=) +- =%u=: Prints current date in inactive format (Example: + =[2021-06-10 Thu]=) +- =%^u=: Prompt for current date in inactive format (Example: + =[2021-06-10 Thu]=) +- =%^{Name}u=: Prompt for current date in inactive format for given + =Name= (visible in calendar title) (Example: =[2021-06-10 Thu]=) +- =%U=: Prints current date and time in inactive format (Example: + =[2021-06-10 Thu 12:30]=) +- =%^U=: Prompt for current date and time in inactive format (Example: + =[2021-06-10 Thu 12:30]=) +- =%^{Name}U=: Prompt for current date and time in inactive format for + given =Name= (visible in calendar title) (Example: + =[2021-06-10 Thu 12:30]=) +- =%a=: File and line number from where capture was initiated (Example: + =[[file:/home/user/projects/myfile.txt +2]]=) +- =%=: Insert current date/time formatted according to + [[https://www.lua.org/pil/22.1.html][lua date]] format (Example: + =%<%Y-%m-%d %A>= produces '2021-07-02 Friday') +- =%x=: Insert content of the clipboard via the "+" register (see :help + clipboard) +- =%?=: Default cursor position when template is opened +- =%^{PROMPT|DEFAULT|COMPLETION...}=: Prompt for input, if completion is + provided an :h inputlist will be used +- =%(EXP)=: Runs the given lua code and inserts the result. NOTE: this + will internally pass the content to the lua =load()= function. So the + body inside =%()= should be the body of a function that returns a + string. + +Templates have the following fields: + +- =description= (=string=) --- description of the template that is + displayed in the template selection menu +- =template= (=string|string[]=) --- body of the template that will be + used when creating capture +- =target= (=string?=) --- name of the file to which the capture content + will be added. If the target is not specified, the content will be + added to the [[#org_default_notes_file][org_default_notes_file]] file +- =headline= (=string?=) --- title of the headline after which the + capture content will be added. If no headline is specified, the + content will be appended to the end of the file +- =datetree (boolean | { time_prompt?: boolean, reversed?: boolean, tree_type: 'day' | 'month' | 'week' | 'custom' })= + Create a [[https://orgmode.org/manual/Template-elements.hml#FOOT84][date tree]] with current day in the target file and put the capture content there. + - =true= - Create ascending datetree (newer dates go to end) with the current date + - ~{ time_prompt = true, reversed?: boolean }~ open up a date picker to select a date before opening up a capture buffer + - ={ reversed: true }= add entries in reversed order (newer dates comes first) + - ={ tree_type: 'day' | 'month' | 'week' | 'custom' }= Which date tree type to use: + - =day= Create year -> month -> day structure, and refile headlines in the day headline + - =month= Create year -> month structure, and refile headlines in the month headline + - =week= Create year -> week number structure, and refile headlines in the week number headline + - =custom= (*Advanced*) - Create custom datetree with own date formats. This requires adding =tree= property in the =datetree= opts. + Example with year and month tree: + #+begin_src lua + datetree = { + tree_type = 'custom', + tree = { + { + format = '%Y', + pattern = '^(%d%d%d%d)$', + order = { 1 } + }, + { + format = '%Y-%m', + pattern = '^(%d%d%d%d)%-(%d%d)$', + order = { 1, 2 } + } + } + } + #+end_src + Check [[https://github.com/nvim-orgmode/orgmode/blob/master/lua/orgmode/capture/template/datetree.lua#L144][this line in source]] for builtin tree types and detailed explanation how to add own tree. +- =regexp (string)= Search for specific line in the target file via regex (same as searching through file from command), + and append the content after that line. For example, if you have line =appendhere= in target file, + put this option to =^appendhere$= to add headlines after that line +- =properties= (=table?=): + - =empty_lines= (=table|number?=) if the value is a number, then empty lines are added before and after the content. + If the value is a table, then the following fields are expected: + - =before= (=integer?=) add empty lines to the beginning of the content + - =after= (=integer?=) add empty lines to the end of the content + +Example: + +#+begin_src lua +{ T = { + description = 'Todo', + template = '* TODO %?\n %u', + target = '~/org/todo.org' +} } +#+end_src + +Journal example: + +#+begin_src lua +{ + j = { + description = 'Journal', + template = '\n*** %<%Y-%m-%d> %<%A>\n**** %U\n\n%?', + target = '~/sync/org/journal.org' + }, +} +#+end_src + +Journal example with dynamic target, i.e. a separate file per month: + +#+begin_src lua +{ + J = { + description = 'Journal', + template = '\n*** %<%Y-%m-%d> %<%A>\n**** %U\n\n%?', + target = '~/sync/org/journal/%<%Y-%m>.org' + }, +} +#+end_src + +Nested key example: + +#+begin_src lua +{ + e = 'Event', + er = { + description = 'recurring', + template = '** %?\n %T', + target = '~/org/calendar.org', + headline = 'recurring' + }, + eo = { + description = 'one-time', + template = '** %?\n %T', + target = '~/org/calendar.org', + headline = 'one-time' + } +} +-- or +{ + e = { + description = 'Event', + subtemplates = { + r = { + description = 'recurring', + template = '** %?\n %T', + target = '~/org/calendar.org', + headline = 'recurring' + }, + o = { + description = 'one-time', + template = '** %?\n %T', + target = '~/org/calendar.org', + headline = 'one-time' + }, + }, + }, +} +#+end_src + +Lua expression example: + +#+begin_src lua +{ + j = { + description = 'Journal', + template = '* %(return vim.fn.getreg "w")', + -- get the content of register "w" + target = '~/sync/org/journal.org' + }, +} +#+end_src + +*** =org_agenda_min_height= +:PROPERTIES: +:CUSTOM_ID: org_agenda_min_height +:END: +- Type: =number= +- Default: =16= +Indicates the minimum height that the agenda window will occupy. + +*** =org_priority_highest= +:PROPERTIES: +:CUSTOM_ID: org_priority_highest +:END: +- Type: =string|number= +- Default: =A= +Indicates highest priority for a task in the agenda view. +Example: +#+begin_src org + * TODO [#A] This task has the highest priority +#+end_src + +*** =org_priority_default= +:PROPERTIES: +:CUSTOM_ID: org_priority_default +:END: +- Type: =string|number= +- Default: =B= +Indicates normal priority for a task in the agenda view. +This is the default priority for all tasks if other priority is not applied +Example: +#+begin_src org +* TODO [#B] This task has the normal priority +* TODO And this one has the same priority +#+end_src + +*** =org_priority_lowest= +:PROPERTIES: +:CUSTOM_ID: org_priority_lowest +:END: +- Type: =string|number= +- Default: =C= +Indicates lowest priority for a task in the agenda view. +Example: +#+begin_src org +* TODO [#B] This task has the normal priority +* TODO And this one has the same priority as above one +* TODO [#C] I'm lowest in priority +#+end_src + +*** =org_agenda_skip_scheduled_if_done= +:PROPERTIES: +:CUSTOM_ID: org_agenda_skip_scheduled_if_done +:END: +- Type: =boolean= +- Default: =false= + +Hide scheduled entries from agenda if they are in a "DONE" state. + +*** =org_agenda_skip_deadline_if_done= +:PROPERTIES: +:CUSTOM_ID: org_agenda_skip_deadline_if_done +:END: +- Type: =boolean= +- Default: =false= + +Hide deadline entries from agenda if they are in a "DONE" state. + +*** =org_agenda_text_search_extra_files= +:PROPERTIES: +:CUSTOM_ID: org_agenda_text_search_extra_files +:END: +- Type: =('agenda-archives')[]= +- Default: ={}= +Additional files to search from agenda search prompt. +Currently it accepts only a single value: =agenda-archives=. +Example value: ={'agenda-archives'}= + +** Calendar settings +:PROPERTIES: +:CUSTOM_ID: calendar-settings +:END: +Adjust behavior of the calendar modal (ex: [[#org_change_date][changing the date under cursor]]). + +*** *calendar.round_min_with_hours* +:PROPERTIES: +:CUSTOM_ID: calendarround_min_with_hours +:END: +- Type: =boolean= +- Default: =true= +Should minutes be rounded, when the hour is changed. It behaves more +fluently when changing the hours, especially when scheduling from the +current time (which can be something odd). If set to false, the minutes +are unchanged while changing the hours. + +*** *calendar.min_big_step* +:PROPERTIES: +:CUSTOM_ID: calendarmin_big_step +:END: +- Type: =number= +- Default: =15= +The step size for changing the minutes while the cursor is on the first +digit. + +*** *calendar.min_small_step* +:PROPERTIES: +:CUSTOM_ID: calendarmin_small_step +:END: +- Type: =number= +- Default: same as [[#org_time_stamp_rounding_minutes][org_time_stamp_rounding_minutes]] +The step size for changing the minutes while the cursor is on the second +digit. + +** Tags settings +:PROPERTIES: +:CUSTOM_ID: tags-settings +:END: +*** =org_tags_column= +:PROPERTIES: +:CUSTOM_ID: org_tags_column +:END: +- Type: =number= +- Default: =80= +The column to which tags should be indented in a headline. If this +number is positive, it specifies the column. If it is negative, it means +that the tags should be flushright to that column. For example, -80 +works well for a normal 80 character screen. When 0, place tags directly +after headline text, with only one space in between. + +*** =org_use_tag_inheritance= +:PROPERTIES: +:CUSTOM_ID: org_use_tag_inheritance +:END: +- Type: =boolean= +- Default: =true= + When set to =true=, tags are +inherited from parents for purposes of searching. Which means that if +you have this structure: + +#+begin_src org +* TODO My top task :MYTAG: +** TODO MY child task :CHILDTAG: +*** TODO Nested task +#+end_example + +First headline has tag =MYTAG= Second headline has tags =MYTAG= and +=CHILDTAG= Third headline has tags =MYTAG= and =CHILDTAG=. +When disabled, headlines have only tags that are directly applied to them. + +*** =org_tags_exclude_from_inheritance= +:PROPERTIES: +:CUSTOM_ID: org_tags_exclude_from_inheritance +:END: +- Type: =string[]= +- Default: ={}= +List of tags that are excluded from inheritance. +Using the example above, setting this variable to ={'MYTAG'}=, second +and third headline would have only =CHILDTAG=, where =MYTAG= would not +be inherited. + +** Mappings +:PROPERTIES: +:CUSTOM_ID: mappings +:END: +Mappings try to mimic some of the Orgmode mappings, but since Orgmode +uses =CTRL + c= as a modifier most of the time, we have to take a +different route. When possible, instead of =CTRL + C=, prefix +=o= is used. This is customizable via the =mappings.prefix= +setting. + +To disable all mappings, just pass ~disable_all = true~ to mappings +settings: + +#+begin_src lua +require('orgmode').setup({ + org_agenda_files = {'~/Dropbox/org/*', '~/my-orgs/**/*'}, + org_default_notes_file = '~/Dropbox/org/refile.org', + mappings = { + disable_all = true + } +}) +#+end_src + +To disable a specific mapping, set it's value to =false=: + +#+begin_src lua +require('orgmode').setup({ + org_agenda_files = {'~/Dropbox/org/*', '~/my-orgs/**/*'}, + org_default_notes_file = '~/Dropbox/org/refile.org', + mappings = { + global = { + org_agenda = false, + org_capture = 'gC' + }, + } +}) +#+end_src + +To change a key mapping's =lhs= but not its =desc=, provide a string or +a table: + +#+begin_src lua +require('orgmode').setup({ + org_agenda_files = {'~/Dropbox/org/*', '~/my-orgs/**/*'}, + org_default_notes_file = '~/Dropbox/org/refile.org', + mappings = { + global = { + -- providing a string + org_agenda = '', + -- providing a table + org_capture = { '' } + }, + } +}) +#+end_src + +To change a key mapping's =lhs= and its =desc=, provide a table: + +#+begin_src lua +require('orgmode').setup({ + org_agenda_files = {'~/Dropbox/org/*', '~/my-orgs/**/*'}, + org_default_notes_file = '~/Dropbox/org/refile.org', + mappings = { + global = { + org_capture = { '', desc = 'Open Capture Prompt' } + } + } +}) +#+end_src + +(The =desc= value is displayed in tools like WhichKey.) + +You can find the configuration file that holds all default mappings +[[../lua/orgmode/config/mappings/init.lua][here]] + +*NOTE*: All mappings are normal mode mappings (=nnoremap=) with +exception of =org_return= + +*** Use Enter in insert mode to add list items/checkboxes/todos +:PROPERTIES: +:CUSTOM_ID: use-enter-in-insert-mode-to-add-list-itemscheckboxestodos +:END: +By default, adding list items/checkboxes/todos is done with +[[#org_meta_return][org_meta_return]] which is a normal mode mapping. If +you want to have an insert mode mapping there are two options: + +1. If your terminal supports it, map a key like =Shift + Enter= to the + meta return mapping (Recommended): + +#+begin_src lua +vim.api.nvim_create_autocmd('FileType', { + pattern = 'org', + callback = function() + vim.keymap.set('i', '', 'lua require("orgmode").action("org_mappings.meta_return")', { + silent = true, + buffer = true, + }) + end, +}) +#+end_src + +2. If you want to use only enter, enable =org_return_uses_meta_return= option: + +#+begin_src lua +require('orgmode').setup({ + org_agenda_files = {'~/Dropbox/org/*', '~/my-orgs/**/*'}, + org_default_notes_file = '~/Dropbox/org/refile.org', + mappings = { + org_return_uses_meta_return = true + } +}) +#+end_src + +This will trigger =org_meta_return= if there is no content after the +cursor position (either at the end of line or has just trailing spaces). +Just note that this option always tries to use =meta_return=, which also +adds new headlines automatically if you are on the headline line, which +can give undesired results. + +*** Global mappings +:PROPERTIES: +:CUSTOM_ID: global-mappings +:END: +There are only 2 global mappings that are accessible from everywhere. + +**** =org_agenda= +:PROPERTIES: +:CUSTOM_ID: org_agenda +:END: +- Mapped to: =oa= +Opens up agenda prompt. + +**** =org_capture= +:PROPERTIES: +:CUSTOM_ID: org_capture +:END: +- Mapped to: =oc= +Opens up capture prompt. + +These live under =mappings.global= and can be overridden like this: + +#+begin_src lua +require('orgmode').setup({ + org_agenda_files = {'~/Dropbox/org/*', '~/my-orgs/**/*'}, + org_default_notes_file = '~/Dropbox/org/refile.org', + mappings = { + global = { + org_agenda = 'gA', + org_capture = 'gC' + } + } +}) +#+end_src + +If you want to use multiple mappings for same thing, pass array of +mappings: + +#+begin_src lua +require('orgmode').setup({ + org_agenda_files = {'~/Dropbox/org/*', '~/my-orgs/**/*'}, + org_default_notes_file = '~/Dropbox/org/refile.org', + mappings = { + global = { + org_agenda = {'gA', 'oa'}, + org_capture = {'gC', 'oc'} + } + } +}) +#+end_src + +*** Agenda mappings +:PROPERTIES: +:CUSTOM_ID: agenda-mappings +:END: +Mappings used in agenda view window. + +**** =org_agenda_later= +:PROPERTIES: +:CUSTOM_ID: org_agenda_later +:END: +- Mapped to: =f= +Go to next agenda span. + +**** =org_agenda_earlier= +:PROPERTIES: +:CUSTOM_ID: org_agenda_earlier +:END: +- Mapped to: =b= +Go to previous agenda span. + +**** =org_agenda_goto_today= +:PROPERTIES: +:CUSTOM_ID: org_agenda_goto_today +:END: +- Mapped to: =.= +Go to span with for today. + +**** =org_agenda_day_view= +:PROPERTIES: +:CUSTOM_ID: org_agenda_day_view +:END: +- Mapped to: =vd= +Show agenda day view. + +**** =org_agenda_week_view= +:PROPERTIES: +:CUSTOM_ID: org_agenda_week_view +:END: +- Mapped to: =vw= +Show agenda week view. + +**** =org_agenda_month_view= +:PROPERTIES: +:CUSTOM_ID: org_agenda_month_view +:END: +- Mapped to: =vm= +Show agenda month view. + +**** =org_agenda_year_view= +:PROPERTIES: +:CUSTOM_ID: org_agenda_year_view +:END: +- Mapped to: =vy= +Show agenda year view. + +**** =org_agenda_quit= +:PROPERTIES: +:CUSTOM_ID: org_agenda_quit +:END: +- Mapped to: =q= +Close agenda. + +**** =org_agenda_switch_to= +:PROPERTIES: +:CUSTOM_ID: org_agenda_switch_to +:END: +- Mapped to: == +Open selected agenda item in the same buffer. + +**** =org_agenda_goto= +:PROPERTIES: +:CUSTOM_ID: org_agenda_goto +:END: +- Mapped to: ={''}= +Open selected agenda item in split window. + +**** =org_agenda_goto_date= +:PROPERTIES: +:CUSTOM_ID: org_agenda_goto_date +:END: +- Mapped to: =J= +Open calendar that allows selecting date to jump to. + +**** =org_agenda_redo= +:PROPERTIES: +:CUSTOM_ID: org_agenda_redo +:END: +- Mapped to: =r= +Reload all org files and refresh current agenda view. + +**** =org_agenda_todo= +:PROPERTIES: +:CUSTOM_ID: org_agenda_todo +:END: +- Mapped to: =t= +Change =TODO= state of an item in both agenda and original Org file. + +**** =org_agenda_clock_in= +:PROPERTIES: +:CUSTOM_ID: org_agenda_clock_in +:END: +- Mapped to: =I= +Clock in item under cursor. +See [[#clocking][Clocking]] for more details. + +**** =org_agenda_clock_out= +:PROPERTIES: +:CUSTOM_ID: org_agenda_clock_out +:END: +- Mapped to: =O= +Clock out currently active clock item. +See [[#clocking][Clocking]] for more details. + +**** =org_agenda_clock_cancel= +:PROPERTIES: +:CUSTOM_ID: org_agenda_clock_cancel +:END: +- Mapped to: =X= +Cancel clock on currently active clock item. +See [[#clocking][Clocking]] for more details. + +**** =org_agenda_clock_goto= +:PROPERTIES: +:CUSTOM_ID: org_agenda_clock_goto +:END: +- Mapped to: =oxj= +Jump to currently clocked in headline. +See [[#clocking][Clocking]] for more details. + +**** =org_agenda_clockreport_mode= +:PROPERTIES: +:CUSTOM_ID: org_agenda_clockreport_mode +:END: +- Mapped to: =R= +Show clock report at the end of the agenda for current agenda time +range +See [[#clocking][Clocking]] for more details. + +**** =org_agenda_priority= +:PROPERTIES: +:CUSTOM_ID: org_agenda_priority +:END: +- Mapped to: =o,= +Choose the priority of a headline item. + +**** =org_agenda_priority_up= +:PROPERTIES: +:CUSTOM_ID: org_agenda_priority_up +:END: +- Mapped to: =+= +Increase the priority of a headline item. + +**** =org_agenda_priority_down= +:PROPERTIES: +:CUSTOM_ID: org_agenda_priority_down +:END: +- Mapped to: =-= +Decrease the priority of a headline item. + +**** =org_agenda_archive= +:PROPERTIES: +:CUSTOM_ID: org_agenda_archive +:END: +- Mapped to: =o$= +Archive headline item to archive location. + +**** =org_agenda_toggle_archive_tag= +:PROPERTIES: +:CUSTOM_ID: org_agenda_toggle_archive_tag +:END: +- Mapped to: =oA= +Toggle "ARCHIVE" tag of a headline item. + +**** =org_agenda_set_tags= +:PROPERTIES: +:CUSTOM_ID: org_agenda_set_tags +:END: +- Mapped to: =ot= +Set tags on current headline item. + +**** =org_agenda_deadline= +:PROPERTIES: +:CUSTOM_ID: org_agenda_deadline +:END: +- Mapped to: =oid= +Insert/Update deadline date on current headline item. + +**** =org_agenda_schedule= +:PROPERTIES: +:CUSTOM_ID: org_agenda_schedule +:END: +- Mapped to: =ois= +Insert/Update scheduled date on current headline item. + +**** =org_agenda_refile= +:PROPERTIES: +:CUSTOM_ID: org_agenda_refile +:END: +- Mapped to: =or= +Refile current headline to a destination org-file. Same as [[#org_refile][org_refile]] but from agenda view. + +**** =org_agenda_add_note= +:PROPERTIES: +:CUSTOM_ID: org_agenda_add_note +:END: +- Mapped to: =ona= +Add note to the current headline + +**** =org_agenda_filter= +:PROPERTIES: +:CUSTOM_ID: org_agenda_filter +:END: +- Mapped to: =/= +Open prompt that allows filtering current agenda view by category, tags +and title (vim regex, see =:help vim.regex()=) +Example: + +Having =todos.org= file with headlines that have tags =mytag= or +=myothertag=, and some of them have =check= in content, this search: +=todos+mytag/check/= +Returns all headlines that are in =todos.org= file, that have =mytag= +tag, and have =check= in headline title. Note that regex is case +sensitive by default. +Use vim regex flag =\c= to make it case insensitive. See +=:help vim.regex()= and =:help /magic=. +Pressing == in filter prompt autocompletes categories and tags. + +**** =org_agenda_show_help= +:PROPERTIES: +:CUSTOM_ID: org_agenda_show_help +:END: +- Mapped to: =g?= +Show help popup with mappings + +These mappings live under =mappings.agenda=, and can be changed like +this: + +#+begin_src lua +require('orgmode').setup({ + org_agenda_files = {'~/Dropbox/org/*', '~/my-orgs/**/*'}, + org_default_notes_file = '~/Dropbox/org/refile.org', + mappings = { + agenda = { + org_agenda_later = '>', + org_agenda_earlier = '<', + org_agenda_goto_today = {'.', 'T'} + } + } +}) +#+end_src + +*** Capture mappings +:PROPERTIES: +:CUSTOM_ID: capture-mappings +:END: +Mappings used in capture window. + +**** =org_capture_finalize= +:PROPERTIES: +:CUSTOM_ID: org_capture_finalize +:END: +- Mapped to: == +Save current capture content to =org_default_notes_file= and close capture window. + +**** =org_capture_refile= +:PROPERTIES: +:CUSTOM_ID: org_capture_refile +:END: +- Mapped to: =or= +Refile capture content to specific destination. + +**** =org_capture_kill= +:PROPERTIES: +:CUSTOM_ID: org_capture_kill +:END: +- Mapped to: =ok= +Close capture window without saving anything. + +**** =org_capture_show_help= +:PROPERTIES: +:CUSTOM_ID: org_capture_show_help +:END: +- Mapped to: =g?= +Show help popup with mappings. + +These mappings live under =mappings.capture=, and can be changed like +this: + +#+begin_src lua +require('orgmode').setup({ + org_agenda_files = {'~/Dropbox/org/*', '~/my-orgs/**/*'}, + org_default_notes_file = '~/Dropbox/org/refile.org', + mappings = { + capture = { + org_capture_finalize = 'w', + org_capture_refile = 'R', + org_capture_kill = 'Q' + } + } +}) +#+end_src + +*** Note mappings +:PROPERTIES: +:CUSTOM_ID: note-mappings +:END: +Mappings used in closing note window. + +**** =org_note_finalize= +:PROPERTIES: +:CUSTOM_ID: org_note_finalize +:END: +- Mapped to: == +Save note window content as closing note for a headline. Ignores first comment (if exists). + +**** =org_note_kill= +:PROPERTIES: +:CUSTOM_ID: org_note_kill +:END: +- Mapped to: =ok= +Close note window without saving anything. + +#+begin_src lua +require('orgmode').setup({ + org_agenda_files = {'~/Dropbox/org/*', '~/my-orgs/**/*'}, + org_default_notes_file = '~/Dropbox/org/refile.org', + mappings = { + note = { + org_note_finalize = 'w', + org_note_kill = 'Q' + } + } +}) +#+end_src + +*** Org mappings +:PROPERTIES: +:CUSTOM_ID: org-mappings +:END: +Mappings for =org= files. + +**** =org_refile= +:PROPERTIES: +:CUSTOM_ID: org_refile +:END: +- Mapped to: =or= +Refile current headline, including its subtree, to a destination +org-file. This file must be one of the files specified for the +=org_agenda_files= setting. A target headline in the destination file +can be specified with =destination.org/=. If there are +multiple headlines with the same name in the destination file, the first +occurence will be used. + +**** =org_timestamp_up= +:PROPERTIES: +:CUSTOM_ID: org_timestamp_up +:END: +- Mapped to: == +Increase date part under under cursor. Accepts count: (Example: +=5=) +=|= in examples references cursor position. + +- Year - Example date: =<202|1-10-01 Fri 10:30>= becomes + =<202|2-10-01 Sat 10:30>= +- Month - Example date: =<2021-1|0-01 Fri 10:30>= becomes + =<2022-1|1-01 Mon 10:30>= +- Day - Example date: =<2021-10-0|1 Fri 10:30>= becomes + =<2022-10-0|2 Sat 10:30>=. Same thing happens when cursor is on day + name. +- Hour - Example date: =<2021-10-01 Fri 1|0:30>= becomes + =<2022-10-02 Sat 1|1:30>=. +- Minute - Example date: =<2021-10-01 Fri 10:3|0>= becomes + =<2022-10-02 Sat 11:3|5>=. See [[#org_time_stamp_rounding_minutes][org_time_stamp_rounding_minutes]] for steps configuration. +- Repeater/Delay range (=h->d->w->m->y=) - Example date: + =<2021-10-01 Fri 10:30 +1|w>= becomes =<2021-10-01 Fri 10:30 +1|m>= +- Active/Inactive state - (=<= to =[= and vice versa) - Example date: + =|<2021-10-01 Fri 10:30>= becomes =|[2021-10-01 Fri 10:30]= + +**** =org_timestamp_down= +:PROPERTIES: +:CUSTOM_ID: org_timestamp_down +:END: +- Mapped to: == +Decrease date part under under cursor. +Same as [[#org_timestamp_up][org_timestamp_up]], just opposite +direction. + +**** =org_timestamp_up_day= +:PROPERTIES: +:CUSTOM_ID: org_timestamp_up_day +:END: +- Mapped to: == +Increase date under cursor by 1 or "count" day(s) (Example count: +=5=). + +**** =org_timestamp_down_day= +:PROPERTIES: +:CUSTOM_ID: org_timestamp_down_day +:END: +- Mapped to: == +Decrease date under cursor by 1 or "count" day(s) (Example count: +=5=). + +**** =org_change_date= +:PROPERTIES: +:CUSTOM_ID: org_change_date +:END: +- Mapped to: =cid= +Change date under cursor. Opens calendar to select new date. + +**** =org_toggle_timestamp_type= +:PROPERTIES: +:CUSTOM_ID: org_toggle_timestamp_type +:END: +- Mapped to: =od!= +Switches the timestamp under the cursor between inactive and active. + +**** =org_priority= +:PROPERTIES: +:CUSTOM_ID: org_priority +:END: +- Mapped to: =o,= +Choose the priority of a headline item. + +**** =org_priority_up= +:PROPERTIES: +:CUSTOM_ID: org_priority_up +:END: +- Mapped to: =ciR= +Increase the priority of a headline item. + +**** =org_priority_down= +:PROPERTIES: +:CUSTOM_ID: org_priority_down +:END: +- Mapped to: =cir= +Decrease the priority of a headline item. + +**** =org_todo= +:PROPERTIES: +:CUSTOM_ID: org_todo +:END: +- Mapped to: =cit= +Cycle todo keyword forward on current headline or open fast access to +TODO states prompt (see [[#org_todo_keywords][org_todo_keywords]]) if it's enabled. + +**** =org_todo_prev= +:PROPERTIES: +:CUSTOM_ID: org_todo_prev +:END: +- Mapped to: =ciT= +Cycle todo keyword backward on current headline. + +**** =org_toggle_checkbox= +:PROPERTIES: +:CUSTOM_ID: org_toggle_checkbox +:END: +- Mapped to: == +Toggle current line checkbox state. + +**** =org_toggle_heading= +:PROPERTIES: +:CUSTOM_ID: org_toggle_heading +:END: +- Mapped to: =o*= +Toggle current line to headline and vice versa. Checkboxes will turn into TODO headlines. + +**** =org_insert_link= +:PROPERTIES: +:CUSTOM_ID: org_insert_link +:END: +- Mapped to: =oli= +Insert a hyperlink at cursor position. When the cursor is on a hyperlink, edit that hyperlink. If there +are any links stored with [[#org_store_link][org_store_link]], pressing == to autocomplete the input will show +list of all stored links to select. Links generated with ID are properly expanded to valid links after +selection. + +**** =org_store_link= +:PROPERTIES: +:CUSTOM_ID: org_store_link +:END: +- Mapped to: =ols= +Generate a link to the closest headline. If [[#org_id_link_to_org_use_id][org_id_link_to_org_use_id]] is +=true=, it appends the =ID= property to the headline, and generates link with that id to be inserted via +[[#org_insert_link][org_insert_link]]. When [[#org_id_link_to_org_use_id][org_id_link_to_org_use_id]] is =false=, +it generates the standard file::*headline link (example: =file:/path/to/my/todos.org::*My headline=) + +**** =org_open_at_point= +:PROPERTIES: +:CUSTOM_ID: org_open_at_point +:END: +- Mapped to: =oo= +Open hyperlink or date under cursor. When date is under the cursor, open +the agenda for that day. + +**** =org_edit_special= +:PROPERTIES: +:CUSTOM_ID: org_edit_special +:END: +- Mapped to: =o'= +Open a source block for editing in a temporary buffer of the associated =filetype=. +This is useful for editing text with language servers attached, etc. +When the buffer is closed, the text of the underlying source block in +the original Org file is updated. +📝 NOTE: if the Org file that the source block comes from is edited before the +special edit buffer is closed, the edits will not be applied. The special edit +buffer contents can be recovered from :messages output + +**** =org_add_note= +:PROPERTIES: +:CUSTOM_ID: org_add_note +:END: +- Mapped to: =ona= +Add note to the current headline. + +**** =org_cycle= +:PROPERTIES: +:CUSTOM_ID: org_cycle +:END: +- Mapped to: == +Cycle folding for current headline. + +**** =org_global_cycle= +:PROPERTIES: +:CUSTOM_ID: org_global_cycle +:END: +- Mapped to: == +Cycle global folding. + +**** =org_archive_subtree= +:PROPERTIES: +:CUSTOM_ID: org_archive_subtree +:END: +- Mapped to: =o$= +Archive current headline to archive location. + +**** =org_set_tags_command= +:PROPERTIES: +:CUSTOM_ID: org_set_tags_command +:END: +- Mapped to: =ot= +Set tags on current headline. + +**** =org_toggle_archive_tag= +:PROPERTIES: +:CUSTOM_ID: org_toggle_archive_tag +:END: +- Mapped to: =oA= +Toggle "ARCHIVE" tag on current headline. + +**** =org_do_promote= +:PROPERTIES: +:CUSTOM_ID: org_do_promote +:END: +- Mapped to: =<<= +Promote headline. + +**** =org_do_demote= +:PROPERTIES: +:CUSTOM_ID: org_do_demote +:END: +- Mapped to: =>>= +Demote headline. + +**** =org_promote_subtree= +:PROPERTIES: +:CUSTOM_ID: org_promote_subtree +:END: +- Mapped to: =s= +Demote subtree. + +**** =org_meta_return= +:PROPERTIES: +:CUSTOM_ID: org_meta_return +:END: +- Mapped to: == +Add headline, list item or checkbox below, depending on current line. + +**** =org_insert_heading_respect_content= +:PROPERTIES: +:CUSTOM_ID: org_insert_heading_respect_content +:END: +- Mapped to: =oih= +Add headline after current headline + it's content with same level. + +**** =org_insert_todo_heading= +:PROPERTIES: +:CUSTOM_ID: org_insert_todo_heading +:END: +- Mapped to: =oiT= +Add TODO headline right after the current headline. + +**** =org_insert_todo_heading_respect_content= +:PROPERTIES: +:CUSTOM_ID: org_insert_todo_heading_respect_content +:END: +- Mapped to: =oit= +Add TODO headliner after current headline + it's content. + +**** =org_move_subtree_up= +:PROPERTIES: +:CUSTOM_ID: org_move_subtree_up +:END: +- Mapped to: =oK= +Move current headline + it's content up by one headline. + +**** =org_move_subtree_down= +:PROPERTIES: +:CUSTOM_ID: org_move_subtree_down +:END: +- Mapped to: =oJ= +Move current headline + it's content down by one headline. + +**** =org_export= +:PROPERTIES: +:CUSTOM_ID: org_export +:END: +- Mapped to: =oe= +Open export options. +*NOTE*: Exports are handled via =emacs= and =pandoc=. This means that =emacs= and/or =pandoc= must be in +=$PATH=. see [[#org_custom_exports][org_custom_exports]] if you want to add your own export options. + +**** =org_next_visible_heading= +:PROPERTIES: +:CUSTOM_ID: org_next_visible_heading +:END: +- Mapped to: =}= +Go to next heading (any level). + +**** =org_previous_visible_heading= +:PROPERTIES: +:CUSTOM_ID: org_previous_visible_heading +:END: +- Mapped to: ={= +Go to previous heading (any level). + +**** =org_forward_heading_same_level= +:PROPERTIES: +:CUSTOM_ID: org_forward_heading_same_level +:END: +- Mapped to: =]]= +Go to next heading on same level. Doesn't go outside of parent. + +**** =org_backward_heading_same_level= +:PROPERTIES: +:CUSTOM_ID: org_backward_heading_same_level +:END: +- Mapped to: =[[= +Go to previous heading on same level. Doesn't go outside of parent. + +**** =outline_up_heading= +:PROPERTIES: +:CUSTOM_ID: outline_up_heading +:END: +- Mapped to: =g{= +Go to parent heading. + +**** =org_deadline= +:PROPERTIES: +:CUSTOM_ID: org_deadline +:END: +- Mapped to: =oid= +Insert/Update deadline date. + +**** =org_schedule= +:PROPERTIES: +:CUSTOM_ID: org_schedule +:END: +- Mapped to: =ois= +Insert/Update scheduled date. + +**** =org_time_stamp= +:PROPERTIES: +:CUSTOM_ID: org_time_stamp +:END: +- Mapped to: =oi.= +Insert/Update date under cursor. + +**** =org_time_stamp_inactive= +:PROPERTIES: +:CUSTOM_ID: org_time_stamp_inactive +:END: +- Mapped to: =oi!= +Insert/Update inactive date under cursor. + +**** =org_clock_in= +:PROPERTIES: +:CUSTOM_ID: org_clock_in +:END: +- Mapped to: =oxi= +Clock in headline under cursor. +See [[#clocking][Clocking]] for more details. + +**** =org_clock_out= +:PROPERTIES: +:CUSTOM_ID: org_clock_out +:END: +- Mapped to: =oxo= +Clock out headline under cursor. +See [[#clocking][Clocking]] for more details. + +**** =org_clock_cancel= +:PROPERTIES: +:CUSTOM_ID: org_clock_cancel +:END: +- Mapped to: =oxq= +Cancel currently active clock on current headline. +See [[#clocking][Clocking]] for more details. + +**** =org_clock_goto= +:PROPERTIES: +:CUSTOM_ID: org_clock_goto +:END: +- Mapped to: =oxj= +Jump to currently clocked in headline. +See [[#clocking][Clocking]] for more details. + +**** =org_set_effort= +:PROPERTIES: +:CUSTOM_ID: org_set_effort +:END: +- Mapped to: =oxe= +Set effort estimate property on for current headline. +See [[#clocking][Clocking]] for more details. + +**** =org_babel_tangle= +:PROPERTIES: +:CUSTOM_ID: org_babel_tangle +:END: +- Mapped to: =obt= +Tangle current file. See [[#extract-source-code-tangle][Extract source code (tangle)]] for more details. + +**** =org_show_help= +:PROPERTIES: +:CUSTOM_ID: org_show_help +:END: +- Mapped to: =g?= +Show help popup with mappings + +These mappings live under =mappings.org=, and can be changed like this: + +#+begin_src lua +require('orgmode').setup({ + org_agenda_files = {'~/Dropbox/org/*', '~/my-orgs/**/*'}, + org_default_notes_file = '~/Dropbox/org/refile.org', + mappings = { + org = { + org_timestamp_up = '+', + org_timestamp_down = '-' + } + } +}) +#+end_src + +*** Edit Src +:PROPERTIES: +:CUSTOM_ID: edit-src +:END: +Mappings applied when editing a =SRC= block content via =org_edit_special=. + +**** =org_edit_src_abort= +:PROPERTIES: +:CUSTOM_ID: org_edit_src_abort +:END: +- Mapped to: =ok= +Abort changes made to temporary buffer created from the content of a =SRC= block, see above. + +**** =org_edit_src_save= +:PROPERTIES: +:CUSTOM_ID: org_edit_src_save +:END: +- Mapped to: =ow= +Apply changes from the special buffer to the source Org buffer. + +**** =org_edit_src_save_exit= +:PROPERTIES: +:CUSTOM_ID: org_edit_src_save_exit +:END: +- Mapped to: ='= +Apply changes from the special buffer to the source Org buffer and close the edit special window. + +**** =org_edit_src_show_help= +:PROPERTIES: +:CUSTOM_ID: org_edit_src_show_help +:END: +- Mapped to: =g?= +Show help within the temporary buffer used to edit the content of a +=SRC= block. + +*** Text objects +:PROPERTIES: +:CUSTOM_ID: text-objects +:END: +Operator mappings for =org= files. Example: Pressing =vir= select everything from current heading and all +child. =inner= means that it doesn't select the stars, where =around= selects =inner= + =stars=. See +[[https://github.com/nvim-orgmode/orgmode/issues/48#issuecomment-884528170][this issue comment]] for visual preview. + +📝 NOTE: Some mappings can clash with other plugin mappings, like [[https://github.com/lewis6991/gitsigns.nvim][gitsigns.nvim]] which also has =ih= operator mapping. + +**** =inner_heading= +:PROPERTIES: +:CUSTOM_ID: inner_heading +:END: +- Mapped to: =ih= +Select inner heading with content. + +**** =around_heading= +:PROPERTIES: +:CUSTOM_ID: around_heading +:END: +- Mapped to: =ah= +Select around heading with content. + +**** =inner_subtree= +:PROPERTIES: +:CUSTOM_ID: inner_subtree +:END: +- Mapped to: =ir= +Select whole inner subtree. + +**** =around_subtree= +:PROPERTIES: +:CUSTOM_ID: around_subtree +:END: +- Mapped to: =ar= +Select around whole subtree. + +**** =inner_heading_from_root= +:PROPERTIES: +:CUSTOM_ID: inner_heading_from_root +:END: +- Mapped to: =Oh= (big letter =o=) +select everything from first level heading to the current heading. + +**** =around_heading_from_root= +:PROPERTIES: +:CUSTOM_ID: around_heading_from_root +:END: +- Mapped to: =OH= (big letter =o=) +select around everything from first level heading to the current +heading. + +**** =inner_subtree_from_root= +:PROPERTIES: +:CUSTOM_ID: inner_subtree_from_root +:END: +- Mapped to: =Or= (big letter =o=) +select everything from first level subtree to the current subtree. + +**** =around_subtree_from_root= +:PROPERTIES: +:CUSTOM_ID: around_subtree_from_root +:END: +- Mapped to: =OR= (big letter =o=) +select around everything from first level subtree to the current +subtree. + +These mappings live under =mappings.text_objects=, and can be changed +like this: + +#+begin_src lua +require('orgmode').setup({ + org_agenda_files = {'~/Dropbox/org/*', '~/my-orgs/**/*'}, + org_default_notes_file = '~/Dropbox/org/refile.org', + mappings = { + text_objects = { + inner_heading = 'ic', + } + } +}) +#+end_src + +**** *markup text objects* +:PROPERTIES: +:CUSTOM_ID: markup-text-objects +:END: +Mappings to select inner/outer markup entries. For example, having =This is *bold*=, and if cursor is in +middle of =*bold*=, doing =ci*= changes only inner text, and doing =ca*= changes outer text. These are +supported: =*=, =_=, =/=, =+=, =~=, === These cannot be changed. + +*** Dot repeat +:PROPERTIES: +:CUSTOM_ID: dot-repeat +:END: +To make all mappings dot repeatable, install [[https://github.com/tpope/vim-repeat][vim-repeat]] plugin. + +** Features +:PROPERTIES: +:CUSTOM_ID: features +:END: +*** Autocompletion +:PROPERTIES: +:CUSTOM_ID: autocompletion +:END: +By default, =omnifunc= is provided in =org= files that autocompletes +these types: + +- Tags +- Todo keywords +- Common drawer properties and values (=:PROPERTIES:=, =:CATEGORY:=, =:END:=, etc.) +- Planning keywords (=DEADLINE=, =SCHEDULED=, =CLOSED=) +- Orgfile special keywords (=#+TITLE=, =#+BEGIN_SRC=, =#+ARCHIVE=, etc.) +- Hyperlinks (=* - headlines=, =# - headlines with CUSTOM_ID property=, =headlines matching title=) + +Autocompletion is context aware, which means that for example +tags autocompletion will kick in only when cursor is at the end of +headline. Example (=|= marks the cursor): + +#+begin_src org +** TODO Some task :| +#+end_src + +Or todo keywords only at the beginning of the headline: + +#+begin_src org +*** | +#+end_src + +Or hyperlinks after double square bracket: + +#+begin_src org +Some content [[| +#+end_src + +To use an autocompletion plugin, check [[file:./plugins.org::#completion-plugins][Completion plugins]] + +*** Clocking +:PROPERTIES: +:CUSTOM_ID: clocking +:END: +There is partial support for [[https://orgmode.org/manual/Clocking-Work-Time.html][Clocking work time]]. + +Supported actions: + +**** Clock in +:PROPERTIES: +:CUSTOM_ID: clock-in +:END: +Org file mapping: =oxi=\\ +Agenda view mapping: =I=\\ +Start the clock by adding or updating the =:LOGBOOK:= drawer. Note that +this clocks out any currently active clock.\\ +Also, agenda/todo/search view highlights item that is clocked in. + +***** Clock out +:PROPERTIES: +:CUSTOM_ID: clock-out +:END: +Org file mapping: =oxo=\\ +Agenda view mapping: =O=\\ +Clock out the entry and update the =:LOGBOOK:= drawer, and also add a +total tracked time.\\ +Note that in agenda view pressing =O= anywhere clocks the currently +active entry, while in org file cursor must be in the headline subtree. + +***** Clock cancel +:PROPERTIES: +:CUSTOM_ID: clock-cancel +:END: +Org file mapping: =oxq=\\ +Agenda view mapping: =X=\\ +Cancel the currently active clock. This just removes the entry added by +clock in from =:LOGBOOK:= drawer.\\ +Note that in agenda view pressing =X= anywhere cancels clock on the +currently active entry, while in org file cursor must be in the headline +subtree. + +***** Clock goto +:PROPERTIES: +:CUSTOM_ID: clock-goto +:END: +Org file mapping: =oxj= +Agenda view mapping: =oxj= +Jump to currently clocked in headline in the current window. + +***** Set effort +:PROPERTIES: +:CUSTOM_ID: set-effort +:END: +- Org file mapping: =oxe= +- Agenda view mapping: =oxe= +Add/Update an Effort estimate property for the current headline. + +***** Clock report table +:PROPERTIES: +:CUSTOM_ID: clock-report-table +:END: +Agenda view mapping: =R= + +Show the clocking report for the current agenda time range. Headlines from table can be jumped to via =/= (underlined). +Note that this is visible only in Agenda view, since it's the only view that have a time range. Todo/Search views are not supported. + +***** Automatic updates of totals +:PROPERTIES: +:CUSTOM_ID: automatic-updates-of-totals +:END: +When updating closed logbook dates that have a total at the right +(~example: ==> 1:05~), updating any of the dates via [[#org_timestamp_up][org_timestamp_up]]/[[#org_timestamp_down][org_timestamp_down]] automatically recalculates this value. + +***** Recalculating totals +:PROPERTIES: +:CUSTOM_ID: recalculating-totals +:END: +Org file mapping: =gq= (Note: This is Vim's built in mapping that calls =formatexpr=, see =:help gq=) + +If you changed any of the dates in closed logbook entry, and want to +recalculate the total, select the line and press =gq=, or if you want to +do it in normal mode, just do =gqgq=. + +***** Statusline function +:PROPERTIES: +:CUSTOM_ID: statusline-function +:END: +Function: =v:lua.orgmode.statusline()= + +Show the currently clocked in headline (if any), with total clocked time / effort estimate (if set). + +#+begin_src vim +set statusline=%{v:lua.orgmode.statusline()} +#+end_src + +*** Formatting +:PROPERTIES: +:CUSTOM_ID: formatting +:END: +Formatting is done via =gq= mapping, which uses =formatexpr= under the +hood (see =:help formatexpr= for more info). For example, to re-format +whole document, you can do =gggqG=. =gg= goes to first line in current +file, =gq= starts the format motion, and =G= goes to last line in file +to make it format the whole thing. To format a single line, do =gqgq=, +or to format selection, select the lines you want to format and just do +=gq=. + +Currently, these things are formatted: + +- Tags are aligned according to the =org_tags_column= setting +- Tables are formatted (see [[#Tables][Tables]] for more info) +- Clock entries total time is recalculated (see + [[#recalculating-totals][Recalculating totals]] in + [[#Clocking][Clocking]] section) +*** Hyperlinks +:PROPERTIES: +:CUSTOM_ID: hyperlinks +:END: +The format for links is either =[[LINK]]= or =[[LINK][DESCRIPTION]]=. If +a description is provided, the actual link is concealed in favor of the +description. + +Hyperlink types supported: + +- URL (=http://=, =https://=) +- File (starts with =file:=. Example: =file:/home/user/.config/nvim/init.lua=) Optionally, target can be specified: + - Headline - It needs to start with =*= (Example: =file:/home/user/org/file.org::*Specific Headline=) + - Custom id - It needs to start with =#= (Example: =file:/home/user/org/file.org::#my-custom-id=) + - Line number - It needs to be a number (Example: =file:/home/user/org/file.org::235=) +- Headline title target within the same file (starts with =*=) (Example: =*Specific headline=) +- Headline with =CUSTOM_ID= property within the same file (starts with =#=) (Example: =#my-custom-id=) +- Fallback: If file path, opens the file, otherwise, tries to find the headline title in the current file. +*** Notifications +:PROPERTIES: +:CUSTOM_ID: notifications +:END: +There is an experimental support for agenda tasks notifications. Related [[https://github.com/nvim-orgmode/orgmode/issues/49][issue #49]]. + +Linux/MacOS has support for notifications via: + +- System notification app (notify-send/terminal-notifier) (See below for setup) +- As part of Neovim running instance in floating window + +Windows support only notifications in running Neovim instance. Any help on this topic is appreciated. + +Default configuration (detailed description below): + +#+begin_src lua +require('orgmode').setup({ + notifications = { + enabled = false, + cron_enabled = true, + repeater_reminder_time = false, + deadline_warning_reminder_time = false, + reminder_time = 10, + deadline_reminder = true, + scheduled_reminder = true, + notifier = function(tasks) + local result = {} + for _, task in ipairs(tasks) do + require('orgmode.utils').concat(result, { + string.format('# %s (%s)', task.category, task.humanized_duration), + string.format('%s %s %s', string.rep('*', task.level), task.todo, task.title), + string.format('%s: <%s>', task.type, task.time:to_string()) + }) + end + + if not vim.tbl_isempty(result) then + require('orgmode.notifications.notification_popup'):new({ content = result }) + end + end, + cron_notifier = function(tasks) + for _, task in ipairs(tasks) do + local title = string.format('%s (%s)', task.category, task.humanized_duration) + local subtitle = string.format('%s %s %s', string.rep('*', task.level), task.todo, task.title) + local date = string.format('%s: %s', task.type, task.time:to_string()) + + -- Linux + if vim.fn.executable('notify-send') == 1 then + vim.loop.spawn('notify-send', { args = { string.format('%s\n%s\n%s', title, subtitle, date) }}) + end + + -- MacOS + if vim.fn.executable('terminal-notifier') == 1 then + vim.loop.spawn('terminal-notifier', { args = { '-title', title, '-subtitle', subtitle, '-message', date }}) + end + end + end + }, +}) +#+end_src + +Options description: + +- =enabled= + - Type: =boolean= + - Default: =false= + Enable notifications inside Neovim. Not needed for cron notifications. +- =cron_enabled= + - Type: =boolean= + - Default: =true= + Enable notifications via cron. Requires additional setup, see [[#cron][Cron]] section. +- =repeater_reminder_time= (boolean|number|number[]) - + - Type: =boolean|number|number[]= + - Default: =false= + Number of minutes before the repeater time to send notifications. + For example, if now is =2021-07-15 15:30=, and there's a todo item + with date =<2021-07-01 15:30 +1w>=, notification will be sent if value + of this setting is =0=. + If this configuration has a value of ={1, 5, 10}=, this means that + notification will be sent on =2021-07-15 15:20=, =2021-07-15 15:25= + and =2021-07-15 15:29=. + =false= means disabled (default). +- =deadline_warning_reminder_time= + - Type: =boolean|number|number[]= + - Default: =0= + Number of minutes before the warning time to send notifications. + For example, if now is =2021-07-15 12:30=, and there's a todo item + with date =<2021-07-15 18:30 -6h>=, notification will be sent. + If this configuration has a value of ={1, 5, 10}=, this means that + notification will be sent on =2021-07-15 12:20=, =2021-07-15 12:25= + and =2021-07-15 12:29=. + =0= (Default) means that it will send notification only on exact warning time +- =reminder_time= + - Type: =boolean|number|number[]= + - Default: =10= + Number of minutes before the time to send notifications. + For example, if now is =2021-07-15 12:30=, and there's a todo item + with date =<2021-07-15 12:40>=, notification will be sent. + If this configuration has a value of ={1, 5, 10}=, this means that + notification will be sent on =2021-07-15 12:20=, =2021-07-15 12:25= + and =2021-07-15 12:29=. + This reminder also applies to both repeater and warning time if the + time is matching. So with the example above, both + =2021-07-15 12:20 +1w= and =2021-07-15 12:20 -3h= will trigger + notification. will trigger notification. + =10= (default) means that it will send notification 10 minutes before the time. +- =deadline_reminder= + - Type: =boolean= + - Default: =true= + Should notifications be sent for DEADLINE dates. +- =scheduled_reminder= + - Type: =boolean= + - Default: =true= + Should notifications be sent for SCHEDULED dates. +- =notifier= + - Type: =fun(tasks: table[])= + - Default: =nil= + Function for sending notification inside Neovim. Accepts array of tasks (see below) and shows floating window with notifications. +- =cron_notifier= + - Type: =fun(tasks: table[])= + - Default: =nil= + Function for sending notification via cron. Accepts array of tasks (see below) and triggers external program to send notifications. + +**Tasks* + +Notifier functions accepts =tasks= parameter which is an array of this +type: + +#+begin_src lua +{ + file = string, -- (Path to org file containing this task. Example: /home/myhome/orgfiles/todos.org) + todo = string, -- (Todo keyword on the task. Example value: TODO) + title = string, -- (Content of the headline without the todo keyword and tag. Example: Submit papers) + level = number, -- (Headline level (number of asterisks). Example: 1) + category = string, -- (file name where this task lives. With example file above, this would be: todos), + priority = string, -- (priority on the task. Example: A) + tags = string[], -- (array of tags applied to the headline. Example: {'WORK', 'OFFICE'}) + original_time = Date, -- (Date object (see [Date object](lua/orgmode/objects/date.lua) for details) containing original time of the task (with adjustments and everything)) + time = Date, -- (Date object (see [Date object](lua/orgmode/objects/date.lua) for details) time that matched the reminder configuration (with applied adjustments)) + reminder_type = string, -- (Type of the date that matched reminder settings. Can be one of these: repeater, warning or time), + minutes = number, -- (Number of minutes before the task) + humanized_duration = string, -- (Humanized duration until the task. Examples: in 10 min., in 5 hr, in 3 hr and 10 min.) + type = string, -- (Date type. Can be one of these: DEADLINE or SCHEDULED), + range = table -- (Start and end line of the headline subtree. Example: { start_line = 2, end_line = 5 }) +} +#+end_src + +**** Cron +:PROPERTIES: +:CUSTOM_ID: cron +:END: +In order to trigger notifications via cron, job needs to be added to the crontab. +This is currently possible only on Linux and MacOS, since I don't know +how would this be done on Windows. Any help on this topic is appreciated. +This works by starting the headless Neovim instance, running one off +function inside orgmode, and quitting the Neovim. + +First try to see if you can run this command: + +#+begin_example +nvim --headless -c 'lua require("orgmode").cron()' +#+end_example + +If it exits without errors, you are ready! + +Here's maximum simplified *Linux* example (Tested on Manjaro/Arch/Ubuntu), but least optimized: + +Run this to open crontab: + +#+begin_example +crontab -e +#+end_example + +Then add this (Ensure path to =nvim= is correct): + +#+begin_src crontab +** * * * * DISPLAY=:0 DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus /usr/local/bin/nvim --headless -c 'lua require("orgmode").cron()' +#+end_src + +More optimized version would be to create a lua file that has only +necessary plugins loaded: + +#+begin_src lua +-- ~/.config/nvim/lua/partials/org_cron.lua + +-- If you are using lazy.vim do this: +local orgmode = vim.fn.stdpath('data') .. '/lazy/orgmode' +vim.opt.runtimepath:append(orgmode) +-- If you are using Packer or any other package manager that uses built-in package manager, do this: +vim.cmd('packadd orgmode') + +-- Run the orgmode cron +require('orgmode').cron({ + org_agenda_files = '~/orgmode/*', + org_default_notes_file = '~/orgmode/notes.org', + notifications = { + reminder_time = {0, 5, 10}, + }, +}) +#+end_src + +And update cron job to this: + +#+begin_src crontab +** * * * * DISPLAY=:0 DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus /usr/local/bin/nvim -u NONE --noplugin --headless -c 'lua require("partials.org_cron")' +#+end_src + +This option is most optimized because it doesn't load plugins and your init.vim +For *MacOS*, things should be very similar, but I wasn't able to test it. Any help on this is appreciated. +*** Tables +:PROPERTIES: +:CUSTOM_ID: tables +:END: +Tables can be formatted via built in =formatexpr= (see =:help gq=) + +For example, having this content: + +#+begin_src org +* TODO My headline + DEADLINE: <2022-05-22 Sun> + + |Header 1|Header 2 + |- + | col 1| col 2| +#+end_example + +And going to line =4= and pressing =gqgq=, it will format it to this: + +#+begin_src org +* TODO My headline + DEADLINE: <2022-05-22 Sun> + + | Header 1 | Header 2 | + |----------+----------| + | col 1 | col 2 | +#+end_example +*** Advanced search +:PROPERTIES: +:CUSTOM_ID: advanced-search +:END: +Part of [[https://orgmode.org/worg/org-tutorials/advanced-searching.html][Advanced search]] functionality is implemented. + +To leverage advanced search, open up agenda prompt (default +=oa=), and select =m= or =M=(todos only) option. + +What is supported: + +- Operators: =|=, =&=, =+= and =-= (examples: =COMPUTER+URGENT=, + =COMPUTER|URGENT=, =+COMPUTER-URGENT=, =COMPUTER|WORK+EMAIL=) +- Search by property with basic arithmetic operators (~<~, ~<=~, ~=~, ~>=~, ~>=~, =<>=) (examples: ~CATEGORY="mycategory"~, ~CUSTOM_ID=my_custom_id~, ~AGE<10~, ~ITEMS>=5~) +- Search by todo keyword (example: =COMPUTER+URGENT/TODO|NEXT=) + +Few examples: + +- Search all with tag =COMPUTER= *or* =WORK= and =EMAIL=: + =COMPUTER|WORK+EMAIL=. =And= always have precedence over =or=. + Workaround to use first =or= is to write it like this: + =COMPUTER+EMAIL|WORK+EMAIL= +- Search all with keyword =TODO=, tag =URGENT= and property =AGE= bigger + than 10: =URGENT+AGE>10/TODO= +- Search all with keyword =DONE= or =DELEGATED=, tag =COMPUTER= and + property =AGE= not equal to 10: =COMPUTER+AGE<>10/DONE|DELEGATED= +- Search all without keyword =DONE=, tag =URGENT= but without tag + =COMPUTER= and property =CATEGORY= equal to =mywork=: + =URGENT-COMPUTER+CATEGORY=mywork/-DONE= + +*** Tangle +Extract source code (tangle) +:PROPERTIES: +:CUSTOM_ID: extract-source-code-tangle +:END: +There is basic support for extracting source code with =tangle= and =noweb=. +(Orgmode link: [[https://orgmode.org/manual/Extracting-Source-Code.html][Extracting source code]]) +These options are supported: + +1. Setting =header-args= on multiple levels: + + 1. Configuration ([[#org_babel_default_header_args][org_babel_default_header_args]]) + 2. File level property (=#+property: header-args :tangle yes=) + 3. Headline level property + #+begin_src org + * Headline + :PROPERTIES: + :header-args: :tangle yes + :END: + #+end_src + + 4. Block level argument + =#+begin_src lua :tangle yes= + +2. Tangling all blocks with these options: + 1. =:tangle no= - Do not tangle + 2. =:tangle yes= - Tangle to same filename as current org file, with + different extension (If org file is =~/org/todo.org= and block is =#+block_src lua=, tangles to =/org/todo.lua=) + 3. =:tangle path= - Tangle to given filename. It can be absolute (=:tangle /path/to/file.ext=) or relative to current file (either =:tangle ./file.ext= or =:tangle file.ext=) + +3. Basic =:noweb= syntax (See [[https://orgmode.org/manual/Noweb-Reference-Syntax.html][Noweb Reference Syntax]]): + 1. =:noweb no= - Do not expand any references + 2. =:noweb yes= - Expand references via =#+name= directive on block. + See example below. + 3. =:noweb tangle= - Same as =:noweb yes= + +Example: Having this file in =~/org/todos.org= + +Block below will pick up reference from the 2nd block name + +=#+begin_src lua :tangle yes :noweb yes= +=<>= +=print('Headline 1')= +=#+end_src= + +=#+name: headline2block= +=#+begin_src lua :tangle yes= +=print('Headline 2')= +=#+end_src= +=#+end_src= + +Running [[#org_babel_tangle][org_babel_tangle]] will create file =~/org/todos.lua= with this content: + +=#+begin_src lua= +=print('Headline 2')= +=print('Headline 1')= +== +=print('Headline 2')= +=#+end_src= + +To extract blocks to specific file, you can set file level property with +default path, and maybe exclude 2nd block to not be repeated: + +=#+property: header-args :tangle ./my_tangled_file.lua= + +=#+begin_src lua :noweb yes= +=<>= +=print('Headline 1')= +=#+end_src= + +Here we disable tangling, so only first block will give results with the noweb +=#+name: headline2block= +=#+begin_src lua :tangle no= +=print('Headline 2')= +=#+end_src= + +Running [[#org_babel_tangle][org_babel_tangle]] will create file =~/org/my_tangled_file.lua= with this content: + +=#+begin_src lua= +=print('Headline 2')= +=print('Headline 1')= +=#+end_src= + +** User interface +:PROPERTIES: +:CUSTOM_ID: user-interface +:END: +*** Colors +:PROPERTIES: +:CUSTOM_ID: colors +:END: +Most of the highlight groups are linked to treesitter highlights where +applicable (see =:h treesitter-highlight=). + +The following highlight groups are used: + +- =@org.headline.level1=: Headline at level 1 - linked to =Title= +- =@org.headline.level2=: Headline at level 2 - linked to =Constant= +- =@org.headline.level3=: Headline at level 3 - linked to =Identifier= +- =@org.headline.level4=: Headline at level 4 - linked to =Statement= +- =@org.headline.level5=: Headline at level 5 - linked to =PreProc= +- =@org.headline.level6=: Headline at level 6 - linked to =Type= +- =@org.headline.level7=: Headline at level 7 - linked to =Special= +- =@org.headline.level8=: Headline at level 8 - linked to =String= +- =@org.priority.highest=: Highest priority marker - linked to =@comment.error= +- =@org.priority.high=: High priority marker - Not linked to anything, defaults to normal text +- =@org.priority.default=: Default priority marker - Not linked to anything, defaults to normal text +- =@org.priority.low=: Lowest priority marker - Not linked to anything, defaults to normal text +- =@org.priority.lowest=: Lowest priority marker - Not linked to anything, defaults to normal text +- =@org.timestamp.active=: An active timestamp - linked to =@keyword= +- =@org.timestamp.inactive=: An inactive timestamp - linked to =@comment= +- =@org.keyword.todo=: TODO keywords color - Parsed from =Error= (see note below) +- =@org.keyword.done=: DONE keywords color - Parsed from =DiffAdd= (see note below) +- =@org.bullet=: A normal bullet under a header item - linked to =@markup.list= +- =@org.properties=: Property drawer start/end delimiters - linked to =@property= +- =@org.drawer=: Drawer start/end delimiters - linked to =@property= +- =@org.tag=: A tag for a headline item, shown on the righthand side like =:foo:= - linked to =@tag.attribute= +- =@org.plan=: =SCHEDULED=, =DEADLINE=, =CLOSED=, etc. keywords - linked to =Constant= +- =@org.comment=: A comment block - linked to =@comment= +- =@org.latex_env=: LaTeX block - linked to =@markup.environment= +- =@org.directive=: Blocks starting with =#+= - linked to =@comment= +- =@org.checkbox=: The default checkbox highlight, including square brackets - linked to =@markup.list.unchecked= +- =@org.checkbox.halfchecked=: A checkbox status (marker between =[]=) checked with =[-]= - linked to =@markup.list.unchecked= +- =@org.checkbox.checked=: A checkbox status (marker between =[]=) checked with either =[x]= or =[X]= - linked to =@markup.list.checked= +- =@org.bold=: *bold* text - linked to =@markup.strong=, +- =@org.bold.delimiter=: bold text delimiter =*= - linked to =@markup.strong=, +- =@org.italic=: /italic/ text - linked to =@markup.italic=, +- =@org.italic.delimiter=: italic text delimiter =/= - linked to =@markup.italic=, +- =@org.strikethrough=: ~strikethrough~ text - linked to =@markup.strikethrough=, +- =@org.strikethrough.delimiter=: strikethrough text delimiter =+= - linked to =@markup.strikethrough=, +- =@org.underline=: underline text - linked to =@markup.underline=, +- =@org.underline.delimiter=: underline text delimiter =_= - linked to =@markup.underline=, +- =@org.code=: =code= text - linked to =@markup.raw=, +- =@org.code.delimiter=: code text delimiter =~= - linked to =@markup.raw=, +- =@org.verbatim=: =verbatim= text - linked to =@markup.raw=, +- =@org.verbatim.delimiter=: verbatim text delimiter === - linked to =@markup.raw=, +- =@org.hyperlink=: [[file:link]] text - linked to =@markup.link.url=, +- =@org.latex=: Inline latex - linked to =@markup.math=, +- =@org.table.delimiter= - =|= and =-= delimiters in tables - linked to =@punctuation.special=, +- =@org.table.heading= - Table headings - linked to =@markup.heading=, +- =@org.edit_src= - The highlight for the source content in an /Org/ buffer while it is being edited in an edit special buffer - linked to =Visual=, +- =@org.agenda.deadline=: A item deadline in the agenda view - Parsed from =Error= (see note below) +- =@org.agenda.scheduled=: A scheduled item in the agenda view - Parsed from =DiffAdd= (see note below) +- =@org.agenda.scheduled_past=: A item past its scheduled date in the agenda view - Parsed from =WarningMsg= (see note below) +- =@org.agenda.day=: Highlight for all days in Agenda view - linked to =Statement= +- =@org.agenda.today=: Highlight for today in Agenda view - linked to =@org.bold= +- =@org.agenda.weekend=: Highlight for weekend days in Agenda view - linked to =@org.bold= + +📝 NOTE: +Colors used for todo keywords and agenda states (deadline, schedule ok, +schedule warning) are parsed from the current colorscheme from several +highlight groups (Error, WarningMsg, DiffAdd, etc.). + +**** Overriding colors +:PROPERTIES: +:CUSTOM_ID: overriding-colors +:END: +All colors can be overridden by either setting new values or linking to +another highlight group: + +#+begin_src lua +vim.api.nvim_create_autocmd('ColorScheme', { + pattern = '*', + callback = function() + -- Define own colors + vim.api.nvim_set_hl(0, '@org.agenda.deadline', { fg = '#FFAAAA' }) + vim.api.nvim_set_hl(0, '@org.agenda.scheduled', { fg = '#AAFFAA' }) + -- Link to another highlight group + vim.api.nvim_set_hl(0, '@org.agenda.scheduled_past', { link = 'Statement' }) + end +}) +#+end_src + +For adding/changing TODO keyword colors see [[#org_todo_keyword_faces][org-todo-keyword-faces]] +*** Menu +:PROPERTIES: +:CUSTOM_ID: menu +:END: +The menu is used when selecting further actions in =agenda=, =capture= +and =export=. Here is an example of the menu you see when opening =agenda=: + +#+begin_example +Press key for an agenda command +------------------------------- +a Agenda for current week or day +t List of all TODO entries +m Match a TAGS/PROP/TODO query +M Like m, but only for TODO entries +s Search for keywords +q Quit +#+end_example + +Users have the option to change the appearance of this menu. To do this, +you need to add a handler in the UI configuration section: + +#+begin_src lua +require("orgmode").setup({ + ui = { + menu = { + handler = function(data) + -- your handler here, for example: + local options = {} + local options_by_label = {} + + for _, item in ipairs(data.items) do + -- Only MenuOption has `key` + -- Also we don't need `Quit` option because we can close the menu with ESC + if item.key and item.label:lower() ~= "quit" then + table.insert(options, item.label) + options_by_label[item.label] = item + end + end + + local handler = function(choice) + if not choice then + return + end + + local option = options_by_label[choice] + if option.action then + option.action() + end + end + + vim.ui.select(options, { + propmt = data.propmt, + }, handler) + end, + }, + }, +}) +#+end_src + +When the menu is called, the handler receives a table =data= with the +following fields as input: + +- =title= (=string=) - menu title +- =items= (=table=) - array containing =MenuItem= (see below) +- =prompt= (=string=) - prompt text used to prompt a keystroke + +Each menu item =MenuItem= is one of two types: =MenuOption= and =MenuSeparator=. + +=MenuOption= is a table containing the following fields: + +- =label= (=string=) - description of the action +- =key= (=string=) - key that will be processed when the keys are + pressed in the menu +- =action= (=function= /optional/) - handler that will be called when + the =key= is pressed in the menu. + +=MenuSeparator= is a table containing the following fields: + +- =icon= (=string= /optional/) - character used as separator. The + default character is =-= +- =length= (=number= /optional/) - number of repetitions of the + separator character. The default length is 80 + +In order for the menu to work as expected, the handler must call =action= from =MenuItem=. + +*** Folds +:PROPERTIES: +:CUSTOM_ID: folds +:END: +In Neovim 0.10+, folds are colored with the same highlight as when they +are expanded. This is enabled by default to be in line with how Emacs +work. + +To use the old way of highlighting folds with =Folded= highlight group, +add this to config: + +#+begin_src lua +require('orgmode').setup({ + ui = { + folds = { + colored = false + } + } +}) +#+end_src diff --git a/docs/contributing.org b/docs/contributing.org new file mode 100644 index 000000000..fb186fb5e --- /dev/null +++ b/docs/contributing.org @@ -0,0 +1,81 @@ +* Contributing Guide +:PROPERTIES: +:CUSTOM_ID: contributing-guide +:END: +Thanks for wanting to help out with nvim-orgmode, we appreciate the effort! + +** Reporting Bugs/Features +:PROPERTIES: +:CUSTOM_ID: reporting-bugsfeatures +:END: + +📣 Please always make a quick search in our [[https://github.com/nvim-orgmode/orgmode/issues][issue-tracker]] before +reporting anything. If the bug/feature has already been reported, +continue the conversation on the existing issue. + +We distinguish between =core= (part of [[https://orgmode.org/][orgmode]]) and +=non-core= features. The former will be prioritized. Bugs get the highest +priority. + +If you're reporting a =core= feature, please be sure to provide a link +that describes it. There are several places where features could be +documented, have a look at these [[https://orgmode.org/worg/#resources][resources]]. The more info you provide the better! + +** Documentation +:PROPERTIES: +:CUSTOM_ID: documentation +:END: +If you spot something missing in our [[file:../index.org][docs]], don't hesitate making a PR. +The [[https://github.com/nvim-orgmode/orgmode/wiki][wiki]] can be edited freely. + +** Development +*** Philosophy +We try to mimic the behavior of Emacs Orgmode as closely as possible. +Variable names follow the same naming convention as in Emacs Orgmode, +except that they are in =snake_case= instead of =kebab-case=. + +Example: =org-agenda-files= in Emacs is =org_agenda_files= in nvim-orgmode. + +*** Local dev +:PROPERTIES: +:CUSTOM_ID: local-dev +:END: +Requirements: + +- [[https://github.com/JohnnyMorganz/StyLua][StyLua]] - For formatting + +To set up local development, run =make setup_dev=. This will add a +pre-commit hook that will auto format all files before committing them. +You can always manually format all files with =make format= command + +*** Code +:PROPERTIES: +:CUSTOM_ID: code +:END: +If you prefer working on an issue that has been reported, please leave a comment voicing your interest. + +Please document any new code you add with [[https://emmylua.github.io/annotation.html][emmylua annotations]]. +Feel free to add annotations/docs to any existing functions integral to your PR that are missing them. + +**** Tests +:PROPERTIES: +:CUSTOM_ID: tests +:END: +To run tests run =make test= in the nvim-orgmode directory: + +#+begin_example +make test +#+end_example + +To run a specific test you can set a =FILE= environment variable to a +specific spec you want to test. Example: + +#+begin_example +make test FILE=./tests/plenary/api/api_spec.lua +#+end_example + +**** Parser +:PROPERTIES: +:CUSTOM_ID: parser +:END: +Parsing is done via builtin treesitter parser and the [[https://github.com/milisims/tree-sitter-org][tree-sitter-org]] grammar. diff --git a/docs/index.org b/docs/index.org new file mode 100644 index 000000000..fe679b95d --- /dev/null +++ b/docs/index.org @@ -0,0 +1,46 @@ +* Nvim Orgmode + +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. + +** Quick start +:PROPERTIES: +:CUSTOM_ID: quick-start +:END: +- Install with [[https://github.com/folke/lazy.nvim][lazy.nvim]]: + #+begin_src lua + { + 'nvim-orgmode/orgmode', + event = 'VeryLazy', + config = function() + -- Setup orgmode + require('orgmode').setup({ + org_agenda_files = '~/orgfiles/**/*', + org_default_notes_file = '~/orgfiles/refile.org', + }) + end, + } + #+end_src +- Capture youf first note with =oc= +- Open up the prompt for agenda with =oa= + +For more details about the installation and usage, check [[./installation.org][Installation page]]. +To see all configuration options, check [[file:./configuration.org][Configuration page]]. + +** Getting started with orgmode +:PROPERTIES: +:CUSTOM_ID: getting-started +:END: +To get a basic idea how Orgmode works, check our hands-on [[file:./tutorial.org][tutorial]]. + +You can also check this screencast from [[https://github.com/dhruvasagar][@dhruvasagar]] +that demonstrates how the similar Orgmode clone [[https://github.com/dhruvasagar/vim-dotoo][vim-dotoo]] works. + +[[https://www.youtube.com/watch?v=nsv33iOnH34]] + +** API docs +:PROPERTIES: +:CUSTOM_ID: api-docs +: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. diff --git a/docs/installation.org b/docs/installation.org new file mode 100644 index 000000000..0da6197cb --- /dev/null +++ b/docs/installation.org @@ -0,0 +1,58 @@ +* Installation + +Orgmode can be installed with any package manager. +Here are few examples: + +1. [[https://github.com/folke/lazy.nvim][lazy.nvim]] (Recommended) + #+begin_src lua + { + 'nvim-orgmode/orgmode', + event = 'VeryLazy', + config = function() + require('orgmode').setup({ + org_agenda_files = '~/orgfiles/**/*', + org_default_notes_file = '~/orgfiles/refile.org', + }) + end, + } + #+end_src +2. [[https://github.com/lewis6991/pckr.nvim][pckr.nvim]] + #+begin_src lua + require('pckr').add({ + { + 'nvim-orgmode/orgmode', + config = function() + require('orgmode').setup({ + org_agenda_files = '~/orgfiles/**/*', + org_default_notes_file = '~/orgfiles/refile.org', + }) + end + } + }) + #+end_src +3. [[https://github.com/junegunn/vim-plug][vim-plug]] + #+begin_src vim + Plug 'nvim-orgmode/orgmode' + + lua << EOF + require('orgmode').setup({ + org_agenda_files = '~/orgfiles/**/*', + org_default_notes_file = '~/orgfiles/refile.org', + }) + EOF + #+end_src +4. [[https://github.com/Shougo/dein.vim][dein.vim]] + #+begin_src vim + call dein#add('nvim-orgmode/orgmode') + + lua << EOF + require('orgmode').setup({ + org_agenda_files = '~/orgfiles/**/*', + org_default_notes_file = '~/orgfiles/refile.org', + }) + EOF + #+end_src + +*** Useful links: +- [[file:./configuration.org][Configuration]] +- [[file:./plugins.org][Plugins]] diff --git a/docs/plugins.org b/docs/plugins.org new file mode 100644 index 000000000..90a14370f --- /dev/null +++ b/docs/plugins.org @@ -0,0 +1,173 @@ +* Plugins + +📝 NOTE: If you create a plugin for orgmode, make sure to tag it with =orgmode-nvim= on github and submit an issue/PR to add it to this list. + +Orgmode supports various plugins to extend its functionality or make it more pretty and user friendly: + +- [[#extend-orgmode][Extend orgmode]] + - [[#org-roamnvim][org-roam.nvim]] + - [[#sniprun][sniprun]] + - [[#telescope-orgmodenvim][telescope-orgmode.nvim]] +- [[#completion-plugins][Completion plugins]] + - [[#blinkcmp][blink.cmp]] + - [[#nvim-cmp][nvim-cmp]] +- [[#aesthetics][Aestehtics]] + - [[#org-bulletsnvim][org-bullets.nvim]] + - [[#headlinesnvim][headlines.nvim]] +- [[#other][Other]] +- [[#example-configuration][Example configuration]] + +** Extend orgmode +:PROPERTIES: +:CUSTOM_ID: extend-orgmode +:END: +*** org-roam.nvim +:PROPERTIES: +:CUSTOM_ID: org-roamnvim +:END: +Link: [[https://github.com/chipsenkbeil/org-roam.nvim][org-roam.nvim]] + +This is the port of Emacs [[https://www.orgroam.com/][org-roam]]. +*** sniprun +:PROPERTIES: +:CUSTOM_ID: sniprun +:END: +Link: [[https://github.com/michaelb/sniprun][sniprun]] + +Plugin for code block evaluation. +*** telescope-orgmode.nvim +:PROPERTIES: +:CUSTOM_ID: telescope-orgmodenvim +:END: +Link: [[https://github.com/nvim-orgmode/telescope-orgmode.nvim][telescope-orgmode.nvim]] +[[https://github.com/nvim-telescope/telescope.nvim][Telescope]] extension for orgmode that adds fuzzy finding of orgmode files, headlines, etc. + +** Completion plugins +:PROPERTIES: +:CUSTOM_ID: completion-plugins +:END: +*** blink.cmp +:PROPERTIES: +:CUSTOM_ID: blinkcmp +:END: +Link: [[https://github.com/Saghen/blink.cmp][blink.cmp]] + +Add the orgmode provider and enable it for =org= filetype. +#+begin_src lua +require('blink.cmp').setup({ + sources = { + per_filetype = { + org = {'ormode'} + }, + providers = { + orgmode = { + name = 'Orgmode', + module = 'orgmode.org.autocompletion.blink', + fallbacks = { 'buffer' }, + }, + }, + }, +}) +#+end_src + +*** nvim-cmp +:PROPERTIES: +:CUSTOM_ID: nvim-cmp +:END: +Link: [[https://github.com/hrsh7th/nvim-cmp][nvim-cmp]] +Add the =orgmode= source to =nvim-cmp= ~sources~ list. +#+BEGIN_SRC lua +require('cmp').setup({ + sources = { + { name = 'orgmode' } + } +}) +#+END_SRC + +** Aestehtics +:PROPERTIES: +:CUSTOM_ID: aesthetics +:END: +*** org-bullets.nvim +:PROPERTIES: +:CUSTOM_ID: org-bulletsnvim +:END: +Link: [[https://github.com/nvim-orgmode/org-bullets.nvim][org-bullets.nvim]] +Port of Emacs [[https://github.com/sabof/org-bullets][org-bullets]]. + +Run after the orgmode setup. +#+BEGIN_SRC lua +-- Your orgmode setup +require('orgmode').setup() + +--Setup org-bullets +require('org-bullets').setup() +#+END_SRC + +*** headlines.nvim +:PROPERTIES: +:CUSTOM_ID: headlinesnvim +:END: +Link: [[https://github.com/lukas-reineke/headlines.nvim][headlines.nvim]] + +Plugin that adds some additional highlights to headlines. +#+BEGIN_SRC lua +-- Your orgmode setup +require('orgmode').setup() + +--Setup headlines.nvim +require("headlines").setup() +#+END_SRC + +** Other +:PROPERTIES: +:CUSTOM_ID: other +:END: +To view all plugins that are tagged for =nvim-orgmode=, visit [[https://github.com/topics/orgmode-nvim][orgmode-nvim]] github tag. + +📝 NOTE: If you create a plugin for orgmode, make sure to tag it with =orgmode-nvim= on github and submit an issue/PR to add it to this list. + +** Example configuration +:PROPERTIES: +:CUSTOM_ID: example-configuration +:END: +Example configuration with few of these plugins using [[https://github.com/folke/lazy.nvim][lazy.nvim]]: +#+begin_src lua +{ + 'nvim-orgmode/orgmode', + dependencies = { + 'nvim-telescope/telescope.nvim', + 'nvim-orgmode/telescope-orgmode.nvim', + 'nvim-orgmode/org-bullets.nvim', + 'Saghen/blink.cmp' + }, + event = 'VeryLazy', + config = function() + require('orgmode').setup({ + org_agenda_files = '~/orgfiles/**/*', + org_default_notes_file = '~/orgfiles/refile.org', + }) + require('org-bullets').setup() + require('blink.cmp').setup({ + sources = { + per_filetype = { + org = {'ormode'} + }, + providers = { + orgmode = { + name = 'Orgmode', + module = 'orgmode.org.autocompletion.blink', + fallbacks = { 'buffer' }, + }, + }, + }, + }) + + require('telescope').setup() + require('telescope').load_extension('orgmode') + vim.keymap.set('n', 'r', require('telescope').extensions.orgmode.refile_heading) + vim.keymap.set('n', 'fh', require('telescope').extensions.orgmode.search_headings) + vim.keymap.set('n', 'li', require('telescope').extensions.orgmode.insert_link) + end, +} +#+end_src diff --git a/docs/troubleshoot.org b/docs/troubleshoot.org new file mode 100644 index 000000000..f06f5f52a --- /dev/null +++ b/docs/troubleshoot.org @@ -0,0 +1,39 @@ +** Troubleshooting +*** Indentation is not working + +Make sure you are not overriding indentexpr in Org buffers with [[https://github.com/nvim-treesitter/nvim-treesitter#indentation][nvim-treesitter indentation]] + +*** I get ~treesitter/query.lua~ errors when opening agenda/capture prompt or org files + +Tree-sitter parser might not be installed. +Try running ~:lua require('orgmode.config'):reinstall_grammar()~ to reinstall it. + +*** Dates are not in English +Dates are generated with Lua native date support, and it reads your current locale when creating them. +#+HTML:
+To use different locale you can add this to your ~init.lua~: + +#+BEGIN_SRC lua +vim.cmd('language en_US.utf8') +#+END_SRC + +Just make sure you have ~en_US~ locale installed on your system. To see what you have available on the system you can +start the command ~:language~ and press ~~ to autocomplete possible options. + +*** Links are not concealed +Links are concealed with Vim's conceal feature (see ~:help conceal~). To enable concealing, add this to your ~init.lua~: + +#+BEGIN_SRC lua +vim.opt.conceallevel = 2 +vim.opt.concealcursor = 'nc' +#+END_SRC + +*** Jumping to file path is not working for paths with forward slash +If you are using Windows, paths are by default written with backslashes. +To use forward slashes, you must enable ~shellslash~ option +(see ~:help shellslash~). + +#+BEGIN_SRC lua +vim.opt.shellslash = true +#+END_SRC +More info on issue [[https://github.com/nvim-orgmode/orgmode/issues/281#issuecomment-1120200775][#281]] diff --git a/docs/tutorial.org b/docs/tutorial.org new file mode 100644 index 000000000..554597756 --- /dev/null +++ b/docs/tutorial.org @@ -0,0 +1,248 @@ +#+title: nvim-orgmode Tutorial +#+author: nvim-orgmode Team + +* Overview +Org-mode is a flexible note-taking system that was originally created for +Emacs. It has gained wide-spread acclaim (this file itself is an Org-mode file, +which is supported by GitHub wikis) and was eventually ported to Neovim. + +1. [[#file-syntax][File Syntax]] +2. [[#basic-customization][Basic Customization]] +3. [[#agenda][Agenda]] +4. [[#captures][Captures]] +5. [[#archiving][Archiving]] +6. [[#exporting][Exporting]] +7. [[#further-resources][Further Resources]] + +To get the hang of it, we will create an org file in which we will keep all +the repositories we want to check out in the future. First, let's create an +empty file called =repos.org=. + +* File Syntax +:PROPERTIES: +:CUSTOM_ID: file-syntax +:END: + +Org files often start with meta-information for the title and the author: + +#+begin_src +#+title: Repositories +#+author: +#+end_src + +These directives are not necessary but may give others (including you in the +future!) a gist what this file is about. There are many more directives +detailed at [TODO: add this to the docs] + +To create a list of repositories, we start a new line with a dash, followed by +the repo name we'd like to remember: + +#+begin_src +- Org Bullets +#+end_src + +Congratulations, you created your first list! :tada: From here, you can easily +add new list items by pressing ==, the so-called org =meta return=. +It has different effects, depending on the current position of the +cursor. If it's on a list item, it will add another one. We will discuss other +uses later on. [TODO: actually do that] + +#+begin_src +- Org Bullets +- vim-table-mode +#+end_src + +Our list is already functional, but it's only scratching the surface of what +Org-mode can do. Let's look at how org files are structured using =headings=. + +** Headings +:PROPERTIES: +:CUSTOM_ID: headings +:END: + +Any line starting with one or more asterisks (*) but without any preceding +whitespace is a heading (also called headline). Let's change our list items +to 1st-level headings by replacing the dashes with asterisks: + +#+begin_src +* Org Bullets +* Vim table-mode +#+end_src + +The number of asterisks denotes the level of the heading: the more asterisks, +the deeper the level. That is how we achieve nested structures in our org +files. + +#+begin_src +* Org Bullets +** Synopsis +* Vim table-mode +#+end_src + +The content within a heading can be free form text, include links, be a list, +or any combination thereof. Let's add a short description: + +#+begin_src +* Org Bullets +** Synopsis + This plugin is a clone of org-bullets. It replaces the asterisks in org + syntax with unicode characters. +* Vim table-mode +#+end_src + +The full syntax for a headline is + +#+begin_src +STARS KEYWORD PRIORITY TITLE TAGS +* TODO [#A] foo :bar:baz: +#+end_src + +- =KEYWORD=, if present, turns the heading into a TODO item. By default this + can be =TODO= or =DONE= (see the [[#basic-customization][Customization]] section to change this). +- =PRIORITY= sets a priority level to be used in the [[#agenda][Agenda]]. +- =TITLE= is the main body of the heading. +- =TAGS= is a colon surrounded and delimited list of tags used in searching + in the [[#agenda][Agenda]]. + +Headings (usually with a =KEYWORD=) can also have deadlines, and/or be +scheduled with timestamps (e.g. <2022-12-31>) [TODO: explain the difference +between deadlines and scheduled headings]. Thus we could enhance our list +of repos like so: + +#+begin_src org +* org-bullets.nvim :org: +** Synopsis + This plugin is a clone of org-bullets. It replaces the asterisks in org + syntax with unicode characters. +* vim-table-mode :org: +** TODO Synopsis + SCHEDULED: +* plenary :lua: +** TODO [#A] Synopsis + DEADLINE: +#+end_src + +** Links +:PROPERTIES: +:CUSTOM_ID: links +:END: + +One final aspect of the org file syntax are links. +Links are of the form =[[link][description]]=, where link can be a +- URL (=http://=, =https://=) +- path to a file (=file:/path/to/org/file=) +- target (any text surrounded by << and >>). If the target is in a different + file the format is ‘file:~/path/to/org/file.org::My Target’ +- headline within the same file +- headline with a custom id (=#your-custom-id=) + +In order to easily go to the repositories we found online, let's link to +their actual website: + +#+begin_src org +* [[https://github.com/akinsho/org-bullets.nvim][org-bullets.nvim]] :org: +** Synopsis + This plugin is a clone of org-bullets. It replaces the asterisks in org + syntax with unicode characters. +* [[https://github.com/dhruvasagar/vim-table-mode][vim-table-mode]] :org: +** TODO Synopsis + SCHEDULED: +* [[https://github.com/nvim-lua/plenary.nvim][plenary]] :lua: +** TODO [#A] Synopsis + DEADLINE: +#+end_src + +* Basic Customization + +A first customization of orgmode would look like: + +#+begin_src lua +-- init.lua +local org = require('orgmode') + +org.setup_ts_grammar() +org.setup({ + org_agenda_files = {'~/path/to/agenda/file/*.org'}, + org_default_notes_file = '~/path/to/default/capture/file.org', +}) +#+end_src + +with all customization options going in the =org.setup({})=. + +All available options are detailed [[file:./configuration.org][here]], including setting new keybindings. + + +* Agenda +:PROPERTIES: +:CUSTOM_ID: agenda +:END: + +The org agenda is used to get an overview of all your different org files. +Pressing =oa= gives you an overview of the various specialized views +into the agenda that are available. From each view you can press =g?= to see +all the available key mappings. The most important ones are: + +- t => change the TODO state of a heading +- => open heading in current (agenda-)window +- => open heading in another window + +* Captures +:PROPERTIES: +:CUSTOM_ID: captures +:END: + +To quickly save thoughts, ideas or other things that come up regularly in your +day without interrupting your current task, Org-mode offers you so-called +captures. They can conveniently opened in any Vim buffer with =oc=. +Here we are presented with a list of availabe capture templates. + +To aid us in our endeavour of saving interesting repos, let's create a custom +capture that saves us from manually adding them to the =repos.org= file. We +add the following in our call to ~org.setup()~: + +#+begin_src lua +org_capture_templates = { + r = { + description = "Repo", + template = "* [[%x][%(return string.match('%x', '([^/]+)$'))]]%?", + target = "~/org/repos.org", + } +} +#+end_src + +After restarting Vim you should be able to select the =Repo= capture-template +with =r= when you initiate a capture. If you have the link to the repo in you +clipboard, it will be inserted into the link correctly. See the docs about the +possible ways to [[file:./configuration.org::#org_capture_templates][configure your templates]]. + +* Archiving +:PROPERTIES: +:CUSTOM_ID: archiving +:END: + +When we no longer need certain parts of our org files, they can be archived. +Let's say we are done with checking out the org-bullets repo, so we archive it +by pressing =o$= while on the heading. This will also archive any +child headings. The default location for archived headings is +.org_archive, which can be changed with the +[[file:./configuration.org::#org_archive_location][org_archive_location]] option. + +* Exporting +:PROPERTIES: +:CUSTOM_ID: exporting +:END: + +In case you want to preview, you can export your .org file to e.g., html with pandoc, see the [[file:./configuration.org::#org_export][docs]]. + +* Further Resources +:PROPERTIES: +:CUSTOM_ID: future-resources +:END: + +Org-mode is has many more features than the tiny subset outlined here. Have a +look around the official [[https://orgmode.org/manual/][manual]] if you are +interested in any particular topic. But please keep in mind, that this is a +work-in-progress port for Neovim and not the original source for Emacs +Org-mode. If you find any features you would like to see here, feel free to +open an issue or (even better) +[[https://github.com/nvim-orgmode/orgmode#development][get your hands dirty]] and create a pull request :wink: diff --git a/lua/orgmode/org/mappings.lua b/lua/orgmode/org/mappings.lua index 4f7ee38b3..1211a6365 100644 --- a/lua/orgmode/org/mappings.lua +++ b/lua/orgmode/org/mappings.lua @@ -881,13 +881,13 @@ end ---Find and move cursor to next visible heading. ---@return integer function OrgMappings:next_visible_heading() - return vim.fn.search([[^\*\+]], 'W', 0, 0, self._skip_invisible_heading) + return vim.fn.search([[^\*\+\s\+]], 'W', 0, 0, self._skip_invisible_heading) end ---Find and move cursor to previous visible heading. ---@return integer function OrgMappings:previous_visible_heading() - return vim.fn.search([[^\*\+]], 'bW', 0, 0, self._skip_invisible_heading) + return vim.fn.search([[^\*\+\s\+]], 'bW', 0, 0, self._skip_invisible_heading) end ---Check if heading is visible. If not, skip it. diff --git a/scripts/build_docs.sh b/scripts/build_docs.sh new file mode 100755 index 000000000..ebdf08999 --- /dev/null +++ b/scripts/build_docs.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +SCRIPTPATH="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" + +pandoc \ + --shift-heading-level-by=0 \ + --metadata=project:orgmode \ + --metadata=vimversion:Neovim \ + --metadata=toc:true \ + '--metadata=description:Orgmode clone written in Lua for Neovim' \ + '--metadata=titledatepattern:%Y %B %d' \ + --metadata=dedupsubheadings:true \ + --metadata=ignorerawblocks:true \ + --metadata=docmapping:true \ + --metadata=docmappingproject:true \ + --metadata=treesitter:true \ + --metadata=incrementheadinglevelby:0 \ + -t $SCRIPTPATH/panvimdoc.lua \ + $SCRIPTPATH/../docs/configuration.org \ + $SCRIPTPATH/../docs/troubleshoot.org \ + -o $SCRIPTPATH/../doc/orgmode.txt diff --git a/scripts/panvimdoc.lua b/scripts/panvimdoc.lua new file mode 100644 index 000000000..5918f2d33 --- /dev/null +++ b/scripts/panvimdoc.lua @@ -0,0 +1,611 @@ +-- Source code completely taken from https://github.com/kdheepak/panvimdoc +-- Only modified to include both lvl 3 and lvl 4 headers in the docmapping +PANDOC_VERSION:must_be_at_least("3.0") + +local pipe = pandoc.pipe +local stringify = (require("pandoc.utils")).stringify +local text = pandoc.text + +function P(s) + require("scripts.logging").temp(s) +end + +-- custom writer for pandoc + +local unpack = unpack or table.unpack +local format = string.format +local stringify = pandoc.utils.stringify +local layout = pandoc.layout +local to_roman = pandoc.utils.to_roman_numeral + +function string.starts_with(str, starts) + return str:sub(1, #starts) == starts +end + +function string.ends_with(str, ends) + return ends == "" or str:sub(-#ends) == ends +end + +-- Character escaping +local function escape(s, in_attribute) + return s +end + +local function indent(s, fl, ol) + local ret = {} + local i = 1 + for l in s:gmatch("[^\r\n]+") do + if i == 1 then + ret[i] = fl .. l + else + ret[i] = ol .. l + end + i = i + 1 + end + return table.concat(ret, "\n") +end + +Writer = pandoc.scaffolding.Writer + +local function inlines(ils) + local buff = {} + for i = 1, #ils do + local el = ils[i] + buff[#buff + 1] = Writer[pandoc.utils.type(el)][el.tag](el) + end + return table.concat(buff) +end + +local function blocks(bs, sep) + local dbuff = {} + for i = 1, #bs do + local el = bs[i] + dbuff[#dbuff + 1] = Writer[pandoc.utils.type(el)][el.tag](el) + end + return table.concat(dbuff, sep) +end + +local PROJECT = "" +local TREESITTER = false +local TOC = false +local VIMVERSION = "0.9.0" +local DESCRIPTION = "" +local DEDUP_SUBHEADINGS = false +local IGNORE_RAWBLOCKS = true +local DOC_MAPPING = true +local DOC_MAPPING_PROJECT = true +local DATE = nil +local TITLE_DATE_PATTERN = "%Y %B %d" + +local CURRENT_HEADER = nil +local SOFTBREAK_TO_HARDBREAK = "space" + +local HEADER_COUNT = 1 +local toc = {} +local links = {} + +local function osExecute(cmd) + local fileHandle = assert(io.popen(cmd, "r")) + local commandOutput = assert(fileHandle:read("*a")) + local returnTable = { fileHandle:close() } + return commandOutput, returnTable[3] -- rc[3] contains returnCode +end + +local function renderTitle() + local t = {} + local function add(s) + table.insert(t, s) + end + local vim_doc_title = PROJECT .. ".txt" + local vim_doc_title_tag = "*" .. vim_doc_title .. "*" + local project_description = DESCRIPTION or "" + if not project_description or #project_description == 0 then + local vim_version = VIMVERSION + if vim_version == nil then + vim_version = osExecute("nvim --version"):gmatch("([^\n]*)\n?")() + if string.find(vim_version, "-dev") then + vim_version = string.gsub(vim_version, "(.*)-dev.*", "%1") + end + if vim_version == "" then + vim_version = osExecute("vim --version"):gmatch("([^\n]*)\n?")() + vim_version = string.gsub(vim_version, "(.*) %(.*%)", "%1") + end + if vim_version == "" then + vim_version = "vim" + end + elseif vim_version == "vim" then + vim_version = osExecute("vim --version"):gmatch("([^\n]*)\n?")() + end + + local date = DATE + if date == nil then + date = os.date(TITLE_DATE_PATTERN) + end + local m = "For " .. vim_version + local r = "Last change: " .. date + local n = math.max(0, 78 - #vim_doc_title_tag - #m - #r) + local s = string.rep(" ", math.floor(n / 2)) + project_description = s .. m .. s .. r + end + local padding_len = math.max(0, 78 - #vim_doc_title_tag - #project_description) + add(vim_doc_title_tag .. string.rep(" ", padding_len) .. project_description) + add("") + return table.concat(t, "\n") +end + +local function renderToc() + if TOC then + local t = {} + local function add(s) + table.insert(t, s) + end + add(string.rep("=", 78)) + local l = "Table of Contents" + local tag = "*" .. PROJECT .. "-" .. string.gsub(string.lower(l), "%s", "-") .. "*" + add(l .. string.rep(" ", 78 - #l - #tag) .. tag) + add("") + for _, elem in pairs(toc) do + local level, item, link = elem[1], elem[2], elem[3] + if level == 1 then + local padding = string.rep(" ", 78 - #item - #link) + add(item .. padding .. link) + elseif level == 2 then + local padding = string.rep(" ", 74 - #item - #link) + add(" - " .. item .. padding .. link) + end + end + add("") + return table.concat(t, "\n") + else + return "" + end +end + +local function renderNotes() + local t = {} + local function add(s) + table.insert(t, s) + end + if #links > 0 then + local left = HEADER_COUNT .. ". Links" + local right = "links" + local right_link = string.format("|%s-%s|", PROJECT, right) + right = string.format("*%s-%s*", PROJECT, right) + local padding = string.rep(" ", 78 - #left - #right) + table.insert(toc, { 1, left, right_link }) + add(string.rep("=", 78) .. "\n" .. string.format("%s%s%s", left, padding, right)) + add("") + for i, v in ipairs(links) do + add(i .. ". *" .. v.caption .. "*" .. ": " .. v.src) + end + end + return table.concat(t, "\n") .. "\n" +end + +local function renderFooter() + return [[Generated by panvimdoc + +vim:tw=78:ts=8:noet:ft=help:norl:]] +end + +Writer.Pandoc = function(doc, opts) + PROJECT = doc.meta.project + TREESITTER = doc.meta.treesitter + TOC = doc.meta.toc + VIMVERSION = doc.meta.vimversion + DESCRIPTION = doc.meta.description + DEDUP_SUBHEADINGS = doc.meta.dedupsubheadings + IGNORE_RAWBLOCKS = doc.meta.ignorerawblocks + DOC_MAPPING = doc.meta.docmapping + DOC_MAPPING_PROJECT = doc.meta.docmappingproject + HEADER_COUNT = HEADER_COUNT + doc.meta.incrementheadinglevelby + DATE = doc.meta.date + TITLE_DATE_PATTERN = doc.meta.titledatepattern + local d = blocks(doc.blocks) + local notes = renderNotes() + local toc = renderToc() + local title = renderTitle() + local footer = renderFooter() + return { title, layout.blankline, toc, d, notes, layout.blankline, footer } +end + +Writer.Block.Header = function(el) + local lev = el.level + local s = stringify(el) + local attr = el.attr + local left, right, right_link, padding + if lev == 1 then + left = string.format("%d. %s", HEADER_COUNT, s) + right = string.lower(string.gsub(s, "%s", "-")) + CURRENT_HEADER = right + right_link = string.format("|%s-%s|", PROJECT, right) + right = string.format("*%s-%s*", PROJECT, right) + padding = string.rep(" ", 78 - #left - #right) + table.insert(toc, { 1, left, right_link }) + s = string.format("%s%s%s", left, padding, right) + HEADER_COUNT = HEADER_COUNT + 1 + s = string.rep("=", 78) .. "\n" .. s + return "\n" .. s .. "\n\n" + end + if lev == 2 then + left = string.upper(s) + right = string.lower(string.gsub(s, "%s", "-")) + if DEDUP_SUBHEADINGS and CURRENT_HEADER then + right_link = string.format("|%s-%s-%s|", PROJECT, CURRENT_HEADER, right) + right = string.format("*%s-%s-%s*", PROJECT, CURRENT_HEADER, right) + else + right_link = string.format("|%s-%s|", PROJECT, right) + right = string.format("*%s-%s*", PROJECT, right) + end + padding = string.rep(" ", 78 - #left - #right) + table.insert(toc, { 2, s, right_link }) + s = string.format("%s%s%s", left, padding, right) + return "\n" .. s .. "\n\n" + end + -- if lev == 3 then + -- left = string.upper(s) + -- return "\n" .. left .. " ~" .. "\n\n" + -- end + if lev == 3 or lev == 4 then + if DOC_MAPPING then + left = s + if attr.attributes.doc then + right = "*" .. attr.attributes.doc .. "*" + elseif DOC_MAPPING_PROJECT then + -- stylua: ignore + right = string.format( + "*%s-%s*", + PROJECT, + s:gsub("{.+}", "") + :gsub("%[.+%]", "") + :gsub("^%s*(.-)%s*$", "%1") + :gsub("^%s*(.-)%s*$", "%1") + :gsub("%s", "-") + ) + else + -- stylua: ignore + right = string.format( + "*%s*", + s:gsub("{.+}", "") + :gsub("%[.+%]", "") + :gsub("^%s*(.-)%s*$", "%1") + :gsub("^%s*(.-)%s*$", "%1") + :gsub("%s", "-") + ) + end + padding = string.rep(" ", 78 - #left - #right) + local r = string.format("%s%s%s", left, padding, right) + return "\n" .. r .. "\n\n" + else + left = string.upper(s) + return "\n" .. left .. "\n\n" + end + end + if lev >= 5 then + left = string.upper(s) + return "\n" .. left .. "\n\n" + end +end + +Writer.Block.Para = function(el) + local s = inlines(el.content) + local t = {} + local current_line = "" + for word in string.gmatch(s, "([^%s]+)") do + if string.match(word, "[.]") and #word == 1 then + current_line = current_line .. word + elseif (#current_line + #word) > 78 then + table.insert(t, current_line) + current_line = word + elseif #current_line == 0 then + current_line = word + else + current_line = current_line .. " " .. word + end + end + table.insert(t, current_line) + return table.concat(t, "\n") .. "\n\n" +end + +Writer.Block.OrderedList = function(items) + local buffer = {} + local i = 1 + items.content:map(function(item) + table.insert(buffer, ("%s. %s"):format(i, blocks(item))) + i = i + 1 + end) + return table.concat(buffer, "\n") .. "\n\n" +end + +Writer.Block.BulletList = function(items) + local buffer = {} + items.content:map(function(item) + table.insert(buffer, indent(blocks(item, "\n"), "- ", " ")) + end) + return table.concat(buffer, "\n") .. "\n\n" +end + +Writer.Block.DefinitionList = function(el) + local buffer = {} + local function add(s) + table.insert(buffer, s) + end + el.content:map(function(item) + local k = inlines(item[1]) + local bs = item[2][1] + local t = {} + for i = 1, #bs do + local e = bs[i] + if e.tag == "Para" then + local tt = {} + e.content:map(function(i) + if i.tag == "SoftBreak" then + table.insert(tt, "\n") + else + table.insert(tt, Writer[pandoc.utils.type(i)][i.tag](i)) + end + end) + table.insert(t, table.concat(tt)) + else + table.insert(t, Writer[pandoc.utils.type(e)][e.tag](e)) + end + end + local str = table.concat(t, "\n") + local i = 1 + + local right = "" + if DOC_MAPPING_PROJECT then + -- stylua: ignore + right = string.format( + "*%s-%s*", + PROJECT, + k:gsub("{.+}", "") + :gsub("%[.+%]", "") + :gsub("^%s*(.-)%s*$", "%1") + :gsub("^%s*(.-)%s*$", "%1") + :gsub("%s", "-") + ) + else + -- stylua: ignore + right = string.format( + "*%s*", + k:gsub("{.+}", "") + :gsub("%[.+%]", "") + :gsub("^%s*(.-)%s*$", "%1") + :gsub("^%s*(.-)%s*$", "%1") + :gsub("%s", "-") + ) + end + add(string.rep(" ", 78 - #right - 2) .. right) + add("\n") + for s in str:gmatch("[^\r\n]+") do + if i == 1 then + add(k .. string.rep(" ", 78 - 40 + 1 - #k) .. s) + else + add(string.rep(" ", 78 - 40 + 1) .. s) + end + i = i + 1 + end + add("\n") + end) + return "\n" .. table.concat(buffer, "\n") .. "\n\n" +end + +Writer.Block.CodeBlock = function(el) + local attr = el.attr + local s = el.text + if #attr.classes > 0 and attr.classes[1] == "vimdoc" then + return s .. "\n\n" + else + local lang = "" + if TREESITTER and #attr.classes > 0 then + lang = attr.classes[1] + end + local t = {} + for line in s:gmatch("([^\n]*)\n?") do + table.insert(t, " " .. escape(line)) + end + return ">" .. lang .. "\n" .. table.concat(t, "\n") .. "\n<\n\n" + end +end + +Writer.Inline.Str = function(el) + local s = stringify(el) + if string.starts_with(s, "(http") and string.ends_with(s, ")") then + return " <" .. string.sub(s, 2, #s - 2) .. ">" + else + return escape(s) + end +end + +Writer.Inline.Space = function() + return " " +end + +Writer.Inline.SoftBreak = function() + if SOFTBREAK_TO_HARDBREAK == "newline" then + return "\n" + elseif SOFTBREAK_TO_HARDBREAK == "space" then + return "\n" + else + return "" + end +end + +Writer.Inline.LineBreak = function() + return "\n" +end + +Writer.Inline.Emph = function(s) + return "_" .. stringify(s) .. "_" +end + +Writer.Inline.Strong = function(s) + return "**" .. stringify(s) .. "**" +end + +Writer.Inline.Subscript = function(s) + return "_" .. stringify(s) +end + +Writer.Inline.Superscript = function(s) + return "^" .. stringify(s) +end + +Writer.Inline.SmallCaps = function(s) + return stringify(s) +end + +Writer.Inline.Strikeout = function(s) + return "~" .. stringify(s) .. "~" +end + +Writer.Inline.Link = function(el) + local s = inlines(el.content) + local tgt = el.target + local tit = el.title + local attr = el.attr + if string.starts_with(tgt, "https://neovim.io/doc/") then + return "|" .. s .. "|" + elseif string.starts_with(tgt, "#") then + return "|" .. PROJECT .. "-" .. s:lower():gsub("%s", "-") .. "|" + elseif string.starts_with(s, "http") then + return "<" .. s .. ">" + else + return s .. " <" .. tgt .. ">" + end +end + +Writer.Inline.Image = function(el) + links[#links + 1] = { caption = inlines(el.caption), src = el.src } +end + +Writer.Inline.Code = function(el) + local content = stringify(el) + local vim_help = string.match(content, "^:h %s*([^%s]+)") + if vim_help then + return string.format("|%s|", escape(vim_help)) + else + return "`" .. escape(content) .. "`" + end +end + +Writer.Inline.Math = function(s) + return "`" .. escape(stringify(s)) .. "`" +end + +Writer.Inline.Quoted = function(el) + if el.quotetype == "DoubleQuote" then + return "\"" .. inlines(el.content) .. "\"" + else + return "'" .. inlines(el.content) .. "'" + end +end + +Writer.Inline.Note = function(el) + return stringify(el) +end + +Writer.Inline.Null = function(s) + return "" +end + +Writer.Inline.Span = function(el) + return inlines(el.content) +end + +Writer.Inline.RawInline = function(el) + if IGNORE_RAWBLOCKS then + return "" + end + local str = el.text + if format == "html" then + if str == "" then + return "" + elseif str == "" then + return " ~" + elseif str == "" or str == "" then + return "_" + elseif str == "" or str == "" then + return "" + else + return str + end + else + return "" + end +end + +Writer.Inline.Citation = function(el) + return el +end + +Writer.Inline.Cite = function(el) + links[#links + 1] = { caption = inlines(el.content), src = "" } + return inlines(el.content) +end + +Writer.Block.Plain = function(el) + return inlines(el.content) +end + +Writer.Block.RawBlock = function(el) + local fmt = el.format + local str = el.text + if fmt == "html" then + if string.starts_with(str, "