(smartparens-global-mode 1)
))
#+END_SRC
+*** expand-region
+ [2015-04-02 Thu 10:32]
+
+#+BEGIN_SRC emacs-lisp
+ (if (= emacs-major-version 24)
+ (progn
+ (add-to-list 'load-path "~/.emacs.d/elpa/expand-region-20141223.1328")
+ (require 'expand-region)
+ (global-set-key (kbd "C-=") 'er/expand-region)
+ ))
+
+#+END_SRC
*** yasnippet
#+BEGIN_SRC emacs-lisp
(key-chord-define-global "uu" 'undo)
(key-chord-define-global "xb" 'ido-switch-buffer)
(key-chord-define-global "xf" 'ido-find-file)
+ (if (= emacs-major-version 24)
+ (progn
+ (key-chord-define-global "==" 'er/expand-region)
+ (key-chord-define-global "--" 'er/contract-region)
+ ))
+
+
#+END_SRC
*** key bindings
--- /dev/null
+;;; cc-mode-expansions.el --- C-specific expansions for expand-region
+
+;; Copyright (C) 2012 François Févotte
+
+;; Author: François Févotte
+;; Based on js-mode-expansions by: Magnar Sveen <magnarsNOSPAMgmail.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 for C-like modes that I've found useful so far:
+;;
+;; er/c-mark-statement
+;; Captures simple and more complex statements.
+;;
+;; er/c-mark-fully-qualified-name
+;; Captures identifiers composed of several '::'-separated parts.
+;;
+;; er/c-mark-function-call[-1|-2]
+;; Captures an identifier followed by a '()'-enclosed block.
+;;
+;; er/c-mark-statement-block[-1|-2]
+;; Captures a statement followed by a '{}'-enclosed block.
+;; This matches function definitions and if/for/... constructs.
+;;
+;; er/c-mark-vector-access[-1|-2]
+;; Captures an identifier followed by a '[]'-enclosed block.
+;;
+;; Feel free to contribute any other expansions for C at
+;;
+;; https://github.com/magnars/expand-region.el
+
+;;; Code:
+
+(require 'expand-region-core)
+(require 'er-basic-expansions)
+(require 'cc-cmds)
+
+(defun er/c-mark-statement ()
+ "Mark the current C statement.
+
+This function tries to ensure that pair-delimited substring are
+either fully inside or fully outside the statement."
+ (interactive)
+ (unless (use-region-p)
+ (set-mark (point)))
+
+ (if (< (point) (mark))
+ (exchange-point-and-mark))
+
+ ;; Contract the region a bit to make the
+ ;; er/c-mark-statement function idempotent
+ (when (>= (- (point) (mark)) 2)
+ (exchange-point-and-mark)
+ (forward-char)
+ (exchange-point-and-mark)
+ (backward-char))
+
+ (let (beg end)
+ ;; Determine boundaries of the outside-pairs region
+ (save-excursion
+ (c-end-of-statement)
+ (er/mark-outside-pairs)
+ (setq beg (point)
+ end (mark)))
+
+ ;; Determine boundaries of the statement as given
+ ;; by c-beginning-of-statement/c-end-of-statement
+ (c-end-of-statement)
+ (exchange-point-and-mark)
+ (c-end-of-statement)(c-beginning-of-statement 1)
+
+ ;; If the two regions overlap, expand the region
+ (cond ((and (<= (point) beg)
+ (< (mark) end))
+ (set-mark end))
+ ((and (> (point) beg)
+ (>= (mark) end))
+ (goto-char beg)
+ (c-end-of-statement)
+ (c-beginning-of-statement 1)))))
+
+(defun er/c-mark-fully-qualified-name ()
+ "Mark the current C++ fully qualified identifier.
+
+This function captures identifiers composed of multiple
+'::'-separated parts."
+ (interactive)
+ (er/mark-symbol)
+ (when (use-region-p)
+ (when (> (point) (mark))
+ (exchange-point-and-mark))
+ (while (er/looking-back-exact "::")
+ (backward-char 2)
+ (skip-syntax-backward "_w"))
+ (exchange-point-and-mark)
+ (while (looking-at "::")
+ (forward-char 2)
+ (skip-syntax-forward "_w"))
+ (exchange-point-and-mark)))
+
+(defmacro er/c-define-construct (name mark-first-part open-brace doc)
+ (let ((docstring (make-symbol "docstring-tmp")))
+ (setq docstring
+ (concat
+ doc "\n\n"
+ "This function tries to mark a region consisting of two parts:\n"
+ (format " - the first part is marked using `%s'\n" (symbol-name mark-first-part))
+ (format " - the second part is a block beginning with '%s'\n\n" open-brace)))
+ `(progn
+ (defun ,(intern (concat (symbol-name name) "-1")) ()
+ ,(concat docstring
+ "This function assumes that point is in the first part and the\n"
+ "region is active.\n\n"
+ (format "See also `%s'." (concat (symbol-name name) "-2")))
+ (interactive)
+ (when (use-region-p)
+ (,mark-first-part)
+ (exchange-point-and-mark)
+ (let ((oldpos (point)))
+ (skip-syntax-forward " ")
+ (if (looking-at ,open-brace)
+ (progn (forward-sexp)
+ (exchange-point-and-mark))
+ (goto-char oldpos)))))
+ (defun ,(intern (concat (symbol-name name) "-2")) ()
+ ,(concat docstring
+ "This function assumes that the block constituting the second part\n"
+ "is already marked and active.\n\n"
+ (format "See also `%s'." (concat (symbol-name name) "-1")))
+ (interactive)
+ (when (use-region-p)
+ (when (> (point) (mark))
+ (exchange-point-and-mark))
+ (when (looking-at ,open-brace)
+ (let ((beg (point))
+ (end (progn (forward-sexp 1)
+ (point))))
+ (goto-char beg)
+ (skip-syntax-backward " ")
+ (backward-char)
+ (deactivate-mark)
+ (,mark-first-part)
+ (set-mark end))))))))
+
+(er/c-define-construct er/c-mark-function-call er/c-mark-fully-qualified-name "("
+ "Mark the current function call.")
+(er/c-define-construct er/c-mark-statement-block er/c-mark-statement "{"
+ "Mark the current block construct (like if, for, etc.)")
+(er/c-define-construct er/c-mark-vector-access er/c-mark-fully-qualified-name "\\["
+ "Mark the current vector access.")
+
+(defun er/add-cc-mode-expansions ()
+ "Adds expansions for buffers in c-mode."
+ (set (make-local-variable 'er/try-expand-list)
+ (append er/try-expand-list
+ '(er/c-mark-statement
+ er/c-mark-fully-qualified-name
+ er/c-mark-function-call-1 er/c-mark-function-call-2
+ er/c-mark-statement-block-1 er/c-mark-statement-block-2
+ er/c-mark-vector-access-1 er/c-mark-vector-access-2))))
+
+(er/enable-mode-expansions 'c-mode 'er/add-cc-mode-expansions)
+(er/enable-mode-expansions 'c++-mode 'er/add-cc-mode-expansions)
+(er/enable-mode-expansions 'objc-mode 'er/add-cc-mode-expansions)
+(er/enable-mode-expansions 'java-mode 'er/add-cc-mode-expansions)
+(er/enable-mode-expansions 'idl-mode 'er/add-cc-mode-expansions)
+(er/enable-mode-expansions 'pike-mode 'er/add-cc-mode-expansions)
+(er/enable-mode-expansions 'awk-mode 'er/add-cc-mode-expansions)
+
+(provide 'cc-mode-expansions)
+
+;; cc-mode-expansions.el ends here
--- /dev/null
+;;; clojure-mode-expansions.el --- Clojure-specific expansions for expand-region
+
+;; Copyright (C) 2011 Magnar Sveen
+
+;; Author: Magnar Sveen <magnarsNOSPAMgmail.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 for clojure-mode:
+;;
+;; * `er/mark-clj-word` - includes dashes, but not slashes.
+;; * `er/mark-clj-regexp-literal`
+;; * `er/mark-clj-function-literal`
+;;
+;; Feel free to contribute any other expansions for Clojure at
+;;
+;; https://github.com/magnars/expand-region.el
+
+;;; Code:
+
+(require 'expand-region-core)
+(require 'er-basic-expansions)
+
+(defun er/mark-clj-word ()
+ "Mark the entire word around or in front of point, including dashes."
+ (interactive)
+ (let ((word-regexp "\\(\\sw\\|-\\)"))
+ (when (or (looking-at word-regexp)
+ (er/looking-back-on-line word-regexp))
+ (while (looking-at word-regexp)
+ (forward-char))
+ (set-mark (point))
+ (while (er/looking-back-on-line word-regexp)
+ (backward-char)))))
+
+(defun er/mark-clj-set-literal ()
+ "Mark clj-set-literal presumes that point is outside the brackets.
+If point is inside the brackets, those will be marked first anyway."
+ (interactive)
+ (when (or (looking-at "#{")
+ (er/looking-back-exact "#"))
+ (forward-char 1)
+ (search-backward "#")
+ (set-mark (point))
+ (search-forward "{")
+ (forward-char -1)
+ (forward-list 1)
+ (exchange-point-and-mark)))
+
+(defun er/mark-clj-regexp-literal ()
+ "Mark clj-regexp-literal presumes that point is outside the string.
+If point is inside the string, the quotes will be marked first anyway."
+ (interactive)
+ (when (or (looking-at "#\"")
+ (er/looking-back-exact "#"))
+ (forward-char 1)
+ (search-backward "#")
+ (set-mark (point))
+ (search-forward "\"")
+ (forward-char 1)
+ (er--move-point-forward-out-of-string)
+ (exchange-point-and-mark)))
+
+(defun er/mark-clj-function-literal ()
+ "Mark clj-function-literal presumes that point is outside the parens.
+If point is inside the parens, they will be marked first anyway."
+ (interactive)
+ (when (or (looking-at "#(")
+ (er/looking-back-exact "#"))
+ (forward-char)
+ (search-backward "#")
+ (set-mark (point))
+ (search-forward "(")
+ (backward-char)
+ (forward-list)
+ (exchange-point-and-mark)))
+
+(defun er/add-clojure-mode-expansions ()
+ "Adds clojure-specific expansions for buffers in clojure-mode"
+ (set (make-local-variable 'er/try-expand-list) (append
+ er/try-expand-list
+ '(er/mark-clj-word
+ er/mark-clj-regexp-literal
+ er/mark-clj-set-literal
+ er/mark-clj-function-literal))))
+
+(er/enable-mode-expansions 'clojure-mode 'er/add-clojure-mode-expansions)
+(er/enable-mode-expansions 'nrepl-mode 'er/add-clojure-mode-expansions)
+
+(provide 'clojure-mode-expansions)
+
+;; clojure-mode-expansions.el ends here
--- /dev/null
+;;; cperl-mode-expansions.el --- perl-specific expansions for expand-region
+
+;; Copyright (C) 2012 Kang-min Liu
+
+;; Author: Kang-min Liu <gugodNOSPAMgugod.org>
+;; Keywords: marking region cperl
+
+;; 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/>.
+
+;;; Code:
+
+(require 'expand-region-core)
+
+(defun er/mark-cperl-variable-name ()
+ "Marks one perl variable"
+ (interactive)
+ (forward-word)
+ (backward-word)
+ (search-backward-regexp "[@$%]" (line-beginning-position))
+ (set-mark (point))
+ (forward-char)
+ (search-forward-regexp "[^a-z_]" (line-end-position))
+ (backward-char)
+ (exchange-point-and-mark))
+
+(defun er/mark-cperl-package-name ()
+ "Marks one perl package name"
+ (interactive)
+ (forward-sexp)
+ (backward-sexp)
+ (set-mark (point))
+ (forward-sexp)
+ (search-backward "::" (line-beginning-position))
+ (exchange-point-and-mark))
+
+(defun er/mark-cperl-subroutine ()
+ "Marks current subroutine body."
+ (interactive)
+ (end-of-defun)
+ (set-mark (point))
+ (beginning-of-defun))
+
+(defun er/add-cperl-mode-expansions ()
+ "Add cprel mode expansinos"
+ (set (make-local-variable 'er/try-expand-list) (append
+ er/try-expand-list
+ '(er/mark-cperl-variable-name
+ er/mark-cperl-package-name
+ er/mark-cperl-subroutine
+ ))))
+
+(er/enable-mode-expansions 'cperl-mode 'er/add-cperl-mode-expansions)
+
+(provide 'cperl-mode-expansions)
+
+;; cperl-mode-expansions.el ends here
--- /dev/null
+;;; css-mode-expansions.el --- CSS-specific expansions for expand-region
+
+;; Copyright (C) 2011 Magnar Sveen
+
+;; Author: Magnar Sveen <magnarsNOSPAMgmail.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:
+
+;; For now I have only found the need for mark-css-declaration.
+;;
+;; Feel free to contribute any other expansions for CSS at
+;;
+;; https://github.com/magnars/expand-region.el
+
+;;; Code:
+
+(require 'expand-region-core)
+
+(defun er/mark-css-declaration ()
+ "Marks one CSS declaration, eg. font-weight: bold;"
+ (interactive)
+ (search-backward-regexp "[;{] ?" (line-beginning-position))
+ (forward-char)
+ (set-mark (point))
+ (search-forward ";" (line-end-position))
+ (exchange-point-and-mark))
+
+(defun er/add-css-mode-expansions ()
+ "Adds CSS-specific expansions for buffers in css-mode"
+ (set (make-local-variable 'er/try-expand-list) (append
+ er/try-expand-list
+ '(er/mark-css-declaration))))
+
+(er/enable-mode-expansions 'css-mode 'er/add-css-mode-expansions)
+
+(provide 'css-mode-expansions)
+
+;; css-mode-expansions.el ends here
--- /dev/null
+;;; enh-ruby-mode-expansions.el --- Expansions for enh-ruby-mode
+
+;; Copyright (C) 2011 Magnar Sveen
+
+;; Author: Magnar Sveen <magnarsNOSPAMgmail.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:
+
+;; enh-ruby-mode doesn't use ruby-mode's mark-defun - it has its own.
+;;
+;; Feel free to contribute any other expansions for enh-ruby-mode at
+;;
+;; https://github.com/magnars/expand-region.el
+
+;;; Code:
+
+(defun er/add-enh-ruby-mode-expansions ()
+ "Adds Ruby-specific expansions for buffers in enh-ruby-mode"
+ (require 'ruby-mode-expansions)
+
+ (set (make-local-variable 'er/try-expand-list) (append
+ (remove 'er/mark-defun er/try-expand-list)
+ '(er/mark-ruby-instance-variable
+ er/mark-ruby-block-up))))
+
+(er/enable-mode-expansions 'enh-ruby-mode 'er/add-enh-ruby-mode-expansions)
+
+(provide 'enh-ruby-mode-expansions)
--- /dev/null
+;;; er-basic-expansions.el --- Words, symbols, strings, et al
+
+;; Copyright (C) 2011-2013 Magnar Sveen
+
+;; Author: Magnar Sveen <magnarsNOSPAMgmail.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:
+
+;; Expansions that are useful in any major mode.
+
+;;; Code:
+
+(require 'expand-region-core)
+
+(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)
+ (er/looking-back-on-line word-regexp))
+ (skip-syntax-forward "w")
+ (set-mark (point))
+ (skip-syntax-backward "w"))))
+
+(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)
+ (er/looking-back-on-line symbol-regexp))
+ (skip-syntax-forward "_w")
+ (set-mark (point))
+ (skip-syntax-backward "_w"))))
+
+(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)
+ (er/looking-back-on-line symbol-regexp))
+ (skip-syntax-forward "'")
+ (skip-syntax-forward "_w")
+ (set-mark (point))
+ (skip-syntax-backward "_w")
+ (skip-syntax-backward "'"))))
+
+;; 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)
+ (er/looking-back-on-line symbol-regexp))
+ (skip-syntax-backward "_w.")
+ (set-mark (point))
+ (when (looking-at symbol-regexp)
+ (goto-char (match-end 0)))
+ (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"
+ (or (nth 4 (syntax-ppss))
+ (memq (get-text-property (point) 'face) '(font-lock-comment-face font-lock-comment-delimiter-face))))
+
+(defun er/mark-comment ()
+ "Mark the entire comment around point."
+ (interactive)
+ (when (er--point-is-in-comment-p)
+ (let ((p (point)))
+ (while (er--point-is-in-comment-p)
+ (forward-char 1))
+ (skip-chars-backward " \n\t\r")
+ (set-mark (point))
+ (goto-char p)
+ (while (er--point-is-in-comment-p)
+ (forward-char -1))
+ (skip-chars-forward " \n\t\r"))))
+
+;; 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."
+ (er--move-point-backward-out-of-string)
+ (forward-sexp))
+
+(defun er--move-point-backward-out-of-string ()
+ "Move point backward until it exits the current quoted string."
+ (goto-char (nth 8 (syntax-ppss))))
+
+(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))
+ (er/looking-back-on-line "\\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 (er/looking-back-on-line "\\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)))
+
+(require 'thingatpt)
+
+(defun er/mark-url ()
+ (interactive)
+ (end-of-thing 'url)
+ (set-mark (point))
+ (beginning-of-thing 'url))
+
+(defun er/mark-email ()
+ (interactive)
+ (end-of-thing 'email)
+ (set-mark (point))
+ (beginning-of-thing 'email))
+
+(defun er/mark-defun ()
+ "Mark defun around or in front of point."
+ (interactive)
+ (end-of-defun)
+ (skip-chars-backward er--space-str)
+ (set-mark (point))
+ (beginning-of-defun)
+ (skip-chars-forward er--space-str))
+
+;; Methods to try expanding to
+(setq er/try-expand-list
+ (append '(er/mark-word
+ er/mark-symbol
+ er/mark-symbol-with-prefix
+ er/mark-next-accessor
+ er/mark-method-call
+ er/mark-inside-quotes
+ er/mark-outside-quotes
+ er/mark-inside-pairs
+ er/mark-outside-pairs
+ er/mark-comment
+ er/mark-url
+ er/mark-email
+ er/mark-defun)
+ er/try-expand-list))
+
+(provide 'er-basic-expansions)
+;;; er-basic-expansions.el ends here
--- /dev/null
+;;; erlang-mode-expansions.el --- Erlang-specific expansions for expand-region
+
+;; Copyright (C) 2012 Gleb Peregud
+
+;; Author: Gleb Peregud
+;; Based on python-mode-expansions by: Ivan Andrus <darthandrusNOSPAMgmail.com>
+;; Keywords: marking region erlang
+
+;; 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:
+
+;; Feel free to contribute any other expansions for Erlang at
+;;
+;; https://github.com/magnars/expand-region.el
+
+;;; Bugs:
+
+;; Doesn't handle many Erlang syntax constructs, just the basics
+
+;;; 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
+ er/try-expand-list
+ '(erlang-mark-function
+ erlang-mark-clause))))
+
+(er/enable-mode-expansions 'erlang-mode 'er/add-erlang-mode-expansions)
+
+(provide 'erlang-mode-expansions)
+
+;; erlang-mode-expansions.el ends here
--- /dev/null
+;;; expand-region-autoloads.el --- automatically extracted autoloads
+;;
+;;; Code:
+
+\f
+;;;### (autoloads (er/expand-region) "expand-region" "expand-region.el"
+;;;;;; (21788 64883 0 0))
+;;; Generated autoloads from expand-region.el
+
+(autoload 'er/expand-region "expand-region" "\
+Increase selected region by semantic units.
+
+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.
+
+\(fn ARG)" t nil)
+
+;;;***
+\f
+;;;### (autoloads (expand-region-exclude-text-mode-expansions expand-region-reset-fast-key
+;;;;;; expand-region-contract-fast-key expand-region-fast-keys-enabled
+;;;;;; expand-region-skip-whitespace expand-region-autocopy-register
+;;;;;; expand-region-guess-python-mode expand-region-preferred-python-mode
+;;;;;; expand-region) "expand-region-custom" "expand-region-custom.el"
+;;;;;; (21788 64883 0 0))
+;;; Generated autoloads from expand-region-custom.el
+
+(let ((loads (get 'expand-region 'custom-loads))) (if (member '"expand-region-custom" loads) nil (put 'expand-region 'custom-loads (cons '"expand-region-custom" loads))))
+
+(defvar expand-region-preferred-python-mode 'python "\
+The name of your preferred python mode")
+
+(custom-autoload 'expand-region-preferred-python-mode "expand-region-custom" t)
+
+(defvar expand-region-guess-python-mode t "\
+If expand-region should attempt to guess your preferred python mode")
+
+(custom-autoload 'expand-region-guess-python-mode "expand-region-custom" t)
+
+(defvar expand-region-autocopy-register "" "\
+If set to a string of a single character (try \"e\"), then the
+contents of the most recent expand or contract command will
+always be copied to the register named after that character.")
+
+(custom-autoload 'expand-region-autocopy-register "expand-region-custom" t)
+
+(defvar expand-region-skip-whitespace t "\
+If expand-region should skip past whitespace on initial expansion")
+
+(custom-autoload 'expand-region-skip-whitespace "expand-region-custom" t)
+
+(defvar expand-region-fast-keys-enabled t "\
+If expand-region should bind fast keys after initial expand/contract")
+
+(custom-autoload 'expand-region-fast-keys-enabled "expand-region-custom" t)
+
+(defvar expand-region-contract-fast-key "-" "\
+Key to use after an initial expand/contract to contract once more.")
+
+(custom-autoload 'expand-region-contract-fast-key "expand-region-custom" t)
+
+(defvar expand-region-reset-fast-key "0" "\
+Key to use after an initial expand/contract to undo.")
+
+(custom-autoload 'expand-region-reset-fast-key "expand-region-custom" t)
+
+(defvar expand-region-exclude-text-mode-expansions '(html-mode nxml-mode) "\
+List of modes which derive from `text-mode' for which text mode expansions are not appropriate.")
+
+(custom-autoload 'expand-region-exclude-text-mode-expansions "expand-region-custom" t)
+
+;;;***
+\f
+;;;### (autoloads nil nil ("cc-mode-expansions.el" "clojure-mode-expansions.el"
+;;;;;; "cperl-mode-expansions.el" "css-mode-expansions.el" "enh-ruby-mode-expansions.el"
+;;;;;; "er-basic-expansions.el" "erlang-mode-expansions.el" "expand-region-core.el"
+;;;;;; "expand-region-pkg.el" "feature-mode-expansions.el" "html-mode-expansions.el"
+;;;;;; "js-mode-expansions.el" "js2-mode-expansions.el" "jsp-expansions.el"
+;;;;;; "latex-mode-expansions.el" "nxml-mode-expansions.el" "octave-expansions.el"
+;;;;;; "python-el-expansions.el" "python-el-fgallina-expansions.el"
+;;;;;; "python-mode-expansions.el" "ruby-mode-expansions.el" "sml-mode-expansions.el"
+;;;;;; "subword-mode-expansions.el" "text-mode-expansions.el" "the-org-mode-expansions.el"
+;;;;;; "web-mode-expansions.el") (21788 64883 251620 0))
+
+;;;***
+\f
+(provide 'expand-region-autoloads)
+;; Local Variables:
+;; version-control: never
+;; no-byte-compile: t
+;; no-update-autoloads: t
+;; coding: utf-8
+;; End:
+;;; expand-region-autoloads.el ends here
--- /dev/null
+;;; expand-region-core.el --- Increase selected region by semantic units.
+
+;; Copyright (C) 2011-2013 Magnar Sveen
+
+;; Author: Magnar Sveen <magnarsNOSPAMgmail.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.
+
+;; See README.md
+
+;;; Code:
+
+(eval-when-compile (require 'cl))
+(require 'expand-region-custom)
+(declare-function er/expand-region "expand-region")
+
+(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))
+
+(set-default 'er--show-expansion-message nil)
+
+(defvar er/try-expand-list nil
+ "A list of functions that are tried when expanding.")
+
+(defun er--prepare-expanding ()
+ (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))))
+
+(defun er--copy-region-to-register ()
+ (when (and (stringp expand-region-autocopy-register)
+ (> (length expand-region-autocopy-register) 0))
+ (set-register (aref expand-region-autocopy-register 0)
+ (filter-buffer-substring (region-beginning) (region-end)))))
+
+(defun er--expand-region-1 ()
+ "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."
+ (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 (point-min))
+ (best-end (point-max))
+ (set-mark-default-inactive nil))
+
+ ;; 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 expand-region-skip-whitespace
+ (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)
+ (er--this-expansion-is-better start end best-start best-end))
+ (setq best-start (point))
+ (setq best-end (mark))
+ (when (and er--show-expansion-message (not (minibufferp)))
+ (message "%S" (car try-list))))))
+ (setq try-list (cdr try-list)))
+
+ (setq deactivate-mark nil)
+ (goto-char best-start)
+ (set-mark best-end)
+
+ (er--copy-region-to-register)
+
+ (when (and (= best-start (point-min))
+ (= best-end (point-max))) ;; We didn't find anything new, so exit early
+ 'early-exit)))
+
+(defun er--this-expansion-is-better (start end best-start best-end)
+ "t if the current region is an improvement on previous expansions.
+
+This is provided as a separate function for those that would like
+to override the heuristic."
+ (and
+ (<= (point) start)
+ (>= (mark) end)
+ (> (- (mark) (point)) (- end start))
+ (or (> (point) best-start)
+ (and (= (point) best-start)
+ (< (mark) best-end)))))
+
+(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)
+
+ (er--copy-region-to-register)
+
+ (when (eq start end)
+ (deactivate-mark)
+ (er/clear-history))))))
+
+(defun er/prepare-for-more-expansions-internal (repeat-key-str)
+ "Return bindings and a message to inform user about them"
+ (let ((msg (format "Type %s to expand again" repeat-key-str))
+ (bindings (list (cons repeat-key-str '(er/expand-region 1)))))
+ ;; If contract and expand are on the same binding, ignore contract
+ (unless (string-equal repeat-key-str expand-region-contract-fast-key)
+ (setq msg (concat msg (format ", %s to contract" expand-region-contract-fast-key)))
+ (push (cons expand-region-contract-fast-key '(er/contract-region 1)) bindings))
+ ;; If reset and either expand or contract are on the same binding, ignore reset
+ (unless (or (string-equal repeat-key-str expand-region-reset-fast-key)
+ (string-equal expand-region-contract-fast-key expand-region-reset-fast-key))
+ (setq msg (concat msg (format ", %s to reset" expand-region-reset-fast-key)))
+ (push (cons expand-region-reset-fast-key '(er/expand-region 0)) bindings))
+ (cons msg bindings)))
+
+(defun er/prepare-for-more-expansions ()
+ "Let one expand more by just pressing the last key."
+ (let* ((repeat-key (event-basic-type last-input-event))
+ (repeat-key-str (single-key-description repeat-key))
+ (msg-and-bindings (er/prepare-for-more-expansions-internal repeat-key-str))
+ (msg (car msg-and-bindings))
+ (bindings (cdr msg-and-bindings)))
+ (when repeat-key
+ (set-temporary-overlay-map
+ (let ((map (make-sparse-keymap)))
+ (dolist (binding bindings map)
+ (define-key map (read-kbd-macro (car binding))
+ `(lambda ()
+ (interactive)
+ (setq this-command `,(cadr ',binding))
+ (or (minibufferp) (message "%s" ,msg))
+ (eval `,(cdr ',binding))))))
+ t)
+ (or (minibufferp) (message "%s" msg)))))
+
+(when (not (fboundp 'set-temporary-overlay-map))
+ ;; Backport this function from newer emacs versions
+ (defun set-temporary-overlay-map (map &optional keep-pred)
+ "Set a new keymap that will only exist for a short period of time.
+The new keymap to use must be given in the MAP variable. When to
+remove the keymap depends on user input and KEEP-PRED:
+
+- if KEEP-PRED is nil (the default), the keymap disappears as
+ soon as any key is pressed, whether or not the key is in MAP;
+
+- if KEEP-PRED is t, the keymap disappears as soon as a key *not*
+ in MAP is pressed;
+
+- otherwise, KEEP-PRED must be a 0-arguments predicate that will
+ decide if the keymap should be removed (if predicate returns
+ nil) or kept (otherwise). The predicate will be called after
+ each key sequence."
+
+ (let* ((clearfunsym (make-symbol "clear-temporary-overlay-map"))
+ (overlaysym (make-symbol "t"))
+ (alist (list (cons overlaysym map)))
+ (clearfun
+ `(lambda ()
+ (unless ,(cond ((null keep-pred) nil)
+ ((eq t keep-pred)
+ `(eq this-command
+ (lookup-key ',map
+ (this-command-keys-vector))))
+ (t `(funcall ',keep-pred)))
+ (remove-hook 'pre-command-hook ',clearfunsym)
+ (setq emulation-mode-map-alists
+ (delq ',alist emulation-mode-map-alists))))))
+ (set overlaysym overlaysym)
+ (fset clearfunsym clearfun)
+ (add-hook 'pre-command-hook clearfunsym)
+
+ (push alist emulation-mode-map-alists))))
+
+(defadvice keyboard-quit (before collapse-region activate)
+ (when (memq last-command '(er/expand-region er/contract-region))
+ (er/contract-region 0)))
+
+(defadvice minibuffer-keyboard-quit (around collapse-region activate)
+ (if (memq last-command '(er/expand-region er/contract-region))
+ (er/contract-region 0)
+ ad-do-it))
+
+(defadvice cua-cancel (before collapse-region activate)
+ (when (memq last-command '(er/expand-region er/contract-region))
+ (er/contract-region 0)))
+
+(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)))
+
+(defun er/enable-mode-expansions (mode add-fn)
+ (add-hook (intern (format "%s-hook" mode)) add-fn)
+ (save-window-excursion
+ (dolist (buffer (buffer-list))
+ (with-current-buffer buffer
+ (when (derived-mode-p mode)
+ (funcall add-fn))))))
+
+;; Some more performant version of `looking-back'
+
+(defun er/looking-back-on-line (regexp)
+ "Version of `looking-back' that only checks current line."
+ (looking-back regexp (line-beginning-position)))
+
+(defun er/looking-back-exact (s)
+ "Version of `looking-back' that only looks for exact matches, no regexp."
+ (string= s (buffer-substring (- (point) (length s))
+ (point))))
+
+(defun er/looking-back-max (regexp count)
+ "Version of `looking-back' that only check COUNT chars back."
+ (looking-back regexp (max 1 (- (point) count))))
+
+(provide 'expand-region-core)
+
+;;; expand-region-core.el ends here
--- /dev/null
+;;; expand-region-custom.el --- Increase selected region by semantic units.
+
+;; Copyright (C) 2012 Magnar Sveen
+
+;; Author: Magnar Sveen <magnarsNOSPAMgmail.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:
+
+;; This file holds customization variables.
+
+;;; Code:
+
+;;;###autoload
+(defgroup expand-region nil
+ "Increase selected region by semantic units."
+ :group 'tools)
+
+;;;###autoload
+(defcustom expand-region-preferred-python-mode 'python
+ "The name of your preferred python mode"
+ :group 'expand-region
+ :type '(choice (const :tag "Emacs' python.el" 'python)
+ (const :tag "fgallina's python.el" 'fgallina-python)
+ (const :tag "python-mode.el" 'python-mode)))
+
+;;;###autoload
+(defcustom expand-region-guess-python-mode t
+ "If expand-region should attempt to guess your preferred python mode"
+ :group 'expand-region
+ :type '(choice (const :tag "Guess" t)
+ (const :tag "Do not guess" nil)))
+
+(defun expand-region-guess-python-mode ()
+ "Guess the user's preferred python mode."
+ (setq expand-region-preferred-python-mode
+ (if (fboundp 'python-setup-brm)
+ 'python
+ 'fgallina-python)))
+
+;;;###autoload
+(defcustom expand-region-autocopy-register ""
+ "If set to a string of a single character (try \"e\"), then the
+contents of the most recent expand or contract command will
+always be copied to the register named after that character."
+ :group 'expand-region
+ :type 'string)
+
+;;;###autoload
+(defcustom expand-region-skip-whitespace t
+ "If expand-region should skip past whitespace on initial expansion"
+ :group 'expand-region
+ :type '(choice (const :tag "Skip whitespace" t)
+ (const :tag "Do not skip whitespace" nil)))
+
+;;;###autoload
+(defcustom expand-region-fast-keys-enabled t
+ "If expand-region should bind fast keys after initial expand/contract"
+ :group 'expand-region
+ :type '(choice (const :tag "Enable fast keys" t)
+ (const :tag "Disable fast keys" nil)))
+
+;;;###autoload
+(defcustom expand-region-contract-fast-key "-"
+ "Key to use after an initial expand/contract to contract once more."
+ :group 'expand-region
+ :type 'string)
+
+;;;###autoload
+(defcustom expand-region-reset-fast-key "0"
+ "Key to use after an initial expand/contract to undo."
+ :group 'expand-region
+ :type 'string)
+
+;;;###autoload
+(defcustom expand-region-exclude-text-mode-expansions
+ '(html-mode nxml-mode)
+ "List of modes which derive from `text-mode' for which text mode expansions are not appropriate."
+ :group 'expand-region
+ :type '(repeat (symbol :tag "Major Mode" unknown)))
+
+(provide 'expand-region-custom)
+
+;;; expand-region-custom.el ends here
--- /dev/null
+(define-package "expand-region" "20141223.1328" "Increase selected region by semantic units." 'nil)
+;; Local Variables:
+;; no-byte-compile: t
+;; End:
--- /dev/null
+;;; expand-region.el --- Increase selected region by semantic units.
+
+;; Copyright (C) 2011 Magnar Sveen
+
+;; Author: Magnar Sveen <magnarsNOSPAMgmail.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:
+
+;; Expand region increases the selected region by semantic units. Just keep
+;; pressing the key until it selects what you want.
+
+;; An example:
+
+;; (setq alphabet-start "abc def")
+
+;; With the cursor at the `c`, it starts by marking the entire word `abc`, then
+;; expand to the contents of the quotes `abc def`, then to the entire quote
+;; `"abc def"`, then to the contents of the sexp `setq alphabet-start "abc def"`
+;; and finally to the entire sexp.
+
+;; You can set it up like this:
+
+;; (require 'expand-region)
+;; (global-set-key (kbd "C-=") 'er/expand-region)
+
+;; 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
+
+;; Expand region works fairly well with most languages, due to the general
+;; nature of the basic expansions:
+
+;; er/mark-word
+;; er/mark-symbol
+;; er/mark-method-call
+;; er/mark-inside-quotes
+;; er/mark-outside-quotes
+;; er/mark-inside-pairs
+;; er/mark-outside-pairs
+
+;; However, most languages also will benefit from some specially crafted
+;; expansions. For instance, expand-region comes with these extra expansions for
+;; html-mode:
+
+;; er/mark-html-attribute
+;; er/mark-inner-tag
+;; er/mark-outer-tag
+
+;; You can add your own expansions to the languages of your choice simply by
+;; creating a function that looks around point to see if it's inside or looking
+;; at the construct you want to mark, and if so - mark it.
+
+;; There's plenty of examples to look at in these files.
+
+;; After you make your function, add it to a buffer-local version of
+;; the `er/try-expand-list`.
+
+;; **Example:**
+
+;; Let's say you want expand-region to also mark paragraphs and pages in
+;; text-mode. Incidentally Emacs already comes with `mark-paragraph` and
+;; `mark-page`. To add it to the try-list, do this:
+
+;; (defun er/add-text-mode-expansions ()
+;; (make-variable-buffer-local 'er/try-expand-list)
+;; (setq er/try-expand-list (append
+;; er/try-expand-list
+;; '(mark-paragraph
+;; mark-page))))
+
+;; (er/enable-mode-expansions 'text-mode 'er/add-text-mode-expansions)
+
+;; Add that to its own file, and require it at the bottom of this one,
+;; where it says "Mode-specific expansions"
+
+;; **Warning:** Badly written expansions might slow down expand-region
+;; dramatically. Remember to exit quickly before you start traversing
+;; 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 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.
+;; * [fgeller](https://github.com/fgeller) and [edmccard](https://github.com/edmccard) contributed better support for python and its multiple modes.
+;; * [François Févotte](https://github.com/ffevotte) contributed expansions for C and C++.
+;; * [Roland Walker](https://github.com/rolandwalker) added option to copy the contents of the most recent action to a register, and some fixes.
+;; * [Damien Cassou](https://github.com/DamienCassou) added option to continue expanding/contracting with fast keys after initial expand.
+
+;; Thanks!
+
+;;; Code:
+
+(require 'expand-region-core)
+(require 'expand-region-custom)
+(require 'er-basic-expansions)
+
+;;;###autoload
+(defun er/expand-region (arg)
+ "Increase selected region by semantic units.
+
+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 (- arg))
+ (er--prepare-expanding)
+ (while (>= arg 1)
+ (setq arg (- arg 1))
+ (when (eq 'early-exit (er--expand-region-1))
+ (setq arg 0)))
+ (when (and expand-region-fast-keys-enabled
+ (not (memq last-command '(er/expand-region er/contract-region))))
+ (er/prepare-for-more-expansions))))
+
+(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 "web-mode" '(require 'web-mode-expansions))
+(eval-after-load "js" '(require 'js-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" '(require 'latex-mode-expansions))
+(eval-after-load "nxml-mode" '(require 'nxml-mode-expansions))
+(eval-after-load "octave-mod" '(require 'octave-expansions))
+(eval-after-load "octave" '(require 'octave-expansions))
+(eval-after-load "python" '(progn
+ (when expand-region-guess-python-mode
+ (expand-region-guess-python-mode))
+ (if (eq 'python expand-region-preferred-python-mode)
+ (require 'python-el-expansions)
+ (require 'python-el-fgallina-expansions))))
+(eval-after-load "python-mode" '(require 'python-mode-expansions))
+(eval-after-load "ruby-mode" '(require 'ruby-mode-expansions))
+(eval-after-load "org" '(require 'the-org-mode-expansions))
+(eval-after-load "cc-mode" '(require 'cc-mode-expansions))
+(eval-after-load "text-mode" '(require 'text-mode-expansions))
+(eval-after-load "cperl-mode" '(require 'cperl-mode-expansions))
+(eval-after-load "sml-mode" '(require 'sml-mode-expansions))
+(eval-after-load "enh-ruby-mode" '(require 'enh-ruby-mode-expansions))
+(eval-after-load "subword-mode" '(require 'subword-mode-expansions))
+
+(provide 'expand-region)
+
+;;; expand-region.el ends here
--- /dev/null
+;;; feature-mode-expansions.el --- cucumber-specific expansions for expand-region
+
+;; Copyright (C) 2012 Raimon Grau
+
+;; Author: Raimon Grau
+;; Based on js-mode-expansions by: Raimon Grau <raimonsterNOSPAMgmail.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:
+
+
+;; expanders to mark feature semantic objects like step or scenario
+;;
+;; Expansions:
+;;
+;;
+;; 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 (concat "^\\( \\)*" start-keywords-regexp))
+ (end-key-words (concat "^\\( \\)*" (or end-keywords-regexp start-keywords-regexp))))
+ (when (looking-at-p "[^\\s-]")
+ (skip-syntax-forward "w."))
+ (if (looking-at-p start-keywords-regexp)
+ (progn (beginning-of-line)
+ (exchange-point-and-mark))
+ (re-search-backward start-key-words)
+ (set-mark (point))
+ (re-search-forward start-key-words))
+ (unless (re-search-forward end-key-words (point-max) t)
+ (goto-char (point-max)))
+ (forward-line 0)
+ (exchange-point-and-mark)))
+
+(defun er/mark-feature-scenario ()
+ (interactive)
+ (er--block-between-keywords "\\(Background:\\|Scenario:\\|Feature:\\)"))
+
+(defun er/mark-feature-step ()
+ (interactive)
+ (er--block-between-keywords "\\(And\\|Given\\|When\\|Then\\)" "\\(And\\|Given\\|When\\|Then\\|Scenario:\\)"))
+
+(defun er/add-feature-mode-expansions ()
+ "Adds cucumber-specific expansions for buffers in feature-mode"
+ (set (make-local-variable 'er/try-expand-list) (append
+ er/try-expand-list
+ '(er/mark-feature-scenario
+ er/mark-feature-step))))
+
+(er/enable-mode-expansions 'feature-mode 'er/add-feature-mode-expansions)
+
+(provide 'feature-mode-expansions)
--- /dev/null
+;;; html-mode-expansions.el --- HTML-specific expansions for expand-region
+
+;; Copyright (C) 2011 Magnar Sveen
+
+;; Author: Magnar Sveen <magnarsNOSPAMgmail.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 for HTML that I've found useful so far:
+;;
+;; er/mark-html-attribute
+;; er/mark-inner-tag
+;; er/mark-outer-tag
+;;
+;; Feel free to contribute any other expansions for HTML at
+;;
+;; https://github.com/magnars/expand-region.el
+
+;;; Code:
+
+(require 'expand-region-core)
+(require 'sgml-mode)
+
+(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
+first anyway. Does not support html-attributes with spaces
+around the equal sign or unquotes attributes atm."
+ (interactive)
+ (when (or (looking-at "\\(\\s_\\|\\sw\\)*=")
+ (er/looking-back-exact "="))
+ (search-backward " ")
+ (forward-char 1)
+ (set-mark (point))
+ (search-forward "=")
+ (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 "<")
+ (>= (mark)
+ (save-excursion
+ (sgml-skip-tag-forward 1)
+ (point)))))
+
+(defun er--inside-tag-p ()
+ "Is point inside a tag?"
+ (save-excursion
+ (not (null (sgml-get-context)))))
+
+(defun er/mark-outer-tag ()
+ "Mark from opening to closing tag, including the tags."
+ (interactive)
+ (when (and (er--inside-tag-p)
+ (or (not (looking-at "<"))
+ (er--looking-at-marked-tag)))
+ (goto-char (aref (car (last (sgml-get-context))) 2)))
+ (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."
+ (interactive)
+ (goto-char (aref (car (last (sgml-get-context))) 3))
+ (set-mark (point))
+ (backward-char 1)
+ (sgml-skip-tag-forward 1)
+ (search-backward "</")
+ (exchange-point-and-mark))
+
+(defun er/add-html-mode-expansions ()
+ "Adds HTML-specific expansions for buffers in html-mode"
+ (set (make-local-variable 'er/try-expand-list) (append
+ er/try-expand-list
+ '(er/mark-html-attribute
+ er/mark-inner-tag
+ er/mark-outer-tag))))
+
+(er/enable-mode-expansions 'html-mode 'er/add-html-mode-expansions)
+(er/enable-mode-expansions 'rhtml-mode 'er/add-html-mode-expansions)
+(er/enable-mode-expansions 'nxhtml-mode 'er/add-html-mode-expansions)
+(er/enable-mode-expansions 'web-mode 'er/add-html-mode-expansions)
+
+(provide 'html-mode-expansions)
+
+;; html-mode-expansions.el ends here
--- /dev/null
+;;; js-mode-expansions.el --- JS-specific expansions for expand-region
+
+;; Copyright (C) 2011 Magnar Sveen
+
+;; Author: Magnar Sveen <magnarsNOSPAMgmail.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 for JavaScript that I've found useful so far:
+;;
+;; er/mark-js-function
+;; er/mark-js-object-property-value
+;; er/mark-js-object-property
+;; er/mark-js-if
+;; er/mark-js-inner-return
+;; er/mark-js-outer-return
+;;
+;; Feel free to contribute any other expansions for JavaScript at
+;;
+;; https://github.com/magnars/expand-region.el
+
+;;; Code:
+
+(require 'expand-region-core)
+
+(defun er/mark-js-function ()
+ "Mark the current JavaScript function."
+ (interactive)
+ (condition-case nil
+ (forward-char 8)
+ (error nil))
+ (word-search-backward "function")
+ (while (or (er--point-inside-string-p)
+ (er--point-is-in-comment-p))
+ (word-search-backward "function"))
+ (set-mark (point))
+ (while (not (looking-at "{"))
+ (forward-char))
+ (forward-list)
+ (exchange-point-and-mark))
+
+(defun er/mark-js-outer-return ()
+ "Mark the current return statement, including return and ending semi-colon"
+ (interactive)
+ (condition-case nil
+ (forward-char 6)
+ (error nil))
+ (word-search-backward "return")
+ (while (or (er--point-inside-string-p)
+ (er--point-is-in-comment-p))
+ (word-search-backward "return"))
+ (set-mark (point))
+ (while (not (looking-at ";"))
+ (if (looking-at "\\s(")
+ (forward-list)
+ (forward-char)))
+ (forward-char)
+ (exchange-point-and-mark))
+
+(defun er/mark-js-inner-return ()
+ "Mark contents of the current return statement, not including return or semi-colon"
+ (interactive)
+ (condition-case nil
+ (forward-char 6)
+ (error nil))
+ (word-search-backward "return")
+ (while (or (er--point-inside-string-p)
+ (er--point-is-in-comment-p))
+ (word-search-backward "return"))
+ (search-forward " ")
+ (set-mark (point))
+ (while (not (looking-at ";"))
+ (if (looking-at "\\s(")
+ (forward-list)
+ (forward-char)))
+ (exchange-point-and-mark))
+
+(defun er/mark-js-if ()
+ "Mark the current if-statement."
+ (interactive)
+ (condition-case nil
+ (forward-char 2)
+ (error nil))
+ (word-search-backward "if")
+ (while (or (er--point-inside-string-p)
+ (er--point-is-in-comment-p))
+ (word-search-backward "if"))
+ (set-mark (point))
+ (while (not (looking-at "("))
+ (forward-char))
+ (forward-list)
+ (while (not (looking-at "{"))
+ (forward-char))
+ (forward-list)
+ (exchange-point-and-mark))
+
+(defun er/mark-js-object-property-value ()
+ "Mark the current object property value, ie. from : to , or }"
+ (interactive)
+ (unless (er--point-inside-pairs-p)
+ (error "Point is not inside an object"))
+ (search-backward ":")
+ (forward-char)
+ (search-forward-regexp "[^\s]")
+ (backward-char)
+ (set-mark (point))
+ (while (not (looking-at "[},]"))
+ (if (looking-at "\\s(")
+ (forward-list)
+ (forward-char)))
+ (when (er/looking-back-max "[\s\n]" 400)
+ (search-backward-regexp "[^\s\n]")
+ (forward-char))
+ (exchange-point-and-mark))
+
+(defun er/mark-js-object-property ()
+ "Mark js-object-property presumes that point is at the assignment part of key: value.
+If point is inside the value, that will be marked first anyway."
+ (interactive)
+ (when (or (looking-at "\"?\\(\\s_\\|\\sw\\| \\)*\":")
+ (looking-at "\\(\\s_\\|\\sw\\)*:")
+ (er/looking-back-max ": ?" 2))
+ (search-backward-regexp "[{,]")
+ (forward-char)
+ (search-forward-regexp "[^\s\n]")
+ (backward-char)
+ (set-mark (point))
+ (search-forward ":")
+ (while (or (not (looking-at "[},]"))
+ (er--point-inside-string-p))
+ (if (looking-at "\\s(")
+ (forward-list)
+ (forward-char)))
+ (when (er/looking-back-max "[\s\n]" 400)
+ (search-backward-regexp "[^\s\n]")
+ (forward-char))
+ (exchange-point-and-mark)))
+
+(defun er/mark-js-call ()
+ "Mark the current symbol (including dots) and then parens or squares."
+ (interactive)
+ (let ((symbol-regexp "\\(\\s_\\|\\sw\\|\\.\\)+"))
+ (when (or (looking-at symbol-regexp)
+ (er/looking-back-on-line symbol-regexp))
+ (skip-syntax-backward "_w.")
+ (when (looking-at "!")
+ (forward-char 1))
+ (set-mark (point))
+ (when (looking-at symbol-regexp)
+ (goto-char (match-end 0)))
+ (if (looking-at "\\[\\|(")
+ (forward-list))
+ (exchange-point-and-mark))))
+
+(defun er/add-js-mode-expansions ()
+ "Adds JS-specific expansions for buffers in js-mode"
+ (set (make-local-variable 'er/try-expand-list) (append
+ er/try-expand-list
+ '(er/mark-js-function
+ er/mark-js-object-property-value
+ er/mark-js-object-property
+ er/mark-js-if
+ er/mark-js-inner-return
+ er/mark-js-outer-return
+ er/mark-js-call))))
+
+(er/enable-mode-expansions 'js-mode 'er/add-js-mode-expansions)
+(er/enable-mode-expansions 'js2-mode 'er/add-js-mode-expansions)
+(er/enable-mode-expansions 'js3-mode 'er/add-js-mode-expansions)
+
+(provide 'js-mode-expansions)
+
+;; js-mode-expansions.el ends here
--- /dev/null
+;;; js2-mode-expansions.el --- Additional expansions for js2-mode
+
+;; Copyright (C) 2011 Magnar Sveen
+
+;; Author: Magnar Sveen <magnarsNOSPAMgmail.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)
+(declare-function js2-node-parent-stmt "js2-mode")
+(declare-function js2-node-at-point "js2-mode")
+(declare-function js2-node-abs-pos "js2-mode")
+(declare-function js2-node-len "js2-mode")
+
+(defun js2-mark-parent-statement ()
+ (interactive)
+ (let* ((parent-statement (if (not (er/looking-back-exact ";"))
+ (js2-node-parent-stmt (js2-node-at-point))
+ (forward-char -1)
+ (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))))
+
+(er/enable-mode-expansions 'js2-mode 'er/add-js2-mode-expansions)
+
+(provide 'js2-mode-expansions)
+
+;; js2-mode-expansions.el ends here
--- /dev/null
+;;; jsp-expansions.el --- JSP-specific expansions for expand-region
+
+;; Copyright (C) 2011 Magnar Sveen
+
+;; Author: Magnar Sveen <magnarsNOSPAMgmail.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 for editing JSP files. To be used in conjunction
+;; with the html-mode expansions
+;;
+;; er/mark-jstl-escape
+;;
+;; These expansions aren't loaded by default, so you'll have to explicitly
+;; ask for them in your init file with:
+;;
+;; (eval-after-load "sgml-mode" '(require 'jsp-expansions))
+;;
+;; Feel free to contribute any other expansions for JSP at
+;;
+;; https://github.com/magnars/expand-region.el
+
+;;; Code:
+
+(require 'expand-region-core)
+
+(defun er/mark-jstl-escape ()
+ "Mark jstl-escape presumes that point is outside the brackets.
+If point is inside the brackets, they will be marked first anyway."
+ (interactive)
+ (when (or (looking-at "\\${")
+ (er/looking-back-exact "$"))
+ (forward-char 1)
+ (search-backward "\$")
+ (set-mark (point))
+ (forward-char 1)
+ (forward-list)
+ (exchange-point-and-mark)))
+
+(defun er/add-jsp-expansions ()
+ "Adds JSP-specific expansions to the buffer"
+ (set (make-local-variable 'er/try-expand-list) (append
+ er/try-expand-list
+ '(er/mark-jstl-escape))))
+
+(er/enable-mode-expansions 'html-mode 'er/add-jsp-expansions)
+
+(provide 'jsp-expansions)
+
+;; jsp-expansions.el ends here
--- /dev/null
+;;; latex-mode-expansions.el --- LaTeX-specific expansions for expand-region
+
+;; Copyright (C) 2012 Ivan Andrus
+
+;; Author: Ivan Andrus
+;; Based on js-mode-expansions by: Magnar Sveen <magnarsNOSPAMgmail.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:
+
+;; This is for AUCTeX, not the builtin latex-mode.
+
+;; Feel free to contribute any other expansions for LaTeX at
+;;
+;; https://github.com/magnars/expand-region.el
+
+;;; Code:
+
+(require 'expand-region-core)
+;referenced free variables and functions defined in mode
+(defvar texmathp-why)
+(defvar texmathp-tex-commands1)
+(defvar texmathp-onoff-regexp)
+(defvar LaTeX-mode-hook)
+(declare-function LaTeX-mark-environment "latex")
+(declare-function texmathp "texmathp")
+
+(defun er/mark-LaTeX-inside-environment ()
+ "Like `LaTeX-mark-environment' but marks the inside of the environment.
+Skips past [] and {} arguments to the environment."
+ (interactive)
+ (LaTeX-mark-environment)
+ (when (looking-at "\\\\begin{")
+ (forward-sexp 2)
+ ;; Assume these are arguments
+ (while (looking-at "[ \t\n]*[{[]")
+ (forward-sexp 1))
+ ;; Go to next line if there is nothing interesting on this one
+ (skip-syntax-forward " ") ;; newlines are ">" i.e. end comment
+ (when (looking-at "%\\|$")
+ (forward-line))
+ ;; Clean up the end portion
+ (exchange-point-and-mark)
+ (backward-sexp 2)
+ (skip-syntax-backward " ")
+ (exchange-point-and-mark)))
+
+(defun er/mark-LaTeX-math ()
+ "Mark current math environment."
+ (interactive)
+ (when (texmathp)
+ (let* ((string (car texmathp-why))
+ (pos (cdr texmathp-why))
+ (reason (assoc string texmathp-tex-commands1))
+ (type (cadr reason)))
+ (cond
+ ((eq type 'env-on) ;; environments equation, align, etc.
+ (er/mark-LaTeX-inside-environment))
+ ((eq type 'arg-on) ;; \ensuremath etc.
+ (goto-char pos)
+ (set-mark (point))
+ (forward-sexp 2)
+ (exchange-point-and-mark))
+ ((eq type 'sw-toggle) ;; $ and $$
+ (goto-char pos)
+ (set-mark (point))
+ (forward-sexp 1)
+ (exchange-point-and-mark))
+ ((eq type 'sw-on) ;; \( and \[
+ (re-search-forward texmathp-onoff-regexp)
+ (set-mark pos)
+ (exchange-point-and-mark))
+ (t (error (format "Unknown reason to be in math mode: %s" type)))))))
+
+(defun er/add-latex-mode-expansions ()
+ "Adds expansions for buffers in latex-mode"
+ (set (make-local-variable 'er/try-expand-list)
+ (append
+ er/try-expand-list
+ '(LaTeX-mark-environment
+ LaTeX-mark-section
+ er/mark-LaTeX-inside-environment
+ er/mark-LaTeX-math))))
+
+(let ((latex-mode-hook LaTeX-mode-hook))
+ (er/enable-mode-expansions 'latex-mode 'er/add-latex-mode-expansions)
+ (setq LaTeX-mode-hook latex-mode-hook))
+
+(provide 'latex-mode-expansions)
+
+;; latex-mode-expansions.el ends here
--- /dev/null
+;;; nxml-mode-expansions.el --- Nxml-specific expansions for expand-region
+
+;; Copyright (C) 2012 Ivan Andrus
+
+;; Author: Ivan Andrus
+;; Based on js-mode-expansions by: Magnar Sveen <magnarsNOSPAMgmail.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:
+
+;; Feel free to contribute any other expansions for Nxml at
+;;
+;; https://github.com/magnars/expand-region.el
+
+;;; Code:
+
+(require 'expand-region-core)
+(require 'html-mode-expansions)
+(require 'nxml-mode)
+
+(defun er/mark-nxml-tag ()
+ "Marks one nxml element e.g. <p>"
+ (interactive)
+ (cond ((looking-at "<")
+ (nxml-mark-token-after))
+ ((er/looking-back-exact ">")
+ (backward-char 1)
+ (nxml-mark-token-after))
+ ((er/looking-back-max "<[^<>]*" 1000)
+ (nxml-mark-token-after))))
+
+(defun er/mark-nxml-element ()
+ "Marks one nxml element e.g. <p>...</p>"
+ (interactive)
+ (if (not (looking-at "<[^/]"))
+ (er/mark-nxml-containing-element)
+ (set-mark (point))
+ (nxml-forward-element)
+ (exchange-point-and-mark)))
+
+(defun er/mark-nxml-containing-element ()
+ "Marks one nxml element, but always e.g. <p>...</p>"
+ (interactive)
+ (nxml-up-element)
+ (set-mark (point))
+ (nxml-backward-element))
+
+(defun er/mark-nxml-inside-element ()
+ "Marks the inside Nxml statement, eg. <p>...</p>"
+ (interactive)
+ (let ((nxml-sexp-element-flag nil))
+ (nxml-up-element)
+ (nxml-forward-balanced-item -1)
+ (set-mark (point))
+ (nxml-backward-up-element)
+ (nxml-forward-balanced-item 1)))
+
+(defun er/inside-nxml-attribute-string? ()
+ "Returns the attribute from `xmltok-attributes' array that
+point is in, or otherwise nil"
+ (save-excursion
+ (forward-char 1)
+ (nxml-token-before))
+ (let ((attr (find-if (lambda (att)
+ (and (<= (xmltok-attribute-value-start att) (point))
+ (>= (xmltok-attribute-value-end att) (point))))
+ xmltok-attributes)))
+ attr))
+
+(defun er/mark-nxml-attribute-inner-string ()
+ "Marks an attribute string"
+ (interactive)
+ (let ((attr (er/inside-nxml-attribute-string?)))
+ (when attr
+ (set-mark (xmltok-attribute-value-start attr))
+ (goto-char (xmltok-attribute-value-end attr))
+ (exchange-point-and-mark))))
+
+(defun er/mark-nxml-attribute-string ()
+ "Marks an attribute string inside quotes."
+ (interactive)
+ (let ((attr (er/inside-nxml-attribute-string?)))
+ (when attr
+ (set-mark (1- (xmltok-attribute-value-start attr)))
+ (goto-char (1+ (xmltok-attribute-value-end attr)))
+ (exchange-point-and-mark))))
+
+(defun er/add-nxml-mode-expansions ()
+ "Adds Nxml-specific expansions for buffers in nxml-mode"
+ (interactive)
+ (set (make-local-variable 'er/try-expand-list)
+ (append
+ '(nxml-mark-paragraph
+ ;; nxml-mark-token-after ;; Marks the current tag, etc. It's a bit schizophrenic
+ er/mark-nxml-tag
+ er/mark-nxml-inside-element
+ er/mark-nxml-element
+ er/mark-nxml-containing-element
+ er/mark-nxml-attribute-string
+ er/mark-nxml-attribute-inner-string
+ ;; Steal from html-mode-expansions
+ 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))))))
+
+(er/enable-mode-expansions 'nxml-mode 'er/add-nxml-mode-expansions)
+
+(provide 'nxml-mode-expansions)
+
+;; nxml-mode-expansions.el ends here
--- /dev/null
+;;; octave-expansions.el --- octave-mode expansions for expand-region
+
+;; Copyright (C) 2012 Mark Hepburn
+
+;; Author: Mark Hepburn
+;; 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:
+
+;; Feel free to contribute any other expansions for Octave at
+;;
+;; https://github.com/magnars/expand-region.el
+
+;;; Code:
+
+(require 'expand-region-core)
+(declare-function octave-mark-block "octave-mod")
+
+;;; Octave-mod received a major rewrite between versions 23 and 24 of
+;;; Emacs, for example using the new smie package instead of
+;;; hand-coding a lot of motion commands. Unfortunately for our
+;;; purposes here, in the process the behaviour of `octave-mark-block'
+;;; changed slightly. So, in order to behave identically across both
+;;; versions we need to check which is which in a few places and
+;;; adjust accordingly:
+(defconst er/old-octave-mod-p (fboundp 'octave-up-block))
+
+(defalias 'er/up-block
+ (if er/old-octave-mod-p 'octave-up-block 'up-list))
+
+(defun er/octave-mark-up-block ()
+ "Mark the containing block, assuming the current block has
+already been marked."
+ (interactive)
+ (when (use-region-p)
+ (when (< (point) (mark))
+ (exchange-point-and-mark))
+ (er/up-block -1) ; -1 means backwards, ie to the front
+ (octave-mark-block)))
+
+(defun er/octave-mark-block ()
+ "Not for general use; this is a work-around for the different
+behaviour of `octave-mark-block' between emacs versions 23 and
+24."
+ (interactive)
+ (forward-word)
+ (octave-mark-block))
+
+(defun er/add-octave-expansions ()
+ "Adds octave/matlab-specific expansions for buffers in octave-mode"
+ (let ((try-expand-list-additions (if er/old-octave-mod-p
+ '(octave-mark-block
+ er/octave-mark-up-block
+ octave-mark-defun)
+ '(octave-mark-block
+ er/octave-mark-block
+ er/octave-mark-up-block
+ mark-defun))))
+ (set (make-local-variable 'er/try-expand-list)
+ (append er/try-expand-list try-expand-list-additions))))
+
+(er/enable-mode-expansions 'octave-mode 'er/add-octave-expansions)
+
+(provide 'octave-expansions)
+;;; octave-expansions.el ends here
--- /dev/null
+;;; python-el-expansions.el --- Python-specific expansions for expand-region
+
+;; Copyright (C) 2012 Ivan Andrus
+
+;; Authors: Ivan Andrus, Felix Geller, @edmccard
+;; Based on js-mode-expansions by: Magnar Sveen <magnarsNOSPAMgmail.com>
+;; Keywords: marking region python
+
+;; 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:
+
+;; For python.el included with GNU Emacs
+;; - Mark functionality taken from python.el:
+;; - `python-mark-block'
+;; - Additions implemented here:
+;; - `er/mark-python-statement'
+;; - `er/mark-inside-python-string'
+;; - `er/mark-outside-python-string'
+;; - Supports multi-line strings
+
+;; There is no need for a er/mark-python-defun since
+;; er/mark-python-block will mark it
+
+;; Feel free to contribute any other expansions for Python at
+;;
+;; https://github.com/magnars/expand-region.el
+
+;;; Code:
+
+(require 'expand-region-core)
+(require 'python)
+
+(declare-function python-beginning-of-string "python-mode")
+
+(defvar er--python-string-delimiter "'\"")
+
+(defun er/mark-python-statement ()
+ "Marks one Python statement, eg. x = 3"
+ (interactive)
+ (python-nav-end-of-statement)
+ (set-mark (point))
+ (python-nav-beginning-of-statement))
+
+(defun er/mark-outside-python-string ()
+ "Marks region outside a (possibly multi-line) Python string"
+ (interactive)
+ (python-beginning-of-string)
+ (set-mark (point))
+ (forward-sexp)
+ (exchange-point-and-mark))
+
+(defun er/mark-inside-python-string ()
+ "Marks region inside a (possibly multi-line) Python string"
+ (interactive)
+ (when (eq 'string (syntax-ppss-context (syntax-ppss)))
+ (python-beginning-of-string)
+ (let ((string-beginning (point)))
+ (forward-sexp)
+ (skip-chars-backward er--python-string-delimiter)
+ (set-mark (point))
+ (goto-char string-beginning)
+ (skip-chars-forward er--python-string-delimiter))))
+
+(defun er/add-python-mode-expansions ()
+ "Adds Python-specific expansions for buffers in python-mode"
+ (let ((try-expand-list-additions '(er/mark-python-statement
+ er/mark-inside-python-string
+ er/mark-outside-python-string
+ python-mark-block)))
+ (set (make-local-variable 'expand-region-skip-whitespace) nil)
+ (set (make-local-variable 'er/try-expand-list)
+ (remove 'er/mark-inside-quotes
+ (remove 'er/mark-outside-quotes
+ (append er/try-expand-list try-expand-list-additions))))))
+
+(er/enable-mode-expansions 'python-mode 'er/add-python-mode-expansions)
+
+(provide 'python-el-expansions)
+
+;; python-el-expansions.el ends here
--- /dev/null
+;;; python-el-fgallina-expansions.el --- fgallina/python.el-specific expansions for expand-region
+
+;; Copyright (C) 2012 Felix Geller
+
+;; Author: Felix Geller
+;; Keywords: marking region python
+
+;; 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:
+;;
+;; - Additions implemented here:
+;; - `er/mark-inside-python-string'
+;; - `er/mark-outside-python-string'
+;; - `er/mark-python-statement'
+;; - `er/mark-python-block'
+;; - `er/mark-outer-python-block'
+;; - `er/mark-python-block-and-decorator'
+;; - Supports multi-line strings
+
+;;; Code:
+
+(require 'expand-region-core)
+
+(if (not (fboundp 'python-syntax-context))
+ (defalias 'python-syntax-context 'python-info-ppss-context))
+(if (not (fboundp 'python-indent-offset))
+ (defalias 'python-indent-offset 'python-indent))
+
+(defvar er--python-string-delimiter
+ "'\""
+ "Characters that delimit a Python string.")
+
+;; copied from @fgallina's python.el as a quick fix. The variable
+;; `python-rx-constituents' is not bound when we use the python-rx
+;; macro from here, so we have to construct the regular expression
+;; manually.
+(defvar er--python-block-start-regex
+ (rx symbol-start
+ (or "def" "class" "if" "elif" "else" "try"
+ "except" "finally" "for" "while" "with")
+ symbol-end)
+ "Regular expression string to match the beginning of a Python block.")
+
+(defun er/mark-python-string (mark-inside)
+ "Mark the Python string that surrounds point.
+
+If the optional MARK-INSIDE is not nil, only mark the region
+between the string delimiters, otherwise the region includes the
+delimiters as well."
+ (let ((beginning-of-string (python-syntax-context 'string (syntax-ppss))))
+ (when beginning-of-string
+ (goto-char beginning-of-string)
+ ;; Move inside the string, so we can use ppss to find the end of
+ ;; the string.
+ (skip-chars-forward er--python-string-delimiter)
+ (while (python-syntax-context 'string (syntax-ppss))
+ (forward-char 1))
+ (when mark-inside (skip-chars-backward er--python-string-delimiter))
+ (set-mark (point))
+ (goto-char beginning-of-string)
+ (when mark-inside (skip-chars-forward er--python-string-delimiter)))))
+
+(defun er/mark-inside-python-string ()
+ "Mark the inside of the Python string that surrounds point.
+
+Command that wraps `er/mark-python-string'."
+ (interactive)
+ (er/mark-python-string t))
+
+(defun er/mark-outside-python-string ()
+ "Mark the outside of the Python string that surrounds point.
+
+Command that wraps `er/mark-python-string'."
+ (interactive)
+ (er/mark-python-string nil))
+
+(defun er/mark-python-statement ()
+ "Mark the Python statement that surrounds point."
+ (interactive)
+ (python-nav-end-of-statement)
+ (set-mark (point))
+ (python-nav-beginning-of-statement))
+
+(defun er/mark-python-block (&optional next-indent-level)
+ "Mark the Python block that surrounds point.
+
+If the optional NEXT-INDENT-LEVEL is given, select the
+surrounding block that is defined at an indentation that is less
+than NEXT-INDENT-LEVEL."
+ (interactive)
+ (back-to-indentation)
+ (let ((next-indent-level
+ (or
+ ;; Use the given level
+ next-indent-level
+ ;; Check whether point is at the start of a Python block.
+ (if (looking-at er--python-block-start-regex)
+ ;; Block start means that the next level is deeper.
+ (+ (current-indentation) python-indent-offset)
+ ;; Assuming we're inside the block that we want to mark
+ (current-indentation)))))
+ ;; Move point to next Python block start at the correct indent-level
+ (while (>= (current-indentation) next-indent-level)
+ (re-search-backward er--python-block-start-regex))
+ ;; Mark the beginning of the block
+ (set-mark (point))
+ ;; Save indentation and look for the end of this block
+ (let ((block-indentation (current-indentation)))
+ (forward-line 1)
+ (while (and
+ ;; No need to go beyond the end of the buffer. Can't use
+ ;; eobp as the loop places the point at the beginning of
+ ;; line, but eob might be at the end of the line.
+ (not (= (point-max) (point-at-eol)))
+ ;; Proceed if: indentation is too deep
+ (or (> (current-indentation) block-indentation)
+ ;; Looking at an empty line
+ (looking-at (rx line-start (* whitespace) line-end))
+ ;; We're not looking at the start of a Python block
+ ;; and the indent is deeper than the block's indent
+ (and (not (looking-at er--python-block-start-regex))
+ (> (current-indentation) block-indentation))))
+ (forward-line 1)
+ (back-to-indentation))
+ ;; Find the end of the block by skipping comments backwards
+ (python-util-forward-comment -1)
+ (exchange-point-and-mark))))
+
+(defun er/mark-outer-python-block ()
+ "Mark the Python block that surrounds the Python block around point.
+
+Command that wraps `er/mark-python-block'."
+ (interactive)
+ (er/mark-python-block (current-indentation)))
+
+(defun er/mark-python-block-and-decorator ()
+ (interactive)
+ (back-to-indentation)
+ (if (or (er--python-looking-at-decorator) (er--python-looking-at-decorator -1))
+ (progn
+ (while (er--python-looking-at-decorator -1)
+ (forward-line -1)
+ (back-to-indentation)
+ )
+ (set-mark (point))
+ (while (er--python-looking-at-decorator)
+ (forward-line)
+ )
+ (python-nav-end-of-block)
+ (exchange-point-and-mark))))
+
+(defun er--python-looking-at-decorator (&optional line-offset)
+ (save-excursion
+ (if line-offset
+ (forward-line line-offset)
+ )
+ (back-to-indentation)
+ (looking-at "@")
+ ))
+
+(defun er/add-python-mode-expansions ()
+ "Adds python-mode-specific expansions for buffers in python-mode"
+ (let ((try-expand-list-additions '(
+ er/mark-inside-python-string
+ er/mark-outside-python-string
+ er/mark-python-statement
+ er/mark-python-block
+ er/mark-python-block-and-decorator
+ er/mark-outer-python-block
+ )))
+ (set (make-local-variable 'expand-region-skip-whitespace) nil)
+ (set (make-local-variable 'er/try-expand-list)
+ (remove 'er/mark-inside-quotes
+ (remove 'er/mark-outside-quotes
+ (append er/try-expand-list try-expand-list-additions))))))
+
+(er/enable-mode-expansions 'python-mode 'er/add-python-mode-expansions)
+
+(provide 'python-el-fgallina-expansions)
+
+;; python-el-fgallina-expansions.el ends here
--- /dev/null
+;;; python-mode-expansions.el --- python-mode-specific expansions for expand-region
+
+;; Copyright (C) 2012 Felix Geller
+
+;; Author: Felix Geller
+;; Based on python-mode-expansions by: Ivan Andrus
+;; Keywords: marking region python
+
+;; 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:
+
+;; Commentary:
+;; cf. https://github.com/magnars/expand-region.el/pull/18
+
+;; For python-mode: https://launchpad.net/python-mode
+;; - Mark functionality taken from python-mode:
+;; - `py-mark-expression'
+;; - `py-mark-statement'
+;; - `py-mark-block'
+;; - `py-mark-class'
+;; - Additions implemented here:
+;; - `er/mark-inside-python-string'
+;; - `er/mark-outside-python-string'
+;; - `er/mark-outer-python-block'
+;; - Supports multi-line strings
+;; - Supports incremental expansion of nested blocks
+
+;;; Code:
+
+(require 'expand-region-core)
+
+(defvar er--python-string-delimiter "'\"")
+
+(defalias 'py-goto-beyond-clause 'py-end-of-clause-bol)
+
+(declare-function py-in-string-p "python-mode")
+(declare-function py-beginning-of-block "python-mode")
+(declare-function py-end-of-block "python-mode")
+(declare-function py-mark-block-or-clause "python-mode")
+(declare-function py-end-of-clause-bol "python-mode")
+(defvar py-indent-offset)
+
+(defun er/mark-outside-python-string ()
+ "Marks region outside a (possibly multi-line) Python string"
+ (interactive)
+ (let ((string-beginning (py-in-string-p)))
+ (when string-beginning
+ (goto-char string-beginning)
+ (set-mark (point))
+ (forward-sexp)
+ (exchange-point-and-mark))))
+
+(defun er/mark-inside-python-string ()
+ "Marks region inside a (possibly multi-line) Python string"
+ (interactive)
+ (let ((string-beginning (py-in-string-p)))
+ (when string-beginning
+ (goto-char string-beginning)
+ (forward-sexp)
+ (skip-chars-backward er--python-string-delimiter)
+ (set-mark (point))
+ (goto-char string-beginning)
+ (skip-chars-forward er--python-string-delimiter))))
+
+(defun er--move-to-beginning-of-outer-python-block (start-column)
+ "Assumes that point is in a python block that is surrounded by
+another that is not the entire module. Uses `py-indent-offset' to
+find the beginning of the surrounding block because
+`py-beginning-of-block-position' just looks for the previous
+block-starting key word syntactically."
+ (while (> (current-column) (- start-column py-indent-offset))
+ (forward-line -1)
+ (py-beginning-of-block)))
+
+(defun er/mark-outer-python-block ()
+ "Attempts to mark a surrounding block by moving to the previous
+line and selecting the surrounding block."
+ (interactive)
+ (let ((start-column (current-column)))
+ (when (> start-column 0) ; outer block is the whole buffer
+ (er--move-to-beginning-of-outer-python-block start-column)
+ (let ((block-beginning (point)))
+ (py-end-of-block)
+ (set-mark (point))
+ (goto-char block-beginning)))))
+
+(defun er/mark-x-python-compound-statement ()
+ "Mark the current compound statement (if, while, for, try) and all clauses."
+ (interactive)
+ (let ((secondary-re
+ (save-excursion
+ (py-mark-block-or-clause)
+ (cond ((looking-at "if\\|for\\|while\\|else\\|elif") "else\\|elif")
+ ((looking-at "try\\|except\\|finally") "except\\|finally"))))
+ start-col)
+ (when secondary-re
+ (py-mark-block-or-clause)
+ (setq start-col (current-column))
+ (while (looking-at secondary-re)
+ (forward-line -1) (back-to-indentation)
+ (while (> (current-column) start-col)
+ (forward-line -1) (back-to-indentation)))
+ (set-mark (point))
+ (py-end-of-clause-bol) (forward-line) (back-to-indentation)
+ (while (and (looking-at secondary-re)
+ (>= (current-column) start-col))
+ (py-end-of-clause-bol) (forward-line) (back-to-indentation))
+ (forward-line -1) (end-of-line)
+ (exchange-point-and-mark))))
+
+(defun er/add-python-mode-expansions ()
+ "Adds python-mode-specific expansions for buffers in python-mode"
+ (let ((try-expand-list-additions '(
+ er/mark-inside-python-string
+ er/mark-outside-python-string
+ py-mark-expression
+ py-mark-statement
+ py-mark-block
+ py-mark-def
+ py-mark-clause
+ er/mark-x-python-compound-statement
+ er/mark-outer-python-block
+ py-mark-class
+ )))
+ (set (make-local-variable 'expand-region-skip-whitespace) nil)
+ (set (make-local-variable 'er/try-expand-list)
+ (remove 'er/mark-inside-quotes
+ (remove 'er/mark-outside-quotes
+ (append er/try-expand-list try-expand-list-additions))))))
+
+(er/enable-mode-expansions 'python-mode 'er/add-python-mode-expansions)
+
+(provide 'python-mode-expansions)
+
+;; python-mode-expansions.el ends here
--- /dev/null
+;;; ruby-mode-expansions.el --- ruby-specific expansions for expand-region
+
+;; Copyright (C) 2011 Magnar Sveen
+
+;; Author: Matt Briggs
+;; Based on js-mode-expansions by: Magnar Sveen <magnarsNOSPAMgmail.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:
+
+
+;; LeWang:
+;;
+;; I think `er/ruby-backward-up' and `er/ruby-forward-up' are nifty
+;; functions in their own right.
+;;
+;; I would bind them to C-M-u and C-M-d respectively.
+
+;; Expansions:
+;;
+;;
+;; er/mark-ruby-block-up
+;;
+
+;;; Code:
+(require 'expand-region-core)
+(require 'ruby-mode)
+
+(defvar er/ruby-block-end-re
+ (concat ruby-block-end-re "\\|}")
+ "like ruby-mode's but also for '}'")
+
+(defun er/ruby-skip-past-block-end ()
+ "If line is blockend, move point to next line."
+ (when (looking-at er/ruby-block-end-re)
+ (forward-line 1)))
+
+(defun er/ruby-end-of-block (&optional arg)
+ "By default `ruby-end-of-block' goes to BOL of line containing end-re.
+
+This moves point to the next line to include the end of the block"
+ (interactive "p")
+ ;; Workaround for `ruby-end-of-block' in Emacs 23.
+ (when (re-search-forward (concat "\\<\\(" ruby-block-beg-re "\\)\\>")
+ (point-at-eol) t)
+ (goto-char (match-beginning 0)))
+ (ruby-end-of-block (or arg 1))
+ (er/ruby-skip-past-block-end))
+
+(defun er/point-at-indentation ()
+ "Return the point where current line's indentation ends."
+ (save-excursion
+ (back-to-indentation)
+ (point)))
+
+(defun er/ruby-backward-up ()
+ "a la `paredit-backward-up'"
+ (interactive)
+ ;; if our current line ends a block, we back a line, otherwise we
+ (when (save-excursion
+ (back-to-indentation)
+ (looking-at-p ruby-block-end-re))
+ (forward-line -1))
+ (let ((orig-point (point))
+ progress-beg
+ progress-end)
+
+ ;; cover the case when point is in the line of beginning of block
+ (unless (progn (ruby-end-of-block)
+ (ruby-beginning-of-block)
+ ;; "Block beginning" is often not at indentation in Emacs 24.
+ (< (er/point-at-indentation) orig-point))
+ (loop do
+ (ruby-beginning-of-block)
+ (setq progress-beg (point))
+ (when (= (point) (point-min))
+ (return))
+ (ruby-end-of-block)
+ (setq progress-end (if (looking-at-p er/ruby-block-end-re)
+ (point-at-bol 0)
+ (point-at-bol 1)))
+ (goto-char progress-beg)
+ (when (> progress-end orig-point)
+ (return))))))
+
+;;; This command isn't used here explicitly, but it's symmetrical with
+;;; `er/ruby-backward-up', and nifty for interactive use.
+(defun er/ruby-forward-up ()
+ "a la `paredit-forward-up'"
+ (interactive)
+ (er/ruby-backward-up)
+ (er/ruby-end-of-block))
+
+(defun er/get-ruby-block (&optional pos)
+ "return (beg . end) of current block"
+ (setq pos (or pos (point)))
+ (save-excursion
+ (goto-char pos)
+ (let (beg end)
+ (cons (progn
+ (er/ruby-backward-up)
+ (er/point-at-indentation))
+ (progn
+ (er/ruby-end-of-block)
+ (point))))))
+
+(defun er/mark-ruby-block-up-1 ()
+ (er/ruby-backward-up)
+ (set-mark (er/point-at-indentation))
+ (er/ruby-end-of-block)
+ (exchange-point-and-mark))
+
+(defun er/mark-ruby-block-up (&optional no-recurse)
+ "mark the next level up."
+ (interactive)
+ (if (use-region-p)
+ (let* ((orig-end (region-end))
+ (orig-beg (region-beginning))
+ (orig-len (- orig-end orig-beg))
+ (prev-block-point
+ (or (save-excursion
+ (goto-char orig-end)
+ (forward-line 0)
+ (back-to-indentation)
+ (cond ((looking-at-p er/ruby-block-end-re)
+ (point-at-bol 0))
+ ((re-search-forward
+ (concat "\\<\\(" ruby-block-beg-re "\\)\\>")
+ (point-at-eol)
+ t)
+ (point-at-bol 2))) )
+ (point)))
+ (prev-block-info (er/get-ruby-block prev-block-point))
+ (prev-block-beg (car prev-block-info))
+ (prev-block-end (cdr prev-block-info))
+ (prev-block-len (- prev-block-end prev-block-beg)))
+ (if (and (>= orig-beg prev-block-beg)
+ (<= orig-end prev-block-end)
+ (< orig-len prev-block-len))
+ ;; expand to previous block if it contains and grows current
+ ;; region
+ (progn
+ (deactivate-mark)
+ (goto-char prev-block-point)
+ (or no-recurse
+ (er/mark-ruby-block-up 'no-recurse)))
+ (er/mark-ruby-block-up-1)))
+ (er/mark-ruby-block-up-1)))
+
+(defun er/mark-ruby-instance-variable ()
+ "Marks instance variables in ruby.
+Assumes that point is at the @ - if it is inside the word, that will
+be marked first anyway."
+ (when (looking-at "@")
+ (forward-char 1))
+ (when (er/looking-back-exact "@")
+ (er/mark-symbol)
+ (forward-char -1)))
+
+(defun er/mark-ruby-heredoc ()
+ "Marks a heredoc, since `er/mark-inside-quotes' assumes single quote chars."
+ (let ((ppss (syntax-ppss)))
+ (when (elt ppss 3)
+ (let ((s-start (elt ppss 8)))
+ (goto-char s-start)
+ (when (save-excursion
+ (beginning-of-line)
+ (re-search-forward "<<\\(-?\\)['\"]?\\([a-zA-Z0-9_]+\\)" s-start nil))
+ (let ((allow-indent (string= "-" (match-string 1)))
+ (terminator (match-string 2))
+ (heredoc-start (save-excursion
+ (forward-line)
+ (point))))
+ (forward-sexp 1)
+ (forward-line -1)
+ (when (looking-at (concat "^" (if allow-indent "[ \t]*" "") terminator "$"))
+ (set-mark heredoc-start)
+ (exchange-point-and-mark))))))))
+
+(defun er/add-ruby-mode-expansions ()
+ "Adds Ruby-specific expansions for buffers in ruby-mode"
+ (set (make-local-variable 'er/try-expand-list)
+ (remove 'er/mark-defun
+ (append
+ (default-value 'er/try-expand-list)
+ '(er/mark-ruby-instance-variable
+ er/mark-ruby-block-up
+ er/mark-ruby-heredoc)))))
+
+(er/enable-mode-expansions 'ruby-mode 'er/add-ruby-mode-expansions)
+(provide 'ruby-mode-expansions)
--- /dev/null
+;;; sml-mode-expansions.el --- Expansions for expand-region to be used in sml-mode
+
+;; Copyright (C) 2012 Alexis Gallagher
+
+;; Author: Alexis Gallagher
+;; Based on js-mode-expansions by: Magnar Sveen <magnarsNOSPAMgmail.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:
+
+;; Provides extra expansions for sml-mode:
+;; - various expression (case, if, let)
+;; - fun bindings
+;;
+;; Tested with sml-mode version 6.3
+;;
+;; Feel free to contribute any other expansions for SML at
+;;
+;; https://github.com/magnars/expand-region.el
+
+;;; Code:
+
+(require 'expand-region-core)
+(declare-function sml-find-matching-starter "sml-mode")
+
+;; TODO: comma-delimited elements within a list,tuple,record
+;; TODO: match expression, patterns
+;; TODO: individual field, record type
+;; TODO: head-or-tail, then cons expression
+
+(defun er/sml-mark-keyword-prefixed-expression ()
+ "Mark the surrounding expression."
+ (interactive)
+ (progn
+ (sml-find-matching-starter '("case" "let" "if" "raise"))
+ (mark-sexp)))
+
+
+(defun er/add-sml-mode-expansions ()
+ "Adds expansions for buffers in `sml-mode'."
+ (set (make-local-variable 'er/try-expand-list)
+ (append er/try-expand-list
+ '(sml-mark-function
+ er/sml-mark-keyword-prefixed-expression
+ mark-sexp))))
+
+(er/enable-mode-expansions 'sml-mode 'er/add-sml-mode-expansions)
+
+(provide 'sml-mode-expansions)
+
+;; sml-mode-expansions.el ends here
--- /dev/null
+;;; subword-mode-expansions.el --- Expansions for subword-mode to be used for CamelCase
+
+;; Copyright (C) 2014 Lefteris Karapetsas
+
+;; Author: Lefteris Karapetsas
+;; 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:
+
+;; Provides extra expansions for subword mode so that when
+;; subword-mode is non-nil different words can be selected in CamelCase.
+;; Feel free to contribute any other expansions:
+;;
+;; https://github.com/magnars/expand-region.el
+
+;;; Code:
+
+(require 'expand-region-core)
+
+(defun er/mark-subword ()
+ "Mark a subword, a part of a CamelCase identifier."
+ (interactive)
+ (subword-right 1)
+ (set-mark (point))
+ (subword-left 1))
+
+(defun er/add-subword-mode-expansions ()
+ "Add expansions for buffers in `subword-mode'."
+ (set (make-local-variable 'er/try-expand-list)
+ (append er/try-expand-list
+ '(er/mark-subword))))
+
+(er/enable-mode-expansions 'subword-mode 'er/add-subword-mode-expansions)
+
+(provide 'subword-mode-expansions)
+;;; subword-mode-expansions.el ends here
--- /dev/null
+;;; text-mode-expansions.el --- Expansions for expand-region to be used in text
+
+;; Copyright (C) 2012 Ivan Andrus
+
+;; Author: Ivan Andrus
+;; Based on js-mode-expansions by: Magnar Sveen <magnarsNOSPAMgmail.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:
+
+;; Feel free to contribute any other expansions for normal text at
+;;
+;; https://github.com/magnars/expand-region.el
+
+;;; Code:
+
+(require 'expand-region-core)
+
+(defun er/mark-text-sentence ()
+ "Marks one sentence."
+ (interactive)
+ ;; The obvious
+ ;; (backward-sentence 1) (mark-end-of-sentence 1)
+ ;; doesn't work here because it's repeated and the selection keeps
+ ;; growing by sentences, which isn't what's wanted.
+ (forward-sentence 1)
+ (set-mark (point))
+ (backward-sentence 1))
+
+(defun er/mark-text-paragraph ()
+ "Marks one paragraph."
+ (interactive)
+ (mark-paragraph)
+ (skip-chars-forward er--space-str))
+
+(defun er/add-text-mode-expansions ()
+ "Adds expansions for buffers in `text-mode' except for `html-mode'.
+Unfortunately `html-mode' inherits from `text-mode' and
+text-mode-expansions don't work well in `html-mode'."
+ (unless (member major-mode expand-region-exclude-text-mode-expansions)
+ (set (make-local-variable 'er/try-expand-list)
+ (append
+ er/try-expand-list
+ '(er/mark-text-sentence
+ er/mark-text-paragraph
+ mark-page)))))
+
+(er/enable-mode-expansions 'text-mode 'er/add-text-mode-expansions)
+
+(provide 'text-mode-expansions)
+
+;; text-mode-expansions.el ends here
--- /dev/null
+;;; the-org-mode-expansions.el --- Expansions for expand-region to be used in org-mode
+
+;; Copyright (C) 2012 Magnar Sveen
+
+;; Author: Magnar Sveen
+;; Based on text-mode-expansions by: Ivan Andrus
+;; 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 file needs to be weirdly name (prefixed with the-) to avoid
+;; conflict with org-reload, which bases its functionality on the names
+;; of files, for some reason.
+;;
+;; Feel free to contribute any other expansions for org-mode at
+;;
+;; https://github.com/magnars/expand-region.el
+
+;;; Code:
+
+(require 'expand-region-core)
+
+(declare-function org-up-element "org")
+(declare-function org-mark-subtree "org")
+
+(defun er/mark-sentence ()
+ "Marks one sentence."
+ (interactive)
+ (forward-char 1)
+ (backward-sentence 1)
+ (set-mark (point))
+ (forward-sentence 1)
+ (exchange-point-and-mark))
+
+(defun er/mark-paragraph ()
+ "Marks one paragraph."
+ (interactive)
+ (mark-paragraph)
+ (exchange-point-and-mark)
+ (skip-chars-backward er--space-str)
+ (exchange-point-and-mark)
+ (skip-chars-forward er--space-str))
+
+(defun er/mark-org-code-block ()
+ "Marks an org-code-block."
+ (interactive)
+ (let ((case-fold-search t)
+ (re "#\\+begin_\\(\\sw+\\)"))
+ (unless (looking-at re)
+ (search-backward-regexp re))
+ (set-mark (point))
+ (search-forward (concat "#+end_" (match-string 1)))
+ (exchange-point-and-mark)))
+
+(defun er/mark-org-parent ()
+ "Marks a heading 1 level up from current subheading"
+ (interactive)
+ (org-up-element)
+ (org-mark-subtree))
+
+(defun er/add-org-mode-expansions ()
+ "Adds org-specific expansions for buffers in org-mode"
+ (set (make-local-variable 'er/try-expand-list) (append
+ er/try-expand-list
+ '(org-mark-subtree
+ er/mark-org-code-block
+ er/mark-sentence
+ er/mark-org-parent
+ er/mark-paragraph))))
+
+(er/enable-mode-expansions 'org-mode 'er/add-org-mode-expansions)
+
+(provide 'the-org-mode-expansions)
--- /dev/null
+;;; web-mode-expansions.el --- Thin layer for adapting fxbois's web-mode-mark-and-expand function
+;;; to expand-region
+
+;; Copyright (C) 2012 Rotem Yaari
+
+;; Authors: Rotem Yaari
+;; Based on, and makes use of web-mode.el by fxbois
+
+;; 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/>.
+
+;;; Code:
+
+(defun er/add-web-mode-expansions ()
+ (set (make-local-variable 'er/try-expand-list)
+ (append er/try-expand-list
+ '(web-mode-mark-and-expand))))
+
+(add-hook 'web-mode-hook 'er/add-web-mode-expansions)
+
+(provide 'web-mode-expansions)
--- /dev/null
+Expand region increases the selected region by semantic units. Just keep
+pressing the key until it selects what you want.
+
+An example:
+
+ (setq alphabet-start "abc def")
+
+With the cursor at the `c`, it starts by marking the entire word `abc`, then
+expand to the contents of the quotes `abc def`, then to the entire quote
+`"abc def"`, then to the contents of the sexp `setq alphabet-start "abc def"`
+and finally to the entire sexp.
+
+You can set it up like this:
+
+ (require 'expand-region)
+ (global-set-key (kbd "C-=") 'er/expand-region)
+
+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
+
+Expand region works fairly well with most languages, due to the general
+nature of the basic expansions:
+
+ er/mark-word
+ er/mark-symbol
+ er/mark-method-call
+ er/mark-inside-quotes
+ er/mark-outside-quotes
+ er/mark-inside-pairs
+ er/mark-outside-pairs
+
+However, most languages also will benefit from some specially crafted
+expansions. For instance, expand-region comes with these extra expansions for
+html-mode:
+
+ er/mark-html-attribute
+ er/mark-inner-tag
+ er/mark-outer-tag
+
+You can add your own expansions to the languages of your choice simply by
+creating a function that looks around point to see if it's inside or looking
+at the construct you want to mark, and if so - mark it.
+
+There's plenty of examples to look at in these files.
+
+After you make your function, add it to a buffer-local version of
+the `er/try-expand-list`.
+
+**Example:**
+
+Let's say you want expand-region to also mark paragraphs and pages in
+text-mode. Incidentally Emacs already comes with `mark-paragraph` and
+`mark-page`. To add it to the try-list, do this:
+
+ (defun er/add-text-mode-expansions ()
+ (make-variable-buffer-local 'er/try-expand-list)
+ (setq er/try-expand-list (append
+ er/try-expand-list
+ '(mark-paragraph
+ mark-page))))
+
+ (er/enable-mode-expansions 'text-mode 'er/add-text-mode-expansions)
+
+Add that to its own file, and require it at the bottom of this one,
+where it says "Mode-specific expansions"
+
+**Warning:** Badly written expansions might slow down expand-region
+dramatically. Remember to exit quickly before you start traversing
+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 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.
+* [fgeller](https://github.com/fgeller) and [edmccard](https://github.com/edmccard) contributed better support for python and its multiple modes.
+* [François Févotte](https://github.com/ffevotte) contributed expansions for C and C++.
+* [Roland Walker](https://github.com/rolandwalker) added option to copy the contents of the most recent action to a register, and some fixes.
+* [Damien Cassou](https://github.com/DamienCassou) added option to continue expanding/contracting with fast keys after initial expand.
+
+Thanks!