Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: gvol/expand-region.el
base: 2a62408df0
...
head fork: gvol/expand-region.el
compare: 9f742505f3
Checking mergeability… Don't worry, you can still create the pull request.
  • 13 commits
  • 16 files changed
  • 0 commit comments
  • 2 contributors
Commits on Feb 20, 2012
@magnars magnars Merge pull request #21 from gvol/master
Improved LaTeX-mode and added nxml-mode support
496a318
@magnars magnars Update README.md b047a1c
Commits on Feb 27, 2012
@magnars magnars Loosen dependency between core and mode expansions.
Extract the functionality of expand-region.el into
expand-region-core.el. The expansions depend upon that,
and expand-region.el pulls it all together.

While the dependency feature-wise is not circular
(all the mode-specific expansions depend on the core,
and not the other way around), expand-region.el should
not load all of its expansions, making it impossible
to cherry-pick what you want.

Ref issue #24
1be3769
@magnars magnars Use eval-after-loads to avoid loading unused code.
Fixes #22
555e5b6
@magnars magnars Require html-mode directly, otherwise it doesn't load. 4742657
@magnars magnars Feature tests for html-mode + minor improvements 4ef90c6
@magnars magnars html-mode is loaded as part of sgml-mode.el 8fc42c8
Commits on Mar 01, 2012
@magnars magnars Turn off text-mode-expansions by default.
 - because of incompatibilities with html-mode
588a0fc
Commits on Mar 04, 2012
Le Wang tighten ruby method definition regexp and matching context 128df8c
@magnars magnars Merge pull request #25 from lewang/master
tighten ruby method def regexp
449184b
Commits on Mar 05, 2012
@magnars magnars js2-mode specific expansions.
 - uses js2-mode AST to do neat tricks.
e234ffa
@magnars magnars Merge branch 'master' of github.com:magnars/expand-region.el 56b98d6
Commits on Mar 06, 2012
@magnars magnars Use an existing elisp function to remove elements from a list.
 - I don't use nxml-mode, but some quick testing makes me think that nxml-mode
   still needs some help to be very useful.

