From: Adam Porter <adam@alphapapa.net>
To: emacs-orgmode@gnu.org
Subject: Re: function for inserting a block
Date: Sat, 02 Sep 2017 21:21:08 -0500 [thread overview]
Message-ID: <87h8wked4b.fsf@alphapapa.net> (raw)
In-Reply-To: 877exghblx.fsf@ericabrahamsen.net
Hi Eric,
Thanks for doing this. I've had some similar code in my config for a
while. I'll share some of it here in case you find it useful in doing
this. You especially might find the org-read-structure-template
function useful.
Note that some of this uses s and hydra, which obviously isn't suitable
for Org proper, but that could be fixed.
#+BEGIN_SRC elisp
(defun ap/org-copy-block (prefix)
"Copy current \"#+BEGIN_...\" block to the kill-ring."
(interactive "p")
(kill-new (ap/org-block-contents (>= prefix 4))))
(defun ap/org-block-contents (&optional whole)
"Return contents of current \"BEGIN_...\" block.
When WHOLE is non-nil, include enclosing meta lines."
(let ((bounds (ap/org-block-boundaries (not whole))))
(buffer-substring-no-properties (car bounds) (cdr bounds))))
(defun ap/org-block-boundaries (&optional contents)
"Return (BEGINNING . END) of current \"#+BEGIN_...\" block.
If CONTENTS is non-nil, return the boundaries of the block's
contents rather than the entire block."
(let ((case-fold-search t)
(re "#\\+begin_\\(\\sw+\\)")
block-beg block-end contents-beg contents-end)
(save-excursion
;; Get block
(unless (looking-at re)
;; If point is in the middle of the "#+BEGIN...",
;; `search-backward-regexp' fails, so go to end of line first.
(end-of-line)
(condition-case nil
(search-backward-regexp re)
(error "Not in a block.")))
(setq block-beg (point))
(setq block-end (search-forward-regexp (concat (rx bol (optional (1+ space)) "#+end_") (match-string 1))))
(goto-char block-beg)
(forward-line)
(setq contents-beg (point))
(goto-char block-end)
(end-of-line 0)
(setq contents-end (point)))
(if contents
`(,contents-beg . ,contents-end)
`(,block-beg . ,block-end))))
(defun ap/org-read-structure-template ()
"Read org-mode structure template with completion. Returns template string."
(let* ((templates (map 'list 'second org-structure-template-alist))
(prefixes (map 'list (lambda (tp)
;; Get template and pre-whitespace prefix for completion
(reverse (s-match (rx (group
(1+ (not (any "\n" space))))
(1+ anything))
tp)))
templates))
(prefix (completing-read "Template: " prefixes nil t))
(template (second (assoc prefix prefixes))))
template))
(defun ap/org-in-block-p ()
"Non-nil when point belongs to a block.
Return first block name matched, or nil. Beware that in case of
nested blocks, the returned name may not belong to the closest
block from point."
(save-match-data
(let ((case-fold-search t)
(lim-up (save-excursion (outline-previous-heading)))
(lim-down (save-excursion (outline-next-heading))))
(org-between-regexps-p "^[ \t]*#\\+begin_" "^[ \t]*#\\+end_"
lim-up lim-down))))
(defun ap/org-indent-src-block ()
(interactive)
(when (ap/org-in-block-p)
(org-edit-src-code)
(insert (replace-regexp-in-string
" +" " " (delete-and-extract-region (point-min) (point-max))))
(ap/indent-whole-buffer)
(whitespace-cleanup)
(org-edit-src-exit)))
(defun ap/org-insert-structure-template-or-enclose-region ()
"Insert structure block template. When region is active, enclose region in block."
(require 's)
(interactive)
(let* ((template (ap/org-read-structure-template))
(text "")
enclosed-text)
(when (use-region-p)
(setq text (buffer-substring-no-properties (region-beginning) (region-end)))
(delete-region (region-beginning) (region-end)))
(setq enclosed-text (s-replace "?" text template))
(insert enclosed-text)
(backward-char (- (length enclosed-text) (length (s-shared-start enclosed-text template))))))
(defun ap/org-change-block-types ()
"Change the type of org-mode block at point, or blocks in region."
(interactive)
(if (use-region-p)
(progn
(deactivate-mark)
(goto-char (region-beginning))
(while (re-search-forward "^ *#\\+BEGIN_" (region-end) nil)
(ap/org-change-block-type-at-point)))
(ap/org-change-block-type-at-point)))
(defun ap/org-change-block-type-at-point ()
"Change type of org-mode block at point."
(interactive)
(unless (ap/org-in-block-p)
(error "Not in an org-mode block."))
(let* ((template (ap/org-read-structure-template))
(case-fold-search t)
(re "#\\+begin_\\(\\sw+\\)")
(block-bounds (ap/org-block-boundaries))
(block-beg (car block-bounds))
(block-end (cdr block-bounds))
(contents (ap/org-block-contents))
new-block)
;; Insert contents into template
(setq new-block (replace-regexp-in-string (rx "?") contents template))
;; Remove extra newline from e.g. SRC blocks
(setq new-block (replace-regexp-in-string (rx "\n\n#+END") "\n#+END" new-block))
;; Replace old block with new one
(goto-char block-beg)
(delete-region block-beg block-end)
(insert new-block)
;; Position cursor (especially for SRC blocks, allowing the user to enter the type)
(search-backward-regexp re)
(search-forward-regexp (rx space))))
;; From https://github.com/abo-abo/hydra/wiki/Org-mode-block-templates
;; With "<" bound to ap/hydra-org-expand-block-template in org-mode-map:
(defhydra hydra-org-block-template (:color blue :hint nil)
"
_c_enter _q_uote _e_macs-lisp _L_aTeX:
_l_atex _E_xample _p_erl _i_ndex:
_a_scii _v_erse _P_erl tangled _I_NCLUDE:
_s_rc ^ ^ plant_u_ml _H_TML:
_h_tml ^ ^ ^ ^ _A_SCII:
"
("s" (ap/org-hydra-expand-template "<s"))
("E" (ap/org-hydra-expand-template "<e"))
("q" (ap/org-hydra-expand-template "<q"))
("v" (ap/org-hydra-expand-template "<v"))
("c" (ap/org-hydra-expand-template "<c"))
("l" (ap/org-hydra-expand-template "<l"))
("h" (ap/org-hydra-expand-template "<h"))
("a" (ap/org-hydra-expand-template "<a"))
("L" (ap/org-hydra-expand-template "<L"))
("i" (ap/org-hydra-expand-template "<i"))
("e" (ap/org-hydra-expand-template "<s" "elisp"))
("p" (ap/org-hydra-expand-template "<s" "perl"))
("u" (ap/org-hydra-expand-template "<s" "plantuml :file CHANGE.png"))
("P" (progn
(insert "#+HEADERS: :results output :exports both :shebang \"#!/usr/bin/env perl\"\n")
(ap/org-hydra-expand-template "<s" "perl")))
("I" (ap/org-hydra-expand-template "<I"))
("H" (ap/org-hydra-expand-template "<H"))
("A" (ap/org-hydra-expand-template "<A"))
("<" self-insert-command "ins")
("o" nil "quit"))
(defun ap/hydra-org-expand-block-template ()
(interactive)
(if (or (use-region-p) (looking-back "^"))
(hydra-org-block-template/body)
(self-insert-command 1)))
(defun ap/org-hydra-expand-template (str &optional mod)
"Expand org template."
(let (text)
(when (use-region-p)
(setq text (buffer-substring (region-beginning) (region-end)))
(delete-region (region-beginning) (region-end)))
(insert str)
(org-try-structure-completion)
(when mod (insert mod) (forward-line))
(when text (insert text))))
#+END_SRC
next prev parent reply other threads:[~2017-09-03 2:22 UTC|newest]
Thread overview: 104+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-09-03 0:25 function for inserting a block Eric Abrahamsen
2017-09-03 2:21 ` Adam Porter [this message]
2017-09-03 3:06 ` Kaushal Modi
2017-09-03 3:34 ` Eric Abrahamsen
2017-09-03 8:10 ` Nicolas Goaziou
2017-09-03 8:19 ` Adam Porter
2017-09-03 8:23 ` Nicolas Goaziou
2017-09-03 15:56 ` Eric Abrahamsen
2017-09-03 18:31 ` Josiah Schwab
2017-09-03 19:28 ` Eric Abrahamsen
2017-09-03 20:26 ` Josiah Schwab
2017-09-03 20:44 ` Eric Abrahamsen
2017-09-08 18:52 ` Eric Abrahamsen
2017-09-10 12:44 ` Nicolas Goaziou
2017-09-10 18:39 ` Eric Abrahamsen
2017-09-29 20:09 ` Nicolas Goaziou
2017-09-30 20:26 ` Eric Abrahamsen
2017-10-05 14:47 ` Nicolas Goaziou
2017-10-07 20:03 ` Eric Abrahamsen
2017-10-14 10:52 ` Nicolas Goaziou
2017-10-16 19:46 ` Eric Abrahamsen
2017-10-16 19:59 ` Eric Abrahamsen
2017-10-17 7:46 ` Nicolas Goaziou
2017-10-17 16:27 ` Eric Abrahamsen
2017-10-17 21:33 ` Nicolas Goaziou
2017-10-17 21:43 ` Eric Abrahamsen
2017-10-17 22:03 ` Eric Abrahamsen
2017-10-18 6:45 ` Carsten Dominik
2017-10-18 14:58 ` Eric Abrahamsen
2017-10-19 15:47 ` Carsten Dominik
2017-10-20 18:04 ` Eric Abrahamsen
2017-10-20 18:39 ` Kaushal Modi
2017-10-20 19:02 ` Kaushal Modi
2017-10-20 21:15 ` Eric Abrahamsen
2017-10-20 21:13 ` Eric Abrahamsen
2017-10-20 21:43 ` Kaushal Modi
2017-10-21 11:30 ` Xebar Saram
2017-10-21 11:59 ` Marco Wahl
2017-10-21 13:32 ` Xebar Saram
2017-10-21 15:56 ` Eric Abrahamsen
2017-10-23 10:52 ` Kaushal Modi
2017-10-23 14:00 ` Carsten Dominik
2017-10-23 14:46 ` Kaushal Modi
2017-10-23 15:11 ` Eric Abrahamsen
2017-10-23 16:55 ` Nicolas Goaziou
2017-10-24 0:18 ` Eric Abrahamsen
2017-10-24 0:20 ` Eric Abrahamsen
2017-10-24 12:10 ` Nicolas Goaziou
2017-10-28 22:27 ` Eric Abrahamsen
2017-10-30 11:05 ` Nicolas Goaziou
2017-10-30 15:08 ` Eric S Fraga
2017-10-30 16:22 ` Eric Abrahamsen
2017-10-30 17:57 ` Eric Abrahamsen
2017-11-05 9:06 ` Nicolas Goaziou
2017-11-05 14:24 ` Kaushal Modi
2017-11-05 14:37 ` Kaushal Modi
2017-11-06 13:48 ` Nicolas Goaziou
2017-11-06 16:23 ` Kaushal Modi
2017-11-05 21:25 ` Eric Abrahamsen
2017-12-10 9:36 ` Thorsten Jolitz
2017-10-22 9:54 ` Nicolas Goaziou
2017-10-22 17:49 ` Eric Abrahamsen
2017-11-08 11:20 ` Bastien
2017-11-08 11:44 ` Nicolas Goaziou
2017-11-08 12:14 ` Bastien
2017-11-08 12:25 ` Restore old easy template feature (Re: function for inserting a block) Kaushal Modi
2017-11-08 12:43 ` Kaushal Modi
2017-11-08 14:08 ` Bastien Guerry
2017-12-18 22:07 ` Matt Price
2017-12-19 1:44 ` Eric Abrahamsen
2017-12-19 10:04 ` Rasmus
2017-12-19 17:49 ` Matt Price
2017-11-08 13:35 ` Nicolas Goaziou
2017-11-08 13:34 ` function for inserting a block Nicolas Goaziou
2017-11-08 14:34 ` Bastien Guerry
2017-11-08 16:01 ` Eric Abrahamsen
2017-11-08 16:33 ` William Denton
2017-11-08 14:07 ` Rasmus
2017-11-08 17:09 ` Berry, Charles
2017-11-08 17:28 ` Nicolas Goaziou
2017-11-08 18:24 ` Thomas S. Dye
2017-11-08 18:51 ` Takaaki Ishikawa
2017-11-08 20:10 ` Eric Abrahamsen
2017-11-08 22:28 ` Nicolas Goaziou
2017-11-09 4:31 ` Thomas S. Dye
2017-11-09 7:55 ` Carsten Dominik
2017-11-12 4:35 ` Matt Lundin
2017-11-12 6:08 ` numbchild
2017-11-09 14:46 ` Rasmus
2017-11-09 16:11 ` Rasmus
2017-11-09 16:50 ` Eric Abrahamsen
2017-11-10 9:31 ` Rasmus
2017-11-10 17:27 ` Eric Abrahamsen
2017-11-11 16:51 ` Thomas S. Dye
2017-11-14 21:36 ` Eric Abrahamsen
2017-11-15 13:13 ` numbchild
2017-11-15 16:24 ` Eric Abrahamsen
2017-11-17 16:19 ` numbchild
2017-11-17 19:14 ` Eric Abrahamsen
2017-11-18 0:09 ` numbchild
2017-11-20 13:40 ` Rasmus
2017-11-20 16:49 ` Eric Abrahamsen
2017-11-11 4:13 ` stardiviner
[not found] <mailman.107.1510246818.12116.emacs-orgmode@gnu.org>
2017-11-10 4:19 ` James Harkins
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.orgmode.org/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87h8wked4b.fsf@alphapapa.net \
--to=adam@alphapapa.net \
--cc=emacs-orgmode@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).