4

So I'm making a website using an org document and tangling.

I've created the basic structure of the site using

* file coolsite.org

#+BEGIN_SRC sh
rails new coolapp
#+END_SRC

This creates a app/views/layouts/appication.html.erb file, with basics like a head tag, body tag, html tag, etc. If I wanted to add for example a <meta name="keywords" content="HTML,CSS,XML,JavaScript"> tag, I would copy that code in to an org src block, and add my new tag.

#+BEGIN_SRC html :tangle app/views/layouts/application.html.erb                                                  
<!DOCTYPE html>                                                                                                  
<html>                                                                                                           
  <head>                                                                                                         
    <title>Abc</title>
    <meta name="keywords" content="HTML,CSS,XML,JavaScript">                                                                                      
    <%= csrf_meta_tags %>                                                                                        
  </head>                                                                                                        
  <body>                                                                                                         
    <%= render 'layouts/navigation' %>                                                                           
    <%= yield %>                                                                                                 
    <%= render 'layouts/footer' %>                                                                               
  </body>                                                                                                        
</html>                                                                                                          
#+END_SRC 

So from the examples I've seen on the web, with literate programming, org files are ordered like a diary. Things are usually added to the end of the org file.

So let's say 1 week after writing the above tangle block, I need to add another meta tag to the file, in this case an author meta tag: <meta name="author" content="John Doe">

Do I: Go back and revise the old tangle block
or
create a new block with the revised code?

If I choose the latter, an interesting situation can arise in the long run where a single org file has multiple :tangle blocks that output to the same file. After the tangling, which one is left? is it the src block that appeared later-most in the org file ....

Note: The site is "generated" by doing C-c C-v t (org-babel-tangle)

4 Answers 4

6

For literate programming, revise the existing tangle block and rely on your version control system to maintain the history.

The examples you're referring to sound more like engineering notebooks / journals where the author is keeping a record of activities performed. While I highly recommend keeping an engineering notebook, keeping a lot of dead code around is not appropriate for literate programming.

2

Short Answer - Update the original code block and tangle again.

Adding the same :tangle header to separate code blocks will concatenate the code when tangling the entire buffer with C-c C-v t but will only tangle the current code block into the file if C-u C-c C-v t is used. This behavior can be confusing when tangling.

In your use case, you created a document that is self contained so I recommend updating the original code block for simplicity.

Long Answer

  1. Update the original code block to use :noweb yes header.
  2. Add or update sections in org document to improve human understanding about your coolapp application.
  3. Add noweb syntax to your original code block, e.g <<coolapp-meta-tags()>>
  4. Tangle the entire buffer with C-c C-v t.

For example:

* Rails coolapp Project

  This is the Rails coolapp documentation

  # Used command to create project

  #+BEGIN_SRC sh :eval never :exports none
    rails new coolapp
  #+END_SRC

** File [[file:app/views/layouts/application.html.erb][application.html.erb]]

   #+BEGIN_SRC html :tangle app/views/layouts/application.html.erb :noweb yes :exports none                                                
   <!DOCTYPE html>                                                                                                  
   <html>                                                                                                           
     <head>                                                                                                         
       <title>Abc</title>
       <<coolapp-meta-tags()>>                                                                                      
       <%= csrf_meta_tags %>                                                                                        
     </head>                                                                                                        
     <body>                                                                                                         
       <%= render 'layouts/navigation' %>                                                                           
       <%= yield %>                                                                                                 
       <%= render 'layouts/footer' %>                                                                               
     </body>                                                                                                        
     </html>                                                                                                          
   #+END_SRC 

*** Meta Tags

    # Just update the table and tangle the file

    #+NAME: coolapp-meta-tags-table
    | Meta-Tag-Name | Meta-Tag-Content        |
    |---------------+-------------------------|
    | author        | John Doe                |
    | keywords      | HTML,CSS,XML,JavaScript |

    #+NAME: coolapp-meta-tags
    #+BEGIN_SRC ruby :var metatags=coolapp-meta-tags-table :exports none
      metatags.map do |d|
        %Q'<meta name="#{d[0]}" content="#{d[1]}">'
      end.join("\n")
    #+END_SRC

    #+RESULTS: coolapp-meta-tags
    : <meta name="author" content="John Doe">
    : <meta name="keywords" content="HTML,CSS,XML,JavaScript">

