{"id":13443294,"url":"https://github.com/progfolio/doct","last_synced_at":"2025-04-05T16:40:13.527Z","repository":{"id":38431433,"uuid":"227148231","full_name":"progfolio/doct","owner":"progfolio","description":"DOCT: Declarative Org Capture Templates for Emacs","archived":false,"fork":false,"pushed_at":"2024-02-01T03:06:29.000Z","size":383,"stargazers_count":363,"open_issues_count":0,"forks_count":8,"subscribers_count":11,"default_branch":"master","last_synced_at":"2024-05-01T18:04:45.055Z","etag":null,"topics":["emacs","emacs-lisp","org","org-mode"],"latest_commit_sha":null,"homepage":"","language":"Emacs Lisp","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/progfolio.png","metadata":{"files":{"readme":"README.org","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"progfolio"}},"created_at":"2019-12-10T15:00:35.000Z","updated_at":"2024-05-30T01:27:29.805Z","dependencies_parsed_at":"2024-01-04T06:31:43.660Z","dependency_job_id":"43a427f3-39e7-48e7-9f32-7dfb4a7903e2","html_url":"https://github.com/progfolio/doct","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/progfolio%2Fdoct","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/progfolio%2Fdoct/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/progfolio%2Fdoct/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/progfolio%2Fdoct/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/progfolio","download_url":"https://codeload.github.com/progfolio/doct/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247369925,"owners_count":20927927,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["emacs","emacs-lisp","org","org-mode"],"created_at":"2024-07-31T03:01:58.754Z","updated_at":"2025-04-05T16:40:13.492Z","avatar_url":"https://github.com/progfolio.png","language":"Emacs Lisp","funding_links":["https://github.com/sponsors/progfolio"],"categories":["Emacs Lisp"],"sub_categories":[],"readme":"* DOCT: Declarative Org Capture Templates\n[[https://melpa.org/#/doct][file:https://melpa.org/packages/doct-badge.svg]]\n\n~doct~ is a function that provides an alternative, declarative syntax for describing Org capture templates.\n\n** tl;dr\n:PROPERTIES:\n:TOC:      ignore\n:END:\n#+begin_src emacs-lisp\n(defun my-org-template-hook ()\n  (when (string= (org-capture-get :key t) \"p1\")\n    (message \"\\\"First Child\\\" selected.\")))\n\n(add-hook 'org-capture-mode-hook 'my-org-template-hook)\n\n(setq org-capture-templates\n      '((\"p\" \"Parent\")\n        (\"p1\" \"First Child\"  entry (file+headline \"~/example.org\" \"One\")\n         \"* TODO %^{Description} \\n:PROPERTIES:\\n:Created: %U\\n:END:\\n%?\"\n         :prepend t)\n        (\"p2\" \"Second Child\" entry (file+headline \"~/example.org\" \"Two\")\n         \"* NEXT %^{Description} \\n:PROPERTIES:\\n:Created: %U\\n:END:\\n%?\"\n         :prepend t)\n        (\"p3\" \"Third Child\"  entry (file+headline \"~/example.org\" \"Three\")\n         \"* MAYBE %^{Description} \\n:PROPERTIES:\\n:Created: %U\\n:END:\\n%?\"\n         :prepend t)))\n#+end_src\n\nbecomes:\n\n#+begin_src emacs-lisp\n(setq org-capture-templates\n      (doct '((\"Parent\" :keys \"p\"\n               :file \"~/example.org\"\n               :prepend t\n               :template (\"* %{todo-state} %^{Description}\"\n                          \":PROPERTIES:\"\n                          \":Created: %U\"\n                          \":END:\"\n                          \"%?\")\n               :children ((\"First Child\"  :keys \"1\"\n                           :headline   \"One\"\n                           :todo-state \"TODO\"\n                           :hook (lambda () (message \"\\\"First Child\\\" selected.\")))\n                          (\"Second Child\" :keys \"2\"\n                           :headline   \"Two\"\n                           :todo-state \"NEXT\")\n                          (\"Third Child\"  :keys \"3\"\n                           :headline   \"Three\"\n                           :todo-state \"MAYBE\"))))))\n#+end_src\n\n** Releases\n\n***  3.2.0\n- add [[#doct-add-to][doct-add-to]] function\n  Add support for \"here\" target (Org 9.7)\n***  3.1.0\n- add [[#doct-add-to][doct-add-to]] function\n***  3.0.0\n- drop support for recursive =%{keyword}= expansion.\n***  2.0.0\n- drop support for =%doct(KEYWORD)= syntax. Replaced with =%{keyword}=\n- =doct-get= now accepts an optional parameter to determine whether to query =org-capture-plist= or =org-capture-current-plist=.\n- adopt semver\n** Contents\n:PROPERTIES:\n:TOC:      :include all\n:END:\n:CONTENTS:\n- [[#doct-declarative-org-capture-templates][DOCT: Declarative Org Capture Templates]]\n  - [[#tldr][tl;dr]]\n  - [[#releases][Releases]]\n    - [[#310][3.1.0]]\n    - [[#300][3.0.0]]\n    - [[#200][2.0.0]]\n  - [[#contents][Contents]]\n  - [[#installation][Installation]]\n    - [[#melpa][MELPA]]\n    - [[#manual][Manual]]\n  - [[#documentation][Documentation]]\n    - [[#doct][doct]]\n      - [[#child][Child]]\n      - [[#parent][Parent]]\n      - [[#group][Group]]\n      - [[#name--keys][Name \u0026 Keys]]\n      - [[#children][Children]]\n      - [[#inherited-properties][Inherited Properties]]\n      - [[#type][Type]]\n      - [[#target][Target]]\n      - [[#template][Template]]\n      - [[#additional-options][Additional options]]\n      - [[#custom-data][Custom data]]\n      - [[#keyword-expansion][%{KEYWORD} Expansion]]\n      - [[#hooks][Hooks]]\n      - [[#contexts][Contexts]]\n      - [[#disabling-templates][Disabling Templates]]\n      - [[#disabling-warnings][Disabling Warnings]]\n    - [[#doct-add-to][doct-add-to]]\n    - [[#custom-variables][Custom Variables]]\n    - [[#contributing][Contributing]]\n:END:\n\n** Installation\n*** MELPA\nTry it with the [[https://github.com/raxod502/straight.el][straight package manager]]:\n#+begin_src emacs-lisp\n(straight-use-package 'doct)\n#+end_src\n\nor [[https://github.com/jwiegley/use-package][use-package]]:\n#+begin_src emacs-lisp\n(use-package doct\n  :ensure t\n  ;;recommended: defer until calling doct\n  :commands (doct))\n#+end_src\n*** Manual\nDownload ~doct~ and make sure it is in your load-path.\nRequire it in your init file.\n#+begin_src emacs-lisp\n(require 'doct)\n#+end_src\n\n** Documentation\n*** doct\n#+begin_src emacs-lisp\n(doct declarations)\n#+end_src\n\n~doct~ expects a declaration or a list of declarations as its sole argument\nand converts it into a list of `org-capture-templates`.\nEach declaration is either a child, parent, or group.\n**** Child\nA child declaration must have:\n\n- a name\n- a ~:keys~ string\n- a template type\n- a target\n- a template\n\nand may also have:\n\n- hook functions defined with the hook keywords\n- contexts declared via the ~:contexts~ keyword\n- additional ~:KEY VAL~ arguments\n\n**** Parent\nA parent declaration must have:\n\n- a name\n- a ~:keys~ string\n- a list of ~:children~\n\nand may also have additional properties inherited by its children.\n\n**** Group\nA group is a special kind of parent declaration.\nIts children inherit its properties, but it is not added to the template selection menu.\nIts name must be the ~:group~ keyword.\nIt may optionally have a descriptive string for the value of ~:group~.\nIt must not have a ~:keys~ value.\n\n\n#+begin_src emacs-lisp :results scalar raw\n(doct '((\"Work\" :keys \"w\" :file \"~/org/work.org\" :children\n         ((:group \"Clocked\" :clock-in t :children\n                  ((\"Phone Call\" :keys \"p\" :template \"* Phone call with %?\")\n                   (\"Meeting\"    :keys \"m\" :template \"* Meeting with %?\")))\n          (\"Browsing\" :keys \"b\" :template \"* Browsing %x\")))))\n#+end_src\n\nreturns:\n\n#+begin_src emacs-lisp\n((\"w\" \"Work\")\n (\"wp\" \"Phone Call\" entry (file \"~/org/work.org\") \"* Phone call with %?\" :clock-in t)\n (\"wm\" \"Meeting\"    entry (file \"~/org/work.org\") \"* Meeting with %?\"    :clock-in t)\n (\"wb\" \"Browsing\"   entry (file \"~/org/work.org\") \"* Browsing %x\"))\n#+end_src\n\n**** Name \u0026 Keys\nEvery declaration must define a name. Unless it is a group , it must also define a ~:keys~ value.\nThe name is the first value in the declaration. The ~:keys~ keyword defines the keys to access the template\nfrom the capture menu.\n\n#+begin_src emacs-lisp\n(doct '((\"example\" :keys \"e\" ...)))\n#+end_src\n\nreturns:\n\n#+begin_src emacs-lisp\n((\"e\" \"example\" ...))\n#+end_src\n\n**** Children\nThe ~:children~ keyword defines a parent's children.\nIts value may be a single declaration or a list of declarations.\nThe parent's ~:keys~ prefix each child's ~:keys~.\n\n#+begin_src emacs-lisp\n(doct '((\"parent\" :keys \"p\"\n         :children\n         ((\"child\" :keys \"c\"\n           :children\n           ((\"grandchild\" :keys \"g\"\n             :file \"\"\n             :type plain\n             :template \"test\")))))))\n#+end_src\n\nreturns:\n\n#+begin_src emacs-lisp\n((\"p\" \"parent\") (\"pc\" \"child\") (\"pcg\" \"grandchild\" plain (file \"\") \"test\"))\n#+end_src\n\n**** Inherited Properties\nA child inherits its ancestors' properties.\nIt may optionally override an inherited property by specifying that property directly.\n\nFor example:\n\n#+begin_src emacs-lisp\n(doct '((\"Grandparent\" :keys \"g\"\n         :file \"example.org\"\n         :children (\"Parent\" :keys \"p\"\n                    :children (\"Child\" :keys \"c\")))))\n#+end_src\n\nThe \"Child\" template inherits its ~:file~ property from the \"Grandparent\" declaration.\nThe \"Parent\" declaration could override this value:\n\n#+begin_src emacs-lisp\n(doct '((\"Grandparent\" :keys \"g\"\n         :file \"example.org\"\n         :children (\"Parent\" :keys \"p\"\n                    :file \"overridden.org\"\n                    :children (\"Child\" :keys \"c\")))))\n#+end_src\n\nAnd the \"Child\" would have its ~:file~ property set to \"overridden.org\".\n\n**** Type\n\nThe ~:type~ keyword defines the template's entry type and accepts the following symbols:\n\n- entry ::\n  An Org node with a headline. The template becomes a child of the target entry\n  or a top level entry.\n\n- item ::\n  A plain list item, placed in the first plain list at the target location.\n\n- checkitem ::\n  A checkbox item. Same as plain list item only it uses a different default template.\n\n- table-line ::\n  A new line in the first table at target location.\n- plain ::\n  Text inserted as is.\n\n~doct-default-entry-type~ defines the entry type when the ~:type~ keyword is not provided.\n\nFor example, with  ~doct-default-entry-type~ set to ~entry~ (the default):\n\n#+begin_src emacs-lisp\n(doct '((\"example\"\n         :keys \"e\"\n         :type entry\n         :file \"\")))\n#+end_src\n\nAnd\n\n#+begin_src emacs-lisp\n(doct '((\"example\"\n         :keys \"e\"\n         :file \"\")))\n#+end_src\n\nBoth return:\n\n#+begin_src emacs-lisp\n((\"e\" \"example\" entry (file \"\") nil))\n#+end_src\n\n**** Target\nThe target defines the location of the inserted template text.\n\nThe first keyword declared in the following group exclusively sets the target.\nThe ~:file~ keyword is not necessary for these.\n\n- :id \"id of existing Org entry\" ::\n  File as child of this entry, or in the body of the entry\n  (see [[https://github.com/emacs-mirror/emacs/blob/d0e2a341dd9a9a365fd311748df024ecb25b70ec/lisp/org/org-id.el#L45][org-id-get-create]] and the [[https://orgmode.org/manual/Template-elements.html#Template-elements][Org Mode Manual]])\n\n- :clock t ::\n  File to the currently clocked entry\n\n- :function (lambda () ;visit file and move point to desired location...) ::\n  This keyword is exclusive when used without the ~:file~ keyword. It is\n  responsible for finding the proper file and location to insert the capture\n  item. If ~:file~ defines a target file, then the function is only\n  responsible for moving point to the desired location within that file.\n\n#+begin_src emacs-lisp\n(doct '((\"example\"\n         :keys \"e\"\n         :type entry\n         :clock t\n         ;;ignored because clock is first\n         :function (lambda () (ignore))\n         ;;also ignored\n         :id \"1\")))\n#+end_src\n\nreturns:\n\n#+begin_src emacs-lisp\n((\"e\" \"example\" entry (clock) nil))\n#+end_src\n\nThe ~:file~ keyword defines the target file for the capture template.\nIt may be:\n\n- a string:\n\n#+begin_src emacs-lisp\n(doct ... :file \"/path/to/target.org\")\n;;empty string defaults to `org-default-notes-file'\n(doct ... :file \"\")\n#+end_src\n\n- a function:\n\n#+begin_src emacs-lisp\n;;lambda\n(doct ... :file (lambda () (concat (read-string \"Org Capture Path: \") \".org\")))\n;;or a function symbol\n(doct ... :file my/get-file-path)\n#+end_src\n\n- or a variable:\n\n#+begin_src emacs-lisp\n(doct ... :file my/file-path)\n#+end_src\n\nThe following keywords refine the target file location:\n\n- :headline \"node headline\" ::\n  File under unique heading in target file.\n\n- :olp (\"Level 1 heading\" \"Level 2 heading\"...) ::\n\n  Define the full outline in the target file.\n\n- :datetree nil|t ::\n  Requires use of the ~:file~  keyword.\n  If ~:datetree~ has a non-nil value, create a date tree for today’s date.\n  If ~:olp~ is given, the date tree is added under that heading path.\n  Use a non-nil ~:time-prompt~ property to prompt for a different date.\n  Set the ~:tree-type~ property to the symbol ~week~ create a week tree instead of the default month tree.\n\n- :regexp \"regexp describing location\" ::\n\n  File to the entry matching regexp in target file\n\n- :function location-finding-function ::\n\n  If used in addition to the ~:file~ keyword, the value should be a function\n  that finds the desired location in that file. If used as an exclusive\n  keyword (see above), the function must locate both the target file and move\n  point to the desired location.\n\n**** Template\nThe ~:template~ keyword defines the template for creating the capture item.\nIt may be either a string, list of strings, or a function.\n~doct~ joins the list with new lines.\nA function must return the template text.\n\n#+begin_src emacs-lisp\n(doct '((... :template (\"Test\" \"One\" \"Two\"))))\n#+end_src\n\nreturns:\n\n#+begin_src emacs-lisp\n((... \"Test\\nOne\\nTwo\"))\n#+end_src\n\nThe ~:template-file~ keyword defines a file containing the text of the template.\nFor example:\n\n#+begin_src emacs-lisp\n(doct '((... :template-file \"~/org/templates/template.txt\")))\n#+end_src\n\nwill use the text of template.txt as the template string.\n\nThe first keyword declared overrides any additional template declarations.\n\n**** Additional options\nKey-value pairs define additional options.\n\n#+begin_src emacs-lisp\n(doct '((... :immediate-finish t)))\n#+end_src\n\nreturns:\n\n#+begin_src emacs-lisp\n((... :immediate-finish t))\n#+end_src\n\nsee the [[https://orgmode.org/manual/Template-elements.html#Template-elements][Org Mode Manual]] for a full list of additional options.\n\n**** Custom data\n:PROPERTIES:\n:CUSTOM_ID: custom-data\n:END:\n~doct~ stores unrecognized keywords on the template's [[https://github.com/emacs-mirror/emacs/blob/d0e2a341dd9a9a365fd311748df024ecb25b70ec/lisp/org/org-capture.el#L450][org-capture-plist]] as members of the doct-custom plist.\nThis makes a template's metadata accessible during capture.\nSee [[#keyword-expansion][%{KEYWORD} Expansion]] for details on using that data.\n\nThe ~:custom~ keyword accepts a plist.\ndoct copies the plist's values to the doct-custom plist.\nThis is only necessary if you wish to use a keyword which doct already uses.\n\nFor example:\n#+begin_src emacs-lisp\n(doct '((\"Music Gear\" :keys \"m\" :file \"\"\n         :custom (:keys \"Moog\"))))\n#+end_src\n\nreturns:\n\n#+begin_src emacs-lisp\n(#1=\"m\" #2=\"Music Gear\" entry (file #3=\"\") nil\n    :doct (#2# :keys #1# :file #3# :custom #4=(:keys \"Moog\") :doct-custom #4#))))\n#+end_src\n\n**** %{KEYWORD} Expansion\n:PROPERTIES:\n:CUSTOM_ID: keyword-expansion\n:END:\nA declaration ~:template~ may include a keyword's value during capture.\nThe syntax is similar to other, built-in \"%-escapes\".\n~%{KEYWORD}~ will insert the value declared with ~:KEYWORD~ in the declaration.\n\nFor example, with:\n\n#+begin_src emacs-lisp\n(doct '((\"Parent\" :keys \"p\"\n         :file \"\"\n         :template \"* %{todo-state} %?\"\n         :children ((\"One\" :keys \"1\" :todo-state \"TODO\")\n                    (\"Two\" :keys \"2\" :todo-state \"IDEA\")))))\n#+end_src\n\nEach child template has its ~:todo-state~ value expanded in the inherited ~:template.~\n\nValues should be strings, functions or nil.\n\n#+begin_src emacs-lisp results raw\n(doct '((\"%{string}\" :keys \"s\" :type plain :file \"\"\n         :string \"string\"\n         :template \"%{string}\")))\n#+end_src\n\nIs replaced with:\n\n#+begin_src emacs-lisp\n\"string\"\n#+end_src\n\n#+begin_src emacs-lisp results raw\n(doct '((\"%{fn}\" :keys \"f\" :type plain :file \"\"\n         :fn (lambda () \"string returned from function\")\n         :template \"%{fn}\")))\n#+end_src\n\nIs replaced with:\n\n#+begin_src emacs-lisp\n\"string returned from function\"\n#+end_src\n\n#+begin_src emacs-lisp\n(doct '((\"%{nil}\" :keys \"f\" :type plain :file \"\"\n         :nil nil\n         :template \"%{nil}\")))\n#+end_src\n\nIs replaced with the empty string\n\n#+begin_src emacs-lisp\n\"\"\n#+end_src\n\nCustom keywords take precedence over other declaration keywords.\nFor example, with:\n\n#+begin_src emacs-lisp\n(doct '((\"Music Gear\" :keys \"m\" :file \"\" :type plain\n         :custom (:keys \"Moog\")\n         :template \"%{keys}\")))\n#+end_src\n\nThe \"Music Gear\" template expands to \"Moog\" instead of \"m\".\nNil values expand to an empty string.\n\n**** Hooks\nAdding the following hook keywords in a declaration adds its value to the appropriate org-capture hook.\nThe value may be a function or a variable.\n\n- :hook function ::\n  - org-capture-mode-hook ::\n\n    Runs FUNCTION when entering the org-capture-mode minor mode.\n\n- :prepare-finalize function ::\n  - org-capture-prepare-finalize-hook ::\n\n    Runs FUNCTION before the finalization starts. The capture buffer is current and\n    narrowed.\n\n- :before-finalize function ::\n  - org-capture-before-finalize-hook ::\n\n    Runs FUNCTION right before a capture process finalizes. The capture buffer is still\n    current and widened to the entire buffer.\n\n- :after-finalize function ::\n  - org-capture-after-finalize-hook  ::\n    Runs FUNCTION right after a capture process finalizes. Suitable for window cleanup.\n\nFor example:\n\n#+begin_src emacs-lisp\n(doct `((\"example\"\n         :keys \"e\"\n         :file \"\"\n         :hook ,(defun my/fn  ()\n                  (ignore)))))\n#+end_src\n\nruns ~my/fn~ during the ~org-capture-mode-hook~ when selecting the \"example\" template.\n\n**** Contexts\nThe ~:contexts~ keyword defines contextual rules for a template.\nIts value may be a single contextual rule or a list of rules.\nThe following keywords are available to create contextual rules:\n\n- :in-buffer regexp ::\n  Show template when REGEXP matches the current buffer's name.\n#+begin_src emacs-lisp :results scalar\n(doct '((\"Only in *scratch*\" :keys \"n\" :file \"\" :contexts (:in-buffer \"^\\\\*scratch\\\\*$\"))))\n#+end_src\n\n- :unless-buffer regexp ::\n  Show template unless REGEXP matches the current buffer's name.\n#+begin_src emacs-lisp :results scalar\n(doct '((\"Except in *scratch*\" :keys \"n\" :file \"\" :contexts (:unless-buffer \"^\\\\*scratch\\\\*$\"))))\n#+end_src\n\n- :in-file regexp ::\n  Show template when REGEXP matches the current buffer's file name.\n#+begin_src emacs-lisp :results scalar\n(doct '((\"Only in work.org\" :keys \"n\" :file \"\" :contexts (:in-file \"work\\\\.org$\"))))\n#+end_src\n\n- :unless-file regexp ::\n  Show template unless REGEXP matches the current buffer's file name.\n#+begin_src emacs-lisp :results scalar\n(doct '((\"Except in work.org\" :keys \"n\" :file \"\" :contexts (:unless-file \"work\\\\.org$\"))))\n#+end_src\n\n- :in-mode regexp ::\n  Show template when REGEXP matches the current buffer's major mode.\n#+begin_src emacs-lisp :results scalar\n(doct '((\"Only in org-mode\" :keys \"n\" :file \"\" :contexts (:in-mode \"org-mode\"))))\n#+end_src\n\n- :unless-mode regexp ::\n  Show template unless REGEXP matches the current buffer's major mode.\n#+begin_src emacs-lisp :results scalar\n(doct '((\"Except in org-mode\" :keys \"n\" :file \"\" :contexts (:unless-mode \"org-mode\"))))\n#+end_src\n\n- :when condition ::\n  Show template when CONDITION evaluates to a non-nil value. Condition may be a function or a single form.\n#+begin_src emacs-lisp :results scalar\n(doct '((\"Show when my/predicate-p returns t\" :keys \"n\" :file \"\" :contexts (:when my/predicate-p))))\n#+end_src\n\n#+begin_src emacs-lisp :results scalar\n(doct '((\"1/3 chance of showing\" :keys \"n\" :file \"\" :contexts (:when (= 2 (random 3))))))\n#+end_src\n\n- :unless condition ::\n  Show template when CONDITION evaluates to a nil value. Condition may be a function or a single form.\n#+begin_src emacs-lisp :results scalar\n(doct '((\"Show when my/predicate-p returns nil\" :keys \"n\" :file \"\" :contexts (:unless my/predicate-p))))\n#+end_src\n\n#+begin_src emacs-lisp :results scalar\n(doct '((\"2/3 chance of showing\" :keys \"n\" :file \"\" :contexts (:unless (= 2 (random 3))))))\n#+end_src\n\n- :function function ::\n  Show template when FUNCTION returns non-nil.\n  The function is not passed any arguments.\n#+begin_src emacs-lisp :results scalar\n(doct '((\"Between 9AM and 5PM\" :keys \"n\" :file \"\"\n         :contexts (:function (lambda () (\u003c= 9 (string-to-number (format-time-string \"%H\")) 17)))))))\n#+end_src\n\nAdding ~:keys~ to a rule does the same as above, but remaps the template's keys to the template with keys matching the ~:keys~ string.\nFor example:\n#+begin_src emacs-lisp :results scalar\n(doct '((\"In *scratch* remapped to t, else use original template\"\n         :keys \"n\" :file \"\" :contexts ((:unless-buffer \"^\\\\*scratch\\\\*$\" :keys \"n\")\n                                       (:in-buffer     \"^\\\\*scratch\\\\*$\" :keys \"t\")))))\n#+end_src\n\nThe above rule keywords, spare ~:function~, ~:when~, and ~:unless~ may also take a list of strings for their values.\n#+begin_src emacs-lisp\n(doct '((\"Only in org-mode or emacs-lisp-mode\" :keys \"n\" :file \"\"\n         :contexts (:in-mode (\"org-mode\" \"emacs-lisp-mode\")))))\n#+end_src\n\n**** Disabling Templates\n:PROPERTIES:\n:CUSTOM_ID: disabling-templates\n:END:\nSetting the ~:disabled~ keyword to t disables a template.\nThe template's declaration is not error checked.\nThis can be useful if you don't have the time to deal with an error right away.\nFor example:\n#+begin_src emacs-lisp :results raw scalar\n(doct '((:group \"All\" :file \"\" :children\n                ((:group \"Enabled\" :children\n                         ((\"One\"   :keys \"1\")\n                          (\"Two\"   :keys \"2\")\n                          (\"Three\" :keys \"3\")))\n                 (:group \"Disabled\" :disabled t :children\n                         ((\"Four\" :keys 4)\n                          (\"Five\" :keys 5)\n                          (\"Six\"  :keys 6)))))))\n#+end_src\n\nreturns:\n\n#+begin_src emacs-lisp\n((\"1\" \"One\"   entry (file \"\") nil)\n (\"2\" \"Two\"   entry (file \"\") nil)\n (\"3\" \"Three\" entry (file \"\") nil))\n#+end_src\n\nNormally template \"Four\" would throw an error because its ~:keys~ are not a string.\n\n**** Disabling Warnings\nThe =:warn= keyword disables =doct='s warnings on a per-declaration basis.\nFor example:\n\n#+begin_src emacs-lisp\n(let ((doct-warnings t))\n  (doct '((\"Ignore unbound symbol warnings\" :keys \"i\"\n           :warn (:not unbound)\n           :file     unbound-variable\n           :function unbound-function)\n          (\"Warn here, though\" :keys \"w\"\n           :file     unbound-variable\n           :function unbound-function))))\n#+end_src\n\nFor global control of warnings and an explanation of accepted values see =doct-warnings= in [[#custom-variables][Custom Variables]].\n\n*** doct-add-to\n#+begin_src emacs-lisp\n(doct-add-to list declarations \u0026optional append)\n#+end_src\n\nReturn a copy of =LIST= with converted =DECLARATIONS= added.\nIf =APPEND= is non-nil, add to back of =LIST=.\nOtherwise, add to the front of =LIST=.\n=DECLARATIONS= are passed to =doct= and must be the same of the same form =doct= accepts.\n\ne.g.\n#+begin_src emacs-lisp\n;; `org-capture-templates' set earlier elsewhere...\n\n(setq org-capture-templates\n      (doct-add-to org-capture-templates\n                   '(\"example\" :keys \"e\" ...)\n                   'append))\n#+end_src\n*** Custom Variables\n:PROPERTIES:\n:CUSTOM_ID: custom-variables\n:END:\n~doct~ supports the following variables for customization:\n\n- doct-default-entry-type 'entry ::\n  The default template entry type.\n  It can be overridden on a per-declaration basis by using the ~:type~ keyword.\n\n- doct-after-conversion-functions ::\n  Abnormal hook run after converting declarations to templates.\n  Hook functions run with the list of templates as their only argument.\n  The templates are not flattened at this point and are of the form:\n  #+begin_src emacs-lisp\n(((parent) (child)...)...).\n  #+end_src\n\n- doct-warnings ::\n  When non-nil, doct will issue warnings. Valid values are:\n  - t ::\n    warn in all cases\n  - nil ::\n    do not warn\n  Or a list containing any of the following symbols:\n  - unbound ::\n    warn when a symbol is unbound during conversion\n  - template-keyword ::\n    warn when %{KEYWORD} is not found on the declaration during conversion.\n  - template-keyword-type ::\n    warn when %{KEYWORD} expansion does not return a string.\n  - template-entry-type ::\n    warn when the expanded template string does not match the capture template's entry type\n  - template-file ::\n    warn when the ~:template-file~'s file is not found during conversion\n  - option-type ::\n    warn when additional options are not the proper type\n\n  If the list's first element is the ~:not~ keyword, the list of warnings is disabled.\n  It can be overridden on a per-declaration basis with the :warn keyword.\"\n\n  For example:\n  #+begin_src emacs-lisp\n(let ((doct-warnings t))\n  (doct '((\"Ignore unbound symbol warnings\" :keys \"i\"\n           :warn (:not unbound)\n           :file     unbound-variable\n           :function unbound-function)\n          (\"Warn here, though\" :keys \"w\"\n           :file     unbound-variable\n           :function unbound-function))))\n  #+end_src\n\n*** Contributing\n\nPull/feature requests, code review, angry comments are all welcome.\n\nPlease add a test to the test suite if you introduce any changes.\n\nThanks,\nnv\n\n#  LocalWords:  DOCT MELPA init doct txt plist unintern nv tl dr semver\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fprogfolio%2Fdoct","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fprogfolio%2Fdoct","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fprogfolio%2Fdoct/lists"}