20

is there a way to keep only source code inside source code, that is make #+BEGIN_SRC and #+END_SRC invisible? It's cosmetic but it makes things clearer when one have to deal with a lot of short code snippets. For exemple:

(defun org-xor (a b)
          "Exclusive or."
          (if a (not b) b))

instead of :

  #+BEGIN_SRC emacs-lisp
       (defun org-xor (a b)
          "Exclusive or."
          (if a (not b) b))
  #+END_SRC
JeanPierre
  • 7,323
  • 1
  • 18
  • 37
loukios
  • 815
  • 1
  • 8
  • 19
  • My comment underneath the question in this semi-related thread shows how to programmatically hide the source block headers/footers. http://emacs.stackexchange.com/q/26163/2287 -- i.e., `(save-excursion (goto-char (point-max)) (while (re-search-backward "#\\+BEGIN_SRC\\|#\\+END_SRC" nil t) (let ((ov (make-overlay (line-beginning-position) (1+ (line-end-position))))) (overlay-put ov 'invisible t))))` To unhide everything, use `(remove-overlays)`. Further work needs to be done for individual entries, and removing only select overlays (instead of all overlays), but that is the general idea. – lawlist Sep 30 '16 at 14:51
  • Thanks, this is interesting...I will play around with this. – loukios Sep 30 '16 at 18:59

6 Answers6

12

The face for all lines starting with #+ is called org-meta-line.

You can customize this face smaller, darker, etc. to make it less visible.

Juancho
  • 5,395
  • 15
  • 20
  • 1
    Indeed. As an example, I have it set up using `(set-face-attribute 'org-meta-line nil :height 0.8 :slant 'normal)`. I find it helps quite a bit. – Harald Hanche-Olsen Sep 30 '16 at 13:37
  • Thanks for your answer, it does help. I've changed the height btw but it does not have any effect... – loukios Sep 30 '16 at 18:59
  • See this Emacs Lisp documentation on the options you can assign to `org-meta-line` https://www.gnu.org/software/emacs/manual/html_node/elisp/Face-Attributes.html – salotz Oct 06 '16 at 14:12
4

I use the following piece of code that goes some of the way. It's not perfect. Maybe it will become a proper minor-mode some day. (source).

Screenshot of the resulting code

