{"id":3402,"date":"2016-10-26T14:19:29","date_gmt":"2016-10-26T18:19:29","guid":{"rendered":"http:\/\/fgiasson.com\/blog\/?p=3402"},"modified":"2017-02-17T10:41:12","modified_gmt":"2017-02-17T15:41:12","slug":"literate-clojure-programming-tangle-all-in-org-mode","status":"publish","type":"post","link":"https:\/\/fgiasson.com\/blog\/index.php\/2016\/10\/26\/literate-clojure-programming-tangle-all-in-org-mode\/","title":{"rendered":"Literate [Clojure] Programming: Tangle All in Org-mode"},"content":{"rendered":"<p>This blog post is the fifth of a series of blog posts about Literate [Clojure] Programming in <a href=\"http:\/\/orgmode.org\/\">Org-mode<\/a> where I explain how I develop my [Clojure] applications using literate programming concepts and principles.<\/p>\n<p>This new blog post introduce a tool that is often necessary when developing literate applications using Org-mode: the <code>tangle all<\/code> script. As I explained in a previous blog post, doing literate programming is often like writing: you write something, you review and update it\u00e2\u20ac\u00a6 often. This means that you may end-up changing multiple files in your Org-mode project. Depending how you configured you Emacs environment and Org-mode, you may have missed to tangle a file you changed that may cause issues down the road. This is the situation I will cover in this post.<\/p>\n<p>This series of blog posts about literate [Clojure] programming in Org-mode is composed of the following articles:<\/p>\n<ol class=\"org-ol\">\n<li><a href=\"https:\/\/fgiasson.com\/blog\/index.php\/2016\/06\/21\/optimal-emacs-settings-for-org-mode-for-literate-programming\/\">Configuring Emacs for Org-mode<\/a><\/li>\n<li><a href=\"https:\/\/fgiasson.com\/blog\/index.php\/2016\/07\/06\/literate-clojure-programming-using-org-mode\/\">Project folder structure<\/a><\/li>\n<li><a href=\"https:\/\/fgiasson.com\/blog\/index.php\/2016\/08\/11\/literate-clojure-programming-anatomy-of-a-org-mode-file\/\">Anatomy of a Org-mode file<\/a><\/li>\n<li><a href=\"https:\/\/fgiasson.com\/blog\/index.php\/2016\/10\/26\/literate-clojure-programming-tangle-all-in-org-mode\/\">Tangling all project files<\/a> (this post)<\/li>\n<li><a href=\"https:\/\/fgiasson.com\/blog\/index.php\/2017\/02\/17\/literate-clojure-programming-publishing-documentation-in-multiple-formats\/\">Publishing documentation in multiple formats<\/a><\/li>\n<li><a href=\"https:\/\/fgiasson.com\/blog\/index.php\/2016\/05\/30\/creating-and-running-unit-tests-directly-in-source-files-with-org-mode\/\">Unit Testing<\/a><\/li>\n<\/ol>\n<p><!--more--><\/p>\n<div id=\"outline-container-orgheadline1\" class=\"outline-2\">\n<h2 id=\"orgheadline1\">Emacs: the Programmable Text Editor<\/h2>\n<div id=\"text-orgheadline1\" class=\"outline-text-2\">\n<p>One of the beauty of <a href=\"https:\/\/www.gnu.org\/software\/emacs\/\">Emacs<\/a> is that it is fully programmable. It is open source, anything can be accessed, changed and modified: even while running. It can be done because at its core, it is an <a href=\"https:\/\/www.gnu.org\/software\/emacs\/manual\/eintr.html\">Emacs Lisp<\/a> interpreter. This is the feature of the development environment that I leveraged to create a series of tools that I can use in my Org-mode literate programming projects.<\/p>\n<\/div>\n<\/div>\n<div id=\"outline-container-orgheadline2\" class=\"outline-2\">\n<h2 id=\"orgheadline2\">Literate [Clojure] Programming Project Folder Structure<\/h2>\n<div id=\"text-orgheadline2\" class=\"outline-text-2\">\n<p>Let&#8217;s take a look at the folder structure of a literate [Clojure] programming project:<\/p>\n<pre class=\"example\">- CHANGELOG.md\n- LICENCE\n- README.md\n- resources\n- org\n  - project.org\n  - publish.org\n  - tangle-all.org\n  - setup.org\n  - org_mode_clj_tests_utils\n    - core.org\n- pom.xml\n- project.clj\n- src\n  - org_mode_clj_tests_utils\n    - core.clj\n- target\n- test\n  - org_mode_clj_tests_utils\n    - core_test.clj\n<\/pre>\n<p>In the root <code>org<\/code> folder we have setup and configuration files, but also some <i>tool<\/i> files. One of them is <code>tangle-all.org<\/code> which we will cover below. This is where I add such tools that helps me with some specific tasks when developing literate programming applications in Emacs.<\/p>\n<p>In my blog post <a href=\"https:\/\/fgiasson.com\/blog\/index.php\/2016\/06\/21\/optimal-emacs-settings-for-org-mode-for-literate-programming\/\">Optimal Emacs Settings for Org-mode for Literate Programming<\/a> I have a section called <a href=\"https:\/\/fgiasson.com\/blog\/index.php\/2016\/06\/21\/optimal-emacs-settings-for-org-mode-for-literate-programming\/#Change-Behaviors-On-Save\">Change Behaviors On Save<\/a> which explains how to configure Emacs and Org-mode to trigger some specific behavior when saving a file. One of these behavior is to automatically tangle the file that is being saved, such that you don&#8217;t forget to tangle it down the road. This is really handy and it works 95% of the time. However there are situations when this won&#8217;t fully work. For example, the file may be changed using another text editor than Emacs. Or someone else that would like to use your literate program may not have your modifications to the save behavior, etc. This is for these situations that such a <code>tangle-all<\/code> script comes handy: the tool ensure you that you tangled all the files of your application.<\/p>\n<\/div>\n<\/div>\n<div id=\"outline-container-orgheadline3\" class=\"outline-2\">\n<h2 id=\"orgheadline3\">Tangle All<\/h2>\n<div id=\"text-orgheadline3\" class=\"outline-text-2\">\n<p>I choose to create, and use, the <code>tangle-all<\/code> function in an Org-mode file. It could easily have been created as an Emacs package, or simply added in the <code>.emacs<\/code> configuration file. However having it as Org files is handy. It becomes really portable. It follows the literate programming project&#8217;s code. It comes really handy when the literate program is shared in a repository like on GitHub. It becomes instantly available for other to be used without having to search and install a third party package or to hack their Emacs text editor. They only have to run the code in Org-mode and they get the capability without having to worry about anything else.<\/p>\n<p>The <code>(tangle-all)<\/code> function uses the <code>(directory-files-recursive)<\/code> function adapted from <a href=\"http:\/\/turingmachine.org\/bl\/2013-05-29-recursively-listing-directories-in-elisp.html\">Daniel M. German&#8217;s work<\/a>. The <a href=\"https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2016\/10\/tangle-all.org.txt\">tangle-all.org<\/a> file is located at the root of the <code>org<\/code> folder. What it does is to recursively check for Org-mode files from that location on the file system, and tangle all of them.<\/p>\n<div class=\"org-src-container\">\n<pre class=\"src src-elisp\"><span style=\"color: #ae81ff;\">(<\/span><span style=\"color: #f92672;\">defun<\/span> <span style=\"color: #a6e22e;\">directory-files-recursive<\/span> <span style=\"color: #66d9ef;\">(<\/span>directory match maxdepth<span style=\"color: #66d9ef;\">)<\/span>\n  <span style=\"color: #75715e;\">\"List files in DIRECTORY and in its sub-directories. <\/span>\n<span style=\"color: #75715e;\">   Return files that match the regular expression MATCH. Recurse only <\/span>\n<span style=\"color: #75715e;\">   to depth MAXDEPTH. If zero or negative, then do not recurse\"<\/span>\n  <span style=\"color: #66d9ef;\">(<\/span><span style=\"color: #f92672;\">let*<\/span> <span style=\"color: #a6e22e;\">(<\/span><span style=\"color: #e6db74;\">(<\/span>files-list '<span style=\"color: #fd971f;\">()<\/span><span style=\"color: #e6db74;\">)<\/span>\n         <span style=\"color: #e6db74;\">(<\/span>current-directory-list\n          <span style=\"color: #fd971f;\">(<\/span>directory-files directory t<span style=\"color: #fd971f;\">)<\/span><span style=\"color: #e6db74;\">)<\/span><span style=\"color: #a6e22e;\">)<\/span>\n    <span style=\"color: #75715e; font-style: italic;\">;; <\/span><span style=\"color: #75715e; font-style: italic;\">while we are in the current directory<\/span>\n    <span style=\"color: #a6e22e;\">(<\/span><span style=\"color: #f92672;\">while<\/span> current-directory-list\n      <span style=\"color: #e6db74;\">(<\/span><span style=\"color: #f92672;\">let<\/span> <span style=\"color: #fd971f;\">(<\/span><span style=\"color: #f92672;\">(<\/span>f <span style=\"color: #ae81ff;\">(<\/span>car current-directory-list<span style=\"color: #ae81ff;\">)<\/span><span style=\"color: #f92672;\">)<\/span><span style=\"color: #fd971f;\">)<\/span>\n        <span style=\"color: #fd971f;\">(<\/span><span style=\"color: #f92672;\">cond<\/span> \n         <span style=\"color: #f92672;\">(<\/span><span style=\"color: #ae81ff;\">(<\/span>and\n           <span style=\"color: #66d9ef;\">(<\/span>file-regular-p f<span style=\"color: #66d9ef;\">)<\/span>\n           <span style=\"color: #66d9ef;\">(<\/span>file-readable-p f<span style=\"color: #66d9ef;\">)<\/span>\n           <span style=\"color: #66d9ef;\">(<\/span>string-match match f<span style=\"color: #66d9ef;\">)<\/span><span style=\"color: #ae81ff;\">)<\/span>\n          <span style=\"color: #ae81ff;\">(<\/span>setq files-list <span style=\"color: #66d9ef;\">(<\/span>cons f files-list<span style=\"color: #66d9ef;\">)<\/span><span style=\"color: #ae81ff;\">)<\/span><span style=\"color: #f92672;\">)<\/span>\n         <span style=\"color: #f92672;\">(<\/span><span style=\"color: #ae81ff;\">(<\/span>and\n           <span style=\"color: #66d9ef;\">(<\/span>file-directory-p f<span style=\"color: #66d9ef;\">)<\/span>\n           <span style=\"color: #66d9ef;\">(<\/span>file-readable-p f<span style=\"color: #66d9ef;\">)<\/span>\n           <span style=\"color: #66d9ef;\">(<\/span>not <span style=\"color: #a6e22e;\">(<\/span>string-equal <span style=\"color: #e6db74;\">\"..\"<\/span> <span style=\"color: #ae81ff;\">(<\/span>substring f -2<span style=\"color: #ae81ff;\">)<\/span><span style=\"color: #a6e22e;\">)<\/span><span style=\"color: #66d9ef;\">)<\/span>\n           <span style=\"color: #66d9ef;\">(<\/span>not <span style=\"color: #a6e22e;\">(<\/span>string-equal <span style=\"color: #e6db74;\">\".\"<\/span> <span style=\"color: #ae81ff;\">(<\/span>substring f -1<span style=\"color: #ae81ff;\">)<\/span><span style=\"color: #a6e22e;\">)<\/span><span style=\"color: #66d9ef;\">)<\/span>\n           <span style=\"color: #66d9ef;\">(<\/span>&gt; maxdepth 0<span style=\"color: #66d9ef;\">)<\/span><span style=\"color: #ae81ff;\">)<\/span>     \n          <span style=\"color: #75715e; font-style: italic;\">;; <\/span><span style=\"color: #75715e; font-style: italic;\">recurse only if necessary<\/span>\n          <span style=\"color: #ae81ff;\">(<\/span>setq files-list <span style=\"color: #66d9ef;\">(<\/span>append files-list <span style=\"color: #a6e22e;\">(<\/span>directory-files-recursive f match <span style=\"color: #ae81ff;\">(<\/span>- maxdepth -1<span style=\"color: #ae81ff;\">)<\/span><span style=\"color: #a6e22e;\">)<\/span><span style=\"color: #66d9ef;\">)<\/span><span style=\"color: #ae81ff;\">)<\/span>\n          <span style=\"color: #ae81ff;\">(<\/span>setq files-list <span style=\"color: #66d9ef;\">(<\/span>cons f files-list<span style=\"color: #66d9ef;\">)<\/span><span style=\"color: #ae81ff;\">)<\/span><span style=\"color: #f92672;\">)<\/span>\n         <span style=\"color: #f92672;\">(<\/span>t<span style=\"color: #f92672;\">)<\/span><span style=\"color: #fd971f;\">)<\/span><span style=\"color: #e6db74;\">)<\/span>\n      <span style=\"color: #e6db74;\">(<\/span>setq current-directory-list <span style=\"color: #fd971f;\">(<\/span>cdr current-directory-list<span style=\"color: #fd971f;\">)<\/span><span style=\"color: #e6db74;\">)<\/span><span style=\"color: #a6e22e;\">)<\/span>\n    files-list<span style=\"color: #66d9ef;\">)<\/span><span style=\"color: #ae81ff;\">)<\/span>\n\n<span style=\"color: #ae81ff;\">(<\/span><span style=\"color: #f92672;\">defun<\/span> <span style=\"color: #a6e22e;\">tangle-all<\/span> <span style=\"color: #66d9ef;\">()<\/span>\n  <span style=\"color: #75715e;\">\"Tangle all the Org-mode files in the directory of the file of the current buffer<\/span>\n<span style=\"color: #75715e;\">   recursively in child folders. Returns the list of tangled files\"<\/span>\n  <span style=\"color: #66d9ef;\">(<\/span>mapcar <span style=\"color: #a6e22e;\">(<\/span><span style=\"color: #f92672;\">lambda<\/span> <span style=\"color: #e6db74;\">(<\/span>f<span style=\"color: #e6db74;\">)<\/span>\n            <span style=\"color: #e6db74;\">(<\/span><span style=\"color: #f92672;\">when<\/span> <span style=\"color: #fd971f;\">(<\/span>not <span style=\"color: #f92672;\">(<\/span>file-directory-p f<span style=\"color: #f92672;\">)<\/span><span style=\"color: #fd971f;\">)<\/span>\n              <span style=\"color: #fd971f;\">(<\/span>org-babel-tangle-file f<span style=\"color: #fd971f;\">)<\/span><span style=\"color: #e6db74;\">)<\/span><span style=\"color: #a6e22e;\">)<\/span>\n          <span style=\"color: #a6e22e;\">(<\/span>directory-files-recursive <span style=\"color: #e6db74;\">(<\/span>file-name-directory <span style=\"color: #fd971f;\">(<\/span>buffer-file-name<span style=\"color: #fd971f;\">)<\/span><span style=\"color: #e6db74;\">)<\/span> <span style=\"color: #e6db74;\">\"\\\\.org$\"<\/span> 20<span style=\"color: #a6e22e;\">)<\/span><span style=\"color: #66d9ef;\">)<\/span><span style=\"color: #ae81ff;\">)<\/span>\n<\/pre>\n<\/div>\n<div class=\"org-src-container\">\n<pre class=\"src src-elisp\"><span style=\"color: #ae81ff;\">(<\/span>tangle-all<span style=\"color: #ae81ff;\">)<\/span>\n<\/pre>\n<\/div>\n<p>The only thing a user as to do to tangle all the files is to open the <code>tangle-all.org<\/code> file and then to execute all the code blocks in the current buffer using <code>C-c C-v b<\/code>. That will evaluate the <code>(tangle-all)<\/code> function and then it will call it. Finally the list of tangled files will be output.<\/p>\n<\/div>\n<\/div>\n<div id=\"outline-container-orgheadline4\" class=\"outline-2\">\n<h2 id=\"orgheadline4\">Conclusion<\/h2>\n<div id=\"text-orgheadline4\" class=\"outline-text-2\">\n<p>As you can see, it is really easy to create <i>tools<\/i> to help us managing our literate programming applications. n the next and final article of this series, I will introduce another such tool used to <code>weave<\/code> all documents in multiple different file formats.<\/p>\n<\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>This blog post is the fifth of a series of blog posts about Literate [Clojure] Programming in Org-mode where I explain how I develop my [Clojure] applications using literate programming concepts and principles. This new blog post introduce a tool that is often necessary when developing literate applications using Org-mode: the tangle all script. As [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[251,279,277,66],"tags":[252,254,274,276],"class_list":["post-3402","post","type-post","status-publish","format-standard","hentry","category-clojure","category-emacs","category-literate-programming","category-programming","tag-clojure-2","tag-emacs","tag-literateprogramming","tag-orgmode"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/fgiasson.com\/blog\/index.php\/wp-json\/wp\/v2\/posts\/3402","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/fgiasson.com\/blog\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/fgiasson.com\/blog\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/fgiasson.com\/blog\/index.php\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/fgiasson.com\/blog\/index.php\/wp-json\/wp\/v2\/comments?post=3402"}],"version-history":[{"count":6,"href":"https:\/\/fgiasson.com\/blog\/index.php\/wp-json\/wp\/v2\/posts\/3402\/revisions"}],"predecessor-version":[{"id":3609,"href":"https:\/\/fgiasson.com\/blog\/index.php\/wp-json\/wp\/v2\/posts\/3402\/revisions\/3609"}],"wp:attachment":[{"href":"https:\/\/fgiasson.com\/blog\/index.php\/wp-json\/wp\/v2\/media?parent=3402"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/fgiasson.com\/blog\/index.php\/wp-json\/wp\/v2\/categories?post=3402"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/fgiasson.com\/blog\/index.php\/wp-json\/wp\/v2\/tags?post=3402"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}