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