org-mode: counter for items, visible in export - emacs

I'm writing a document in org-mode. Is it possible to use a counter for exercises that are spread across the document instead of numbering them myself? I am exporting this to HTML and PDF (via LaTeX). Example:
* First chapter
Blabla.
Exercise 1.
* Second chapter.
Blabla
Exercise 2.
* Third chapter.
Exercise 3.
Exercise 4.

I solved this using dynamic blocks in org-mode.
In my init.el I defined the following:
(setf exercise-counter 0)
(defun org-dblock-write:reset-exercise-counter (params)
(setf exercise-counter 0))
(defun org-dblock-write:exercise (params)
(incf exercise-counter)
(insert (concat "Exercise " (int-to-string exercise-counter) ".")))
At the top of my document I reset the counter:
#+BEGIN: reset-counter
#+END
Spread across the document I can now put this:
#+BEGIN: exercise
#+END
Blablabla.
#+BEGIN: exercise
#+END
Blablabla.
After calling org-update-all-dblocks the right numbers will be inserted.
Open for suggestions if anything can be improved.
How do I call org-update-all-dblocks automatically when exporting?
ANSWER: like this: (add-hook 'org-export-first-hook 'org-update-all-dblocks)

Related

How to get org mode file "Title" and other file-level properties from an arbitrary file?