(with-eval-after-load 'org
  (defvar-local rasmus/org-at-src-begin -1
    "Variable that holds whether last position was a ")

  (defvar rasmus/ob-header-symbol ?☰
    "Symbol used for babel headers")

  (defun rasmus/org-prettify-src--update ()
    (let ((case-fold-search t)
          (re "^[ \t]*#\\+begin_src[ \t]+[^ \f\t\n\r\v]+[ \t]*")
          found)
      (save-excursion
        (goto-char (point-min))
        (while (re-search-forward re nil t)
          (goto-char (match-end 0))
          (let ((args (org-trim
                       (buffer-substring-no-properties (point)
                                                       (line-end-position)))))
            (when (org-string-nw-p args)
              (let ((new-cell (cons args rasmus/ob-header-symbol)))
                (cl-pushnew new-cell prettify-symbols-alist :test #'equal)
                (cl-pushnew new-cell found :test #'equal)))))
        (setq prettify-symbols-alist
              (cl-set-difference prettify-symbols-alist
                                 (cl-set-difference
                                  (cl-remove-if-not
                                   (lambda (elm)
                                     (eq (cdr elm) rasmus/ob-header-symbol))
                                   prettify-symbols-alist)
                                  found :test #'equal)))
        ;; Clean up old font-lock-keywords.
        (font-lock-remove-keywords nil prettify-symbols--keywords)
        (setq prettify-symbols--keywords (prettify-symbols--make-keywords))
        (font-lock-add-keywords nil prettify-symbols--keywords)
        (while (re-search-forward re nil t)
          (font-lock-flush (line-beginning-position) (line-end-position))))))

  (defun rasmus/org-prettify-src ()
    "Hide src options via `prettify-symbols-mode'.

  `prettify-symbols-mode' is used because it has uncollpasing. It's
  may not be efficient."
    (let* ((case-fold-search t)
           (at-src-block (save-excursion
                           (beginning-of-line)
                           (looking-at "^[ \t]*#\\+begin_src[ \t]+[^ \f\t\n\r\v]+[ \t]*"))))
      ;; Test if we moved out of a block.
      (when (or (and rasmus/org-at-src-begin
                     (not at-src-block))
                ;; File was just opened.
                (eq rasmus/org-at-src-begin -1))
        (rasmus/org-prettify-src--update))
      ;; Remove composition if at line; doesn't work properly.
      ;; (when at-src-block
      ;;   (with-silent-modifications
      ;;     (remove-text-properties (match-end 0)
      ;;                             (1+ (line-end-position))
      ;;                             '(composition))))
      (setq rasmus/org-at-src-begin at-src-block)))

  (defun rasmus/org-prettify-symbols ()
    (mapc (apply-partially 'add-to-list 'prettify-symbols-alist)
          (cl-reduce 'append
                     (mapcar (lambda (x) (list x (cons (upcase (car x)) (cdr x))))
                             `(("#+begin_src" . ?✎) ;; ➤  ➟ ➤ ✎
                               ("#+end_src"   . ?□) ;; ⏹
                               ("#+header:" . ,rasmus/ob-header-symbol)
                               ("#+begin_quote" . ?»)
                               ("#+end_quote" . ?«)))))
    (turn-on-prettify-symbols-mode)
    (add-hook 'post-command-hook 'rasmus/org-prettify-src t t))
  (add-hook 'org-mode-hook #'rasmus/org-prettify-symbols))
rasmus
  • 2,682
  • 13
  • 20
3

The org-present package does this. Specifically, it is taken care of by (org-present-add-overlays), which then uses (overlay-put) to make the text invisible. This approach is further described in section 39.6 of the Emacs Lisp manual.

James Brusey
  • 169
  • 1
  • 5
1

The face for #+BEGIN is org-block-begin-line and for #+END is org-block-end-line. If you already have a dark theme, something like this will make it well nigh invisible, and can be tweaked to your liking or to fit a light theme (hint for light, start with #ffffff):

(set-face-attribute 'org-block-begin-line nil :foreground "#000000")
(set-face-attribute 'org-block-end-line nil :foreground "#000000")

For example, here is the code you posted, with these face attributes set, on top of the Spacemacs dark theme:

begin and end nearly invisible

Note that this will apply not only to SRC blocks but also to QUOTE blocks, etc.

Keith Pinson
  • 269
  • 1
  • 3
  • 25
1
  ;; Org mode
  (add-hook 'org-mode-hook
            '(lambda ()
               ;; Hide org block lines

               ;; Unset any previous customization for the background color
               (set-face-attribute 'org-block-begin-line nil :background 'unspecified)
               (set-face-attribute 'org-block-end-line nil :background 'unspecified)

               ;; Set the foreground color to the value of the background color
               (set-face-attribute 'org-block-begin-line nil
                :foreground (face-background 'org-block-begin-line nil 'default))
               (set-face-attribute 'org-block-end-line nil
                :foreground (face-background 'org-block-end-line nil 'default))
               ))

Sets the foreground color to the background color, which effectively means hiding the text.

Note: you might need to restart emacs (instead of just reloading the config) for the changes to take effect.

Ejez
  • 111
  • 2
0

Yet another way to do this is using hide-lines.

The following code is from my emacs config (with a few modifications because I have a lot of self-written macros).

(use-package hide-lines :commands hide-lines hide-lines-matching)

;; The line ~(overlay-put overlay 'invisible 'hl)~ in [[helpfn:][hide-lines-add-overlay]] wouldn't
;; work with the argument =hl=. It works when you set it to =t= instead. Maybe =hl= is
;; depreciated.

(define-advice hide-lines-add-overlay (:override (start end) fix-adding-overlay)
  "Add an overlay from `start' to `end' in the current buffer.
Push the overlay into `hide-lines-invisible-areas'."
  (let ((overlay (make-overlay start end)))
    (setq hide-lines-invisible-areas (cons overlay hide-lines-invisible-areas))
    (overlay-put overlay 'invisible t)))

(defun org/hide-source-block-delimiters ()
  "Hide property drawers."
  (interactive)
  (let (selective-display-ellipses org-ellipsis)
    ;; If properties are folded, ellipsis will show.
    (org-show-all)
    (hide-lines-matching (rx "#+" (or "begin" "end") "_src" (* nonl) "\n"))))
Aquaactress
  • 1,393
  • 8
  • 11