9

I use org-edit-special and it's really convenient, when editing source code, that's stored in org files. However I often only want to copy some code and I'm used to the highlighting of highlight-parentheses-mode when I'm reading elisp and I only want it to be turned on in this situation.

Another example is line numbers in large babel blocks. I avoid using files for my own code and I have several blocks that don't fit on my screen. As I don't use nlinum in my org files this would be nice to additionally emphasize large code blocks.

Is it possible to enable the features of minor modes in org buffers, but only activate them for certain blocks ? Just like org-src-fontify-natively enables syntax highlighting in source code blocks.

3 Answers 3

6
+25

I don't know a way to do this. There is mmm-mode, which allows you to have multiple major modes in one buffer. It is not obvious that mode hook functions get run though to setup minor modes, e.g. I do not see numbers in code blocks, and lispy is not active in elisp blocks.

For temporary line numbers in code blocks see: http://kitchingroup.cheme.cmu.edu/blog/2015/10/13/Line-numbers-in-org-mode-code-blocks/

In org-mode, mmm-mode prevents you from then using org-edit-special, and also to run and capture the code blocks. Also, some things like checkers (via flycheck I guess) get applied to the whole buffer.

You could try this and see if you like it. Use mmm-mode-off to turn it off.

(require 'mmm-mode)
(setq mmm-global-mode 'maybe)
(mmm-add-mode-ext-class 'org-mode nil 'org-python)
(mmm-add-mode-ext-class 'org-mode nil 'org-elisp)

(mmm-add-group
 'org-python
 '((python-src-block
    :submode python-mode
    :face org-block
    :front "#\\+BEGIN_SRC python.*\n"
    :back "#\\+END_SRC")))

(mmm-add-group
 'org-elisp
 '((elisp-src-block
    :submode emacs-lisp-mode
    :face org-block
    :front "#\\+BEGIN_SRC emacs-lisp.*\n"
    :back "#\\+END_SRC")))
1
  • Thanks for the answer, but I can't get this to work. I'll take a look at it when I have a little more time. But mmm-mode looks promising.
    – bertfred
    Oct 31, 2016 at 12:33
4

After some comments and some modifications of the question it turned out that this is not the expected answer to the question. Nevertheless, applying local variables to source code blocks when they are edited with org-edit-special is very useful. So I do not delete this answer.


I already use local variables in source blocks for some time. Activating minor modes is one of the use cases for file local variables. Below I demonstrate how I activate flyspell-mode within some source code blocks. I think this scheme fits your aim to activate linum in source code blocks.

Add the following line to your initialization files:

(add-hook 'org-src-mode-hook 'hack-local-variables)

After evaluation of this line you can use local variables in source code blocks with org-edit-special.

You should add a page-break (i.e., C-q C-l) after the source block. This prevents emacs to interpret the local variables of the source block as local variables of the org-file.

Example:

* Some header

#+BEGIN_SRC text
Netter Text in Deutsch.
Local Variables:
ispell-dictionary: "de_DE"
eval: (flyspell-mode 1)
End:
#+END_SRC
^L

Some org-text

As for highlight-parenthesis-mode why don't you put it into emacs-lisp-mode-hook?

