I'm making a little script using treesitter that will extract all code blocks inside an ORG file, but only if they're under an headline with a specific property (:TANGLE:).
I was able to make this query, which works, but only finds code blocks that are immediate children of the headline:
(section
(property_drawer
(property
name: (expr) #prop_name (#eq? #prop_name "TANGLE")
value: (value) #file
)
)
(body
(block
contents: (contents) #code
)
)
)
It works with this org file:
* Headline
:PROPERTIES:
:TANGLE: file.lua
:END:
#+begin_src lua
print("test")
#+end_src
But not with this one, because the code block is not directly inside "Headline 1":
* Headline 1
:PROPERTIES:
:TANGLE: file.lua
:END:
** Headline 2
#+begin_src lua
print("test")
#+end_src
Is there a way using treesitter queries to get nodes nested at any depth inside the headline?
I couldn't find any way to do that, so in the end, I decided to do a deep search recursively.
This was a script for neovim, so I used these functions:
tsnode:iter_children() -- used in a for loop
tsnode:type() -- Check the node type
ts_utils.get_node_text() -- To get the text content of a node
I hope this could be helpful for others too.
Related
In emacs org-mode, is it possible to apply markup to the RESULTS section of a SRC block output when exporting to PDF (or any export format)?
For example, here is a src code block:
#+BEGIN_SRC python :results output :exports both
print '*I would like this line to be bold*'
#+END_SRC
#+RESULTS:
: *I would like this line to be bold*
The RESULTS section is generated by the usual C-c C-c.
Normally org-mode will mark up text in * as bold, but it obviously doesn't do this if that text is in a RESULTS block (or, it appears in a SRC block). In my example, if I export this (PDF via Latex) then I just get the exact output of
*I would like this line to be bold*
...there's no markup.
Answering my own question.
There are formatting modifiers you can add in the header section of the SRC block to do what I want. One of them is 'raw'.
#+BEGIN_SRC python :results output raw
print '*I would like this line to be bold*'
#+END_SRC
#+RESULTS:
*I would like this line to be bold*
(Ironically on Stack Overflow I'm not sure how to mix code blocks and bold face, but the bold line is the result of running the code block in org-mode).
There is a full list of ways to format output here:
http://orgmode.org/manual/results.html#results
I'm writing my thesis in Org→Latex. As well as the individual chapter files, I keep track of the overall structure and progress in a separate file. One thing I look at and have to report on is the number of pages written versus the intended length.
I can use pdfinfo to get the number of physical pages in the individual chapters and get this into the outline with a code block. And I can generate a "columnview" table that automatically updates from the chapter info in the outline. I'd like to find out how I could put the two together.
Example
Hopefully this shows what I'm trying to do. In the real thing, there are obviously more like a dozen chapters.
#+TITLE: Thesis Outline
#+COLUMNS: %2ID %35ITEM %Target_Pages{+}
#+NAME: count-pdf-pages
#+BEGIN_SRC elisp :exports none :var pdf-file=""
(let
((pdf-file-info (shell-command-to-string (concat "pdfinfo " pdf-file))))
(string-match "Pages:[[:blank:]]+\\([0-9]+\\)" pdf-file-info)
(match-string 1 pdf-file-info)
)
#+END_SRC
* Chapter outlines
:PROPERTIES:
:ID: outlines
:END:
** 1. Introduction
:PROPERTIES:
:Target_Pages: 5
:END:
This is the introduction of the thesis. It currently has this many pages:
#+NAME: intro-page-count
#+CALL: count-pdf-pages("latex/intro-chapter.pdf")
* Page Allocation and Completion
#+BEGIN: columnview :hlines 1 :id outlines
| ID | ITEM | Target_Pages |
|----------+--------------------+--------------|
| outlines | * Chapter outlines | 5 |
| | ** 1. Introduction | 5 |
#+END
Question
What I would like to do is be able to use the return value of the CALL block for each chapter within the outline table at the end. However, having read through the relevant section of the manual a few times, I can't see whether it's possible to set a heading's property (say Written_Pages) to be the result of a code block.
Obviously, I'm also open to other org ways of approaching the problem of generating a table from the results of multiple code calls.
Org-mode properties can be set via elisp using org-set-properties. For example, (org-set-properties "Written_Pages" "5") (note that the property value must be a string. So just add an extra source block:
#+BEGIN_SRC elisp :export none :results none :var p=intro-page-count
(org-set-property "Written_Pages" p)
#+END_SRC
I use emacs org a lot to export parts of org documents to latex/pdf. I was wondering whether there is a way to promote all headings of the selected parts during the export process. For instance, suppose the file looks like this:
* Project 1
** Task 1 :export:
*** Introduction
Text text text.
*** Results
Text text text.
* Project 2
The emacs org export to latex would produce a tex file of the following structure:
\section{Project 1}
\subsection{Task 1}
\subsubsection{Introduction}
Text text text.
\subsubsection{Results}
Text text text.
But because there is not highest level in the part to be exported, it would make more sense to have the following structure:
\section{Task 1}
\subsection{Introduction}
Text text text.
\subsection{Results}
Text text text.
Or, even better:
\title{Task 1}
\maketitle
\section{Introduction}
Text text text.
\section{Results}
Text text text.
I was wondering whether anyone has an idea how to go about this? My lisp skills are unfortunately very rudimentary, seems like it should not be too hard.
Thanks!
Stephan
The first behavior you describe can be achieved by adding the following to your .emacs:
;; Define a function for turning a single subtree into a top-level tree
;; (:export: headings might be located at an arbitrary nesting level,
;; so a single call to "org-promote-subtree" is not enough):
(defun org-promote-to-top-level ()
"Promote a single subtree to top-level."
(let ((cur-level (org-current-level)))
(loop repeat (/ (- cur-level 1) (org-level-increment))
do (org-promote-subtree))))
;; Define a function that applies "org-promote-to-top-level"
;; to each :export: subtree:
(defun org-export-trees-to-top-level (backend)
"Promote all subtrees tagged :export: to top-level.
BACKEND is the export back-end being used, as a symbol."
(org-map-entries 'org-promote-to-top-level "+export"))
;; Make org-mode run "org-export-subtrees-to-top-level" as part of the export
;; process:
(add-hook 'org-export-before-parsing-hook 'org-export-trees-to-top-level)
Implementing the second behavior is a bit trickier but you can use theorg-export-trees-to-top-level function as a starting point if that's what you ultimately need. I'd like to point out, however, that this will not work for files with more than one :export: subtree (unless you also come up with a way to decide which headline would become the \title in these cases).
Sources:
Logic of org-promote-to-top-level based on source code of org-cycle-level command
Using the org-mode mapping API
Relevant information about export hooks
I really want to use org-mode.
But, I want to use org-mode to understand structured documents that have already been written using different heading syntax,
e.g. using twiki's ---+
---+ H1
Top level
---++ H2
Nested
---+ H1 #2
Second top level
Or mediawiki like
= H1 =
Top level
== H2 ==
Nested
= H1 #2 =
Second top level
I'd like to have all of the goodness of org-mode folding, etc., just using these different heading styles.
Actually, worse that that:
I would like, say, the twiki or mediawaiki headings to take priority over org mode asterisk headings. But I would like to have both in use.
= H1 =
Top level
* this is a list
** nested
* list
** nested
== H2 ==
Nested
= H1 #2 =
Second top level
--+ What I have tried so far
I have been able to use outline mode to handle twiki,
for example via
---+ Emacs stuff
# try (defvar twiki-outline-regexp "---+\\++ \\|\\(\\(?: \\)+\\)[0-9*] ")
Local Variables: ***
outline-regexp: "^---\\++" ***
org-outline-regexp: "^---\\++" ***
End: ***
However, org-outline-regexp doesn't do hwat I would hope.
emacs' outline-mode's out-level function looks almost exactly like what I want.
(defvar outline-level 'outline-level
"*Function of no args to compute a header's nesting level in an outline.
It can assume point is at the beginning of a header line and that the match
data reflects the `outline-regexp'.")
i.e. instead of regexps, a generic function.
But I have not managed to make it work with org-mode. It looks like org-mode does not really use this, or, rather, has other stuff.
;; In Org buffers, the value of `outline-regexp' is that of
;; `org-outline-regexp'. The only function still directly relying on
;; `outline-regexp' is `org-overview' so that `org-cycle' can do its
;; job when `orgstruct-mode' is active.
(defvar org-outline-regexp "\\*+ "
"Regexp to match Org headlines.")
(defconst org-outline-regexp-bol "^\\*+ "
"Regexp to match Org headlines.
This is similar to `org-outline-regexp' but additionally makes
sure that we are at the beginning of the line.")
(defconst org-heading-regexp "^\\(\\*+\\)\\(?: +\\(.*?\\)\\)?[ \t]*$"
"Matches an headline, putting stars and text into groups.
Stars are put in group 1 and the trimmed body in group 2.")
Failing this, well, the main thing that I want from org-mode is links, Asking another question here
How can I "linkify" a non-org-mode buffer in emacs
My frustration was simply that org-mode has different rules for what constitutes a new outline section than outline-mode does. It requires a space after the asterisks, so it doesn't work on my extensive collection of notes, which forgo those spaces.
I resolved that by removing the trailing space in the not-well-documented org-outline-regexp variable, which is used to initialize the buffer-local variable outline-regexp, and that seems to be working for me. E.g. (set-variable 'org-outline-regexp "\\*+")
As to your actual question, my guess is that other regexp's and code would have to change to handle radically different stuff like twiki or mediawiki headings.
In standard Latex, one can use something like...
\section[short head]{A longer and more meaningful heading version for the section}
...that gives both a long and short version of a section (or other sectioning command) Thus, allowing for both meaningful sectioning 'titles' and, also, reasonable-looking running heads, TOCs, beamer navigation, etc..
Is there any way to easily achieve this in org mode? (That is without hard coding the sectioning commands in LATEX snippets and, thus, defeating most of the flexibility of changing sectioning levels and repurposing content for beamer, book, and article classes that is my reason for wanting to try orgmode, in first place?)
I tried a "workaround" that did not work. I tried editing the possible latex export classes by adding another class to org-export-latex-classes. This new class changes sectioning commands from \section{%s} to \section%s(EDIT-Fixed typo in slashes). Then I tested using [short]{longer version} in orgmode sections of the file. It worked, except it acted as if the longer version section heading was just "{" and "longer version" was body text! What is up with that?
Since version 8.0 the "org-export-latex-classes" strategy won't work anymore.
Instead, and dare I say much more elegantly, you can set the ALT_TITLE property for the heading.
See http://orgmode.org/manual/Table-of-contents.html.
The following org code:
* The Long Title of Section 1
:PROPERTIES:
:ALT_TITLE: Section 1
:END:
Lorem ipsum.
** The Long Title of Subsection 1-1
:PROPERTIES:
:ALT_TITLE: Subsection 1-1
:END:
Dolor sit amet.
will export to LaTeX as:
[...]
\section[Section 1]{The Long Title of Section 1}
\label{sec-1}
Lorem ipsum.
\subsection[Subsection 1-1]{The Long Title of Subsection 1-1}
\label{sec-1-1}
Dolor sit amet.
You had the right idea with creating your own LaTeX class. The problem lies with the way the templates are filled by the default org-fill-template function. I'm not so great with Lisp, but this this hack will do the trick. Add the following to your .emacs file:
(defun my-section (level text)
(let* ((in "") (out "")
(short-title (if (string-match "\\[.*\\]" text)
(substring text (match-beginning 0)
(match-end 0))
nil)))
(if short-title (setq text (substring text (match-end 0) -1)))
(setq in (org-fill-template
"\\section%S{%s}"
(list (cons "S" (or short-title ""))
(cons "s" (or text ""))))
out (copy-sequence "\\end{section}"))
(cons text (list in out in out))))
(add-to-list 'org-export-latex-classes
'("test"
"\\documentclass{article}"
my-section))
This declares a new latex class by adding a "test" class to the org-export-latex-classes. Here we declare, instead of the normal \\section{%s} stuff a function that takes two parameters --- the current level and the headline text --- and returns a modified cons cell. Some details of this information can be found in org-latex-export.el.
Above the adding to the list is where we actually define the function. This is honestly a hacky version, and I pulled a lot from the org-beamer-sectioning function in org-beamer.el file. This function basically searches the headline for anything that is like a LaTeX short label (i.e. [....]) removes it from the headline and sticks it before the actual section label. Right now this hack will only generate \section statements, no matter how deep the level - if you want something more intelligent like \chapter or \subsection or even unnumbered items, you'll need to do some more Lisping; again, see org-beamer.el for some help.
This bit of org-mode code
#+latex_class: test
* [short 1] this is 1 star
test
** this is a 2 star
test
*** [short 3] this is a 3 star
test
**** what happens
exports to LaTeX as (only relevant sections shown here):
\section[short 1]{ this is 1 star}
\label{sec-1}
test
\section{ this is a 2 star }
\label{sec-1-1}
test
\section[short 3]{ this is a 3 star}
\label{sec-1-1-1}
test
\section{ what happens }
\label{sec-1-1-1-1}
\end{section}
\end{section}
\end{section}
\end{section}
Although it's not a straight org-mode solution, it seems to work and can be a starting point for you. One of these days I might try to write it up properly and get it folded into the org-mode distribution.
It is possible to use the following commands in latex to define the text that should appear in the header to replace section names. But the TOC will still contain the original names.
\chaptermarks
\sectionmarks
\subsectionmarks
...
So, in org-mode you can write
* Long section title
#+LaTeX: \sectionmark{Short title}
edit: it actually doesn't work on the very page where the section name appears. On this one only, the full name is still put in the header.