Skip to content

gmoutso/org-annotate-code

Repository files navigation

Description

org-annotate-code allows you to annotate files in a separate org-mode file. The annotations created are nested headings with the annotation at the deepest node. By default, the first level is the filename and the second is the line number where the annotation is made. However, other annotations are possible according to the annotator that is used. For instance, the second level can be a word in the file at a given position, see org-annotate-word, or for python files the second level can be the python function name where the annotation was made, see org-annotate-python. The headlines of the trees in the org-file can be changed, and each heading in the annotation is identified by its CUSTOM_ID. In the annotation file, you can visit the annotated file by C-c C-o on the annotation’s heading. Conversely, if you trigger to re-annotate the same section in the file, you will be adding to the already created heading.

The main way to annotate is by using org-mode’s capture function. This package defines at the highest level some capture finding functions that are used in org-capture~templates. Locally for each file you can specify:

  • in which file the annotations are stored
  • if there is a custom top-level heading always inserted
  • which annotator is used with the generic capure function

You can also specify which annotator to be used by default for each major-mode. If neither a local file annotator is defined nor a major-mode associated annotater, the default annotator will be used.

Use

To start using, simply load it

(add-to-list 'load-path "~/path/to/org-annotate-code")
(require 'org-annotate-code)

The annotation can be made using a capture template with the function org-annotate-code-capture-finding-location

("a" "Annotate" plain #'org-annotate-code-capture-finding-location "%?")

Without further configuration, this template will use the default annotator.

There are annotators for specific modes. For instance, to annotate python files

(require 'org-annotate-python)

This will associate all python files with the python annotator when using the generic capture template. The python annotation will make specific links, eg to the python function that is annotated. Registering for a major mode is done by modifying the alist org-annotate-code-info-alist, eg

(add-to-list 'org-annotate-code-info-alist (cons 'python-mode 'org-annotate-python-info-at-point))

will annotate python files with the python annotator. This association is already made when you load org-annotate-python. Not all annotators will register with modes like this.

If you want to use word annotations by default then

(setq org-annotate-code-info-default 'org-annotate-word-info-at-point)

will make annotations that point to the annotated word at (or near) a position in the file.

Functions such as org-annotate-python-info-at-point or org-annotate-word-info-at-point are at the core of what is an annotator. You can also override the default annotator with the local variable org-annotate-code-info-override. For this, you will need to know the annotator’s function name, eg in a given buffer

(setq org-annotate-code-info-override 'org-annotate-word-info-at-point)

this becomes a local buffer variable. Setting dir-locals.el can make use of different annotators per file.

Finally, you can remove python from the alist above and use a separate special template for python in the org-capture~templates, eg

("p" "Python" plain #'org-annotate-python-capture-finding-location "%?")

For this, you will need to know the name of the capture finding location. For each annotator there is one annotator function like org-annotate-python-info-at-point and one special capture finding function like org-annotate-python-capture-finding-location. The first is used to modify the generic template, the latter is used in a special org-capture template.

One can insert a top-level heading, either globally or per file, by setting org-annotate-code-heading0. Beyond this level, typically the top-level heading is the filename, but ultimately this depends on the annotator used. One can also customize the annotation file locally by setting org-annotation-code-org-file. So for instance, each project can save annotations under a different top-level heading in the same file, or in separate files per project, or any combination defined in dir-locals.el.

An annotator that annotates the word at point is defined in org-annotate-word. This creates links that point to a word at a position in a file, and by default clicking on the link takes one to the nearest word at that position. If the minor mode org-annotate-live-mode is loaded while the annotated file is edited, it will change the CUSTOM_ID so that the positions are corrected. This is work in progress.

There can be arbitrary nodes of the annotation tree, depending on the annotator used. The annotator functions return a list of nodes and each node is a plist with keys :id and :heading and possibly :properties. The top-level heading is inserted after these annotators have done their work. It is then possible to extend org-annotate-code by writing such functions.

Once the annotation is created, the custom id links should not be changed but the headings can change at will. The whole tree can be moved and/or demoted somewhere else in the annotation file. If an annotation at the same place is triggered, there are two options to search for the annotation tree in the org file:

  • a bottom-top search that places importance on the last custom id to exist
  • a top-bottom search that places importance on the whole hierarchy of custom ids to exist

Either the moved entry is found by its id or a new hierarchy of items will be created. To customize which of these two methods is used, see org-annotate-code-search-annotation-method.

Annotators

Line numbers

Creates a tree structure like file name -> line number. This can be achieved out of the box with org-mode. It is loaded by default and is the default annotator.

python

(require 'org-annotate-python)

An annotation might look like the nested headings file name -> function definition -> local variable or filename -> global variable. Links are possible by defining a new link type, eg [[pydef:filename.py::newfun.newsubfun.localvariable]]. Clicking on the link will try to find the definition in nested python blocks.

When creating an annotation, the user can select what is to be annotated, eg newfun, newfun.newsubfun or newfun.newsubfun.localvariable. If the user chooses to annotate newfun.newsubfun then the annotation will have hierarchy filename.py -> newfun -> newfun.newsubfun. One can customize these settings by changing org-annotate-python-squash-annotation-level and org-annotate-python-squash-candidates-level.

The first level heading is a filename. It is possible to use relative paths using projectile. Filename headings are dotted by default as in python modules, but this can be changed.

dired

An annotator function is register to dired buffers when loading

(require 'org-annotate-dired)

It allows to annotate the file at point in dired. The annotations will still be in org-annotate-code-org-file and under the top-level heading if set.

word

To use, load

(require 'org-annotate-word)

This creates a link like [[word:filename::position::word]] that searches for the word near a line number in a file. It will not register with any modes by default.

As it stands, the links will quickly become stale as the file is editted. This annotator will keep track of word position changes if the text is changed while org-annotate-live-mode minor mode is loaded. It will change the org-file accordingly each time:

  • The file is saved
  • The user calls org-annotate-live-sync-register
  • A new annotation is made

However, if you use the live mode, link ids will be renamed to stale if the file changed while org-annotate-live-mode was not loaded. The live mode is still experimental. There is currently the option to use file hashes to invalidate links to stale or a strict search for the word at the link’s position. Future word might feature using git.

You can also checkout annotation-mode, a maturer project, for live changing the line numbers as text is edited.

index

To start using

(require 'org-annotate-index)

Allows adding the file name, either the current buffer or the file pointed at in dired, in an index.org file in the same directory as the file. That is org-annotate-code-org-file or the top-level heading is not used here.

The annotator function is org-annotate-code-info-at-point-index but it shouldn’t be used. This does not register an annotator with the org-annotate-code-info-alist. One would add org-annotate-index-capture-finding-location in a sepratate capure template, as in

("i" "Insert file to index" plain #'org-annotate-index-capture-finding-location "%?")

You can then start building an index with descriptions of your files in each directory.

projects

To start using

(require 'org-annotate-index)

This will add hierarchical nodes based on the folders and subfolders relative to a projectile root. Besides a custom id that is used for identifying the nodes, a DIR property is also set so that you can use org-attach. To use it with org-capture add this to the templates

("f" "Insert file to index" plain #'org-annotate-projects-capture-finding-location "%?")

Alternatively, you can use org-annotate-projects-create. The folders are saved by default in a single projects.org in the root folder, which you can visit with org-annotate-projects-visit-org-file.

Similar Packages

If you know of similar packages, please let me know

  • org-annotate-file is similar, but org-annotate-code is presently configurable
  • annotation-mode is a useful package that annotates non-destructively files.

About

Annotate files non-destructively with orgmode

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published