Emacs: Set region boundaries cleanly in functions

master
Pierre Neidhardt 2017-05-14 12:00:34 +05:30
parent e3a4ec4c79
commit b257ecf262
2 changed files with 47 additions and 32 deletions

View File

@ -1,11 +1,27 @@
;; Functions ;; Functions
;; Note on mark and region: to get a consistent behaviour whether transient mode ;; Notes on mark and region: to get a consistent behaviour whether Transient
;; is on or off, check `mark-active' to know if the region is active. It will ;; mode is on or off, check `mark-active'. It will work as expected if
;; work as expected if transient. If not, it will always be true as soon as the ;; transient. If not, it will always be true as soon as the mark has been set
;; mark has been set once; so you need to make sure the mark is set as you want ;; once; so you need to make sure the mark is set as you want beforehand (e.g.
;; beforehand (e.g. whole buffer, single line...). This is the behaviour of ;; whole buffer, single line...). This is the behaviour of `sort-lines'.
;; `sort-lines'. ;;
;; The clean way to get region boundaries and fallback on buffer:
; (let (start end)
; (if mark-active
; (setq start (region-beginning) end (region-end))
; (setq start (point-min) end (point-max)))
;
;; If several commands act on region and the region size/pos is susceptible to change:
; (save-excursion
; (unless mark-active
; (mark-whole-buffer))
;; Then call (region-beginning) and (region-end)
;;
;; For commands that only work on regions:
; (defun count-lines-region (start end)
; "Print number of lines and characters in the region."
; (interactive "r")
(defun add-hook-and-eval (hook function) (defun add-hook-and-eval (hook function)
"Add FUNCTION to HOOK and evaluate it. "Add FUNCTION to HOOK and evaluate it.
@ -77,10 +93,7 @@ optional parameters."
(save-excursion (save-excursion
(while (re-search-forward (while (re-search-forward
regex regex
(if (not mark-active) (if (not mark-active) (point-max) (region-end))
(point-max)
(when (> (point) (mark)) (exchange-point-and-mark))
(mark))
t) t)
(replace-match to-string)))) (replace-match to-string))))
@ -324,15 +337,16 @@ WARNING: this may slow down editing on big files."
"(Un)tabifies according to `indent-tabs-mode', indents and deletes trailing whitespace. "(Un)tabifies according to `indent-tabs-mode', indents and deletes trailing whitespace.
Works on buffer or region. Requires `tabify-leading'." Works on buffer or region. Requires `tabify-leading'."
(interactive) (interactive)
(save-excursion (let (start end)
(unless mark-active (if mark-active
(mark-whole-buffer)) (setq start (region-beginning) end (region-end))
(setq start (point-min) end (point-max)))
(if indent-tabs-mode (if indent-tabs-mode
(tabify-leading) (tabify-leading)
(untabify (region-beginning) (region-end))) (untabify start end))
(indent-region (region-beginning) (region-end)) (indent-region start end)
(save-restriction (save-restriction
(narrow-to-region (region-beginning) (region-end)) (narrow-to-region start end)
(delete-trailing-whitespace)))) (delete-trailing-whitespace))))
(defun shell-last-command () (defun shell-last-command ()
@ -376,14 +390,15 @@ Hook function for skeletons."
"Remove trailing white space, then duplicate lines, then sort the result. "Remove trailing white space, then duplicate lines, then sort the result.
Do not fold case with \\[universal-argument] or non-nil ARG." Do not fold case with \\[universal-argument] or non-nil ARG."
(interactive "P") (interactive "P")
(unless mark-active ;; We use save-excursion here because the region boundaries change during
(mark-whole-buffer)) ;; execution, so it's more convenient to track them with region functions.
(when (> (point) (mark)) (save-excursion
(exchange-point-and-mark)) (unless mark-active
(delete-trailing-whitespace (point) (mark)) (mark-whole-buffer))
(delete-duplicate-lines (point) (mark)) (let ((sort-fold-case (if arg nil t)))
(let ((sort-fold-case (if arg nil t))) (delete-trailing-whitespace (region-beginning) (region-end))
(sort-lines nil (point) (mark)))) (delete-duplicate-lines (region-beginning) (region-end))
(sort-lines nil (region-beginning) (region-end)))))
(defun swap-windows () (defun swap-windows ()
"If 2 windows are up, swap them." "If 2 windows are up, swap them."

View File

@ -48,17 +48,17 @@ restored."
(defun cc-fmt () (defun cc-fmt ()
"Run uncrustify(1) on current buffer or region." "Run uncrustify(1) on current buffer or region."
(interactive) (interactive)
(unless mark-active (let (status
(mark-whole-buffer)) start end
(when (> (point) (mark)) (formatbuf (get-buffer-create "*C format buffer*")))
(exchange-point-and-mark)) (if mark-active
(let ((status) (setq start (region-beginning) end (region-end))
(formatbuf (get-buffer-create "*C format buffer*"))) (setq start (point-min) end (point-max)))
(setq status (setq status
(call-process-region (point) (mark) "uncrustify" nil formatbuf nil "-lc" "-q" "-c" (concat (getenv "HOME") "/.uncrustify.cfg"))) (call-process-region start end "uncrustify" nil formatbuf nil "-lc" "-q" "-c" (concat (getenv "HOME") "/.uncrustify.cfg")))
(if (/= status 0) (if (/= status 0)
(error "error running uncrustify") (error "error running uncrustify")
(delete-region (point) (mark)) (delete-region start end)
(insert-buffer formatbuf) (insert-buffer formatbuf)
(kill-buffer formatbuf)))) (kill-buffer formatbuf))))