This example would also create the documentation for the coolapp when exported.

e.g. Exported as text

    * Rails coolapp Project

      This is the Rails coolapp documentation

    ** File [application.html.erb]


    *** Meta Tags

    Meta-Tag-Name  Meta-Tag-Content        
   ----------------------------------------
    author         John Doe                
    keywords       HTML,CSS,XML,JavaScript 

    [application.html.erb] file:app/views/layouts/application.html.erb

This code was tested using:
GNU Emacs 25.2.1 (x86_64-unknown-cygwin, GTK+ Version 3.22.10)
Org mode version 9.1.2

4
  • interesting answer because mentions noweb. I get your point, but should mention the OP mentioned that after 1 week, he's adding a meta author tag ( and not a meta keyword tag) Commented Feb 20, 2018 at 18:48
  • @joshsverns good point!! I'll update my answer
    – Melioratus
    Commented Feb 20, 2018 at 18:52
  • @joshsverns - I updated answer to show how adding other meta tags like author might be done. This is just a simple contrived example. The new code block could just as easily been erb code with the table values appended to a ruby data file. The point of literate programming is to write our program in a way that helps maximize human understanding and improve design while minimizing the tedious boiler plate aspects of coding. I've also found literate programming to very useful in tracking and updating other stuff that is coupled to the code such as data files, configurations, diagrams, etc...
    – Melioratus
    Commented Feb 20, 2018 at 19:44
  • @joshsverns - Did updating my example with the author meta tag help?
    – Melioratus
    Commented Feb 24, 2018 at 1:57
1

I address here only the following part of your question:

If I choose the latter, an interesting situation can arise in the long run where a single org file has multiple :tangle blocks that output to the same file. After the tangling, which one is left?

The org info manual says in Section 14.4 Extracting source code:

When Org tangles ‘src’ code blocks, it expands, merges, and transforms them. Then Org recomposes them into one or more separate files, as configured through the options.

You are right. That passage is not very clear about what happens to multiple source blocks with the same tangle file name.

One gets a rough picture when one reads on and on in the manual. There are several places where it is noted that separators of several kinds (newlines, comments, ...) can be added between the pieces of source code resulting from different source blocks for the same tangle file.

The principal structure of org-babel-tangle with respect to tangling serveral source blocks into the same file is (ignoring implementation specific details):

(defun org-babel-tangle ()
  (let (path-collector) ;; We remember here already visited tangle files.
    (mapc ;; map over all languages
     (lambda (by-lang)
       (let* ((lang (car by-lang))
              (specs (cdr by-lang))) ;; list of source code blocks with language LANG
         (mapc
          (lambda (spec) ;; individual source block
            (let ((file-name (get-spec :tangle spec))) ;; We assume `get-spec' is intuitively clear.
              ;; delete any old versions of file
              (when (and (file-exists-p file-name)
                         (not (member file-name path-collector))
                         (delete-file file-name))
                ;; drop source-block to file
                (with-temp-buffer
                  (org-babel-spec-to-string spec) ;; insert block into temp buffer
                  (append-to-file nil nil file-name)) ;; append temp buffer contents to file
                (add-to-list 'path-collector file-name))))
          specs)))
     (org-babel-tangle-collect-blocks lang tangle-file))))

In short:

  1. If a pair of a tangle file name and a programming language occurs for the first time during the current tangling the tangle file is initially overwritten with the contents of the corresponding source block.
  2. All source blocks that follow during the tangling with the same name and the same programming language are sequentially appended to the new tangle file created at 1.
1

One idea is to make copies of the blocks as you go along. But remove the :tangle app/views/layouts/application.html.erb part from the older block(s). So the tangling is done once when pressing C-c v t. This does mean that your coolsite.org file builds up a lot of dead code. For some folks (I'm undecided atm) dead code can be actually useful history, it's part of the story of how the code came to be in the current state.

Of course, if history is crucial, there's always version control (as @tad mentioned) and an alias like this can help

alias g='git add .; git commit -a -m '\''Quick commit'\'';'

Sometimes, you don't want the diary/thoughts ending up in version control, because when you do git push things are deployed to your team/www. If your though process is captured in the .org file, you can .gitignore the .org file.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.