(add-hook 'emacs-lisp-mode-hook (lambda () (highlight-parentheses-mode 1)))

This is the best way if you want to have it always when you are editing emacs lisp -- independent on whether you edit it directly or via org-edit-special.

3
  • 1
    Thanks for the answer, but what I want is to use the features of those minor modes in org buffers. Just like org-src-fontify-natively enables syntax highlighting in the source code blocks.
    – bertfred
    Oct 28, 2016 at 8:28
  • @bertfred Okay, but, editing directly in the org-mode buffer is not what org-edit-special does and org-edit-special is what you have originally asked for. You should clarify your question.
    – Tobias
    Oct 28, 2016 at 8:46
  • 1
    I wanted to point out that I already do know org-edit-special and that it's not what I'm looking for. Sorry for not being clear enough in my question.
    – bertfred
    Oct 28, 2016 at 8:51
3

I am not aware of any established general method that would allow to restrict minor modes to sub-regions of a buffer.

Nevertheless, for minor modes that do not use restrictions you can use narrow-to-region on the minor-mode functions that affect the buffer. I demonstrate this for linenum-mode and highlight-parentheses-mode in the following lisp code. Line numbers are only shown and parentheses are only highlighted for the source block with the point in it.

If you want to try the code evaluate it and switch on bertfred-mode in your org-mode buffer.

Pityingly, the concept is not so simple for linenum-mode. There also a function for pre-redisplay-functions is required to make line-numberings responsive for point-motion functions without scrolling (i.e., when point enters a source block without scrolling).

  • An advantage over the method proposed by John Kitchin is that line-numbering remains permanent and consistent when one edits the source code block. The line numbering disappears if you place point in the region with his method (Note: I did not try this method but I watched the end of his youtube video. Please give me a note if I misunderstood this part of the video. I will delete this section if the statement turns out to be wrong.)

  • An disadvantage with respect of the method proposed by John is that the border for line-numbering is shown in the full org-mode buffer -- also at places where no line-numbering takes place.

(defun org-narrow-to-block-contents ()
  "Narrow buffer to the current source block contents.
This is almost a copy of `org-narrow-to-block'."
  (interactive)
  (let* ((case-fold-search t)
     (blockp (org-between-regexps-p "^[ \t]*#\\+begin_.*"
                    "^[ \t]*#\\+end_.*")))
    (if blockp
    (narrow-to-region (save-excursion
                (goto-char (car blockp))
                (line-beginning-position  2))
              (save-excursion
                (goto-char (cdr blockp))
                (line-end-position 0)))
      (user-error "Not in a block"))))

(defun org-restrict-fun-to-src-block (oldfun &rest args)
  "Restrict minor-mode function to source block."
  (if bertfred-mode
      (when (org-in-src-block-p)
    (save-excursion
      (save-restriction
        (org-narrow-to-block-contents)
        (apply oldfun args))))
    (apply oldfun args)))

(defvar-local org-linum-redisplay nil
  "Update line numbers of source code blocks.")

(defun org-linum-redisplay-function (window)
  "Trigger linum update at `redisplay' "
  (when (and bertfred-mode
     (eq (window-buffer window) (current-buffer)))
    (let ((in-src-block (org-in-src-block-p))
      (selected-window (selected-window)))
      (when (and (null org-linum-redisplay)
         in-src-block)
    (linum-update-window selected-window))
      (setq org-linum-redisplay in-src-block))))

(define-minor-mode bertfred-mode
  "Use `linum-mode' and `highlight-paren-mode' for source blocks in `org-mode'."
  :lighter " BF"
  (if bertfred-mode
      (progn
    (advice-add #'linum-update-window :around #'org-restrict-fun-to-src-block)
    (advice-add #'hl-paren-highlight :around #'org-restrict-fun-to-src-block)
    (add-hook 'pre-redisplay-functions #'org-linum-redisplay-function nil t)
    (linum-mode 1)
    (highlight-parentheses-mode 1))
    (advice-remove #'linum-update-window #'org-restrict-fun-to-src-block)
    (advice-remove #'hl-paren-highlight #'org-restrict-fun-to-src-block)
    (remove-hook 'pre-redisplay-functions #'org-linum-redisplay-function t)
    (linum-mode 0)
    (highlight-parentheses-mode 0)))
3
  • Thanks! Really nice solution. Is it possible to enable highlight-paren-mode only in elisp blocks ? And the highlighted parens sometimes don't disappear and they sometimes don't appear on cursor movement commands, but only when using the mouse or other commands. Do you have any idea how this could be fixed ?
    – bertfred
    Oct 31, 2016 at 12:24
  • @bertfred I am using emacs 25.1.50.2 under ubuntu. When I try with emacs -q and load only the required packages (linum and highlight-parentheses) the parentheses are only highlighted within the source code blocks and parentheses don't disappear with the test file tn-home.de/test.org. I tried motion commands, mouse clicks, and editing.
    – Tobias
    Oct 31, 2016 at 14:30
  • @bertfred Please do not accept one of the three answers you got up to now. I do not like the current solutions. I started with the first answer -- which is nice but does not really answer your question. I wanted to provide you with something more appropriate with this answer if nothing better comes up. I knot that this answer is sub-optimal because it is a very special solution to your example use cases. Maybe there is somebody else who has a more general approach. Best regards,
    – Tobias
    Oct 31, 2016 at 14:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.