|
|
|
@ -1,11 +1,27 @@ |
|
|
|
|
[[file:https://cdn.rawgit.com/syl20bnr/spacemacs/442d025779da2f62fc86c2082703697714db6514/assets/spacemacs-badge.svg]] |
|
|
|
|
|
|
|
|
|
* Features Tree |
|
|
|
|
* Table of content :TOC_5_gh:noexport: |
|
|
|
|
- [[#tree-to-dot][Tree to dot]] |
|
|
|
|
- [[#presentation][Presentation]] |
|
|
|
|
- [[#usage][Usage]] |
|
|
|
|
- [[#tldr][TL;DR]] |
|
|
|
|
- [[#elisp][Elisp]] |
|
|
|
|
- [[#scheme][Scheme]] |
|
|
|
|
- [[#more-details][More details]] |
|
|
|
|
- [[#elisp-1][Elisp]] |
|
|
|
|
- [[#scheme-1][Scheme]] |
|
|
|
|
- [[#my-elements-are-not-alignedcentered-what-do][My elements are not aligned/centered, what do?]] |
|
|
|
|
- [[#how-can-i-do-that-on-windows][How can I do that on Windows?]] |
|
|
|
|
- [[#scheme-2][Scheme]] |
|
|
|
|
- [[#elisp-2][Elisp]] |
|
|
|
|
- [[#license][License]] |
|
|
|
|
|
|
|
|
|
* Tree to dot |
|
|
|
|
|
|
|
|
|
** Presentation |
|
|
|
|
|
|
|
|
|
*Features Tree* is a small utility for linguists and especially conlangers |
|
|
|
|
that allows them to declare trees with any number of children per node. I |
|
|
|
|
*Tree to dot* is a small utility for linguists and especially conlangers that |
|
|
|
|
allows them to declare trees with any number of children per node. I |
|
|
|
|
especially made it with the option in mind to make feature contrastive trees |
|
|
|
|
as presentented by Joseph Windsor in his talk during the /Language Creation |
|
|
|
|
Conference 8/, with examples below. |
|
|
|
@ -18,163 +34,213 @@ |
|
|
|
|
|
|
|
|
|
*** TL;DR |
|
|
|
|
|
|
|
|
|
In your *NIX terminal, clone the project, edit the example trees or create a |
|
|
|
|
new one, and execute this: |
|
|
|
|
#+BEGIN_SRC sh |
|
|
|
|
cd features-tree |
|
|
|
|
chicken-csc features-tree.scm # Compile the .scm file |
|
|
|
|
./features-tree | dot -Tpng -o output.png # for PNG output |
|
|
|
|
./features-tree | dot -Tsvg -o output.svg # for SVG output |
|
|
|
|
#+END_SRC |
|
|
|
|
**** Elisp |
|
|
|
|
|
|
|
|
|
Load this source code within Emacs, either in a ~emacs-lisp-mode~ buffer or |
|
|
|
|
in a source block in your ~org-mode~ buffer. Create trees, pass them as |
|
|
|
|
arguments to ~tree-to-dot~, execute, and voilà. |
|
|
|
|
|
|
|
|
|
**** Scheme |
|
|
|
|
|
|
|
|
|
In your *NIX terminal, clone the project, edit the example trees or create |
|
|
|
|
a new one, and execute this: |
|
|
|
|
#+BEGIN_SRC sh |
|
|
|
|
cd features-tree |
|
|
|
|
chicken-csc features-tree.scm # Compile the .scm file |
|
|
|
|
./features-tree | dot -Tpng -o output.png # for PNG output |
|
|
|
|
./features-tree | dot -Tsvg -o output.svg # for SVG output |
|
|
|
|
#+END_SRC |
|
|
|
|
|
|
|
|
|
*** More details |
|
|
|
|
|
|
|
|
|
For now, the workflow is not the best, as you have to edit yourself the |
|
|
|
|
source code and re-compile it each time you edit your own tree. |
|
|
|
|
|
|
|
|
|
You will have to declare a Scheme list containing your tree, and your |
|
|
|
|
typical node should be declared like so: |
|
|
|
|
#+BEGIN_SRC scheme |
|
|
|
|
("text" (child1) (child2) ...) |
|
|
|
|
#+END_SRC |
|
|
|
|
Each child is itself a tree that should follow the same type of declaration, |
|
|
|
|
with as many child as you like per node –I discourage you to have more than |
|
|
|
|
nine children though, otherwise it might break the output. If a node does |
|
|
|
|
not have any child, it should be declared like so: |
|
|
|
|
#+BEGIN_SRC scheme |
|
|
|
|
("text") |
|
|
|
|
#+END_SRC |
|
|
|
|
As an example, here is the tree that was used to declare the first example |
|
|
|
|
image: |
|
|
|
|
#+BEGIN_SRC scheme |
|
|
|
|
(define vowels |
|
|
|
|
'("[vowel]" |
|
|
|
|
("[back]" |
|
|
|
|
("[tense]" |
|
|
|
|
("[high]" ("ü")) |
|
|
|
|
("{high}" ("ö"))) |
|
|
|
|
("{tense}" |
|
|
|
|
("[high]" ("u")) |
|
|
|
|
("{high}" ("o")))) |
|
|
|
|
("{back}" |
|
|
|
|
("[tense]" |
|
|
|
|
("[high]" ("y")) |
|
|
|
|
("{high}" ("ë"))) |
|
|
|
|
("{tense}" |
|
|
|
|
("[high]" ("i")) |
|
|
|
|
("{high}" ("e")))))) |
|
|
|
|
#+END_SRC |
|
|
|
|
And here is the source code of the second example image: |
|
|
|
|
#+BEGIN_SRC scheme |
|
|
|
|
(define syntax-tree '("S" |
|
|
|
|
("Obl") |
|
|
|
|
("S'" |
|
|
|
|
("NPerg" |
|
|
|
|
("NP")) |
|
|
|
|
("VP" |
|
|
|
|
("NPdat" |
|
|
|
|
**** Elisp |
|
|
|
|
|
|
|
|
|
The Elisp code was written with the intent of being used from org-mode in |
|
|
|
|
order to create inline images out of code. Put that source code in a code |
|
|
|
|
block in org-mode, and declare it as a noweb block. |
|
|
|
|
#+BEGIN_SRC org |
|
|
|
|
,#+NAME: process-tree |
|
|
|
|
,#+BEGIN_SRC emacs-lisp :exports none :noweb yes |
|
|
|
|
Code here! |
|
|
|
|
,#+END_SRC |
|
|
|
|
#+END_SRC |
|
|
|
|
Don’t forget to name your source blocks, it will be important for the noweb |
|
|
|
|
part later. |
|
|
|
|
|
|
|
|
|
Then, you can declare later a beautiful tree in another code block, like |
|
|
|
|
so, and call your ~tree-to-dot~ function on it: |
|
|
|
|
#+BEGIN_SRC org |
|
|
|
|
,#+NAME: my-tree |
|
|
|
|
,#+BEGIN_SRC emacs-lisp :noweb yes :exports none |
|
|
|
|
(defvar mytree |
|
|
|
|
'("Tree" |
|
|
|
|
("First child" |
|
|
|
|
("First child’s child")) |
|
|
|
|
("Second child" |
|
|
|
|
("Second child’s first child") |
|
|
|
|
("Second child’s second child")))) |
|
|
|
|
,#+END_SRC |
|
|
|
|
#+END_SRC |
|
|
|
|
|
|
|
|
|
You can now finally create one last code block in order to get your image: |
|
|
|
|
#+BEGIN_SRC org |
|
|
|
|
,#+BEGIN_SRC dot :file whatever.png :var input=my-tree :exports results |
|
|
|
|
$input |
|
|
|
|
,#+END_SRC |
|
|
|
|
#+END_SRC |
|
|
|
|
You can now export this last code block only to get your image. It will be |
|
|
|
|
automatically evaluated when you export your org buffer, but you can also |
|
|
|
|
manually trigger the evaluation by typing ~C-c C-c~ with your cursor on |
|
|
|
|
this last code block. Be sure to have enabled the dot language in babel and |
|
|
|
|
to have configured it properly ([[https://www.orgmode.org/worg/org-contrib/babel/languages/ob-doc-dot.html][this]] might help). |
|
|
|
|
|
|
|
|
|
**** Scheme |
|
|
|
|
|
|
|
|
|
For now, the workflow is not the best, as you have to edit yourself the |
|
|
|
|
source code and re-compile it each time you edit your own tree. |
|
|
|
|
|
|
|
|
|
You will have to declare a Scheme list containing your tree, and your |
|
|
|
|
typical node should be declared like so: |
|
|
|
|
#+BEGIN_SRC scheme |
|
|
|
|
("text" (child1) (child2) ...) |
|
|
|
|
#+END_SRC |
|
|
|
|
Each child is itself a tree that should follow the same type of |
|
|
|
|
declaration, with as many child as you like per node –I discourage you to |
|
|
|
|
have more than nine children though, otherwise it might break the output. |
|
|
|
|
If a node does not have any child, it should be declared like so: |
|
|
|
|
#+BEGIN_SRC scheme |
|
|
|
|
("text") |
|
|
|
|
#+END_SRC |
|
|
|
|
As an example, here is the tree that was used to declare the first example |
|
|
|
|
image: |
|
|
|
|
#+BEGIN_SRC scheme |
|
|
|
|
(define vowels |
|
|
|
|
'("[vowel]" |
|
|
|
|
("[back]" |
|
|
|
|
("[tense]" |
|
|
|
|
("[high]" ("ü")) |
|
|
|
|
("{high}" ("ö"))) |
|
|
|
|
("{tense}" |
|
|
|
|
("[high]" ("u")) |
|
|
|
|
("{high}" ("o")))) |
|
|
|
|
("{back}" |
|
|
|
|
("[tense]" |
|
|
|
|
("[high]" ("y")) |
|
|
|
|
("{high}" ("ë"))) |
|
|
|
|
("{tense}" |
|
|
|
|
("[high]" ("i")) |
|
|
|
|
("{high}" ("e")))))) |
|
|
|
|
#+END_SRC |
|
|
|
|
And here is the source code of the second example image: |
|
|
|
|
#+BEGIN_SRC scheme |
|
|
|
|
(define syntax-tree '("S" |
|
|
|
|
("Obl") |
|
|
|
|
("S'" |
|
|
|
|
("NPerg" |
|
|
|
|
("NP")) |
|
|
|
|
("VP'" |
|
|
|
|
("NPabs" |
|
|
|
|
("NP" |
|
|
|
|
("S") |
|
|
|
|
("NP'" |
|
|
|
|
("Adj") |
|
|
|
|
("N")))) |
|
|
|
|
("V'" |
|
|
|
|
("Mood") |
|
|
|
|
("Tense") |
|
|
|
|
("V") |
|
|
|
|
("Neg"))))))) |
|
|
|
|
#+END_SRC |
|
|
|
|
|
|
|
|
|
Once you’ve declared the tree you want to get, modify the last line of the |
|
|
|
|
source code =(tree-to-dot ...)= by replacing the default argument with the |
|
|
|
|
name of your tree. For the first example, we would call |
|
|
|
|
=(tree-to-dot vowels)=, while for the second we would call |
|
|
|
|
=(tree-to-dot syntax-tree)=. |
|
|
|
|
|
|
|
|
|
*Only one =(tree-to-dot)= call can be done at once, else what follows might |
|
|
|
|
break!* |
|
|
|
|
|
|
|
|
|
Once you’ve done that, compile your file! I personally use [[https://call-cc.org/][Chicken]] as my |
|
|
|
|
Scheme compiler, but if you already have another, you can use your own. Just |
|
|
|
|
replace my calls to =chicken-csc= by your own compiler’s command. Also, be |
|
|
|
|
aware that I use =chicken-csc= as the command for che Chicken compiler, but |
|
|
|
|
if you also use Chicken, you might have to call =csc= instead (this might |
|
|
|
|
mean you have an older version than the one I use). |
|
|
|
|
|
|
|
|
|
Now that you’ve compiled your file, you will have to execute it. If your |
|
|
|
|
edits were alright, you should have some text output that looks like this, |
|
|
|
|
except that it will be way more compact. |
|
|
|
|
#+BEGIN_SRC dot |
|
|
|
|
graph{ |
|
|
|
|
node[shape=plaintext]; |
|
|
|
|
graph[bgcolor="transparent"]; |
|
|
|
|
0[label="[vowel]"]; |
|
|
|
|
1[label="[back]"]; |
|
|
|
|
0 -- 1; |
|
|
|
|
11[label="[tense]"]; |
|
|
|
|
1 -- 11; |
|
|
|
|
111[label="[high]"]; |
|
|
|
|
11 -- 111; |
|
|
|
|
1111[label="ü"]; |
|
|
|
|
111 -- 1111; |
|
|
|
|
112[label="{high}"]; |
|
|
|
|
11 -- 112; |
|
|
|
|
1121[label="ö"]; |
|
|
|
|
112 -- 1121; |
|
|
|
|
12[label="{tense}"]; |
|
|
|
|
1 -- 12; |
|
|
|
|
121[label="[high]"]; |
|
|
|
|
12 -- 121; |
|
|
|
|
1211[label="u"]; |
|
|
|
|
121 -- 1211; |
|
|
|
|
122[label="{high}"]; |
|
|
|
|
12 -- 122; |
|
|
|
|
1221[label="o"]; |
|
|
|
|
122 -- 1221; |
|
|
|
|
2[label="{back}"]; |
|
|
|
|
0 -- 2; |
|
|
|
|
21[label="[tense]"]; |
|
|
|
|
2 -- 21; |
|
|
|
|
211[label="[high]"]; |
|
|
|
|
21 -- 211; |
|
|
|
|
2111[label="y"]; |
|
|
|
|
211 -- 2111; |
|
|
|
|
212[label="{high}"]; |
|
|
|
|
21 -- 212; |
|
|
|
|
2121[label="ë"]; |
|
|
|
|
212 -- 2121; |
|
|
|
|
22[label="{tense}"]; |
|
|
|
|
2 -- 22; |
|
|
|
|
221[label="[high]"]; |
|
|
|
|
22 -- 221; |
|
|
|
|
2211[label="i"]; |
|
|
|
|
221 -- 2211; |
|
|
|
|
222[label="{high}"]; |
|
|
|
|
22 -- 222; |
|
|
|
|
2221[label="e"]; |
|
|
|
|
222 -- 2221; |
|
|
|
|
} |
|
|
|
|
#+END_SRC |
|
|
|
|
If you get some errors, then you fucked up somewhere in your tree, probably |
|
|
|
|
missing some parenthesis or you forgot to add the ='= before the first |
|
|
|
|
parenthesis after the name of your tree. Go back to your source file and fix |
|
|
|
|
that. Also, it might be easier to edit the file if you have a decent text |
|
|
|
|
editor, I’d recommend using something along the lines of VS Code, Atom or |
|
|
|
|
Brackets, or even Emacs if you are not afraid by steep –but extremely |
|
|
|
|
rewarding– learning curves. |
|
|
|
|
|
|
|
|
|
Now, you need to have [[https://graphviz.org/][Graphviz]]’s dot tool installed to generate images. In |
|
|
|
|
your terminal, either redirect the output of your newly compiled program |
|
|
|
|
like so: |
|
|
|
|
#+BEGIN_SRC sh |
|
|
|
|
./features-tree | dot -Tpng -o output.png |
|
|
|
|
#+END_SRC |
|
|
|
|
Or simply copy and paste the output in a separate file, then only run the |
|
|
|
|
dot part of the above command. You’ve got an ~output.png~ file containing |
|
|
|
|
your tree now! |
|
|
|
|
("VP" |
|
|
|
|
("NPdat" |
|
|
|
|
("NP")) |
|
|
|
|
("VP'" |
|
|
|
|
("NPabs" |
|
|
|
|
("NP" |
|
|
|
|
("S") |
|
|
|
|
("NP'" |
|
|
|
|
("Adj") |
|
|
|
|
("N")))) |
|
|
|
|
("V'" |
|
|
|
|
("Mood") |
|
|
|
|
("Tense") |
|
|
|
|
("V") |
|
|
|
|
("Neg"))))))) |
|
|
|
|
#+END_SRC |
|
|
|
|
|
|
|
|
|
Once you’ve declared the tree you want to get, modify the last line of the |
|
|
|
|
source code =(tree-to-dot ...)= by replacing the default argument with the |
|
|
|
|
name of your tree. For the first example, we would call =(tree-to-dot |
|
|
|
|
vowels)=, while for the second we would call =(tree-to-dot syntax-tree)=. |
|
|
|
|
|
|
|
|
|
*Only one =(tree-to-dot)= call can be done at once, else what follows might |
|
|
|
|
break!* |
|
|
|
|
|
|
|
|
|
Once you’ve done that, compile your file! I personally use [[https://call-cc.org/][Chicken]] as my |
|
|
|
|
Scheme compiler, but if you already have another, you can use your own. |
|
|
|
|
Just replace my calls to =chicken-csc= by your own compiler’s command. |
|
|
|
|
Also, be aware that I use =chicken-csc= as the command for che Chicken |
|
|
|
|
compiler, but if you also use Chicken, you might have to call =csc= instead |
|
|
|
|
(this might mean you have an older version than the one I use). |
|
|
|
|
|
|
|
|
|
Now that you’ve compiled your file, you will have to execute it. If your |
|
|
|
|
edits were alright, you should have some text output that looks like this, |
|
|
|
|
except that it will be way more compact. |
|
|
|
|
#+BEGIN_SRC dot |
|
|
|
|
graph{ |
|
|
|
|
node[shape=plaintext]; |
|
|
|
|
graph[bgcolor="transparent"]; |
|
|
|
|
0[label="[vowel]"]; |
|
|
|
|
1[label="[back]"]; |
|
|
|
|
0 -- 1; |
|
|
|
|
11[label="[tense]"]; |
|
|
|
|
1 -- 11; |
|
|
|
|
111[label="[high]"]; |
|
|
|
|
11 -- 111; |
|
|
|
|
1111[label="ü"]; |
|
|
|
|
111 -- 1111; |
|
|
|
|
112[label="{high}"]; |
|
|
|
|
11 -- 112; |
|
|
|
|
1121[label="ö"]; |
|
|
|
|
112 -- 1121; |
|
|
|
|
12[label="{tense}"]; |
|
|
|
|
1 -- 12; |
|
|
|
|
121[label="[high]"]; |
|
|
|
|
12 -- 121; |
|
|
|
|
1211[label="u"]; |
|
|
|
|
121 -- 1211; |
|
|
|
|
122[label="{high}"]; |
|
|
|
|
12 -- 122; |
|
|
|
|
1221[label="o"]; |
|
|
|
|
122 -- 1221; |
|
|
|
|
2[label="{back}"]; |
|
|
|
|
0 -- 2; |
|
|
|
|
21[label="[tense]"]; |
|
|
|
|
2 -- 21; |
|
|
|
|
211[label="[high]"]; |
|
|
|
|
21 -- 211; |
|
|
|
|
2111[label="y"]; |
|
|
|
|
211 -- 2111; |
|
|
|
|
212[label="{high}"]; |
|
|
|
|
21 -- 212; |
|
|
|
|
2121[label="ë"]; |
|
|
|
|
212 -- 2121; |
|
|
|
|
22[label="{tense}"]; |
|
|
|
|
2 -- 22; |
|
|
|
|
221[label="[high]"]; |
|
|
|
|
22 -- 221; |
|
|
|
|
2211[label="i"]; |
|
|
|
|
221 -- 2211; |
|
|
|
|
222[label="{high}"]; |
|
|
|
|
22 -- 222; |
|
|
|
|
2221[label="e"]; |
|
|
|
|
222 -- 2221; |
|
|
|
|
} |
|
|
|
|
#+END_SRC |
|
|
|
|
If you get some errors, then you fucked up somewhere in your tree, probably |
|
|
|
|
missing some parenthesis or you forgot to add the ='= before the first |
|
|
|
|
parenthesis after the name of your tree. Go back to your source file and |
|
|
|
|
fix that. Also, it might be easier to edit the file if you have a decent |
|
|
|
|
text editor, I’d recommend using something along the lines of VS Code, Atom |
|
|
|
|
or Brackets, or even Emacs if you are not afraid by steep –but extremely |
|
|
|
|
rewarding– learning curves. |
|
|
|
|
|
|
|
|
|
Now, you need to have [[https://graphviz.org/][Graphviz]]’s dot tool installed to generate images. In |
|
|
|
|
your terminal, either redirect the output of your newly compiled program |
|
|
|
|
like so: |
|
|
|
|
#+BEGIN_SRC sh |
|
|
|
|
./features-tree | dot -Tpng -o output.png |
|
|
|
|
#+END_SRC |
|
|
|
|
Or simply copy and paste the output in a separate file, then only run the |
|
|
|
|
dot part of the above command. You’ve got an ~output.png~ file containing |
|
|
|
|
your tree now! |
|
|
|
|
|
|
|
|
|
*** My elements are not aligned/centered, what do? |
|
|
|
|
|
|
|
|
@ -184,10 +250,17 @@ |
|
|
|
|
|
|
|
|
|
*** How can I do that on Windows? |
|
|
|
|
|
|
|
|
|
IDK. Get a UNIX terminal (like the Linux subsystem, Putty(?) or Cygwin) and |
|
|
|
|
apply what has been said before, maybe. If you have a better explanation, |
|
|
|
|
you are more than welcome to either send it with a new issue or a pull |
|
|
|
|
request. |
|
|
|
|
**** Scheme |
|
|
|
|
|
|
|
|
|
IDK. Get a UNIX terminal (like the Linux subsystem, Putty(?) or Cygwin) and |
|
|
|
|
apply what has been said before, maybe. If you have a better explanation, |
|
|
|
|
you are more than welcome to either send it with a new issue or a pull |
|
|
|
|
request. |
|
|
|
|
|
|
|
|
|
**** Elisp |
|
|
|
|
|
|
|
|
|
This should work properly with Emacs on Windows, provided you’ve configured |
|
|
|
|
properly org-babel. I haven’t tested it though. |
|
|
|
|
|
|
|
|
|
* License |
|
|
|
|
|
|
|
|
|