Change the node attributes in Org-mode Mind-Map - emacs

Trying to modify org-mind-map to change the attributes of the nodes and edges. I haven't really learned the internals of emacs and org-mode, and use them "as is" - without making modifications, and therefore not really understanding. So, it would be great if one could explain what custom options means and how to implement them in a org file. This will help me work with other org-mode files also. I do not know how to even call this problem properly, otherwise I would have google-fu'd this.
So, as an example, if I want to change the "shape" of node to "circle" for only a particular heading, where should that property be written within the headline of the org file? So in the example taken from the main project, this works.
* This is an org-mode tree with tags
:PROPERTIES:
:OMM-COLOR: GREEN
:OMM-LEGEND: Legend entry
:END:
To change the shape of the node, the documentation mentions using :OMM-NODE-FMT and something about custom options.
;;; Customizable Options:
;; Below is a list of customizable options:
;; `org-mind-map-default-node-attribs'
;; Alist of default node attributes and values.
;; default = '(("shape" . "plaintext"))
;; You can customize the style of the graph by adding :OMM-NODE-FMT and :OMM-EDGE-FMT properties
;; to the headlines in the tree.
And in the code the documentation tells us,
(defcustom org-mind-map-default-node-attribs '(("shape" . "plaintext"))
"Alist of default node attributes and values.
Each item in the alist should be a cons cell of the form (ATTRIB . VALUE)
where ATTRIB and VALUE are strings.
For a list of value attributes, see here: https://graphviz.gitlab.io/_pages/doc/info/attrs.html"
:type '(alist :key-type (string :tag "Attribute") :value-type (string :tag " Value"))
:group 'org-mind-map)
So, for a headline in org-mode if I want to change the shape of the node, where should I put those options? Should I do something like this
* This is an org-mode tree with tags
:PROPERTIES:
:OMM-NODE-FMT: '(("shape" . "circle"))
:OMM-COLOR: GREEN
:OMM-LEGEND: Legend entry
:END:
This isn't working, of course. Please help!

To use :OMM-NODE-FMT: and :OMM-EDGE-FMT: you actually have to create a
function and add it to org-mind-map-node-formats respectively org-mind-map-node-formats.
Fortunately there are some auxiliary macros predefined to make this as easy as
possible:
for node: (org-mind-map-make-node-fn NAME DOC PROPS &optional SHAPE COLOR OTHER)
for edge: (org-mind-map-make-edge-fn NAME DOC PROPS &optional STYLE COLOR OTHER)
Unfortunately the node one seems to not have been updated after some changes to
org-mind-map and is therefore only useable with a little workaround (see below).
I created a new issue on the github page. The owner of org-mind-map has not been
active on github for a long time, so this will probably not be resolved.
This is how you do it:
:OMM-NODE-FMT:
(require 'ox-org)
(org-mind-map-make-node-fn circle "circle shape" nil "circle" nil nil)
;; until fixed: wrap inside a lambda.
(add-to-list 'org-mind-map-node-formats
'("circle" . (lambda (title tags color hm el &optional content images)
(org-mind-map-circle-node title tags color hm el))))
Check the documentation for org-mind-map-make-node-fn to get more infos about the arguments.
Then use as follows:
* circle
:PROPERTIES:
:OMM-NODE-FMT: circle
:END:
** rectangle
Result:
:OMM-EDGE-FMT:
This would be the way to do it, but it's not working (created another issue on the github page):
(require 'ox-org)
(org-mind-map-make-edge-fn dashed "dashed, red and empty arrowhead"
nil "dashed" "red" "arrowhead=empty")
(add-to-list 'org-mind-map-edge-formats
'("dashed" . org-mind-map-dashed-edge))
Even changing (setq org-mind-map-edge-format-default "[style=dotted]") has no
effect.
Only way to change edge style globally is by modifying (setq
org-mind-map-default-edge-attribs '(("style" . "dotted"))).

Related

Overriding emacs org-mode faces

I am trying to override the default syntax highlighting in org-mode and org-agenda-mode buffers.
To clarify my intention: my current reason for doing this is to highlight headings (or parts of headings) based on their tags. The built-in variable org-tag-faces only allows customisation of the tag itself, not the heading containing the tag.
With reference to the following related questions:
Emacs font lock mode: provide a custom color instead of a face
https://emacs.stackexchange.com/questions/8211/color-code-a-new-generic-character-combination
https://emacs.stackexchange.com/questions/8222/how-to-make-the-custom-font-lock-keywords-not-override-the-default-major-mode-fo#comment12615_8222
In thread 2 the accepted answer is to use font-lock for this purpose.
In thread 3 I am trying to achieve the exact opposite of the poster. The last comment by Jordon Biondo says:
take out the t from your keywords, what that t specifies is that font-lock should override already colored things.
Since I want to override already coloured things I am adding in the t but as far as I can tell the org-mode highlighting is still overriding my custom face.
In org-mode buffers this manifests as the main body of the heading text being changed but any other items such as todo-states, dates, tags etc. retaining there existing faces.
In org-agenda-mode buffers it completely fails to modify any aspect of the matched lines.
By way of a simple example here is some code I'm trying to use to set any lines containing :TT: to red in org-mode buffers:
(add-hook 'org-mode-hook
(lambda ()
(font-lock-add-keywords
'org-mode
'(
("^.*:TT:.*$" 0 '(:foreground "#FF0000") t)
))))
This mostly works for me:
(add-hook 'org-mode-hook
(lambda ()
(font-lock-add-keywords
'org-mode
'(("^.*:TT:.*$" . font-lock-warning-face)))))
The headline is red, although the tag itself is not.

Can Emacs' org-mode recognize tags within (instead of just at the endof ) a headline

I am learning how to use Emacs and org-mode, and am wondering whether Emacs can support tags within rather than just at the end of headlines (whether natively or through a package or configuration in ~/.emacs).
Put differently, Emacs natively supports tags in this form:
* This is a headline. :tag1:tag2:
Is there a way to get Emacs to recognize tags in the format below in addition?
* This is a headline with :tag1: and :tag2:.
I've been searching for answers for several hours, and haven't found this question anywhere else; I'd be grateful for any advice!
The real answer to this question is in #lawlist's comment above, that (to quote #lawlist) it "is not possible [to get org-mode to recognize tags within a line of text instead of at the end of the line] without substantially modifying several aspects of org-mode yourself."
For this reason, if #lawlist writes the comment up as an answer, I'll accept it. I'm also writing up this additional answer, though, for anyone like me who comes along and, learning this, wants a way to take some text and automatically generate org-mode tags for it. Following the discussion in the comments above, I've written a function in elisp below, which allows a user to highlight some text and automatically find any tags within the text (here, in the form {{tag}}) and concatenate them in org-mode tag format at the end of the first line.
(defvar tag-regexp-for-generating-org-mode-tag-list-from-text "{{\\(.*?\\)}}"
"A regular expression, in double-quotes, used for finding 'tags' within lines of text (these can then be translated into org-mode syntax tags.
For example, in the string \"This text contains the 'tags' {{tag1}} and {{tag2}}\", the default regular expression
\"{{\\(.*?\\)}}\"
would find \"tag1\" and \"tag2\", which could then be transformed into org-mode syntax tags, \":tag1:tag2:\"")
;; Following https://emacs.stackexchange.com/a/12335, use just the selected region.
(defun generate-org-mode-tag-list-from-selected-text (beginning-of-selected-region end-of-selected-region)
"Take a highlighted section of text, find all strings within that text that match the search parameters defined in the variable tag-regexp-for-generating-org-mode-tag-list-from-text (by default, strings of the form {{tag1}} {{tag2}}), and concatenate them into a set of org-mode tags (:tag1:tag2:)
When text is highlighted, the argumentes beginning-of-selected-region and end-of-selected-region will be automatically populated.
"
(interactive "r") ;; 'r' mode will auto-populate 'beginning-of-selected-region' and 'end-of-selected-region' above with the values of region-beginning and region-end.
(if (use-region-p) ;; If a region is actively highlighted
(progn ;; Start a multi-line sequence of commands
;; Following https://learnxinyminutes.com/docs/elisp/, go to the beginning-of-selected-region (here, of the selected region), and do a find-and-replace.
(setq list-of-tag-strings (list)) ;; Create a blank list, which we'll fill in below.
(goto-char beginning-of-selected-region) ;; Go to the beginning of the selected region (we'll then search forward from there.
;; A regex of "{{\\(.*?\\)}}" below looks for tags in {{this}} form. You can specify any other regex here instead.
(while (re-search-forward tag-regexp-for-generating-org-mode-tag-list-from-text end-of-selected-region 't) ;; Search forward, but only up to the end-point of the selected region (otherwise, end-of-selected-region could be replaced with nil here).
(add-to-list 'list-of-tag-strings ;; Add to the list called list-of-tag-strings
(replace-regexp-in-string "[[:space:]|:|-]+" "_" (match-string 1)) ;; Since org-mode tags cannot have spaces or colons (or dashes?) within them, replace any of those in the first capture group from the regular expression above ('match-string 1' returns whatever was in the parentheses in the regular expression above) with an underscore.
t) ;; Append (first checking for duplicate items) the first capture group from the regular expression above (i.e., what's inside the parentheses in the regular expression) to a list. The t tells the function to append (rather than prepend) to the list.
) ;; End of while statement
;; Go to the end of the first line of the selected region.
(goto-char beginning-of-selected-region)
(end-of-line)
(if (> (length list-of-tag-strings) 0) ;; If the length of the list of found tags is greater than 0:
(insert " " ":" (mapconcat 'identity list-of-tag-strings ":") ":")) ;; Insert two spaces, a ':', the items from the list each separated by a ':', and a final ':'.
(message "Tags gathered from the selected region (which comprises character markers %d to %d) and printed on the first line of the region." beginning-of-selected-region end-of-selected-region))
;; 'Else' part of the statement:
(message "No region is selected for gathering tags. To run the function, you need to highlight a region first.")
))
You can then highlight text like this, and run the function with M-x generate-tag-list-from-selected-text:
This is a test {{with}} some {{tags}} in it.
This is another test with an {{additional tag}} and {{one:more}}.
This text will then become
This is a test {{with}} some {{tags}} in it. :with:tags:additional_tag:one_more:
This is another test with an {{additional tag}} and {{one:more}}.
Since this is the first function I've written in elisp, I used two sources for understanding the basics of elisp syntax, specifically regarding a) using just a selected area of text and b) running find-and-replace operations on that text. Given that the function uses the generic structure of the code vs. its specific content, I'm thinking that I'm within my rights to open up the function with a CC0 dedication (I do this because of StackOverflow's ongoing discussion about licensing of code on this site).

Secret structure in org-mode?

I'm wondering I if there's any functionality in org-mode that can make me able to operate with secret structure, that is: structure that I can see when I'm editing but that is treated as if it wasn't there when exporting. It's mainly importing when I export to ascii.
Example:
I would like this in the .org file:
* Normal heading
** Secret heading 1
Some text 1
** Secret heading 2
Some text 2
** Secret heading 3
Some text 3
To be exported to this:
Normal heading
--------------
Some text 1
Some text 2
Some text 3
What makes the headings secret can be anything like a tag, a property or something else but the secret headings should be foldable.
Edit:
Found this solution (from here) (I'm using org-mode 7.9.3 f. It doesn't work. Headlines with the :ignoreheading: tag are still displayed:
;; backend aware export preprocess hook
(defun sa-org-export-preprocess-hook ()
"My backend aware export preprocess hook."
(save-excursion
(when (eq org-export-current-backend 'latex)
;; ignoreheading tag for bibliographies and appendices
(let* ((tag "ignoreheading"))
(org-map-entries (lambda ()
(delete-region (point-at-bol) (point-at-eol)))
(concat ":" tag ":"))))))
(add-hook 'org-export-preprocess-hook 'sa-org-export-preprocess-hook)
You can use the EXCLUDE_TAGS property and tag certain sections, then export with org-export-exclude-tags. E.g:
#+EXCLUDE_TAGS: noexport
* Public Section
* Secret Section :noexport:
Documentation here.
What you want is addressed here -- and here's the answer (repeated):
Add the following to your .emacs file:
(require 'ox-extra)
(ox-extras-activate '(ignore-headlines))
Use the ignore tag on headlines you'd like to have ignored (while not ignoring their content)
I upgraded to org-mode 8.2.5h and with that this works:
(defun sa-ignore-headline (contents backend info)
"Ignore headlines with tag `ignoreheading'."
(when (and (org-export-derived-backend-p backend 'latex 'html 'ascii)
(string-match "\\`.*ignoreheading.*\n"
(downcase contents)))
(replace-match "" nil nil contents)))
(add-to-list 'org-export-filter-headline-functions 'sa-ignore-headline)
But only if you don't have the options: #+OPTIONS: tags:nil. Guess it's sort of obvious that tags shouldn't be filtered away before a filtering that relies on a certain tag is invoked - but that bugged me for quite some time.
Note: when exporting to ascii the headline underlining will remain without the headline, so you need this setting too:
(setq org-ascii-underline (quote ((ascii) (latin1) (utf-8))))
... to remove headlines all together.
In the linked question about the ignoreheading tag I posted a working, simpler org-export-before-parsing-hook solution for Org 8.2.10 in Emacs 24.1.1.
It is based on the documentation of the org-map-entries function which also states that it wraps it in save-recursion automatically. It is simpler than using concat because the second argument to org-map-entries is an agenda-style match string.
While trying to solve the same problem I found this thread describing how to extend ox-extra.el using a notignore tag. This method does not export any headings unless explicitly tagged notignore. Content of the heading are exported normally.
For most of my documents the notignore approach is more useful than the 'ignore' approach because the majority of headings are 'secret structure' not intended for export.
Presently I have notignore-headlines activated in my init.el file. Can anyone suggest a way to activate this on a per document basis.

