All Projects → progfolio → Doct

progfolio / Doct

Licence: gpl-3.0
DOCT: Declarative Org Capture Templates for Emacs

Projects that are alternatives of or similar to Doct

Verb
Organize and send HTTP requests from Emacs
Stars: ✭ 205 (-2.38%)
Mutual labels:  emacs, org-mode
Org Fragtog
Automatically toggle Org mode LaTeX fragment previews as the cursor enters and exits them
Stars: ✭ 149 (-29.05%)
Mutual labels:  emacs, org-mode
Walkman
Write HTTP requests in Org mode and replay them at will using cURL
Stars: ✭ 120 (-42.86%)
Mutual labels:  emacs, org-mode
Toc Org
toc-org is an Emacs utility to have an up-to-date table of contents in the org files without exporting (useful primarily for readme files on GitHub)
Stars: ✭ 202 (-3.81%)
Mutual labels:  emacs, org-mode
Org Pdftools
A custom org link type for pdf-tools
Stars: ✭ 165 (-21.43%)
Mutual labels:  emacs, org-mode
Emacs Gtd
Get Things Done with Emacs
Stars: ✭ 111 (-47.14%)
Mutual labels:  emacs, org-mode
Org Graph View
View Org buffers as a clickable, graphical mind-map
Stars: ✭ 141 (-32.86%)
Mutual labels:  emacs, org-mode
Organice
An implementation of Org mode without the dependency of Emacs - built for mobile and desktop browsers
Stars: ✭ 1,327 (+531.9%)
Mutual labels:  emacs, org-mode
Hexo Renderer Org
Hexo renderer plugin for emacs org-mode
Stars: ✭ 157 (-25.24%)
Mutual labels:  emacs, org-mode
Org Msg
OrgMsg is a GNU/Emacs global minor mode mixing up Org mode and Message mode to compose and reply to emails in a Outlook HTML friendly style.
Stars: ✭ 153 (-27.14%)
Mutual labels:  emacs, org-mode
Org Brain
Org-mode wiki + concept-mapping
Stars: ✭ 1,512 (+620%)
Mutual labels:  emacs, org-mode
Go Org
Org mode parser with html & pretty printed org rendering. also shitty static site generator.
Stars: ✭ 177 (-15.71%)
Mutual labels:  emacs, org-mode
Weblorg
Static Site Generator for Emacs
Stars: ✭ 103 (-50.95%)
Mutual labels:  emacs, org-mode
Cheatsheet
Pretty cheat sheets, or ``reference cards'', obtainable from Org files.
Stars: ✭ 116 (-44.76%)
Mutual labels:  emacs, org-mode
Ox Rst
reStructuredText Back-End for Org-Mode Export Engine
Stars: ✭ 94 (-55.24%)
Mutual labels:  emacs, org-mode
Novels.org
Novels.org - Your Novels in Plain Text (Emacs . org-mode)
Stars: ✭ 120 (-42.86%)
Mutual labels:  emacs, org-mode
Ox Jira.el
Org-mode export backend for JIRA markup
Stars: ✭ 88 (-58.1%)
Mutual labels:  emacs, org-mode
Eless
A Better 'less' - A bash script that loads emacs with minimal view-mode config - Created with Org mode
Stars: ✭ 94 (-55.24%)
Mutual labels:  emacs, org-mode
Writingwithemacs
Tips, Examples, and Resources for Writing with Emacs
Stars: ✭ 150 (-28.57%)
Mutual labels:  emacs, org-mode
Orgro
An org-mode file viewer for iOS and Android
Stars: ✭ 175 (-16.67%)
Mutual labels:  emacs, org-mode
  • DOCT: Declarative Org Capture Templates [[https://melpa.org/#/doct][file:https://melpa.org/packages/doct-badge.svg]]

doct is a function that provides an alternative, declarative syntax for describing Org capture templates.

** tl;dr :PROPERTIES: :TOC: ignore :END: #+begin_src emacs-lisp (defun my-org-template-hook () (when (string= (org-capture-get :key t) "p1") (message ""First Child" selected.")))

(add-hook 'org-capture-mode-hook 'my-org-template-hook)

(setq org-capture-templates '(("p" "Parent") ("p1" "First Child" entry (file+headline "/example.org" "One") "* TODO %^{Description} \n:PROPERTIES:\n:Created: %U\n:END:\n%?" :prepend t) ("p2" "Second Child" entry (file+headline "/example.org" "Two") "* NEXT %^{Description} \n:PROPERTIES:\n:Created: %U\n:END:\n%?" :prepend t) ("p3" "Third Child" entry (file+headline "~/example.org" "Three") "* MAYBE %^{Description} \n:PROPERTIES:\n:Created: %U\n:END:\n%?" :prepend t))) #+end_src

becomes:

#+begin_src emacs-lisp (setq org-capture-templates (doct '(("Parent" :keys "p" :file "~/example.org" :prepend t :template ("* %{todo-state} %^{Description}" ":PROPERTIES:" ":Created: %U" ":END:" "%?") :children (("First Child" :keys "1" :headline "One" :todo-state "TODO" :hook (lambda () (message ""First Child" selected."))) ("Second Child" :keys "2" :headline "Two" :todo-state "NEXT") ("Third Child" :keys "3" :headline "Three" :todo-state "MAYBE")))))) #+end_src

** Releases

*** 3.1.0

  • add [[#doct-add-to][doct-add-to]] function *** 3.0.0
  • drop support for recursive =%{keyword}= expansion. *** 2.0.0
  • drop support for =%doct(KEYWORD)= syntax. Replaced with =%{keyword}=
  • =doct-get= now accepts an optional parameter to determine whether to query =org-capture-plist= or =org-capture-current-plist=.
  • adopt semver ** Contents :PROPERTIES: :TOC: :include all :END: :CONTENTS:
  • [[#doct-declarative-org-capture-templates][DOCT: Declarative Org Capture Templates]]
    • [[#tldr][tl;dr]]
    • [[#releases][Releases]]
      • [[#310][3.1.0]]
      • [[#300][3.0.0]]
      • [[#200][2.0.0]]
    • [[#contents][Contents]]
    • [[#installation][Installation]]
      • [[#melpa][MELPA]]
      • [[#manual][Manual]]
    • [[#documentation][Documentation]]
      • [[#doct][doct]]
        • [[#child][Child]]
        • [[#parent][Parent]]
        • [[#group][Group]]
        • [[#name--keys][Name & Keys]]
        • [[#children][Children]]
        • [[#inherited-properties][Inherited Properties]]
        • [[#type][Type]]
        • [[#target][Target]]
        • [[#template][Template]]
        • [[#additional-options][Additional options]]
        • [[#custom-data][Custom data]]
        • [[#keyword-expansion][%{KEYWORD} Expansion]]
        • [[#hooks][Hooks]]
        • [[#contexts][Contexts]]
        • [[#disabling-templates][Disabling Templates]]
        • [[#disabling-warnings][Disabling Warnings]]
      • [[#doct-add-to][doct-add-to]]
      • [[#custom-variables][Custom Variables]]
      • [[#contributing][Contributing]] :END:

** Installation *** MELPA Try it with the [[https://github.com/raxod502/straight.el][straight package manager]]: #+begin_src emacs-lisp (straight-use-package 'doct) #+end_src

or [[https://github.com/jwiegley/use-package][use-package]]: #+begin_src emacs-lisp (use-package doct :ensure t ;;recommended: defer until calling doct :commands (doct)) #+end_src *** Manual Download doct and make sure it is in your load-path. Require it in your init file. #+begin_src emacs-lisp (require 'doct) #+end_src

** Documentation *** doct #+begin_src emacs-lisp (doct declarations) #+end_src

doct expects a declaration or a list of declarations as its sole argument and converts it into a list of org-capture-templates. Each declaration is either a child, parent, or group. **** Child A child declaration must have:

  • a name
  • a :keys string
  • a template type
  • a target
  • a template

and may also have:

  • hook functions defined with the hook keywords
  • contexts declared via the :contexts keyword
  • additional :KEY VAL arguments

**** Parent A parent declaration must have:

  • a name
  • a :keys string
  • a list of :children

and may also have additional properties inherited by its children.

**** Group A group is a special kind of parent declaration. Its children inherit its properties, but it is not added to the template selection menu. Its name must be the :group keyword. It may optionally have a descriptive string for the value of :group. It must not have a :keys value.

#+begin_src emacs-lisp :results scalar raw (doct '(("Work" :keys "w" :file "~/org/work.org" :children ((:group "Clocked" :clock-in t :children (("Phone Call" :keys "p" :template "* Phone call with %?") ("Meeting" :keys "m" :template "* Meeting with %?"))) ("Browsing" :keys "b" :template "* Browsing %x"))))) #+end_src

returns:

#+begin_src emacs-lisp (("w" "Work") ("wp" "Phone Call" entry (file "/org/work.org") "* Phone call with %?" :clock-in t) ("wm" "Meeting" entry (file "/org/work.org") "* Meeting with %?" :clock-in t) ("wb" "Browsing" entry (file "~/org/work.org") "* Browsing %x")) #+end_src

**** Name & Keys Every declaration must define a name. Unless it is a group , it must also define a :keys value. The name is the first value in the declaration. The :keys keyword defines the keys to access the template from the capture menu.

#+begin_src emacs-lisp (doct '(("example" :keys "e" ...))) #+end_src

returns:

#+begin_src emacs-lisp (("e" "example" ...)) #+end_src

**** Children The :children keyword defines a parent's children. Its value may be a single declaration or a list of declarations. The parent's :keys prefix each child's :keys.

#+begin_src emacs-lisp (doct '(("parent" :keys "p" :children (("child" :keys "c" :children (("grandchild" :keys "g" :file "" :type plain :template "test"))))))) #+end_src

returns:

#+begin_src emacs-lisp (("p" "parent") ("pc" "child") ("pcg" "grandchild" plain (file "") "test")) #+end_src

**** Inherited Properties A child inherits its ancestors' properties. It may optionally override an inherited property by specifying that property directly.

For example:

#+begin_src emacs-lisp (doct '(("Grandparent" :keys "g" :file "example.org" :children ("Parent" :keys "p" :children ("Child" :keys "c"))))) #+end_src

The "Child" template inherits its :file property from the "Grandparent" declaration. The "Parent" declaration could override this value:

#+begin_src emacs-lisp (doct '(("Grandparent" :keys "g" :file "example.org" :children ("Parent" :keys "p" :file "overridden.org" :children ("Child" :keys "c"))))) #+end_src

And the "Child" would have its :file property set to "overridden.org".

**** Type

The :type keyword defines the template's entry type and accepts the following symbols:

  • entry :: An Org node with a headline. The template becomes a child of the target entry or a top level entry.

  • item :: A plain list item, placed in the first plain list at the target location.

  • checkitem :: A checkbox item. Same as plain list item only it uses a different default template.

  • table-line :: A new line in the first table at target location.

  • plain :: Text inserted as is.

doct-default-entry-type defines the entry type when the :type keyword is not provided.

For example, with doct-default-entry-type set to entry (the default):

#+begin_src emacs-lisp (doct '(("example" :keys "e" :type entry :file ""))) #+end_src

And

#+begin_src emacs-lisp (doct '(("example" :keys "e" :file ""))) #+end_src

Both return:

#+begin_src emacs-lisp (("e" "example" entry (file "") nil)) #+end_src

**** Target The target defines the location of the inserted template text.

The first keyword declared in the following group exclusively sets the target. The :file keyword is not necessary for these.

  • :id "id of existing Org entry" :: File as child of this entry, or in the body of the entry (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]])

  • :clock t :: File to the currently clocked entry

  • :function (lambda () ;visit file and move point to desired location...) :: This keyword is exclusive when used without the :file keyword. It is responsible for finding the proper file and location to insert the capture item. If :file defines a target file, then the function is only responsible for moving point to the desired location within that file.

#+begin_src emacs-lisp (doct '(("example" :keys "e" :type entry :clock t ;;ignored because clock is first :function (lambda () (ignore)) ;;also ignored :id "1"))) #+end_src

returns:

#+begin_src emacs-lisp (("e" "example" entry (clock) nil)) #+end_src

The :file keyword defines the target file for the capture template. It may be:

  • a string:

#+begin_src emacs-lisp (doct ... :file "/path/to/target.org") ;;empty string defaults to `org-default-notes-file' (doct ... :file "") #+end_src

  • a function:

#+begin_src emacs-lisp ;;lambda (doct ... :file (lambda () (concat (read-string "Org Capture Path: ") ".org"))) ;;or a function symbol (doct ... :file my/get-file-path) #+end_src

  • or a variable:

#+begin_src emacs-lisp (doct ... :file my/file-path) #+end_src

The following keywords refine the target file location:

  • :headline "node headline" :: File under unique heading in target file.

  • :olp ("Level 1 heading" "Level 2 heading"...) ::

    Define the full outline in the target file.

  • :datetree nil|t :: Requires use of the :file keyword. If :datetree has a non-nil value, create a date tree for today’s date. Use a non-nil :time-prompt property to prompt for a different date. Set the :tree-type property to the symbol week create a week tree instead of the default month tree.

  • :regexp "regexp describing location" ::

    File to the entry matching regexp in target file

  • :function location-finding-function ::

    If used in addition to the :file keyword, the value should be a function that finds the desired location in that file. If used as an exclusive keyword (see above), the function must locate both the target file and move point to the desired location.

**** Template The :template keyword defines the template for creating the capture item. It may be either a string, list of strings, or a function. doct joins the list with new lines. A function must return the template text.

#+begin_src emacs-lisp (doct '((... :template ("Test" "One" "Two")))) #+end_src

returns:

#+begin_src emacs-lisp ((... "Test\nOne\nTwo")) #+end_src

The :template-file keyword defines a file containing the text of the template. For example:

#+begin_src emacs-lisp (doct '((... :template-file "~/org/templates/template.txt"))) #+end_src

will use the text of template.txt as the template string.

The first keyword declared overrides any additional template declarations.

**** Additional options Key-value pairs define additional options.

#+begin_src emacs-lisp (doct '((... :immediate-finish t))) #+end_src

returns:

#+begin_src emacs-lisp ((... :immediate-finish t)) #+end_src

see the [[https://orgmode.org/manual/Template-elements.html#Template-elements][Org Mode Manual]] for a full list of additional options.

**** Custom data :PROPERTIES: :CUSTOM_ID: custom-data :END: 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. This makes a template's metadata accessible during capture. See [[#keyword-expansion][%{KEYWORD} Expansion]] for details on using that data.

The :custom keyword accepts a plist. doct copies the plist's values to the doct-custom plist. This is only necessary if you wish to use a keyword which doct already uses.

For example: #+begin_src emacs-lisp (doct '(("Music Gear" :keys "m" :file "" :custom (:keys "Moog")))) #+end_src

returns:

#+begin_src emacs-lisp (#1="m" #2="Music Gear" entry (file #3="") nil :doct (#2# :keys #1# :file #3# :custom #4=(:keys "Moog") :doct-custom #4#)))) #+end_src

**** %{KEYWORD} Expansion :PROPERTIES: :CUSTOM_ID: keyword-expansion :END: A declaration :template may include a keyword's value during capture. The syntax is similar to other, built-in "%-escapes". %{KEYWORD} will insert the value declared with :KEYWORD in the declaration.

For example, with:

#+begin_src emacs-lisp (doct '(("Parent" :keys "p" :file "" :template "* %{todo-state} %?" :children (("One" :keys "1" :todo-state "TODO") ("Two" :keys "2" :todo-state "IDEA"))))) #+end_src

Each child template has its :todo-state value expanded in the inherited :template.

Values should be strings, functions or nil.

#+begin_src emacs-lisp results raw (doct '(("%{string}" :keys "s" :type plain :file "" :string "string" :template "%{string}"))) #+end_src

Is replaced with:

#+begin_src emacs-lisp "string" #+end_src

#+begin_src emacs-lisp results raw (doct '(("%{fn}" :keys "f" :type plain :file "" :fn (lambda () "string returned from function") :template "%{fn}"))) #+end_src

Is replaced with:

#+begin_src emacs-lisp "string returned from function" #+end_src

#+begin_src emacs-lisp (doct '(("%{nil}" :keys "f" :type plain :file "" :nil nil :template "%{nil}"))) #+end_src

Is replaced with the empty string

#+begin_src emacs-lisp "" #+end_src

Custom keywords take precedence over other declaration keywords. For example, with:

#+begin_src emacs-lisp (doct '(("Music Gear" :keys "m" :file "" :type plain :custom (:keys "Moog") :template "%{keys}"))) #+end_src

The "Music Gear" template expands to "Moog" instead of "m". Nil values expand to an empty string.

**** Hooks Adding the following hook keywords in a declaration adds its value to the appropriate org-capture hook. The value may be a function or a variable.

  • :hook function ::

    • org-capture-mode-hook ::

      Runs FUNCTION when entering the org-capture-mode minor mode.

  • :prepare-finalize function ::

    • org-capture-prepare-finalize-hook ::

      Runs FUNCTION before the finalization starts. The capture buffer is current and narrowed.

  • :before-finalize function ::

    • org-capture-before-finalize-hook ::

      Runs FUNCTION right before a capture process finalizes. The capture buffer is still current and widened to the entire buffer.

  • :after-finalize function ::

    • org-capture-after-finalize-hook :: Runs FUNCTION right after a capture process finalizes. Suitable for window cleanup.

For example:

#+begin_src emacs-lisp (doct `(("example" :keys "e" :file "" :hook ,(defun my/fn () (ignore))))) #+end_src

runs my/fn during the org-capture-mode-hook when selecting the "example" template.

**** Contexts The :contexts keyword defines contextual rules for a template. Its value may be a single contextual rule or a list of rules. The following keywords are available to create contextual rules:

  • :in-buffer regexp :: Show template when REGEXP matches the current buffer's name. #+begin_src emacs-lisp :results scalar (doct '(("Only in scratch" :keys "n" :file "" :contexts (:in-buffer "^\scratch\$")))) #+end_src

  • :unless-buffer regexp :: Show template unless REGEXP matches the current buffer's name. #+begin_src emacs-lisp :results scalar (doct '(("Except in scratch" :keys "n" :file "" :contexts (:unless-buffer "^\scratch\$")))) #+end_src

  • :in-file regexp :: Show template when REGEXP matches the current buffer's file name. #+begin_src emacs-lisp :results scalar (doct '(("Only in work.org" :keys "n" :file "" :contexts (:in-file "work\.org$")))) #+end_src

  • :unless-file regexp :: Show template unless REGEXP matches the current buffer's file name. #+begin_src emacs-lisp :results scalar (doct '(("Except in work.org" :keys "n" :file "" :contexts (:unless-file "work\.org$")))) #+end_src

  • :in-mode regexp :: Show template when REGEXP matches the current buffer's major mode. #+begin_src emacs-lisp :results scalar (doct '(("Only in org-mode" :keys "n" :file "" :contexts (:in-mode "org-mode")))) #+end_src

  • :unless-mode regexp :: Show template unless REGEXP matches the current buffer's major mode. #+begin_src emacs-lisp :results scalar (doct '(("Except in org-mode" :keys "n" :file "" :contexts (:unless-mode "org-mode")))) #+end_src

  • :when condition :: Show template when CONDITION evaluates to a non-nil value. Condition may be a function or a single form. #+begin_src emacs-lisp :results scalar (doct '(("Show when my/predicate-p returns t" :keys "n" :file "" :contexts (:when my/predicate-p)))) #+end_src

#+begin_src emacs-lisp :results scalar (doct '(("1/3 chance of showing" :keys "n" :file "" :contexts (:when (= 2 (random 3)))))) #+end_src

  • :unless condition :: Show template when CONDITION evaluates to a nil value. Condition may be a function or a single form. #+begin_src emacs-lisp :results scalar (doct '(("Show when my/predicate-p returns nil" :keys "n" :file "" :contexts (:unless my/predicate-p)))) #+end_src

#+begin_src emacs-lisp :results scalar (doct '(("2/3 chance of showing" :keys "n" :file "" :contexts (:unless (= 2 (random 3)))))) #+end_src

  • :function function :: Show template when FUNCTION returns non-nil. The function is not passed any arguments. #+begin_src emacs-lisp :results scalar (doct '(("Between 9AM and 5PM" :keys "n" :file "" :contexts (:function (lambda () (<= 9 (string-to-number (format-time-string "%H")) 17))))))) #+end_src

Adding :keys to a rule does the same as above, but remaps the template's keys to the template with keys matching the :keys string. For example: #+begin_src emacs-lisp :results scalar (doct '(("In scratch remapped to t, else use original template" :keys "n" :file "" :contexts ((:unless-buffer "^\scratch\$" :keys "n") (:in-buffer "^\scratch\$" :keys "t"))))) #+end_src

The above rule keywords, spare :function, :when, and :unless may also take a list of strings for their values. #+begin_src emacs-lisp (doct '(("Only in org-mode or emacs-lisp-mode" :keys "n" :file "" :contexts (:in-mode ("org-mode" "emacs-lisp-mode"))))) #+end_src

**** Disabling Templates :PROPERTIES: :CUSTOM_ID: disabling-templates :END: Setting the :disabled keyword to t disables a template. The template's declaration is not error checked. This can be useful if you don't have the time to deal with an error right away. For example: #+begin_src emacs-lisp :results raw scalar (doct '((:group "All" :file "" :children ((:group "Enabled" :children (("One" :keys "1") ("Two" :keys "2") ("Three" :keys "3"))) (:group "Disabled" :disabled t :children (("Four" :keys 4) ("Five" :keys 5) ("Six" :keys 6))))))) #+end_src

returns:

#+begin_src emacs-lisp (("1" "One" entry (file "") nil) ("2" "Two" entry (file "") nil) ("3" "Three" entry (file "") nil)) #+end_src

Normally template "Four" would throw an error because its :keys are not a string.

**** Disabling Warnings The =:warn= keyword disables =doct='s warnings on a per-declaration basis. For example:

#+begin_src emacs-lisp (let ((doct-warnings t)) (doct '(("Ignore unbound symbol warnings" :keys "i" :warn (:not unbound) :file unbound-variable :function unbound-function) ("Warn here, though" :keys "w" :file unbound-variable :function unbound-function)))) #+end_src

For global control of warnings and an explanation of accepted values see =doct-warnings= in [[#custom-variables][Custom Variables]].

*** doct-add-to #+begin_src emacs-lisp (doct-add-to list declarations &optional append) #+end_src

Return a copy of =LIST= with converted =DECLARATIONS= added. If =APPEND= is non-nil, add to back of =LIST=. Otherwise, add to the front of =LIST=. =DECLARATIONS= are passed to =doct= and must be the same of the same form =doct= accepts.

e.g. #+begin_src emacs-lisp ;; `org-capture-templates' set earlier elsewhere...

(setq org-capture-templates (doct-add-to org-capture-templates '("example" :keys "e" ...) 'append)) #+end_src *** Custom Variables :PROPERTIES: :CUSTOM_ID: custom-variables :END: doct supports the following variables for customization:

  • doct-default-entry-type 'entry :: The default template entry type. It can be overridden on a per-declaration basis by using the :type keyword.

  • doct-after-conversion-functions :: Abnormal hook run after converting declarations to templates. Hook functions run with the list of templates as their only argument. The templates are not flattened at this point and are of the form: #+begin_src emacs-lisp (((parent) (child)...)...). #+end_src

  • doct-warnings :: When non-nil, doct will issue warnings. Valid values are:

    • t :: warn in all cases
    • nil :: do not warn Or a list containing any of the following symbols:
    • unbound :: warn when a symbol is unbound during conversion
    • template-keyword :: warn when %{KEYWORD} is not found on the declaration during conversion.
    • template-keyword-type :: warn when %{KEYWORD} expansion does not return a string.
    • template-entry-type :: warn when the expanded template string does not match the capture template's entry type
    • template-file :: warn when the :template-file's file is not found during conversion
    • option-type :: warn when additional options are not the proper type

    If the list's first element is the :not keyword, the list of warnings is disabled. It can be overridden on a per-declaration basis with the :warn keyword."

    For example: #+begin_src emacs-lisp (let ((doct-warnings t)) (doct '(("Ignore unbound symbol warnings" :keys "i" :warn (:not unbound) :file unbound-variable :function unbound-function) ("Warn here, though" :keys "w" :file unbound-variable :function unbound-function)))) #+end_src

*** Contributing

Pull/feature requests, code review, angry comments are all welcome.

Please add a test to the test suite if you introduce any changes.

Thanks, nv

LocalWords: DOCT MELPA init doct txt plist unintern nv tl dr semver

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].