99

org-mode has the ability to render source code, with blocks of the following syntax:

#+NAME: <name>
#+BEGIN_SRC <language> <switches> <header arguments>
    <body>
#+END_SRC

Is there an existing command to quickly insert these blocks in org-mode, or do I need to use an external tool like yasnippet?

3

6 Answers 6

121

As @kaushalmodi mentions in the comments you can use (org) Structure Templates to speed up insertion of different types of blocks.

The general procedure is to insert < followed by a template selector (usually a single letter) on an otherwise empty line and press TAB.

The template selector for a generic source block template is s, so typing <s followed by TAB will give you this:

#+BEGIN_SRC 

#+END_SRC

Point will be positioned at the end of the first line.

This is a good first approximation of what you want to achieve, but this is Emacs, so let's make it better!

You can define custom templates by adding one or more entries to a variable called org-structure-template-alist. For example:

(add-to-list 'org-structure-template-alist '("n" "#+NAME: ?"))

This code adds a #+NAME: template to org-structure-template-alist, using n as a template selector. After expanding this template point will be positioned at the location of ?.

If you always name your code blocks, you can also overwrite the original version of the source block template with an extended version that includes the #+NAME: line:

(add-to-list 'org-structure-template-alist
             '("s" "#+NAME: ?\n#+BEGIN_SRC \n\n#+END_SRC"))

Typing <s followed by TAB will then give you:

#+NAME: 
#+BEGIN_SRC 

#+END_SRC

This is just the tip of the iceberg; you can use a similar approach to define additional templates for language-specific code blocks, code blocks with specific header arguments, etc.

11
  • 3
    Note: Easy Template is replaced with incompatible way in org-mode HEAD. I recommend to use yasnippet.
    – lurdan
    Apr 9, 2018 at 7:17
  • @lurdan is this still the case? I just tried <s TAB on Emacs 25 on Mac OS X and it seemed to work. Oct 23, 2018 at 15:53
  • 2
    @RudolfOlah Yes, at least for org-mode (git) HEAD. Even with emacs26, bundled org-mode still has org-try-structure-completion function (for Easy-templates). But anyway, it will be replaced by Structure-templates in the future. cf. code.orgmode.org/bzg/org-mode/commit/…
    – lurdan
    Oct 25, 2018 at 7:30
  • 8
    You now need (require 'org-tempo) to use <s TAB, but otherwise it works just as before.
    – Clément
    Feb 10, 2020 at 17:39
  • 15
    Nowadays it's C-c C-, which runs (org-insert-structure-template)
    – mgalgs
    Jan 8, 2021 at 19:24
15

Here's a function which inserts the code block:

(defun org-insert-source-block (name language switches header)
  "Asks name, language, switches, header.
Inserts org-mode source code snippet"
  (interactive "sname? 
slanguage? 
sswitches? 
sheader? ")
  (insert 
   (if (string= name "")
       ""
     (concat "#+NAME: " name) )
   (format "
#+BEGIN_SRC %s %s %s

#+END_SRC" language switches header
)
   )
  (forward-line -1)
  (goto-char (line-end-position))
  )
1
  • Because it’s better to have an org function to call than to copy-paste stuff from SE (people could write it themselves, but that’s probably what would happen). Oct 17, 2020 at 9:38
14

With just a few keystrokes, it is possible to insert empty structural blocks, such as ‘#+BEGIN_SRC’ … ‘#+END_SRC’, or to wrap existing text in such a block.

C-c C-, (org-insert-structure-template)

Documentation

3
  • I used to use Easy Templates, but this way is quite better for me. Thanks.
    – gsl
    Apr 17, 2020 at 11:22
  • C-c C-, means I hit c and then hit , with the Ctrl pressed? it does not work for me.
    – ZhaoGang
    May 21, 2021 at 2:39
  • 1
    C-, might not work in a terminal: it should work in GUI Emacs. You can always bind a different key to the function though: (define-key org-mode-map (kbd "C-c e") #'org-insert-structure-template). This is just an example: choose a key that is not used already.
    – NickD
    Jul 8, 2021 at 16:38
8

On my box 99% of the time I'm creating source blocks and 1% of the time I'm doing everything else. For the 1% Easy Templates are perfect and for the 99% I've got a YaSnippet.

  • It creates a unique NAME using org-id but that doesn't matter just us anything) and then it asks me what language I want to use limiting it those the ones that I told Org-Mode Literate Programming (babel)
  • Presents a list of language types that you told Org-Mode that you want to use, and to choose from, instead of typing every type (though I don't use all of them)
  • If the language has to generates a file it asks for the output file name

Here is the YaSnippet with my supporting code at the end.

# -*- mode: snippet -*-
# key: sc
# name: Source Block
# group: HELP
# contributor: gcr@wisdomandwonder.com
# expand-env: ((yas-indent-line 'fixed))
# --
#+NAME: ${1:`(help/org-id-new)`}
#+BEGIN_SRC ${2:$$(let ((langs (sort (-map (lambda (x) (symbol-name (car x))) (if (-contains? org-babel-load-languages '(js . t)) (-snoc org-babel-load-languages '(javascript . t)) org-babel-do-load-languages)) 'string<))) (yas-choose-value (if (-contains? langs "shell") (-snoc langs "sh") langs)))}${2:$(when (-contains? '("ditaa" "dot" "plantuml") yas-text) (concat " :file \\"./image/" (yas-field-value 1) ".png\\""))} $3
$0
#+END_SRC

It requires dash and org-mode loaded.

(require 'org-id)
(setq org-id-link-to-org-use-id 'nil)
(setq org-id-prefix (concat "org_" (user-real-login-name) "_" (format-time-string "%Y-%m-%d") "_" (system-name)))
(setq org-id-method 'uuid)
(defun help/org-id-new ()
  "Re-purposing `org-id' hit a snag when colons were forbidden in Source-Block
  names. Adding support for a user-defined Org-Id separator would have fixed
  this but with no benefit to Org-Id. So this function removes the colon
  instead.
 "
  (interactive)
  (let* ((gend (org-id-new))
         (newid (replace-regexp-in-string ":" "_" gend)))
    newid))

Here is an example of you might this id function:

C-u M-:
(insert (help/org-id-new))

Results in

org_gcr_2017-08-06_mara_DD608C9A-33B0-4A8D-9123-298746BE973Anil
1
;;; package --- Summary
;;; Commentary:
;;; Code:
(defvar org-sai-src-default "C++"
 "This is the list used to store the default label for source code section.")

(defun org-insert-src-block ()
  "Insert the source code section in `org-mode'."
  (interactive)
  (let* ((src-code-types
          '("emacs-lisp" "python" "C" "sh" "java" "js" "clojure" "C++" "css"
            "calc" "asymptote" "dot" "gnuplot" "ledger" "lilypond" "mscgen"
            "octave" "oz" "plantuml" "R" "sass" "screen" "sql" "awk" "ditaa"
            "haskell" "latex" "lisp" "matlab" "ocaml" "org" "perl" "ruby"
            "scheme" "sqlite"))
         (src-prompt-str
          (concat "Source code type (default "
                  org-sai-src-default
                  "): "))
         (temp-src-code-types 
          (cons org-sai-src-default src-code-types))
         (src-type-str
          (completing-read src-prompt-str temp-src-code-types
                           nil nil nil nil org-sai-src-default)))
    (setq org-sai-src-default src-type-str))
    (insert (format "#+BEGIN_SRC %s\n" src-type-str))
    (newline)
    (org-indent-line)
    (insert "#+END_SRC\n")
    (forward-line -2))))

(add-hook 'org-mode-hook
          (lambda ()
            ;; keybinding for inserting code blocks
            (local-set-key (kbd "C-c s") 'org-insert-src-block)))

(provide 'orgAuxiliary)
;;; orgAuxiliary.el ends here
0

Here is an interactive function I came up with that not only adds a source code block, but if you are using Org Babel You can also pull in the contents of an existing file with the :tangle header argument conveniently added for you.

I have this setup with the following key binding

(define-key global-map (kbd "C-c s") 'org-insert-source-code-block)

So to just insert a plain source block with a prompt for the language just run C-c s and if you want to also be prompted for a file to 'tangle' with C-u C-c s

It is pretty cool to 'suck-in' the contents of a file, edit it right there in org mode then 'tangle' your changes to update the original file.

And the function itself:

(defun org-insert-source-code-block(&optional language file)
  "Insert source code block for LANGUAGE.  Optionally pull in FILE contents.
Will prompt for LANGUAGE when called interactively.
With a `\\[universal-argument]' prefix, prompts for FILE.
The `:tangle FILE` header argument will be added when pulling in file contents."
  (interactive)
  (let ((col (current-column))
        (lang (or language (read-from-minibuffer "Source block language: ") ))
        (file (if current-prefix-arg (read-file-name "Enter file name: ") nil)))
    (insert
     (format "#+begin_src %s%s" lang (if file (concat " :tangle " file) "")))
    (newline)(newline)
    (move-to-column col t)(insert "#+end_src")(newline)
    (forward-line -2)(move-to-column col t)
    (if file (insert-file-contents file))))

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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