I have files with this format
#+TITLE: Magit Cheatsheet
:PROPERTIES:
:Status: Open
:Tags: tools, emacs, org, magit
:Creation: [2021-03-03 Wed]
:END:
I'd like to be able to read the title and these properties for a given file name (not the currently open file) with elisp. I found this but it isn't working for me and seems too complex for something as simple as this.
I cannot answer the question about the properties until you fix the file (how you fix it will affect the proposed solution).
For the title however, the following code works (Q: what is the shortest lie in computing? A: It works!):
#+begin_src elisp :results drawer
(defun ndk/get-keyword-key-value (kwd)
(let ((data (cadr kwd)))
(list (plist-get data :key)
(plist-get data :value))))
(defun ndk/org-current-buffer-get-title ()
(nth 1
(assoc "TITLE"
(org-element-map (org-element-parse-buffer 'greater-element)
'(keyword)
#'ndk/get-keyword-key-value))))
(defun ndk/org-file-get-title (file)
(with-current-buffer (find-file-noselect file)
(ndk/org-current-buffer-get-title)))
(ndk/org-file-get-title "/tmp/foo86.org")
#+end_src
The main function is the last one ndk/org-file-get-title which takes care of opening the file and running the ndk/org-current-buffer-get-title function on the resulting buffer. The latter functions uses the almighty org-element-map function on a subset of the data that the parser returns (that's for efficiency only): we map the ndk/get-keyword-key-value function on all the keyword elements. This function returns a (key value) list for each of the keywords that it gets called on, and the mapper accumulates those pairs into a list. We then select the pair that contains the string "TITLE" as the key, and the (nth 1 ...) call gets the value part of the pair (the key part would be (nth 0 ...)).
A minor variation of this would also work for dealing with #+PROPERTY keywords, but dealing with property drawers under a headline would be more complicated (I think - I haven't tried it out).

How to vote for a heading in org-mode?

I have thousands of headings in org-mode agenda files and use this structure for a long time. I want to set up org-mode so that it has a voting system. I press a hotkey, org-mode adds +1 to a heading and then I can filter the headings by the number of votes.
Upd. I have to clarify the question. I can see how this can be done:
* heading
:PROPERTIES:
:VOTES: 5
:END:
1) property drawers are searchable http://orgmode.org/worg/org-tutorials/advanced-searching.html, so I can use the comparison operators for filtering, e.g. VOTES>4.
2) I can use the propertу API http://orgmode.org/manual/Using-the-property-API.html for increasing and decreasing the counter.
Here is the solution. I add + to a speed command in org-mode. You could also bind this to some key.
(defun plusone ()
"Increase the VOTES property in an org-heading by one. Create
the property if needed."
(interactive)
(org-entry-put
(point)
"VOTES"
(format "%s" (+ 1 (string-to-number
(or
(org-entry-get (point) "VOTES")
"0"))))))
(add-to-list 'org-speed-commands-user '("+" . (plusone)))

folding multi-line-comments in emacs automatically

in my .emacs configuration, i have the following :
(defun fold-long-comment-lines ()
"This functions allows us to fold long comment lines
automatically in programming modes. Quite handy."
(auto-fill-mode 1)
(set (make-local-variable 'fill-no-break-predicate)
(lambda ()
(not (eq (get-text-property (point) 'face)
'font-lock-comment-face)))))
the above gets invoked as part of "c-mode-common-hook" and correctly provides folding long comment lines automatically.
however, the above thing works indiscriminately, whether i am using a single line comment e.g. describing struct fields, or multi-line comments describing some complicated piece of code.
so, the basic question is, how can i get automatic folding of long comment lines only if it is a multi-line comment ?
thanks
anupam
edit-1: multi-line-comment explanation
when i say "multi-line-comment", it basically means comments like this:
/*
* this following piece of code does something totally funky with client
* state, but it is ok.
*/
code follows
a correspondingly, a single line comment would be something like this
struct foo {
char buf_state : 3; // client protocol state
char buf_value : 5; // some value
}
the above elisp code, dutifully folds both these comment lines. i would like to fold only the former, not the latter.
If you only want it to affect auto-fill-mode and not general filling (e.g. not when you hit M-q), then your code can be replaced by setting comment-auto-fill-only-comments. As for having it apply only to "multi-line comments", I think you're first going to have to explain what is the difference between. Are you saying that you only want to auto-fill when the comment already spans more than one line, or is there some other characteristic of a comment that can let Emacs figure out that a comment that currently only spans a single line can be spread over multiple lines.
You could try something like:
(set (make-local-variable 'fill-no-break-predicate)
(lambda ()
(let ((ppss (syntax-ppss)))
(or (null (nth 4 ppss)) ;; Not inside a comment.
(save-excursion
(goto-char (nth 8 ppss))
(skip-chars-backward " \t")
(not (bolp))))))) ;; Comment doesn't start at indentation.

show org-mode outline up to a certain heading level

I'm making an outline for my thesis using org-mode, and I'd like to show all headings up to a certain level (e.g. all level-1 and level-2 headings).
I haven't found anything about that in the org-mode manual. Cycling shows either only level-1 headings, or all headings, which is too much information in my outline right now.
Thanks,
daniel.
Update: I found a workaround for his: set the variable org-cycle-max-level. This is a global setting, though.
Just stumbled on this question. One year later but what the heck.. There are commands for this that allows you to show headings to a certain level.
One command is C-<n> C-c tab will show subheadings up to level <n> (<n>=1,2,3...).
Another command is C-<n> S-tab which will operate on the whole buffer. It shows all headings up to level <n> (<n>=1,2,3...)
I found a solution that suits me: The command org-content shows the folder hierarchy, and giving it a numeric argument does exactly what I want: limit the maximum level shown. In my example, I wanted to show 2 levels, so I can do C-2 M-x org-content <RET>.
I also added my own command to my .emacs init file, binding that command to C-c m
(defun org-show-two-levels ()
(interactive)
(org-content 2))
(add-hook 'org-mode-hook
(lambda ()
(define-key org-mode-map "\C-cm" 'org-show-two-levels)))
If the prefix arguments from M. Kullman's answer take too much mental capacity for you (a limited resource when you are thinking hard about something else at the same time) then you can use the following functions to expand contract headings
(defvar hf-org-depth-point nil)
(defvar hf-org-depth-depth nil)
(defun hf-org-depth-increase ()
(interactive)
(hf-org-depth-incr 1))
(defun hf-org-depth-decrease ()
(interactive)
(hf-org-depth-incr -1))
(defun hf-org-depth-incr (incr)
(when (not (equal (point) hf-org-depth-point))
(setq hf-org-depth-point nil)
(setq hf-org-depth-depth 0))a
(setq hf-org-depth-point (point))
(setq hf-org-depth-depth (max (+ hf-org-depth-depth incr) 0))
(hide-subtree)
(show-children hf-org-depth-depth))
```
I am way late to the party, but let us add a simple way for posterity. Simply use Cycle Global Visibility (<backtab>). If your headings are open, it will close them. However, if you apply it repeatedly with all headings collapsed, they will open to the level you want.
I use it from the keyboard by <SHIFT>+<TAB>. You can also find it in the Org menu (in Emacs) under Show/Hide -> Cycle Global Visibility ()

How do I get emacs to indent other things like it indents define?

So Emacs is pretty good at editing Scheme/Racket/Lisp code. One good thing it does is when you type code like:
(define (make-position-table)
(for/list ([i (in-range 256)])
`()))
It does a very clever thing and indents the second line to two columns. Now the third line it does what it does with all lisp code and indents that to align all the arguments.
How do I customize Emacs so that it indents the third line as though I was introducing a new body. What I'd like is:
(define (make-position-table)
(for/list ([i (in-range 256)])
`()))
I'm guessing this is possible and that I just haven't figured out the arcane Emacs variable to set. Does anyone know how to do this?
You can add this to your .emacs file:
(put 'for/list 'scheme-indent-function 1)
See also a hacked version of scheme mode that does many more racket-isms.
I believe (put 'for/list 'scheme-indent-function 'defun) should do what you want.
Repeat for other symbols. My .emacs includes
(mapc (lambda (sym) (put sym 'scheme-indent-function 'defun))
(list 'for 'for/list 'for/and 'for/or
'match 'case 'syntax-parse 'test-suite 'test-case
'define-syntax-rule 'match-let 'match-let*))
from the days when I was dabbling in PLT Scheme.