Hello stardiviner, I actually don't mind using absoute paths in my org files, and I think that using something like that header var and expansion is more trouble than it is worth. If I wanted to move the org file to another folder, I would just do a *replace-string* of the old path with the new path and be done with it. Another approach would be to put a block like the following at the top of the file: #+BEGIN_SRC sh // Make a symbolic link of the current directory into ~/code ln -s $PWD ~/code #+END_SRC And after running that block, I can just use require("~/code/src/tangled-file.js") in the js blocks and it would work just fine. I consider all the tangled js files in ./src as throwaway code, meaning that I can recreate them at any time, and I would never check them into a repository. I usually put them in ./src and add the src folder to my .gitignore. I find both of these approaches simpler than tangling expanded header arguments. Just my 2c. Happy holidays Martin On Sat, Dec 23, 2017 at 10:14 PM numbchild@gmail.com wrote: > > I come up with an idea, use babel header argument :var to pass in the > absolute path of tangled file. > And ob-js will expand and replace that :var variable inside of JavaScript > src block. > So that you don't need to repeatly manually typing the absolute path of > the tangled file. Maybe it only one for "require". One question is that I > don't know whether tangle to auto expand and substitute the :var. > After a quick test, seems it should be expanded but not indeed. Check out > the info node of `:no-expand`. > Here is my quick test: > > * Test tangle will auto expand and substitute :var > > #+begin_src js :tangle kk.js > console.log("hello, world!"); > #+end_src > > #+begin_src js :var name="chris" :tangle require-kk.js > // require("kk.js"); > console.log("Hi, ", name); > #+end_src > > #+RESULTS: > : Hi, chris > > #+NAME: check whether tangle expand and substitute :var > #+begin_src shell > cat require-kk.js > #+end_src > > #+RESULTS: check whether tangle expand and substitute :var > : var name="chris"; > : console.log("Hi, ", name); > > > > > [stardiviner] GPG key ID: 47C32433 > IRC(freeenode): stardiviner Twitter: @numbchild > Key fingerprint = 9BAA 92BC CDDD B9EF 3B36 CB99 B8C4 B8E5 47C3 2433 > Blog: http://stardiviner.github.io/ > > On Sat, Dec 23, 2017 at 11:06 AM, Martin Alsinet > wrote: > >> Hello, >> >> I don't have a blog yet, it is in my list of new year's resolutions. I >> will try to explain it here anyway, maybe it can serve as a draft for a >> blog post. >> >> When you hit *C-c* inside of a javascript source block, *ob-js* takes >> the js code from the js block and saves it into a temp file (in linux the >> temp file will be in saved /tmp/random-name, while in Mac OS X it will be >> saved in /var/folders/random-name). Then, it uses *org-babel-eval* to >> execute the js code, which in turn creates a temp buffer, inserts the >> contents of the temp file into the temp buffer and uses >> *shell-command-on-region* to run the js code with *node* as the executed >> command. >> >> That is the reason why you must use absolute paths in the require, >> because when the code runs it is no longer in the same directory of the org >> file, but in a temporary folder. If you use >> require("./src/my-component.js"), require won't find the js file because >> it is in another directory. >> >> Let's try an example (if you want you can send me one of your examples >> and I can modify it to use my approach) >> >> First, I will define two functions to show an array of javascript objects >> as an org-mode table: >> >> #+BEGIN_SRC js :tangle src/table.js >> function table_row(cells){ >> console.log("|" + cells.join("|") + "|"); >> } >> function table(rows){ >> console.log("|---|"); >> table_row(Object.keys(rows[0])); >> console.log("|---|"); >> rows.map(row => table_row(Object.keys(row).map(k => row[k]))); >> console.log("|---|"); >> } >> module.exports = table; >> #+END_SRC >> >> Notice the :tangle src/table.js property, which I will use to require it >> in a later block: >> >> #+BEGIN_SRC js :results output raw drawer >> var data = [ { day: 'SUNDAY', accidents: 3986 }, >> { day: 'MONDAY', accidents: 6109 }, >> { day: 'SATURDAY', accidents: 6274 }, >> { day: 'WEDNESDAY', accidents: 6453 }, >> { day: 'THURSDAY', accidents: 6546 }, >> { day: 'TUESDAY', accidents: 6557 }, >> { day: 'FRIDAY', accidents: 6916 } ]; >> >> // here you have to use the full path to the table.js file >> var view_as_table = require("/app/src/table.js"); >> >> view_as_table(data); >> #+END_SRC >> >> Then I run *org-babel-tangle* to write the table.js file, and when I hit >> *C-c* inside of this last block, it requires the tangled table.js file, >> runs the function and we get the following results: >> >> #+RESULTS: >> :RESULTS: >> |-----------+-----------| >> | day | accidents | >> |-----------+-----------| >> | SUNDAY | 3986 | >> | MONDAY | 6109 | >> | SATURDAY | 6274 | >> | WEDNESDAY | 6453 | >> | THURSDAY | 6546 | >> | TUESDAY | 6557 | >> | FRIDAY | 6916 | >> |-----------+-----------| >> :END: >> >> About the order of execution, if you used sessions in my example, you >> have to run the first block (which defines the function) before running the >> second (which uses it), or it would fail because the table function has not >> been loaded. >> >> Now imagine a very long document with dozens of source blocks. In order >> to run the block number 23, you will have to run all the preceding blocks >> on which that block depends. I don't like that, even if the document is >> meant to be read sequentially, from start to finish, I want to be able to >> open the org file, go to any section and running any source code block >> without having to remember the sequence of dependencies between them. Worst >> case, all I have to do is run org-babel-tangle to update the tangled files. >> This has also the added benefit that it forces me to structure my blocks >> correctly, from a code architecture point of view. >> >> I hope this makes it clearer for you. >> >> >> Martin >> >> On Fri, Dec 22, 2017 at 8:07 PM numbchild@gmail.com >> wrote: >> >>> >>> Can you describe how do you do this in detailed? >>> Like: >>> > but since I am using docker containers to run node, I always mount the >>> current directory as a volume in /app inside the container, so that works >>> out fine. >>> > I also think that this way forces me to separate the code in modular >>> blocks, which is already a good practice in itself. >>> How to do this? About this: > With sessions you have to make sure to >>> execute the blocks in the correct order to build the "state" that your >>> current block needs. >>> I think have to use `noweb` reference here. >>> (If you have a blog article describe this whole JS literate programming >>> setup, that will be useful.) >>> Finally, thanks you provide this paradigm. >>> >>> [stardiviner] GPG key ID: 47C32433 >>> IRC(freeenode): stardiviner Twitter: @numbchild >>> Key fingerprint = 9BAA 92BC CDDD B9EF 3B36 CB99 B8C4 B8E5 47C3 2433 >>> Blog: http://stardiviner.github.io/ >>> >>> On Sat, Dec 23, 2017 at 2:32 AM, Martin Alsinet >>> wrote: >>> >>>> Hello stardiviner, >>>> >>>> On Fri, Dec 22, 2017 at 6:57 AM stardiviner >>>> wrote: >>>> >>>>> >>>>> I wish to do JavaScript Literate Programming in Org-mode. >>>>> >>>>> So the :session header argument is very necessary. >>>>> >>>>> >>>> I do Literate Programming in Javascript with Org-mode, and I have found >>>> a workaround using a combination of tangled files and require. >>>> >>>> I separate the logic in source code blocks which then I tangle into js >>>> files and I require those js files in other source blocks. >>>> >>>> Example: >>>> >>>> #+BEGIN_SRC js :tangle src/parser.js >>>> const fs = require('fs'); >>>> const parse = require('csv-parse') >>>> >>>> function columns(line){ >>>> return line.map(s => s.toLowerCase()); >>>> } >>>> parse_csv = function(filename, fn, limit){ >>>> fs.readFile(filename, "utf8", function (err, fileData) { >>>> var opts = {columns: columns, trim: true}; >>>> if (limit) { >>>> opts.to = limit; >>>> } >>>> parse(fileData, opts, (err, rows) => fn(rows)); >>>> }); >>>> } >>>> module.exports = parse_csv; >>>> #+END_SRC >>>> >>>> So, I tangle that source block into a js file, and then I can use it >>>> from other blocks, without needing sessions at all: >>>> >>>> #+BEGIN_SRC >>>> const parser = require("/app/src/parser.js"); >>>> const inputFile = './data/records.csv'; >>>> parse_csv(inputFile, console.log); >>>> #+END_SRC >>>> >>>> The only drawback is that you have to use absolute paths requiring the >>>> js files, but since I am using docker containers to run node, I always >>>> mount the current directory as a volume in /app inside the container, so >>>> that works out fine. >>>> I also think that this way forces me to separate the code in modular >>>> blocks, which is already a good practice in itself. >>>> With sessions you have to make sure to execute the blocks in the >>>> correct order to build the "state" that your current block needs. >>>> This way source blocks function as standalone units that can be run at >>>> any time, I just run *org-babel-tangle* and then hit *C-c *inside the >>>> js block. >>>> >>>> I hope that helps you. >>>> >>>> >>>> Martin >>>> >>> >>> >