Emacs lisp: "Fall through" type for defcustom.

TL;DR
Is there some standard fallback handling in the customize
system, for handling partially invalid composite customization
variables, e.g. an alist where one entry is not a cons?
Long Version
The customize-mechanism of emacs is quite powerful by using
composite :type arguments to defcustom provides a nifty
unified interface for customizing variables.
However, when for whatever reason a single entry of the variable
is wrong the whole system breaks down and it will just show the
bare s-expression. There is then no help to fix this expect for
deleting the customizations hoping that the default value matches
the type description.
At least that is what I have experienced so far.
If I have a customization variable that is a complicated data
structure, is there some mechanism that allows showing only the
corrupted part of the variable as a bare s-expression?
Think e.g. about
(defcustom x
'((org-mode . "a\\|b")
(text-mode . "b\\|c"))
"Some variable"
:group 'x
:type '(repeat
(cons :tag "Entry"
(function :tag "Mode" :value text-mode)
(regexp))))
Normally M-x customize-variable x will no display a nice input mask.
Hide X:
INS DEL Entry:
Mode: org-mode
Regexp: a\|b
INS DEL Entry:
Mode: text-mode
Regexp: b\|c
INS
State : STANDARD.
Some variable
Groups: X
When I now do
(add-to-list 'x 1)
the mask becomes a significantly less user friendly
Hide x:
'(1
(org-mode . "a\\|b")
(text-mode . "b\\|c"))
State : CHANGED outside Customize. (mismatch)
Some variable
Groups: X
Now of course I can include a fallback option by changing the
definition to something like
(defcustom x
'((org-mode . "a\\|b")
(text-mode . "b\\|c"))
"Some variable"
:group 'x
:type '(repeat
(choice
(cons :tag "Entry"
(function :tag "Mode" :value text-mode)
(regexp))
(sexp :tag "MISMATCHED ENTRY!"))))
which gives a customization mask
Hide X:
INS DEL Choice: Value Menu MISMATCHED ENTRY!: 1
INS DEL Choice: Value Menu Entry:
Mode: org-mode
Regexp: a\|b
INS DEL Choice: Value Menu Entry:
Mode: text-mode
Regexp: b\|c
INS
State : CHANGED outside Customize.
Some variable
Groups: X
However this does now include an awkward drop-down menu that
gives the user the choice between an entry and an invalid value.
Rather I'd have the drop down value hidden by default and shown
only when there is a mismatch with the valid option. As a user my
first thought seeing such would be along the lines of “”.
Is there some standard way in the customization system to handle
partly invalid values? I couldn't find any in the documentation.¹
¹ http://www.gnu.org/software/emacs/manual/html_node/elisp/Customization-Types.html#Customization-Types
You can edit (and save) the "raw sexp" displayed. I agree it would be even better if the valid part were displayed using the usual widgets and only the invalid part is displayed as "raw sexp". Patches welcome.
You might want to use/implement your widget's :validate.
From The Emacs Widget Library – 5 Basic Types (read with C-h i m Widget RET m Basic RET):
‘:validate’
A function which takes a widget as an argument, and returns ‘nil’
if the widget’s current value is valid for the widget. Otherwise
it should return the widget containing the invalid data, and set
that widget’s ‘:error’ property to a string explaining the error.
The following predefined function can be used:
-- Function: widget-children-validate widget
All the ‘:children’ of WIDGET must be valid.
In your example, all widgets in use should have :validate implemented, so you need only apply it.

