orgmode icon indicating copy to clipboard operation
orgmode copied to clipboard

Added tangle functionality to org files

Open andreadev-it opened this issue 3 years ago • 7 comments

This PR has been created to propose a way to implement the tangling functionality existing in ORG Mode (following Discussion #275 ). The current code will add a tangle function as a method of an Org File, since this seemed the most flexible way to implement this.

With this PR, you can write the following in order to tangle block files found under specific headings:

* Heading 1
  :PROPERTY:
  :TANGLE: ./filename.lua
  :END:
  
  #+begin_src lua
  print("Test")
  #+end_src

Since this is a stub, I've not yet thought if the action should be triggered by a keymap or by a command. Currently, you can tangle the file from lua using this code:

local file = require("orgmode.parse.files").get_current_file()
file:tangle()

This is not a 1:1 copy of the syntax that is implemented in the original Org Mode, since it seems like treesitter isn't able to comprehend the original one.

Things that I'd like to discuss about this implementations are:

  • The currently used syntax is different from what Org Mode does. It was meant to be more easily parsed by treesitter, but other options are welcome
  • How to handle when the filename isn't defined (the original uses the filename + an extension based on the code block language)
  • How to expose this functionality to the user
  • I've added a function that changes a relative path to an absolute one. This has been done elsewere in the code, but I think it could need some improment, maybe we can create a function in utils.lua?

Of course, if there are other questions or suggestions, don't hold back! Hope this can be of some help 🙂

andreadev-it avatar Nov 02 '22 13:11 andreadev-it

@andreadev-it Thanks for the PR. From what I see in Emacs docs https://orgmode.org/manual/Extracting-Source-Code.html, it seems this is handled differently. Looks like it needs to be defined like this:

* Heading 1  
  #+begin_src lua :tangle yes
  print("Test")
  #+end_src

Did you use property for some specific reason?

kristijanhusak avatar Apr 29 '23 12:04 kristijanhusak

Hi @kristijanhusak, thank for taking a look at this PR 🙂 Yes, the syntax I integrated is different right now, mostly for semplicity reasons. I saw that treesitter isn't (or maybe wasn't) detecting code blocks properties and other similar-looking syntax. It seemed to me that there are also different ways of setting that option in orgmode that I couldn't completely understand.

andreadev-it avatar Apr 29 '23 13:04 andreadev-it

You should be able to parse this with treesitter. See how we do it for detecting filetype blocks https://github.com/nvim-orgmode/orgmode/blob/60e8700469a96e839c5e776a1849034af5f830a4/lua/orgmode/parser/file.lua#L398-L414

kristijanhusak avatar Apr 29 '23 13:04 kristijanhusak

Thank you for the info, I took a look at the code and, the treesitter tree and the org grammar. If I understood correctly, to support tangling files there are three syntax that should be handled:

  1. document properties
#+PROPERTY: header-args :tangle yes
  1. header properties
* Heading 1
:PROPERTIES:
:header-args: :tangle yes
:END:
  1. block properties
#+BEGIN_SRC lua :tangle yes 
-- code here
#+END_SRC

Is this correct? I wrote them here both as a way to ask for confirmation about this and to have a local reference to the spec.

andreadev-it avatar Apr 29 '23 21:04 andreadev-it

Yeah, this seems right. But I would say to implement only point 3, since the first 2 points are just used to propagate the values to its children, in terms that if you set the top level #+PROPERTY, it sets that property to each headline, and if you have :header-args: :tangle yes property on a headline, it applies that to each block inside. This inheritance of properties needs to be generally added so it's out of scope for this feature.

kristijanhusak avatar Apr 30 '23 06:04 kristijanhusak

Ok, I understand. It should be easy to change the code to support only point 3. I'll do it as soon as I can 👍 However I do think that, for this functionality to be useful, it should support at least one of the other methods too... When property inheritance is added, I could implement it for the tangling functionality with a new PR, if needed

andreadev-it avatar Apr 30 '23 07:04 andreadev-it

Few notes while you are updating it:

  • Move the tangle() method from parser/file.lua to treesitter/init.lua. We are generally trying to move from this parsed file and move everything to parsing via treesitter.
  • Use custom query similar to what we have for block filetypes (thing I posted above) to figure out the nodes that have tangle. Iterating children is generally fine, but custom query should be simpler and it will not require doing any recursion.

kristijanhusak avatar Apr 30 '23 07:04 kristijanhusak

Some support was added in https://github.com/nvim-orgmode/orgmode/pull/685. We can build up on that. Closing this. Thanks for the PR anyway!

kristijanhusak avatar Feb 25 '24 21:02 kristijanhusak