;;
;;; Change Log:
-;; 0.3 - 2014/10/23 - Implement a smarter engine for non-lisp modes.
-;; 0.2 - 2014/10/20 - Reactivate `electric-indent-mode'.
-;; 0.2 - 2014/10/19 - Add variable `aggressive-indent-dont-indent-if', so the user can prevent indentation.
-;; 0.1 - 2014/10/15 - Release.
+;; 0.3.1 - 2014/10/30 - Define new delete-backward bound to backspace.
+;; 0.3 - 2014/10/23 - Implement a smarter engine for non-lisp modes.
+;; 0.2 - 2014/10/20 - Reactivate `electric-indent-mode'.
+;; 0.2 - 2014/10/19 - Add variable `aggressive-indent-dont-indent-if', so the user can prevent indentation.
+;; 0.1 - 2014/10/15 - Release.
;;; Code:
(require 'cl-lib)
(require 'names)
+(defmacro aggressive-indent--do-softly (&rest body)
+ "Execute body unobstrusively.
+This means:
+ 1. Do nothing in several situations, specified by
+ `aggressive-indent-dont-indent-if' and
+ `aggressive-indent--internal-dont-indent-if'.
+ 2. Silence all messages.
+ 3. Never throw errors.
+Meant for use in functions which go in hooks."
+ (declare (debug t))
+ `(unless (or (run-hook-wrapped
+ 'aggressive-indent--internal-dont-indent-if
+ #'eval)
+ (aggressive-indent--run-user-hooks))
+ (ignore-errors
+ (cl-letf (((symbol-function 'message) #'ignore))
+ ,@body))))
+
;;;###autoload
(define-namespace aggressive-indent- :group indent
"List of major-modes where `electric-indent-mode' should be disabled."
:type '(choice
(const :tag "Never use `electric-indent-mode'." t)
- (repeat :tag "Major-modes to avoid `electric-indent-mode'" symbol))
+ (repeat :tag "List of major-modes to avoid `electric-indent-mode'." symbol))
:package-version '(aggressive-indent . "0.3.1"))
(defcustom excluded-modes
(add-to-list 'aggressive-indent--internal-dont-indent-if
'ac-completing)))
-(eval-after-load 'css-mode
- '(add-hook
- 'css-mode-hook
- (lambda () (unless defun-prompt-regexp
- (setq-local defun-prompt-regexp "^[^[:blank:]].*")))))
-
(defcustom dont-indent-if '()
"List of variables and functions to prevent aggressive indenting.
This variable is a list where each element is a lisp form.
(setq -has-errored t)
(message -error-message er))))))
-(defmacro -do-softly (&rest body)
- "Execute body unobstrusively.
-This means: do nothing if mark is active (to avoid deactivaing
-it), or if buffer is not modified (to avoid creating accidental
-modifications), or if any of the forms in
-`aggressive-indent-dont-indent-if' evaluates to non-nil.
-
-Also, never throw errors nor messages.
-Meant for use in functions which go in hooks."
- (declare (debug t))
- `(unless (or (run-hook-wrapped
- 'aggressive-indent--internal-dont-indent-if
- #'eval)
- (aggressive-indent--run-user-hooks))
- (ignore-errors
- (cl-letf (((symbol-function 'message) #'ignore))
- ,@body))))
-
:autoload
(defun indent-defun ()
"Indent current defun.
"Indent current defun unobstrusively.
Like `aggressive-indent-indent-defun', but wrapped in a
`aggressive-indent--do-softly'."
- (unless (or (run-hook-wrapped
- 'aggressive-indent--internal-dont-indent-if
- #'eval)
- (aggressive-indent--run-user-hooks))
- (ignore-errors
- (cl-letf (((symbol-function 'message) #'ignore))
- (indent-defun)))))
+ (aggressive-indent--do-softly (indent-defun)))
:autoload
(defun indent-region-and-on (l r)
(let ((p (point-marker))
was-begining-of-line)
(set-marker-insertion-type p t)
- (goto-char r)
- (setq was-begining-of-line
- (= r (line-beginning-position)))
- ;; If L is at the end of a line, skip that line.
- (unless (= l r)
- (goto-char l)
- (when (= l (line-end-position))
- (cl-incf l)))
- ;; Indent the affected region.
- (unless (= l r) (indent-region l r))
- ;; `indent-region' doesn't do anything if R was the beginning of a line, so we indent manually there.
- (when was-begining-of-line
- (indent-according-to-mode))
- ;; And then we indent each following line until nothing happens.
- (forward-line 1)
- (while (and (null (eobp))
- (/= (progn (skip-chars-forward "[:blank:]\n")
- (point))
- (progn (indent-according-to-mode)
- (point))))
- (forward-line 1))
- (goto-char p)))
+ (unwind-protect
+ (progn
+ (goto-char r)
+ (setq was-begining-of-line
+ (= r (line-beginning-position)))
+ ;; If L is at the end of a line, skip that line.
+ (unless (= l r)
+ (goto-char l)
+ (when (= l (line-end-position))
+ (cl-incf l)))
+ ;; Indent the affected region.
+ (unless (= l r) (indent-region l r))
+ ;; `indent-region' doesn't do anything if R was the beginning of a line, so we indent manually there.
+ (when was-begining-of-line
+ (indent-according-to-mode))
+ ;; And then we indent each following line until nothing happens.
+ (forward-line 1)
+ (while (and (null (eobp))
+ (/= (progn (skip-chars-forward "[:blank:]\n")
+ (point))
+ (progn (indent-according-to-mode)
+ (point))))
+ (forward-line 1)))
+ (goto-char p))))
(defun -softly-indent-region-and-on (l r &rest _)
"Indent current defun unobstrusively.
Like `aggressive-indent-indent-region-and-on', but wrapped in a
`aggressive-indent--do-softly'."
- (unless (or (run-hook-wrapped
- 'aggressive-indent--internal-dont-indent-if
- #'eval)
- (aggressive-indent--run-user-hooks))
- (ignore-errors
- (cl-letf (((symbol-function 'message) #'ignore))
- (indent-region-and-on l r)))))
-
-(defvar changed-list-right nil
+ (aggressive-indent--do-softly (indent-region-and-on l r)))
+
+(defvar -changed-list-right nil
"List of right limit of regions changed in the last command loop.")
-(defvar changed-list-left nil
+(defvar -changed-list-left nil
"List of left limit of regions changed in the last command loop.")
(defun -indent-if-changed ()
"Indent any region that changed in the last command loop."
(let ((inhibit-modification-hooks t))
- (when changed-list-left
+ (when -changed-list-left
(-softly-indent-region-and-on
- (apply #'min changed-list-left)
- (apply #'max changed-list-right))
- (setq changed-list-left nil
- changed-list-right nil))))
+ (apply #'min -changed-list-left)
+ (apply #'max -changed-list-right))
+ (setq -changed-list-left nil
+ -changed-list-right nil))))
(defun -keep-track-of-changes (l r &rest _)
"Store the limits of each change that happens in the buffer."
- (push l changed-list-left)
- (push r changed-list-right))
+ (push l -changed-list-left)
+ (push r -changed-list-right))
(defun -in-comment-p ()
"Return non-nil if point is inside a comment.
Assumes that the syntax table is sufficient to find comments."
(nth 4 (syntax-ppss)))
+\f
+;;; Keymap
+(defun delete-backward ()
+ "Either `delete-indentation' or call [backspace]."
+ (interactive)
+ (if (looking-back "^[[:blank:]]+")
+ (call-interactively 'delete-indentation)
+ (let ((mode nil))
+ (execute-kbd-macro [backspace]))))
+
+(define-key mode-map "\C-c\C-q" #'indent-defun)
+(define-key mode-map [backspace] #'delete-backward)
+
\f
;;; Minor modes
:autoload
-(define-minor-mode mode nil nil " =>"
- '(("\C-c\C-q" . aggressive-indent-indent-defun))
+(define-minor-mode mode nil nil " =>" nil
(if mode
(if (and global-aggressive-indent-mode
(or (cl-member-if #'derived-mode-p excluded-modes)