Fixes #27
9f74250
View
4 README.md
@@ -84,7 +84,7 @@ great if you opened a pull-request. The repo is at:
https://github.com/magnars/expand-region.el
-Changes to the `er/expand-region` functions itself must be accompanied by feature tests.
+Changes to `expand-region-core` itself must be accompanied by feature tests.
They are written in [Ecukes](http://ecukes.info), a Cucumber for Emacs.
To fetch the test dependencies:
@@ -105,7 +105,7 @@ that is utterly excellent.
* [Josh Johnston](https://github.com/joshwnj) contributed `er/contract-region`
* [Le Wang](https://github.com/lewang) contributed consistent handling of the mark ring, expanding into pairs/quotes just left of the cursor, and general code clean-up.
* [Matt Briggs](https://github.com/mbriggs) contributed expansions for ruby-mode.
-* [Ivan Andrus](https://github.com/gvol) contributed expansions for python-mode, text-mode and LaTeX-mode.
+* [Ivan Andrus](https://github.com/gvol) contributed expansions for python-mode, text-mode, LaTeX-mode and nxml-mode.
* [Raimon Grau](https://github.com/kidd) added support for when transient-mark-mode is off.
* [Gleb Peregud](https://github.com/gleber) contributed expansions for erlang-mode.
View
2  clojure-mode-expansions.el
@@ -32,6 +32,8 @@
;;; Code:
+(require 'expand-region-core)
+
(defun er/mark-clj-word ()
"Mark the entire word around or in front of point, including dashes."
(interactive)
View
2  css-mode-expansions.el
@@ -28,6 +28,8 @@
;;; Code:
+(require 'expand-region-core)
+
(defun er/mark-css-declaration ()
"Marks one CSS declaration, eg. font-weight: bold;"
(interactive)
View
2  erlang-mode-expansions.el
@@ -31,6 +31,8 @@
;;; Code:
+(require 'expand-region-core)
+
(defun er/add-erlang-mode-expansions ()
"Adds Erlang-specific expansions for buffers in erlang-mode"
(set (make-local-variable 'er/try-expand-list) (append
View
393 expand-region-core.el
@@ -0,0 +1,393 @@
+;;; expand-region-core.el --- Increase selected region by semantic units.
+
+;; Copyright (C) 2011 Magnar Sveen
+
+;; Author: Magnar Sveen <magnars@gmail.com>
+;; Keywords: marking region
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; The core functionality of expand-region.
+
+;; All changes to this file must be accompanied by feature tests.
+;; They are written in [Ecukes](http://ecukes.info), a Cucumber for Emacs.
+;;
+;; To fetch the test dependencies:
+;;
+;; $ cd /path/to/expand-region
+;; $ git submodule init
+;; $ git submodule update
+;;
+;; Run the tests with:
+;;
+;; $ ./util/ecukes/ecukes features
+
+;;; Code:
+
+(defvar er/history '()
+ "A history of start and end points so we can contract after expanding.")
+
+;; history is always local to a single buffer
+(make-variable-buffer-local 'er/history)
+
+(defvar er--space-str " \t\n")
+(defvar er--blank-list (append er--space-str nil))
+
+;; Default expansions
+
+(defun er/mark-word ()
+ "Mark the entire word around or in front of point."
+ (interactive)
+ (let ((word-regexp "\\sw"))
+ (when (or (looking-at word-regexp)
+ (looking-back word-regexp))
+ (skip-syntax-forward "w")
+ (set-mark (point))
+ (while (looking-back word-regexp)
+ (backward-char)))))
+
+(defun er/mark-symbol ()
+ "Mark the entire symbol around or in front of point."
+ (interactive)
+ (let ((symbol-regexp "\\s_\\|\\sw"))
+ (when (or (looking-at symbol-regexp)
+ (looking-back symbol-regexp))
+ (skip-syntax-forward "_w")
+ (set-mark (point))
+ (while (looking-back symbol-regexp)
+ (backward-char)))))
+
+(defun er/mark-symbol-with-prefix ()
+ "Mark the entire symbol around or in front of point, including prefix."
+ (interactive)
+ (let ((symbol-regexp "\\s_\\|\\sw")
+ (prefix-regexp "\\s'"))
+ (when (or (looking-at prefix-regexp)
+ (looking-at symbol-regexp)
+ (looking-back symbol-regexp))
+ (skip-syntax-forward "'")
+ (skip-syntax-forward "_w")
+ (set-mark (point))
+ (while (or (looking-back symbol-regexp)
+ (looking-back prefix-regexp))
+ (backward-char)))))
+
+;; Mark method call
+
+(defun er/mark-next-accessor ()
+ "Presumes that current symbol is already marked, skips over one
+period and marks next symbol."
+ (interactive)
+ (when (use-region-p)
+ (when (< (point) (mark))
+ (exchange-point-and-mark))
+ (let ((symbol-regexp "\\s_\\|\\sw"))
+ (when (looking-at "\\.")
+ (forward-char 1)
+ (skip-syntax-forward "_w")
+ (exchange-point-and-mark)))))
+
+(defun er/mark-method-call ()
+ "Mark the current symbol (including dots) and then paren to closing paren."
+ (interactive)
+ (let ((symbol-regexp "\\s_\\|\\sw\\|\\."))
+ (when (or (looking-at symbol-regexp)
+ (looking-back symbol-regexp))
+ (skip-syntax-backward "_w.")
+ (set-mark (point))
+ (while (looking-at symbol-regexp)
+ (forward-char))
+ (if (looking-at "(")
+ (forward-list))
+ (exchange-point-and-mark))))
+
+;; Comments
+
+(defun er--point-is-in-comment-p ()
+ "t if point is in comment, otherwise nil"
+ (nth 4 (syntax-ppss)))
+
+(defun er--move-point-forward-out-of-comment ()
+ "Move point forward until it exits the current quoted comment."
+ (while (er--point-is-in-comment-p) (forward-char)))
+
+(defun er--move-point-backward-out-of-comment ()
+ "Move point backward until it exits the current quoted comment."
+ (while (er--point-is-in-comment-p) (backward-char)))
+
+(defun er/mark-comment ()
+ "Mark the current comment."
+ (interactive)
+ (when (or (er--point-is-in-comment-p)
+ (looking-at "\\s<"))
+ (er--move-point-backward-out-of-comment)
+ (set-mark (point))
+ (forward-char)
+ (er--move-point-forward-out-of-comment)
+ (backward-char)
+ (exchange-point-and-mark)))
+
+(defun er/mark-comment-block ()
+ "Mark the current block of comments."
+ (interactive)
+ (when (or (er--point-is-in-comment-p)
+ (looking-at "\\s<"))
+ (er--move-point-backward-out-of-comment)
+ (while (save-excursion
+ (skip-syntax-backward " ")
+ (backward-char)
+ (er--point-is-in-comment-p))
+ (skip-syntax-backward " ")
+ (backward-char)
+ (er--move-point-backward-out-of-comment))
+ (set-mark (point))
+ (forward-char)
+ (er--move-point-forward-out-of-comment)
+ (while (looking-at "\\s *\\s<")
+ (back-to-indentation)
+ (forward-char)
+ (er--move-point-forward-out-of-comment))
+ (exchange-point-and-mark)))
+
+;; Quotes
+
+(defun er--current-quotes-char ()
+ "The char that is the current quote delimiter"
+ (nth 3 (syntax-ppss)))
+
+(defalias 'er--point-inside-string-p 'er--current-quotes-char)
+
+(defun er--move-point-forward-out-of-string ()
+ "Move point forward until it exits the current quoted string."
+ (while (er--point-inside-string-p) (forward-char)))
+
+(defun er--move-point-backward-out-of-string ()
+ "Move point backward until it exits the current quoted string."
+ (while (er--point-inside-string-p) (backward-char)))
+
+(defun er/mark-inside-quotes ()
+ "Mark the inside of the current string, not including the quotation marks."
+ (interactive)
+ (when (er--point-inside-string-p)
+ (er--move-point-backward-out-of-string)
+ (forward-char)
+ (set-mark (point))
+ (er--move-point-forward-out-of-string)
+ (backward-char)
+ (exchange-point-and-mark)))
+
+(defun er/mark-outside-quotes ()
+ "Mark the current string, including the quotation marks."
+ (interactive)
+ (if (er--point-inside-string-p)
+ (er--move-point-backward-out-of-string)
+ (when (and (not (use-region-p))
+ (looking-back "\\s\""))
+ (backward-char)
+ (er--move-point-backward-out-of-string)))
+ (when (looking-at "\\s\"")
+ (set-mark (point))
+ (forward-char)
+ (er--move-point-forward-out-of-string)
+ (exchange-point-and-mark)))
+
+;; Pairs - ie [] () {} etc
+
+(defun er--point-inside-pairs-p ()
+ "Is point inside any pairs?"
+ (> (car (syntax-ppss)) 0))
+
+(defun er/mark-inside-pairs ()
+ "Mark inside pairs (as defined by the mode), not including the pairs."
+ (interactive)
+ (when (er--point-inside-pairs-p)
+ (goto-char (nth 1 (syntax-ppss)))
+ (set-mark (save-excursion
+ (forward-char 1)
+ (skip-chars-forward er--space-str)
+ (point)))
+ (forward-list)
+ (backward-char)
+ (skip-chars-backward er--space-str)
+ (exchange-point-and-mark)))
+
+(defun er--looking-at-pair ()
+ "Is point looking at an opening pair char?"
+ (looking-at "\\s("))
+
+(defun er--looking-at-marked-pair ()
+ "Is point looking at a pair that is entirely marked?"
+ (and (er--looking-at-pair)
+ (use-region-p)
+ (>= (mark)
+ (save-excursion
+ (forward-list)
+ (point)))))
+
+(defun er/mark-outside-pairs ()
+ "Mark pairs (as defined by the mode), including the pair chars."
+ (interactive)
+ (if (looking-back "\\s)+\\=")
+ (ignore-errors (backward-list 1))
+ (skip-chars-forward er--space-str))
+ (when (and (er--point-inside-pairs-p)
+ (or (not (er--looking-at-pair))
+ (er--looking-at-marked-pair)))
+ (goto-char (nth 1 (syntax-ppss))))
+ (when (er--looking-at-pair)
+ (set-mark (point))
+ (forward-list)
+ (exchange-point-and-mark)))
+
+;; Methods to try expanding to
+
+(setq er/try-expand-list '(er/mark-word
+ er/mark-symbol
+ er/mark-symbol-with-prefix
+ er/mark-next-accessor
+ er/mark-method-call
+ er/mark-comment
+ er/mark-comment-block
+ er/mark-inside-quotes
+ er/mark-outside-quotes
+ er/mark-inside-pairs
+ er/mark-outside-pairs))
+
+;; The magic expand-region method
+
+;;;###autoload
+(defun er/expand-region (arg)
+ "Increase selected region by semantic units.
+Basically it runs all the mark-functions in `er/try-expand-list'
+and chooses the one that increases the size of the region while
+moving point or mark as little as possible.
+
+With prefix argument expands the region that many times.
+If prefix argument is negative calls `er/contract-region'.
+If prefix argument is 0 it resets point and mark to their state
+before calling `er/expand-region' for the first time."
+ (interactive "p")
+ (if (< arg 1)
+ ;; `er/contract-region' will take care of negative and 0 arguments
+ (er/contract-region (- arg))
+ ;; We handle everything else
+
+ (when (and (er--first-invocation)
+ (not (use-region-p)))
+ (push-mark nil t) ;; one for keeping starting position
+ (push-mark nil t)) ;; one for replace by set-mark in expansions
+
+ (when (not (eq t transient-mark-mode))
+ (setq transient-mark-mode (cons 'only transient-mark-mode)))
+
+ (while (>= arg 1)
+ (setq arg (- arg 1))
+ (let* ((p1 (point))
+ (p2 (if (use-region-p) (mark) (point)))
+ (start (min p1 p2))
+ (end (max p1 p2))
+ (try-list er/try-expand-list)
+ (best-start 1)
+ (best-end (buffer-end 1)))
+
+ ;; add hook to clear history on buffer changes
+ (unless er/history
+ (add-hook 'after-change-functions 'er/clear-history t t))
+
+ ;; remember the start and end points so we can contract later
+ ;; unless we're already at maximum size
+ (unless (and (= start best-start)
+ (= end best-end))
+ (push (cons start end) er/history))
+
+ (when (and (er--point-is-surrounded-by-white-space)
+ (= start end))
+ (skip-chars-forward er--space-str)
+ (setq start (point)))
+
+ (while try-list
+ (save-excursion
+ (ignore-errors
+ (funcall (car try-list))
+ (when (and (region-active-p)
+ (<= (point) start)
+ (>= (mark) end)
+ (> (- (mark) (point)) (- end start))
+ (or (> (point) best-start)
+ (and (= (point) best-start)
+ (< (mark) best-end))))
+ (setq best-start (point))
+ (setq best-end (mark))
+ (unless (minibufferp)
+ (message "%S" (car try-list))))))
+ (setq try-list (cdr try-list)))
+
+ (goto-char best-start)
+ (set-mark best-end)
+
+ (when (and (= best-start 0)
+ (= best-end (buffer-end 1))) ;; We didn't find anything new, so exit early
+ (setq arg 0))))))
+
+(defun er/contract-region (arg)
+ "Contract the selected region to its previous size.
+With prefix argument contracts that many times.
+If prefix argument is negative calls `er/expand-region'.
+If prefix argument is 0 it resets point and mark to their state
+before calling `er/expand-region' for the first time."
+ (interactive "p")
+ (if (< arg 0)
+ (er/expand-region (- arg))
+ (when er/history
+ ;; Be sure to reset them all if called with 0
+ (when (= arg 0)
+ (setq arg (length er/history)))
+
+ (when (not transient-mark-mode)
+ (setq transient-mark-mode (cons 'only transient-mark-mode)))
+
+ ;; Advance through the list the desired distance
+ (while (and (cdr er/history)
+ (> arg 1))
+ (setq arg (- arg 1))
+ (setq er/history (cdr er/history)))
+ ;; Reset point and mark
+ (let* ((last (pop er/history))
+ (start (car last))
+ (end (cdr last)))
+ (goto-char start)
+ (set-mark end)
+ (when (eq start end)
+ (deactivate-mark)
+ (er/clear-history))))))
+
+(defun er/clear-history (&rest args)
+ "Clear the history."
+ (setq er/history '())
+ (remove-hook 'after-change-functions 'er/clear-history t))
+
+(defsubst er--first-invocation ()
+ "t if this is the first invocation of er/expand-region or er/contract-region"
+ (not (memq last-command '(er/expand-region er/contract-region))))
+
+(defun er--point-is-surrounded-by-white-space ()
+ (and (or (memq (char-before) er--blank-list)
+ (eq (point) (point-min)))
+ (memq (char-after) er--blank-list)))
+
+(provide 'expand-region-core)
+
+;;; expand-region-core.el ends here
View
431 expand-region.el
@@ -40,7 +40,7 @@
;; There's also `er/contract-region` if you expand too far.
;; ## Video
-;;
+
;; You can [watch an intro to expand-region at Emacs Rocks](http://emacsrocks.com/e09.html).
;; ## Language support
@@ -51,6 +51,8 @@
;; er/mark-word
;; er/mark-symbol
;; er/mark-method-call
+;; er/mark-comment
+;; er/mark-comment-block
;; er/mark-inside-quotes
;; er/mark-outside-quotes
;; er/mark-inside-pairs
@@ -80,12 +82,12 @@
;; `mark-page`. To add it to the try-list, do this:
;; (defun er/add-text-mode-expansions ()
-;; (set (make-local-variable 'er/try-expand-list)
-;; (append
-;; er/try-expand-list
-;; '(mark-paragraph
-;; mark-page))))
-;;
+;; (make-variable-buffer-local 'er/try-expand-list)
+;; (setq er/try-expand-list (append
+;; er/try-expand-list
+;; '(mark-paragraph
+;; mark-page))))
+
;; (add-hook 'text-mode-hook 'er/add-text-mode-expansions)
;; Add that to its own file, and require it at the bottom of this one,
@@ -96,386 +98,65 @@
;; the entire document looking for constructs to mark.
;; ## Contribute
-;;
+
;; If you make some nice expansions for your favorite mode, it would be
;; great if you opened a pull-request. The repo is at:
-;;
+
;; https://github.com/magnars/expand-region.el
+;; Changes to `expand-region-core` itself must be accompanied by feature tests.
+;; They are written in [Ecukes](http://ecukes.info), a Cucumber for Emacs.
+
+;; To fetch the test dependencies:
+
+;; $ cd /path/to/expand-region
+;; $ git submodule init
+;; $ git submodule update
+
+;; Run the tests with:
+
+;; $ ./util/ecukes/ecukes features
+
+;; If you want to add feature-tests for your mode-specific expansions as well,
+;; that is utterly excellent.
+
;; ## Contributors
-;;
+
;; * [Josh Johnston](https://github.com/joshwnj) contributed `er/contract-region`
;; * [Le Wang](https://github.com/lewang) contributed consistent handling of the mark ring, expanding into pairs/quotes just left of the cursor, and general code clean-up.
;; * [Matt Briggs](https://github.com/mbriggs) contributed expansions for ruby-mode.
-;; * [Ivan Andrus](https://github.com/gvol) contributed expansions for various modes.
-;;
+;; * [Ivan Andrus](https://github.com/gvol) contributed expansions for python-mode, text-mode, LaTeX-mode and nxml-mode.
+;; * [Raimon Grau](https://github.com/kidd) added support for when transient-mark-mode is off.
+;; * [Gleb Peregud](https://github.com/gleber) contributed expansions for erlang-mode.
+
;; Thanks!
;;; Code:
-(defvar er/history '()
- "A history of start and end points so we can contract after expanding.")
-
-;; history is always local to a single buffer
-(make-variable-buffer-local 'er/history)
-
-(defvar er--space-str " \t\n")
-(defvar er--blank-list (append er--space-str nil))
-
-;; Default expansions
-
-(defun er/mark-word ()
- "Mark the entire word around or in front of point."
- (interactive)
- (let ((word-regexp "\\sw"))
- (when (or (looking-at word-regexp)
- (looking-back word-regexp))
- (skip-syntax-forward "w")
- (set-mark (point))
- (while (looking-back word-regexp)
- (backward-char)))))
-
-(defun er/mark-symbol ()
- "Mark the entire symbol around or in front of point."
- (interactive)
- (let ((symbol-regexp "\\s_\\|\\sw"))
- (when (or (looking-at symbol-regexp)
- (looking-back symbol-regexp))
- (skip-syntax-forward "_w")
- (set-mark (point))
- (while (looking-back symbol-regexp)
- (backward-char)))))
-
-(defun er/mark-symbol-with-prefix ()
- "Mark the entire symbol around or in front of point, including prefix."
- (interactive)
- (let ((symbol-regexp "\\s_\\|\\sw")
- (prefix-regexp "\\s'"))
- (when (or (looking-at prefix-regexp)
- (looking-at symbol-regexp)
- (looking-back symbol-regexp))
- (skip-syntax-forward "'")
- (skip-syntax-forward "_w")
- (set-mark (point))
- (while (or (looking-back symbol-regexp)
- (looking-back prefix-regexp))
- (backward-char)))))
-
-;; Mark method call
-
-(defun er/mark-next-accessor ()
- "Presumes that current symbol is already marked, skips over one
-period and marks next symbol."
- (interactive)
- (when (use-region-p)
- (when (< (point) (mark))
- (exchange-point-and-mark))
- (let ((symbol-regexp "\\s_\\|\\sw"))
- (when (looking-at "\\.")
- (forward-char 1)
- (skip-syntax-forward "_w")
- (exchange-point-and-mark)))))
-
-(defun er/mark-method-call ()
- "Mark the current symbol (including dots) and then paren to closing paren."
- (interactive)
- (let ((symbol-regexp "\\s_\\|\\sw\\|\\."))
- (when (or (looking-at symbol-regexp)
- (looking-back symbol-regexp))
- (skip-syntax-backward "_w.")
- (set-mark (point))
- (while (looking-at symbol-regexp)
- (forward-char))
- (if (looking-at "(")
- (forward-list))
- (exchange-point-and-mark))))
-
-;; Comments
-
-(defun er--point-is-in-comment-p ()
- "t if point is in comment, otherwise nil"
- (nth 4 (syntax-ppss)))
-
-(defun er--move-point-forward-out-of-comment ()
- "Move point forward until it exits the current quoted comment."
- (while (er--point-is-in-comment-p) (forward-char)))
-
-(defun er--move-point-backward-out-of-comment ()
- "Move point backward until it exits the current quoted comment."
- (while (er--point-is-in-comment-p) (backward-char)))
-
-(defun er/mark-comment ()
- "Mark the current comment."
- (interactive)
- (when (or (er--point-is-in-comment-p)
- (looking-at "\\s<"))
- (er--move-point-backward-out-of-comment)
- (set-mark (point))
- (forward-char)
- (er--move-point-forward-out-of-comment)
- (backward-char)
- (exchange-point-and-mark)))
-
-(defun er/mark-comment-block ()
- "Mark the current block of comments."
- (interactive)
- (when (or (er--point-is-in-comment-p)
- (looking-at "\\s<"))
- (er--move-point-backward-out-of-comment)
- (while (save-excursion
- (skip-syntax-backward " ")
- (backward-char)
- (er--point-is-in-comment-p))
- (skip-syntax-backward " ")
- (backward-char)
- (er--move-point-backward-out-of-comment))
- (set-mark (point))
- (forward-char)
- (er--move-point-forward-out-of-comment)
- (while (looking-at "\\s *\\s<")
- (back-to-indentation)
- (forward-char)
- (er--move-point-forward-out-of-comment))
- (exchange-point-and-mark)))
-
-;; Quotes
-
-(defun er--current-quotes-char ()
- "The char that is the current quote delimiter"
- (nth 3 (syntax-ppss)))
-
-(defalias 'er--point-inside-string-p 'er--current-quotes-char)
-
-(defun er--move-point-forward-out-of-string ()
- "Move point forward until it exits the current quoted string."
- (while (er--point-inside-string-p) (forward-char)))
-
-(defun er--move-point-backward-out-of-string ()
- "Move point backward until it exits the current quoted string."
- (while (er--point-inside-string-p) (backward-char)))
-
-(defun er/mark-inside-quotes ()
- "Mark the inside of the current string, not including the quotation marks."
- (interactive)
- (when (er--point-inside-string-p)
- (er--move-point-backward-out-of-string)
- (forward-char)
- (set-mark (point))
- (er--move-point-forward-out-of-string)
- (backward-char)
- (exchange-point-and-mark)))
-
-(defun er/mark-outside-quotes ()
- "Mark the current string, including the quotation marks."
- (interactive)
- (if (er--point-inside-string-p)
- (er--move-point-backward-out-of-string)
- (when (and (not (use-region-p))
- (looking-back "\\s\""))
- (backward-char)
- (er--move-point-backward-out-of-string)))
- (when (looking-at "\\s\"")
- (set-mark (point))
- (forward-char)
- (er--move-point-forward-out-of-string)
- (exchange-point-and-mark)))
-
-;; Pairs - ie [] () {} etc
-
-(defun er--point-inside-pairs-p ()
- "Is point inside any pairs?"
- (> (car (syntax-ppss)) 0))
-
-(defun er/mark-inside-pairs ()
- "Mark inside pairs (as defined by the mode), not including the pairs."
- (interactive)
- (when (er--point-inside-pairs-p)
- (goto-char (nth 1 (syntax-ppss)))
- (set-mark (save-excursion
- (forward-char 1)
- (skip-chars-forward er--space-str)
- (point)))
- (forward-list)
- (backward-char)
- (skip-chars-backward er--space-str)
- (exchange-point-and-mark)))
-
-(defun er--looking-at-pair ()
- "Is point looking at an opening pair char?"
- (looking-at "\\s("))
-
-(defun er--looking-at-marked-pair ()
- "Is point looking at a pair that is entirely marked?"
- (and (er--looking-at-pair)
- (use-region-p)
- (>= (mark)
- (save-excursion
- (forward-list)
- (point)))))
-
-(defun er/mark-outside-pairs ()
- "Mark pairs (as defined by the mode), including the pair chars."
- (interactive)
- (progn
- (if (looking-back "\\s)+\\=")
- (ignore-errors (backward-list 1))
- (skip-chars-forward er--space-str)))
- (when (and (er--point-inside-pairs-p)
- (or (not (er--looking-at-pair))
- (er--looking-at-marked-pair)))
- (goto-char (nth 1 (syntax-ppss))))
- (when (er--looking-at-pair)
- (set-mark (point))
- (forward-list)
- (exchange-point-and-mark)))
-
-;; Methods to try expanding to
-
-(setq er/try-expand-list '(er/mark-word
- er/mark-symbol
- er/mark-symbol-with-prefix
- er/mark-next-accessor
- er/mark-method-call
- er/mark-comment
- er/mark-comment-block
- er/mark-inside-quotes
- er/mark-outside-quotes
- er/mark-inside-pairs
- er/mark-outside-pairs))
-
-;; The magic expand-region method
-
-;;;###autoload
-(defun er/expand-region (arg)
- "Increase selected region by semantic units.
-Basically it runs all the mark-functions in `er/try-expand-list'
-and chooses the one that increases the size of the region while
-moving point or mark as little as possible.
-
-With prefix argument expands the region that many times.
-If prefix argument is negative calls `er/contract-region'.
-If prefix argument is 0 it resets point and mark to their state
-before calling `er/expand-region' for the first time."
- (interactive "p")
- (if (< arg 1)
- ;; `er/contract-region' will take care of negative and 0 arguments
- (er/contract-region (- arg))
- ;; We handle everything else
-
- (when (and (er--first-invocation)
- (not (use-region-p)))
- (push-mark nil t) ;; one for keeping starting position
- (push-mark nil t)) ;; one for replace by set-mark in expansions
-
- (when (not (eq t transient-mark-mode))
- (setq transient-mark-mode (cons 'only transient-mark-mode)))
-
- (while (>= arg 1)
- (setq arg (- arg 1))
- (let* ((p1 (point))
- (p2 (if (use-region-p) (mark) (point)))
- (start (min p1 p2))
- (end (max p1 p2))
- (try-list er/try-expand-list)
- (best-start 1)
- (best-end (buffer-end 1)))
-
- ;; add hook to clear history on buffer changes
- (unless er/history
- (add-hook 'after-change-functions 'er/clear-history t t))
-
- ;; remember the start and end points so we can contract later
- ;; unless we're already at maximum size
- (unless (and (= start best-start)
- (= end best-end))
- (push (cons start end) er/history))
-
- (when (and (er--point-is-surrounded-by-white-space)
- (= start end))
- (skip-chars-forward er--space-str)
- (setq start (point)))
-
- (while try-list
- (save-excursion
- (ignore-errors
- (funcall (car try-list))
- (when (and (region-active-p)
- (<= (point) start)
- (>= (mark) end)
- (> (- (mark) (point)) (- end start))
- (or (> (point) best-start)
- (and (= (point) best-start)
- (< (mark) best-end))))
- (setq best-start (point))
- (setq best-end (mark))
- (unless (minibufferp)
- (message "%S" (car try-list))))))
- (setq try-list (cdr try-list)))
-
- (goto-char best-start)
- (set-mark best-end)
-
- (when (and (= best-start 0)
- (= best-end (buffer-end 1))) ;; We didn't find anything new, so exit early
- (setq arg 0))))))
-
-(defun er/contract-region (arg)
- "Contract the selected region to its previous size.
-With prefix argument contracts that many times.
-If prefix argument is negative calls `er/expand-region'.
-If prefix argument is 0 it resets point and mark to their state
-before calling `er/expand-region' for the first time."
- (interactive "p")
- (if (< arg 0)
- (er/expand-region (- arg))
- (when er/history
- ;; Be sure to reset them all if called with 0
- (when (= arg 0)
- (setq arg (length er/history)))
-
- (when (not transient-mark-mode)
- (setq transient-mark-mode (cons 'only transient-mark-mode)))
-
- ;; Advance through the list the desired distance
- (while (and (cdr er/history)
- (> arg 1))
- (setq arg (- arg 1))
- (setq er/history (cdr er/history)))
- ;; Reset point and mark
- (let* ((last (pop er/history))
- (start (car last))
- (end (cdr last)))
- (goto-char start)
- (set-mark end)
- (when (eq start end)
- (deactivate-mark)
- (er/clear-history))))))
-
-(defun er/clear-history (&rest args)
- "Clear the history."
- (setq er/history '())
- (remove-hook 'after-change-functions 'er/clear-history t))
-
-(defsubst er--first-invocation ()
- "t if this is the first invocation of er/expand-region or er/contract-region"
- (not (memq last-command '(er/expand-region er/contract-region))))
-
-(defun er--point-is-surrounded-by-white-space ()
- (and (or (memq (char-before) er--blank-list)
- (eq (point) (point-min)))
- (memq (char-after) er--blank-list)))
-
-;; Mode-specific expansions
-(require 'js-mode-expansions)
-(require 'ruby-mode-expansions)
-(require 'html-mode-expansions)
-(require 'css-mode-expansions)
-(require 'clojure-mode-expansions)
-(require 'python-mode-expansions)
-(require 'text-mode-expansions)
-(require 'latex-mode-expansions)
-(require 'erlang-mode-expansions)
-(require 'feature-mode-expansions)
+(require 'expand-region-core)
+
+(eval-after-load "clojure-mode" '(require 'clojure-mode-expansions))
+(eval-after-load "css-mode" '(require 'css-mode-expansions))
+(eval-after-load "erlang-mode" '(require 'erlang-mode-expansions))
+(eval-after-load "feature-mode" '(require 'feature-mode-expansions))
+(eval-after-load "sgml-mode" '(require 'html-mode-expansions)) ;; html-mode is defined in sgml-mode.el
+(eval-after-load "rhtml-mode" '(require 'html-mode-expansions))
+(eval-after-load "nxhtml-mode" '(require 'html-mode-expansions))
+(eval-after-load "js2-mode" '(require 'js-mode-expansions))
+(eval-after-load "js2-mode" '(require 'js2-mode-expansions))
+(eval-after-load "js3-mode" '(require 'js-mode-expansions))
+(eval-after-load "LaTeX-mode" '(require 'latex-mode-expansions))
+(eval-after-load "nxml-mode" '(require 'nxml-mode-expansions))
+(eval-after-load "python" '(require 'python-mode-expansions))
+(eval-after-load "python-mode" '(require 'python-mode-expansions))
+(eval-after-load "ruby-mode" '(require 'ruby-mode-expansions))
+
+;; unfortunately html-mode inherits from text-mode
+;; and text-mode-expansions don't work well in html-mode
+;; so if you want text-mode-expansions, add this to your
+;; own init:
+;;
+;; (eval-after-load "text-mode" '(require 'text-mode-expansions))
(provide 'expand-region)
View
2  feature-mode-expansions.el
@@ -30,6 +30,8 @@
;; er/mark-feature-scenario
;; er/mark-feature-step
+(require 'expand-region-core)
+
(defun er--block-between-keywords (start-keywords-regexp &optional end-keywords-regexp)
(let* ((start-key-words (concatenate 'string "^\\( \\)*" start-keywords-regexp))
(end-key-words (concatenate 'string "^\\( \\)*" (or end-keywords-regexp start-keywords-regexp))))
View
68 features/html-mode-expansions.feature
@@ -0,0 +1,68 @@
+Feature: html-mode expansions
+ In order to quickly and precisely mark html units
+ As an Emacs user
+ I want to expand to them
+
+ Scenario: Mark html attribute from start
+ Given I turn on html-mode
+ And there is no region selected
+ When I insert "<div id="5">"
+ And I place the cursor between " " and "id"
+ And I expand the region 3 times
+ Then the region should be "id="5""
+
+ Scenario: Mark html attribute from end
+ Given I turn on html-mode
+ And there is no region selected
+ When I insert "<div id="5">"
+ And I go to point "12"
+ And I expand the region 2 times
+ Then the region should be "id="5""
+
+ Scenario: Mark html tags, part 1
+ Given I turn on html-mode
+ And there is no region selected
+ When I insert "... <div class='hi'><div>before <span></span></div> after</div> ..."
+ And I place the cursor between "before " and "<span>"
+ And I expand the region
+ Then the region should be "<span>"
+
+ Scenario: Mark html tags, part 2
+ Given I turn on html-mode
+ And there is no region selected
+ When I insert "... <div class='hi'><div>before <span></span></div> after</div> ..."
+ And I place the cursor between "before " and "<span>"
+ And I expand the region 2 times
+ Then the region should be "<span></span>"
+
+ Scenario: Mark html tags, part 3
+ Given I turn on html-mode
+ And there is no region selected
+ When I insert "... <div class='hi'><div>before <span></span></div> after</div> ..."
+ And I place the cursor between "before " and "<span>"
+ And I expand the region 3 times
+ Then the region should be "before <span></span>"
+
+ Scenario: Mark html tags, part 4
+ Given I turn on html-mode
+ And there is no region selected
+ When I insert "... <div class='hi'><div>before <span></span></div> after</div> ..."
+ And I place the cursor between "before " and "<span>"
+ And I expand the region 4 times
+ Then the region should be "<div>before <span></span></div>"
+
+ Scenario: Mark html tags, part 5
+ Given I turn on html-mode
+ And there is no region selected
+ When I insert "... <div class='hi'><div>before <span></span></div> after</div> ..."
+ And I place the cursor between "before " and "<span>"
+ And I expand the region 5 times
+ Then the region should be "<div>before <span></span></div> after"
+
+ Scenario: Mark html tags, part 6
+ Given I turn on html-mode
+ And there is no region selected
+ When I insert "... <div class='hi'><div>before <span></span></div> after</div> ..."
+ And I place the cursor between "before " and "<span>"
+ And I expand the region 6 times
+ Then the region should be "<div class='hi'><div>before <span></span></div> after</div>"
View
13 html-mode-expansions.el
@@ -32,6 +32,8 @@
;;; Code:
+(require 'expand-region-core)
+
(defun er/mark-html-attribute ()
"Mark html-attribute presumes that point is at the assignment part of attr=\"value\".
If point is inside the value-string, the quotes will be marked
@@ -44,15 +46,13 @@ around the equal sign or unquotes attributes atm."
(forward-char 1)
(set-mark (point))
(search-forward "=")
- ;; (forward-char 1)
- ;; (er--move-point-forward-out-of-string)
(forward-sexp 1)
(exchange-point-and-mark)))
(defun er--looking-at-marked-tag ()
"Is point looking at a tag that is entirely marked?"
(and (looking-at "<")
- (eq (mark)
+ (>= (mark)
(save-excursion
(sgml-skip-tag-forward 1)
(point)))))
@@ -69,9 +69,10 @@ around the equal sign or unquotes attributes atm."
(or (not (looking-at "<"))
(er--looking-at-marked-tag)))
(goto-char (aref (car (last (sgml-get-context))) 2)))
- (set-mark (point))
- (sgml-skip-tag-forward 1)
- (exchange-point-and-mark))
+ (when (looking-at "<")
+ (set-mark (point))
+ (sgml-skip-tag-forward 1)
+ (exchange-point-and-mark)))
(defun er/mark-inner-tag ()
"Mark the contents of an open tag, not including the tags."
View
2  js-mode-expansions.el
@@ -39,6 +39,8 @@
;;; Code:
+(require 'expand-region-core)
+
(defun er/mark-js-function ()
"Mark the current JavaScript function."
(interactive)
View
53 js2-mode-expansions.el
@@ -0,0 +1,53 @@
+;;; js2-mode-expansions.el --- Additional expansions for js2-mode
+
+;; Copyright (C) 2011 Magnar Sveen
+
+;; Author: Magnar Sveen <magnars@gmail.com>
+;; Keywords: marking region
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Extra expansions specifically for js2-mode, since it has
+;; a semantic parser.
+;;
+;; Feel free to contribute any other expansions for JavaScript at
+;;
+;; https://github.com/magnars/expand-region.el
+
+;;; Code:
+
+(require 'expand-region-core)
+
+(defun js2-mark-parent-statement ()
+ (interactive)
+ (let* ((parent-statement (js2-node-parent-stmt (js2-node-at-point)))
+ (beg (js2-node-abs-pos parent-statement))
+ (end (+ beg (js2-node-len parent-statement))))
+ (goto-char beg)
+ (set-mark end)))
+
+(defun er/add-js2-mode-expansions ()
+ "Adds expansions for buffers in js2-mode"
+ (set (make-local-variable 'er/try-expand-list) (append
+ er/try-expand-list
+ '(js2-mark-parent-statement))))
+
+(add-hook 'js2-mode-hook 'er/add-js2-mode-expansions)
+;(add-hook 'js3-mode-hook 'er/add-js2-mode-expansions) -- works?
+
+(provide 'js2-mode-expansions)
+
+;; js2-mode-expansions.el ends here
View
2  latex-mode-expansions.el
@@ -29,6 +29,8 @@
;;; Code:
+(require 'expand-region-core)
+
(defun er/mark-LaTeX-inside-environment ()
"Like `LaTeX-mark-environment' but marks the inside of the environment.
Skips past [] and {} arguments to the environment."
View
10 nxml-mode-expansions.el
@@ -27,6 +27,8 @@
;;; Code:
+(require 'expand-region-core)
+
(defun er/mark-nxml-tag ()
"Marks one nxml element e.g. <p>...</p>"
(interactive)
@@ -81,9 +83,11 @@
er/mark-nxml-element
er/mark-nxml-attribute-string
;; Steal from html-mode-expansions
- er/mark-html-attribute)))
- ;; Selecting symbols is confusing since < and > symbols
- (remove-from-list 'er/try-expand-list 'er/mark-symbol))
+ er/mark-html-attribute)
+ ;; some normal marks are more hindrance than help:
+ (remove 'er/mark-method-call
+ (remove 'er/mark-symbol-with-prefix
+ (remove 'er/mark-symbol er/try-expand-list))))))
(add-hook 'nxml-mode-hook 'er/add-nxml-mode-expansions)
View
2  python-mode-expansions.el
@@ -36,6 +36,8 @@
;;; Code:
+(require 'expand-region-core)
+
(defun er/mark-python-statement ()
"Marks one Python statement, eg. x = 3"
(interactive)
View
10 ruby-mode-expansions.el
@@ -31,6 +31,9 @@
;; er/mark-ruby-function
;;; Code:
+
+(require 'expand-region-core)
+
(defun er/mark-ruby-block ()
(interactive)
(ruby-beginning-of-block)
@@ -45,9 +48,10 @@
(condition-case nil
(forward-char 3)
(error nil))
- (word-search-backward "def")
- (while (er--point-inside-string-p)
- (word-search-backward "def"))
+ (let ((ruby-method-regex "^[\t ]*def\\_>"))
+ (word-search-backward ruby-method-regex)
+ (while (syntax-ppss-context (syntax-ppss))
+ (word-search-backward ruby-method-regex)))
(set-mark (point))
(ruby-end-of-block)
(end-of-line)
View
2  text-mode-expansions.el
@@ -27,6 +27,8 @@
;;; Code:
+(require 'expand-region-core)
+
(defun er/mark-text-sentence ()
"Marks one sentence."
(interactive)

No commit comments for this range

Something went wrong with that request. Please try again.