Skip to content

Instantly share code, notes, and snippets.

@astanin
Created October 25, 2012 13:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save astanin/3952605 to your computer and use it in GitHub Desktop.
Save astanin/3952605 to your computer and use it in GitHub Desktop.
Move Emacs cursor to the begining and end of the current indentation block
;;; indent-blocks.el ---
;;; move to the begining and end of the current indentation block
;; Indent blocks are defined as a sequence of lines with the same or
;; bigger indent size than that of the current line.
;;
;; Indentat blocks are common in YAML, Python, and Haskell and other
;; markup and programming languages with significant indentation, and
;; in these languages they usually are semantic units.
;;
;; Functions to find boundaries of the current indent block:
;;
;; (indent-block-beginning-position)
;; (indent-block-end-position)
;;
;; Interactive functions to move the point around:
;;
;; (beginning-of-indent-block &optional EXPAND)
;; (end-of-indent-block &optional EXPAND)
;;
;; With EXPAND argument, these two expand move the point to the
;; parent indent block with smaller indent size.
;;
;; Copyright: Sergey Astanin <sastanin@gmail.com>, 2012
;; License: MIT
;; Version: 1
(defun current-indent-size
()
"Return the horizontal position of the first non-whitespace
character on the current line. The first position is 0."
(interactive)
(save-excursion
(back-to-indentation)
(current-column)))
(defun indent-block-find-boundary-position
(step)
"Return character position of the begining of the current
indent block (step = -1), or the last character of the current
indent block (step = 1)."
(save-excursion
(make-local-variable 'other-indent-size)
(let ((indent-size (current-indent-size)))
(setq other-indent-size (save-excursion
(forward-line step)
(current-indent-size)))
(while (and (<= indent-size other-indent-size)
(< (point-min) (point))
(< (point) (point-max)))
(forward-line step)
(setq other-indent-size (save-excursion
(forward-line step)
(current-indent-size))))
(kill-local-variable 'other-indent-size)
(if (< 0 step)
(end-of-line)
(back-to-indentation))
(point))))
(defun indent-block-beginning-position
()
"Return the character position of the first non-white space
character of the current indent block (a sequence of line with
same or bigger indention with respect ot the current line)."
(indent-block-find-boundary-position -1))
(defun indent-block-end-position
()
"Return the last character position of the last line of the
current indent block (a sequence of line with same or bigger
indention with respect ot the current line)."
(indent-block-find-boundary-position 1))
(defun beginning-of-indent-block
(&optional EXPAND)
"Move point to the beginning of the current indent block (a
sequence of lines which indent size is not less than tat of the
current line).
With argument EXPAND is not nil, and point is already on the
beginning of the indent block, then move it backward to the
smaller indentatation of the parent block.
If point reaches the beginning of buffer, it stops there."
(interactive "^P")
(let ((bb (indent-block-beginning-position)))
(if (and EXPAND
(= (point) bb)
(< 0 (current-indent-size))
(< (point-min) (point)))
(backward-to-indentation)
(goto-char bb))))
(defun end-of-indent-block
(&optional EXPAND)
"Move point to the end of the current indent block (a
sequence of lines which indent size is not less than tat of the
current line).
With argument EXPAND is not nil, and point is already at the end
of the indent block, then move it further to the end of the
parent block with smaller indent size.
If point reaches the end of buffer, it stops there."
(interactive "^P")
(let ((bb (indent-block-end-position)))
(if (and EXPAND
(= (point) bb)
(< (point) (point-max)))
(progn
(forward-line 1)
(goto-char (indent-block-end-position)))
(goto-char bb))))
(provide 'indent-blocks)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment