{"id":3889,"date":"2023-10-31T08:20:07","date_gmt":"2023-10-31T13:20:07","guid":{"rendered":"https:\/\/fgiasson.com\/blog\/?p=3889"},"modified":"2023-10-31T08:30:31","modified_gmt":"2023-10-31T13:30:31","slug":"orgweb-cli-org-mode-environment-for-web-like-development-without-emacs","status":"publish","type":"post","link":"https:\/\/fgiasson.com\/blog\/index.php\/2023\/10\/31\/orgweb-cli-org-mode-environment-for-web-like-development-without-emacs\/","title":{"rendered":"OrgWeb: CLI Org-Mode Environment for WEB like development without Emacs"},"content":{"rendered":"\n<p>There is a wide range of tools and framework currently available for doing <a href=\"https:\/\/fgiasson.com\/blog\/index.php\/2023\/08\/28\/what-is-literate-programming-why\/\">literate programming<\/a> development. You have the ancestors like <a href=\"https:\/\/github.com\/ascherer\/cweb\">CWEB<\/a>, <a href=\"https:\/\/www.cs.tufts.edu\/~nr\/noweb\/\">NOWEB<\/a> and <a href=\"https:\/\/sourceforge.net\/projects\/nuweb\/\">nuweb<\/a>. You have full editors like <a href=\"https:\/\/leo-editor.github.io\/leo-editor\/\">Leo<\/a>. And then you have more modern approaches like <a href=\"https:\/\/nbdev.fast.ai\">nbdev<\/a>, <a href=\"https:\/\/github.com\/slott56\/py-web-tool\">PyWebTool<\/a> and <a href=\"https:\/\/fsprojects.github.io\/FSharp.Formatting\/\">FSharp.Formatting<\/a>.&nbsp;<\/p>\n<p>However, most of them are specific to a programming language. Some of them are general like NOWEB, but they are lacking some kind of integrations in modern IDE environments.<\/p>\n<p>For the last 8 years, I always fallback to the same: Org-Mode.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Org-mode<\/h2>\n\n\n\n<p>Org-mode is many things, but its most interesting feature has always been its code blocks to me. Org&#8217;s syntax is clean and powerful. Org is not specific to a particular programming languages: it supports tens of programming languages or other kind of configuration\/scripting languages. Code blocks can be executed, tangled or weaved.&nbsp;<\/p>\n<p>Its drawback: the best (and frankly only) Org-mode implementation is in Emacs. Some, myself included, will say it is great because we love working with Emacs, and are happily willing to pay the cost. But we are not the norm, but the exception. Emacs is wonderfully different and it doesn&#8217;t appeal to all developers. I can understand that in today&#8217;s industry where the only incentive is to ship, ship, ship features.<\/p>\n<p>But, how could we get the best of Org-mode without having to force people to use Emacs? One possibility could be to develop Org-mode plugins for other IDEs, the first on the list would most likely be VS Code. But this is not a small undertaking.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Org-mode CLI<\/h2>\n\n\n\n<p>There are some modules existing in other IDEs that support org-mode like on <a href=\"https:\/\/github.com\/nvim-orgmode\/orgmode\">Vim<\/a>, <a href=\"https:\/\/github.com\/vscode-org-mode\/vscode-org-mode\">VS Code<\/a>, etc. But those are mostly syntax highlighter, or implement some features mostly related to org-agenda and headings manipulation. It is a good start, but far from enough for a literate programming framework.<\/p>\n<p>The goal of <a href=\"https:\/\/github.com\/fgiasson\/orgweb\/tree\/main\">OrgWeb<\/a> is to develop a simple tool that any developer could use to leverage the full power of doing literate programming using Org-mode and their preferred IDE.&nbsp;<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">OrgWeb<\/h2>\n\n\n\n<p><a href=\"https:\/\/github.com\/fgiasson\/orgweb\/tree\/main\">OrgWeb<\/a> is a simple CLI tool that can be installed using this command:<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-bash\" data-lang=\"Bash\"><code>pip install orgweb<\/code><\/pre><\/div>\n\n\n\n<p>The tool only has four commands:<\/p>\n<ol>\n<li><code>tangle<\/code>: extract code from code blocks into their source files<\/li>\n<li><code>detangle<\/code>: sync source files back to their original Org-mode code blocks<\/li>\n<li><code>execute<\/code>: execute code blocks such that they produce their side effects<\/li>\n<li><code>monitor<\/code>: monitor local file system to tangle\/detangle files automatically<\/li>\n<\/ol>\n<p>The tangle, detangle and execute commands can be performed on a folder (recursively) or one or multiple specific files.<\/p>\n<p>Note: I am not covering all the details of how we can use Org mode to do literate programming. You can search my blog which has plenty of posts about that, but also refer to the <a href=\"https:\/\/orgmode.org\/manual\/Working-with-Source-Code.html\">Org-mode documentation to read about all and every features available to you<\/a>.<\/p>\n<p>In addition to the <code>orgweb CLI<\/code>, you will need Docker available in your environment. <a href=\"https:\/\/docs.docker.com\/desktop\/\">If it is not already installed, you can follow those instructions to install it on your system<\/a>.&nbsp;<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">VS Code + Org-mode<\/h3>\n\n\n\n<p>For this blog post, I will cover how Org-mode can be used in conjunction with VS Code to develop an application using literate programming. To start, you can simply clone OrgWeb&#8217;s repository, install this <a href=\"https:\/\/github.com\/vscode-org-mode\/vscode-org-mode\">Org-mode module<\/a> in VS Code. The general development layout is:<\/p>\n<p><a href=\"https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/10\/general-dev-layout-scaled.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/10\/general-dev-layout-scaled.jpg\" alt=\"\" width=\"2560\" height=\"1372\" class=\"alignnone size-full wp-image-3898\" srcset=\"https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/10\/general-dev-layout-scaled.jpg 2560w, https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/10\/general-dev-layout-300x161.jpg 300w, https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/10\/general-dev-layout-1024x549.jpg 1024w, https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/10\/general-dev-layout-768x412.jpg 768w, https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/10\/general-dev-layout-1536x823.jpg 1536w, https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/10\/general-dev-layout-2048x1098.jpg 2048w\" sizes=\"auto, (max-width: 2560px) 100vw, 2560px\" \/><\/a><\/p>\n<p>In the bottom window, this is where we have the terminal instances. This is where OrgWeb commands happens. In the main edit window, this is where the Org files, or the tangled source files will be manipulated.<\/p>\n<p>You can notice that the Org-mode VS code module does some basic syntax highlighting, even within the code blocks using Python&#8217;s syntax highlighter. This is far than enough to easily understand and follow the Org files.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Tangling<\/h3>\n\n\n\n<p>Tangling is the action of extracting code blocks from a literate file into its executable source code file.<\/p>\n<p><a href=\"https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/10\/orgweb_tangling-scaled.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/10\/orgweb_tangling-scaled.jpg\" alt=\"\" width=\"2560\" height=\"1361\" class=\"alignnone size-full wp-image-3901\" srcset=\"https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/10\/orgweb_tangling-scaled.jpg 2560w, https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/10\/orgweb_tangling-300x159.jpg 300w, https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/10\/orgweb_tangling-1024x544.jpg 1024w, https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/10\/orgweb_tangling-768x408.jpg 768w, https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/10\/orgweb_tangling-1536x816.jpg 1536w, https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/10\/orgweb_tangling-2048x1089.jpg 2048w\" sizes=\"auto, (max-width: 2560px) 100vw, 2560px\" \/><\/a><\/p>\n<p>Once ready to tangle the Org file, this command will tangle that specific file:<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-bash\" data-lang=\"Bash\"><code>orgweb tangle . --file main.org<\/code><\/pre><\/div>\n\n\n\n<p>It asks OrgWeb to tangle the current directory <code>.<\/code> but to only tangle the <code>main.org<\/code> file. It will find all the Org files recursively, and tangle only the ones specified. If no files are specified, it will tangle all the Org files it finds. Then the <code>main.py<\/code> file will be generated from all the code blocks from <code>main.org<\/code>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Detangling<\/h3>\n\n\n\n<p>Developers will often end-up working on the source files that have been generated from Org files. There are all kind of reasons for that, such as modifying a source file while debugging an application. When this happens, the literate Org files and the source files get desynchronized. Changes could be copy\/paste to the Org files, but there is a much easier way to do it: <code>detangling<\/code>.<\/p>\n<p>Detangling synchronize back any tangled code blocks from source files to their original Org file:<\/p>\n<p><a href=\"https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/10\/orgweb_detangle-scaled.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/10\/orgweb_detangle-scaled.jpg\" alt=\"\" width=\"2560\" height=\"1346\" class=\"alignnone size-full wp-image-3904\" srcset=\"https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/10\/orgweb_detangle-scaled.jpg 2560w, https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/10\/orgweb_detangle-300x158.jpg 300w, https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/10\/orgweb_detangle-1024x538.jpg 1024w, https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/10\/orgweb_detangle-768x404.jpg 768w, https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/10\/orgweb_detangle-1536x807.jpg 1536w, https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/10\/orgweb_detangle-2048x1077.jpg 2048w\" sizes=\"auto, (max-width: 2560px) 100vw, 2560px\" \/><\/a><\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-plain\"><code>orgweb detangle . --file main.py<\/code><\/pre><\/div>\n\n\n\n<p>It asks OrgWeb to detangle the current directory <code>.<\/code> but to only detangle the <code>main.py<\/code> file. It will find all the Org files recursively, and tangle only the ones specified. Then the <code>main.org<\/code>&nbsp;file will be generated from all the code blocks from <code>main.py<\/code>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Executing<\/h3>\n\n\n\n<p>The <code>execute<\/code> command is like the tangling command but instead of moving code in source files, it does execute the code blocks that needs to be executed. Code blocks that get executed produces side effects. It is those side effects that we want to force with the <code>execute<\/code> command.<\/p>\n<p><a href=\"https:\/\/github.com\/fgiasson\/orgweb\/blob\/main\/README.org?plain=1#L41\">One example are the PlantUML code blocks in the README.org file<\/a>. When we execute them, the schema images will be generated.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Monitoring<\/h3>\n\n\n\n<p>This is all good, but it is still inconvenient to have to run commands in the terminal every time you want to tangle or detangle some files.<\/p>\n<p>This is why there exists the <code>monitor<\/code> command:<\/p>\n<p><a href=\"https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/10\/orgweb_monitor-scaled.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/10\/orgweb_monitor-scaled.jpg\" alt=\"\" width=\"2560\" height=\"1489\" class=\"alignnone size-full wp-image-3907\" srcset=\"https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/10\/orgweb_monitor-scaled.jpg 2560w, https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/10\/orgweb_monitor-300x174.jpg 300w, https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/10\/orgweb_monitor-1024x595.jpg 1024w, https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/10\/orgweb_monitor-768x447.jpg 768w, https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/10\/orgweb_monitor-1536x893.jpg 1536w, https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/10\/orgweb_monitor-2048x1191.jpg 2048w\" sizes=\"auto, (max-width: 2560px) 100vw, 2560px\" \/><\/a><\/p>\n<p>The <code>orgweb monitor .<\/code> command will keep monitoring the specified folder. Every file that changes within that folder (recursively) will potentially be <code>tangled<\/code> or <code>detangled<\/code> by the running orgweb instance. If a <code>.orgwebignore<\/code> file exists in the target folder, then everything within that file will be ignores by the monitoring process.<\/p>\n<p>In the envisioned development workflow, developers will simply run the monitoring in background such that every Org and source files automatically gets tangled and detangled every time they are saved. That way, developers will be sure that both files are always in sync.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">How does it work?<\/h2>\n\n\n\n<p dir=\"auto\">As we know, <code>orgweb<\/code> is designed in a way that developers can use all the power of Org-mode, in any IDE they like, without having to rely on Emacs directly.<\/p>\n<p dir=\"auto\">To do that, it leverages Docker to build an image where Emacs is properly installed and configured to implement the commands that are exposed via the command line tool.<\/p>\n<p dir=\"auto\">If the <code>orgweb<\/code> docker image is not currently existing in the environment, then it will request Docker to build the image using the <code>Dockerfile<\/code>. The build process will install and configure all the components required to implement all <code>orgweb<\/code> commands.<\/p>\n<p dir=\"auto\"><code>orgweb<\/code> check if it exists every time it is invoked from the command line. This process will happen any time that the image is not available in the environment.<\/p>\n<p dir=\"auto\"><a href=\"https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/10\/orgweb.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/10\/orgweb.png\" alt=\"\" width=\"401\" height=\"179\" class=\"size-full wp-image-3911 aligncenter\" srcset=\"https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/10\/orgweb.png 401w, https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/10\/orgweb-300x134.png 300w\" sizes=\"auto, (max-width: 401px) 100vw, 401px\" \/><\/a><\/p>\n<p dir=\"auto\">If the image is existing in the environment, then the following will happen.<\/p>\n<p dir=\"auto\"><code>orgweb<\/code> will ask Docker to create a container based on the image. Once the container is running, it will execute a command on the container\u2019s terminal to run Emacs. Emacs is used directly from the command line by evaluating ELisp code it gets as input.<\/p>\n<p dir=\"auto\">Every time a <code>orgweb<\/code> command line is executed, a new container is created and when the commands finishes, the container gets deleted:<\/p>\n<p dir=\"auto\"><a href=\"https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/10\/orgweb_2.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/10\/orgweb_2.png\" alt=\"\" width=\"461\" height=\"238\" class=\"size-full wp-image-3912 aligncenter\" srcset=\"https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/10\/orgweb_2.png 461w, https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/10\/orgweb_2-300x155.png 300w\" sizes=\"auto, (max-width: 461px) 100vw, 461px\" \/><\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Other possible avenues<\/h2>\n\n\n\n<p>OrgWeb works fine, but it won&#8217;t ever be as interesting as a proper IDE integration, like what is available in Emacs. Another interesting option worth investigating would be to use Emacs as a Org-mode backend of a LSP server. That way, IDE modules developers could more easily develop fully fledged Org-mode modules for specific IDE integration. That way, we could &#8220;easily&#8221; get the full Org-mode power within any IDE, being able to not only leverage code blocks but <code>org-agenda<\/code>, <code>org-roam<\/code>, <code>tagging<\/code>, <code>date time<\/code>, <code>org-capture<\/code>, etc.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>OrgWeb is a command line tool that enables any developers to leverage Org-mode to do literate programming using their preferred IDE environment.<\/p>\n<p>In this blog post, we will explore how it works and the development workflow it enables.<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[277,66],"tags":[274,323,324],"class_list":["post-3889","post","type-post","status-publish","format-standard","hentry","category-literate-programming","category-programming","tag-literateprogramming","tag-org-mode","tag-vscode"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/fgiasson.com\/blog\/index.php\/wp-json\/wp\/v2\/posts\/3889","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=3889"}],"version-history":[{"count":30,"href":"https:\/\/fgiasson.com\/blog\/index.php\/wp-json\/wp\/v2\/posts\/3889\/revisions"}],"predecessor-version":[{"id":3926,"href":"https:\/\/fgiasson.com\/blog\/index.php\/wp-json\/wp\/v2\/posts\/3889\/revisions\/3926"}],"wp:attachment":[{"href":"https:\/\/fgiasson.com\/blog\/index.php\/wp-json\/wp\/v2\/media?parent=3889"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/fgiasson.com\/blog\/index.php\/wp-json\/wp\/v2\/categories?post=3889"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/fgiasson.com\/blog\/index.php\/wp-json\/wp\/v2\/tags?post=3889"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}