Picaud Vincent
Picaud Vincent

Reputation: 10982

org-mode, how to automatically generate nice file hierarchy trees with well-formed Org links

When working with Org-Mode, I am looking for a solution to automatically generate tree of well-formed org-mode links.

For instance, to create links to all c++ files under a directory, I want something like:

enter image description here


Update: I just tried @DamianChrzanowski suggestion, the org-fstree package. However I am a little bit disappointed by the results:

enter image description here

The html export result is even worst:

enter image description here

My conclusion is that package does not fulfil my needs. Anyway, thanks to @DamianChrzanowski for his answer.

Upvotes: 4

Views: 2436

Answers (3)

vv111y
vv111y

Reputation: 13

I just tried org-fs-tree and it seems to do the job well. It's a newer package, looks like org-fstree is orphaned.

Upvotes: 1

Picaud Vincent
Picaud Vincent

Reputation: 10982

With the linux tree command installed I came with the following script that fulfils all my needs:

#+NAME: createTree
#+BEGIN_SRC sh :results drawer :var toInclude="*.org" :var toExclude="" :var directory="./" :var createLink="true" :exports none
set -e
buffer=$(mktemp /tmp/buffer.XXXXXXXXX)
current_directory=$(pwd)
cd $(eval echo "$directory")
tree -a -P "$toInclude" -I "$toExclude" -if --noreport  --prune \
    | sed "s/.//"  | sed "s/^\///"  > "$buffer"

if [ $(grep --regexp="$" --count "$buffer") -eq 0 ]; then
    echo "**ERROR empty list**"
else
    for f in $(cat "$buffer")
    do 
    filename=$(basename $f)
    ext="${filename##*.}"
    baseFilename="${filename%.*}"
    if [ -f $f ]; then
        # removes org extension (only)
        if [ "$ext" = "org" ]; then
        filename="$baseFilename"
        fi
        # creates org link (or not)
        if [ "$createLink" = true ]; then 
        echo "$(echo "$f" | tr -cd / | tr / \\t)+ [[file:"$directory/$f"][$filename]]"
        else
        echo "$(echo "$f" | tr -cd / | tr / \\t)+ $filename"
        fi
    else
        echo  "$(echo "$f" | tr -cd / | tr / \\t)+ $filename/"
    fi
    done
fi
rm "$buffer"
cd "$current_directory"
#+END_SRC

If you want to create a file tree of your C++ code, simply use something like:

#+CALL: createTree(toInclude="*.[hc]pp",toExclude="*test*",directory="~/MyProject")

Also, note that you can use it as an alternative to sitemap when you export/publish your org-mode documents. Simply use:

* My site content

#+CALL: createTree(toInclude="*.org",toExclude="Setup")

The previous #+CALL commands will generate tree like the one I posted in my question. After Org HTML export, you will get something like: enter image description here


The command arguments/options are:

  • toInclude="..." : pattern to include
  • toExclude="..." : pattern to exclude
  • directory="..." : directory
  • createLink="true" or "false" : if false the tree is created without links

Note 1: you can store the script in any .org file and load it thanks to Library-of-Babel :

In your init.el file:

(org-babel-lob-ingest "~/path/to/your/scripts.org")

Note 2: I answered my own question, but I am still open to a pure Emacs-Lisp solution.

Upvotes: 5

Damian Chrzanowski
Damian Chrzanowski

Reputation: 479

There usually is a package :-) org-fstree

Upvotes: 1

Related Questions