Colorize snippets of text in emacs

Suppose I have a few words I would like to highlight, so I want to change the color of those few words only to, say, green.
Is there an easy way to do this in emacs?
Thank you.
This is what I've done, using font-lock-add-keywords. I wanted to highlight the words TODO:, HACK:, and FIXME: in my code.
(defface todo-face
'((t ()))
"Face for highlighting comments like TODO: and HACK:")
(set-face-background 'todo-face cyan-name)
;; Add keywords we want highlighted
(defun add-todo-to-current-mode ()
(font-lock-add-keywords nil
'(("\\(TODO\\|HACK\\|FIXME\\):" 1 'todo-face prepend))
t))
Use library HighLight. You can use overlays or text properties. You can save the highlighting permanently or let it be temporary. You can highlight in many ways (regexp, mouse-drag,...). Lots of possibilities.
The highlight package has hlt-highlight-regexp-region and hlt-highlight-regexp-to-end, which do exactly what you want.
http://www.emacswiki.org/cgi-bin/wiki/highlight.el
Use the function font-lock-add-keywords to define a new matcher for the string in question, binding that matcher to some face you've defined that will display as green. For example:
(font-lock-add-keywords nil
'("\\<foo\\>" 0 my-green-face))
Note that you can specify a particular mode where I wrote nil above, and the matching forms can take on any of six different styles. See the documentation for the variable font-lock-keywords for the rules and a few examples.
If you want them highlighted only temporarily, I find M-x highlight-regexp command very helpful, it is especially nice for looking through log files of sorts. For example you made yourself a logging class that outputs some tracing info like MyClass::function() > when function is run and MyClass::function() < when it exits (can be especially useful sometimes when debugging multithreading issues) then you just ask emacs to highlight some of them green and other red and then you can see how did the execution go.
I use what Dimitri suggested. In particular, I have the following two lines in my .emacs
(global-hi-lock-mode t)
(global-set-key (kbd "C-M-h") 'highlight-regexp)
Every-time I need to highlight a certain word (or regex) in a buffer, I hit "C-M-h", which then prompts me for the word (or regex) I want to be displayed differently and then for a face to display it in.