settings

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

commit ac5cbfaae7c65f560c70911f76df4cab6379c500
Author: Paul Longtine <paullongtine@gmail.com>
Date:   Thu Jun  5 17:27:28 2014

added all the things

Diffstat:
 emacs/.emacs                                                                        |   32 ++-
 emacs/.emacs.d/.mc-lists.el                                                         |   13 +-
 emacs/.emacs.d/auto-save-list/.saves-10991-warning.home~                            |    6 +-
 emacs/.emacs.d/auto-save-list/.saves-13254-warning.home~                            |    6 +-
 emacs/.emacs.d/auto-save-list/.saves-14224-warning~                                 |    4 +-
 emacs/.emacs.d/auto-save-list/.saves-14744-warning~                                 |    0
 emacs/.emacs.d/auto-save-list/.saves-16833-warning~                                 |    2 +-
 emacs/.emacs.d/auto-save-list/.saves-18580-warning~                                 |    2 +-
 emacs/.emacs.d/auto-save-list/.saves-2250-home~                                     |    0
 emacs/.emacs.d/auto-save-list/.saves-2269-warning~                                  |    8 +-
 emacs/.emacs.d/auto-save-list/.saves-22796-warning~                                 |    2 +-
 emacs/.emacs.d/auto-save-list/.saves-2315-home~                                     |    0
 emacs/.emacs.d/auto-save-list/.saves-2357-home~                                     |    0
 emacs/.emacs.d/auto-save-list/.saves-2369-home~                                     |    0
 emacs/.emacs.d/auto-save-list/.saves-2381-warning~                                  |   16 +-
 emacs/.emacs.d/auto-save-list/.saves-23863-warning~                                 |    2 +-
 emacs/.emacs.d/auto-save-list/.saves-2396-home~                                     |    0
 emacs/.emacs.d/auto-save-list/.saves-2475-home~                                     |    0
 emacs/.emacs.d/auto-save-list/.saves-24850-warning~                                 |    4 +-
 emacs/.emacs.d/auto-save-list/.saves-25053-warning.home~                            |    8 +-
 emacs/.emacs.d/auto-save-list/.saves-2831-home~                                     |    0
 emacs/.emacs.d/auto-save-list/.saves-28895-warning~                                 |    0
 emacs/.emacs.d/auto-save-list/.saves-3084-warning~                                  |   10 +-
 emacs/.emacs.d/auto-save-list/.saves-3197-home~                                     |    0
 emacs/.emacs.d/auto-save-list/.saves-3202-home~                                     |    0
 emacs/.emacs.d/auto-save-list/.saves-3850-home~                                     |    0
 emacs/.emacs.d/auto-save-list/.saves-3862-warning.home~                             |    0
 emacs/.emacs.d/auto-save-list/.saves-4030-warning.home~                             |    2 +-
 emacs/.emacs.d/auto-save-list/.saves-4213-warning~                                  |    0
 emacs/.emacs.d/auto-save-list/.saves-4325-warning~                                  |    0
 emacs/.emacs.d/auto-save-list/.saves-4396-warning~                                  |    0
 emacs/.emacs.d/auto-save-list/.saves-4657-warning.home~                             |    0
 emacs/.emacs.d/auto-save-list/.saves-5180-home~                                     |    0
 emacs/.emacs.d/auto-save-list/.saves-6206-warning~                                  |    6 +-
 emacs/.emacs.d/auto-save-list/.saves-7875-home~                                     |    0
 emacs/.emacs.d/auto-save-list/.saves-7906-warning~                                  |    2 +-
 emacs/.emacs.d/auto-save-list/.saves-8433-warning~                                  |    4 +-
 emacs/.emacs.d/auto-save-list/.saves-8788-warning~                                  |    2 +-
 emacs/.emacs.d/auto-save-list/.saves-9494-warning~                                  |    0
 emacs/.emacs.d/auto-save-list/.saves-9918-warning.home~                             |    0
 emacs/.emacs.d/auto-save-list/.saves-9969-warning~                                  |    6 +-
 emacs/.emacs.d/autopair.el                                                          | 1126 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 emacs/.emacs.d/master.zip                                                           | Bin 0 -> 37705 bytes
 emacs/.emacs.d/multiple-cursors/.gitignore                                          |    2 +-
 emacs/.emacs.d/multiple-cursors/.travis.yml                                         |   21 +-
 emacs/.emacs.d/multiple-cursors/Cask                                                |    9 +-
 emacs/.emacs.d/multiple-cursors/README.md                                           |  199 ++++++++++++++-
 emacs/.emacs.d/multiple-cursors/features/edit-lines.feature                         |  140 ++++++++++-
 emacs/.emacs.d/multiple-cursors/features/insert-numbers.feature                     |   13 +-
 emacs/.emacs.d/multiple-cursors/features/mark-all-dwim-html.feature                 |   94 +++++++-
 emacs/.emacs.d/multiple-cursors/features/mark-all-dwim.feature                      |   90 ++++++-
 emacs/.emacs.d/multiple-cursors/features/mark-more.feature                          |  144 ++++++++++-
 emacs/.emacs.d/multiple-cursors/features/mark-pop.feature                           |   88 ++++++-
 emacs/.emacs.d/multiple-cursors/features/mark-things.feature                        |  137 ++++++++++-
 emacs/.emacs.d/multiple-cursors/features/multiple-cursors-core.feature              |  188 +++++++++++++-
 emacs/.emacs.d/multiple-cursors/features/rectangular-region.feature                 |   73 +++++-
 emacs/.emacs.d/multiple-cursors/features/sort-and-reverse.feature                   |   19 +-
 emacs/.emacs.d/multiple-cursors/features/step-definitions/multiple-cursors-steps.el |  139 ++++++++++-
 emacs/.emacs.d/multiple-cursors/features/support/env.el                             |   45 +++-
 emacs/.emacs.d/multiple-cursors/mc-cycle-cursors.el                                 |  122 +++++++++-
 emacs/.emacs.d/multiple-cursors/mc-edit-lines.el                                    |  110 ++++++++-
 emacs/.emacs.d/multiple-cursors/mc-mark-more.el                                     |  561 ++++++++++++++++++++++++++++++++++++++++-
 emacs/.emacs.d/multiple-cursors/mc-mark-pop.el                                      |   22 ++-
 emacs/.emacs.d/multiple-cursors/mc-separate-operations.el                           |   90 ++++++-
 emacs/.emacs.d/multiple-cursors/multiple-cursors-core.el                            |  729 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 emacs/.emacs.d/multiple-cursors/multiple-cursors-pkg.el                             |    2 +-
 emacs/.emacs.d/multiple-cursors/multiple-cursors.el                                 |  191 ++++++++++++++-
 emacs/.emacs.d/multiple-cursors/rectangular-region-mode.el                          |  124 +++++++++-
 emacs/.emacs.d/multiple-cursors/run-tests.sh                                        |    2 +-
 emacs/.emacs.d/multiple-cursors/run-travis-ci.sh                                    |   13 +-
 emacs/.emacs.d/multiple-cursors/watch-tests.watchr                                  |   45 +++-
 emacs/.emacs.d/php-mode.el                                                          | 1103 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 i3/.i3status.conf                                                                   |   70 +++++-
 i3/config                                                                           |  190 +++++++++++++-
 74 files changed, 6038 insertions(+), 0 deletions(-)

diff --git a/emacs/.emacs b/emacs/.emacs @@ -0,0 +1,32 @@ +; Young .emacs for the powerful + +(custom-set-variables + '(make-backup-files nil) + '(scroll-bar-mode nil) + '(tool-bar-mode nil) + '(menu-bar-mode nil) + '(tooltip-mode nil)) + +(add-to-list 'load-path "~/.emacs.d/") + +;; Multiple Cursor +(add-to-list 'load-path "~/.emacs.d/multiple-cursors") +(require 'multiple-cursors) +(global-set-key (kbd "C-c d") 'mc/edit-lines) +(global-set-key (kbd "C-c x") 'mc/mark-all-like-this) +(global-set-key (kbd "C-c n") 'mc/mark-next-like-this) +(global-set-key (kbd "C-c p") 'mc/mark-previous-like-this) + +(require 'autopair) +(autopair-global-mode) + +;; keybind yo + +(global-set-key (kbd "C-c {") 'enlarge-window-horizontally) +(global-set-key (kbd "C-c }") 'shrink-window-horizontally) + +;; make whitespace-mode use just basic coloring + +(setq whitespace-style (quote (spaces tabs space-mark tab-mark))) + +(global-whitespace-mode 1) diff --git a/emacs/.emacs.d/.mc-lists.el b/emacs/.emacs.d/.mc-lists.el @@ -0,0 +1,13 @@ +;; This file is automatically generated by the multiple-cursors extension. +;; It keeps track of your preferences for running commands with multiple cursors. + +(setq mc/cmds-to-run-for-all + '( + kill-region + undefined + )) + +(setq mc/cmds-to-run-once + '( + write-file + )) diff --git a/emacs/.emacs.d/auto-save-list/.saves-10991-warning.home~ b/emacs/.emacs.d/auto-save-list/.saves-10991-warning.home~ @@ -0,0 +1,6 @@ +/home/paul/.i3status.conf +/home/paul/#.i3status.conf# +/home/paul/.i3/config +/home/paul/.i3/#config# +/home/paul/.emacs +/home/paul/#.emacs# diff --git a/emacs/.emacs.d/auto-save-list/.saves-13254-warning.home~ b/emacs/.emacs.d/auto-save-list/.saves-13254-warning.home~ @@ -0,0 +1,6 @@ +/home/paul/Dropbox/stuffs/web/eport2/style/style.css +/home/paul/Dropbox/stuffs/web/eport2/style/#style.css# +/home/paul/Dropbox/stuffs/web/eport2/index.html +/home/paul/Dropbox/stuffs/web/eport2/#index.html# +/home/paul/.i3status.conf +/home/paul/#.i3status.conf# diff --git a/emacs/.emacs.d/auto-save-list/.saves-14224-warning~ b/emacs/.emacs.d/auto-save-list/.saves-14224-warning~ @@ -0,0 +1,4 @@ +/usr/share/themes/Ambiance/gtk-3.0/gtk.css +/usr/share/themes/Ambiance/gtk-3.0/#gtk.css# +/home/paul/.i3/config +/home/paul/.i3/#config# diff --git a/emacs/.emacs.d/auto-save-list/.saves-14744-warning~ b/emacs/.emacs.d/auto-save-list/.saves-14744-warning~ diff --git a/emacs/.emacs.d/auto-save-list/.saves-16833-warning~ b/emacs/.emacs.d/auto-save-list/.saves-16833-warning~ @@ -0,0 +1,2 @@ +/home/paul/.i3/config +/home/paul/.i3/#config# diff --git a/emacs/.emacs.d/auto-save-list/.saves-18580-warning~ b/emacs/.emacs.d/auto-save-list/.saves-18580-warning~ @@ -0,0 +1,2 @@ +/home/paul/.i3/config +/home/paul/.i3/#config# diff --git a/emacs/.emacs.d/auto-save-list/.saves-2250-home~ b/emacs/.emacs.d/auto-save-list/.saves-2250-home~ diff --git a/emacs/.emacs.d/auto-save-list/.saves-2269-warning~ b/emacs/.emacs.d/auto-save-list/.saves-2269-warning~ @@ -0,0 +1,8 @@ +/home/paul/.config/user-dirs.dirs +/home/paul/.config/#user-dirs.dirs# +/home/paul/.dotfiles/source/command_prompt.sh +/home/paul/.dotfiles/source/#command_prompt.sh# +/home/paul/Desktop/pnbp/mod/blog.py +/home/paul/Desktop/pnbp/mod/#blog.py# +/home/paul/Desktop/pnbp/compile.py +/home/paul/Desktop/pnbp/#compile.py# diff --git a/emacs/.emacs.d/auto-save-list/.saves-22796-warning~ b/emacs/.emacs.d/auto-save-list/.saves-22796-warning~ @@ -0,0 +1,2 @@ +/usr/share/themes/Ambiance/gtk-2.0/gtkrc +/usr/share/themes/Ambiance/gtk-2.0/#gtkrc# diff --git a/emacs/.emacs.d/auto-save-list/.saves-2315-home~ b/emacs/.emacs.d/auto-save-list/.saves-2315-home~ diff --git a/emacs/.emacs.d/auto-save-list/.saves-2357-home~ b/emacs/.emacs.d/auto-save-list/.saves-2357-home~ diff --git a/emacs/.emacs.d/auto-save-list/.saves-2369-home~ b/emacs/.emacs.d/auto-save-list/.saves-2369-home~ diff --git a/emacs/.emacs.d/auto-save-list/.saves-2381-warning~ b/emacs/.emacs.d/auto-save-list/.saves-2381-warning~ @@ -0,0 +1,16 @@ +/home/paul/desktop/pnbp/mod/blog.py +/home/paul/desktop/pnbp/mod/#blog.py# +/home/paul/desktop/pnbp/data/test.json +/home/paul/desktop/pnbp/data/#test.json# +/home/paul/desktop/pnbp/pages.json +/home/paul/desktop/pnbp/#pages.json# +/home/paul/desktop/pnbp/compile.py +/home/paul/desktop/pnbp/#compile.py# +/home/paul/desktop/pnbp/data/admin/post.php +/home/paul/desktop/pnbp/data/admin/#post.php# +/home/paul/desktop/pnbp/data/admin/index.php +/home/paul/desktop/pnbp/data/admin/#index.php# +/home/paul/desktop/pnbp/templates/std.html +/home/paul/desktop/pnbp/templates/#std.html# +/home/paul/desktop/pnbp/data/styles/style.css +/home/paul/desktop/pnbp/data/styles/#style.css# diff --git a/emacs/.emacs.d/auto-save-list/.saves-23863-warning~ b/emacs/.emacs.d/auto-save-list/.saves-23863-warning~ @@ -0,0 +1,2 @@ +/usr/share/themes/Ambiance/gtk-2.0/gtkrc +/usr/share/themes/Ambiance/gtk-2.0/#gtkrc# diff --git a/emacs/.emacs.d/auto-save-list/.saves-2396-home~ b/emacs/.emacs.d/auto-save-list/.saves-2396-home~ diff --git a/emacs/.emacs.d/auto-save-list/.saves-2475-home~ b/emacs/.emacs.d/auto-save-list/.saves-2475-home~ diff --git a/emacs/.emacs.d/auto-save-list/.saves-24850-warning~ b/emacs/.emacs.d/auto-save-list/.saves-24850-warning~ @@ -0,0 +1,4 @@ +/usr/share/themes/Ambiance/gtk-2.0/gtkrc +/usr/share/themes/Ambiance/gtk-2.0/#gtkrc# +/home/paul/.i3/config +/home/paul/.i3/#config# diff --git a/emacs/.emacs.d/auto-save-list/.saves-25053-warning.home~ b/emacs/.emacs.d/auto-save-list/.saves-25053-warning.home~ @@ -0,0 +1,8 @@ +/home/paul/Dropbox/stuffs/web/eport2/index.html +/home/paul/Dropbox/stuffs/web/eport2/#index.html# +/home/paul/Dropbox/stuffs/web/eport2/style/style.css +/home/paul/Dropbox/stuffs/web/eport2/style/#style.css# +/home/paul/Dropbox/stuffs/web/eport2/projects/index.html +/home/paul/Dropbox/stuffs/web/eport2/projects/#index.html# +/home/paul/Dropbox/stuffs/web/eport2/contact/index.html +/home/paul/Dropbox/stuffs/web/eport2/contact/#index.html# diff --git a/emacs/.emacs.d/auto-save-list/.saves-2831-home~ b/emacs/.emacs.d/auto-save-list/.saves-2831-home~ diff --git a/emacs/.emacs.d/auto-save-list/.saves-28895-warning~ b/emacs/.emacs.d/auto-save-list/.saves-28895-warning~ diff --git a/emacs/.emacs.d/auto-save-list/.saves-3084-warning~ b/emacs/.emacs.d/auto-save-list/.saves-3084-warning~ @@ -0,0 +1,10 @@ +/home/paul/.i3status.conf +/home/paul/#.i3status.conf# +/home/paul/.i3/config +/home/paul/.i3/#config# +/home/paul/.conkyrc +/home/paul/#.conkyrc# +/home/paul/Dropbox/stuffs/config/.conkyrc +/home/paul/Dropbox/stuffs/config/#.conkyrc# +/home/paul/bin/conky-i3bar +/home/paul/bin/#conky-i3bar# diff --git a/emacs/.emacs.d/auto-save-list/.saves-3197-home~ b/emacs/.emacs.d/auto-save-list/.saves-3197-home~ diff --git a/emacs/.emacs.d/auto-save-list/.saves-3202-home~ b/emacs/.emacs.d/auto-save-list/.saves-3202-home~ diff --git a/emacs/.emacs.d/auto-save-list/.saves-3850-home~ b/emacs/.emacs.d/auto-save-list/.saves-3850-home~ diff --git a/emacs/.emacs.d/auto-save-list/.saves-3862-warning.home~ b/emacs/.emacs.d/auto-save-list/.saves-3862-warning.home~ diff --git a/emacs/.emacs.d/auto-save-list/.saves-4030-warning.home~ b/emacs/.emacs.d/auto-save-list/.saves-4030-warning.home~ @@ -0,0 +1,2 @@ +/home/paul/.i3/config +/home/paul/.i3/#config# diff --git a/emacs/.emacs.d/auto-save-list/.saves-4213-warning~ b/emacs/.emacs.d/auto-save-list/.saves-4213-warning~ diff --git a/emacs/.emacs.d/auto-save-list/.saves-4325-warning~ b/emacs/.emacs.d/auto-save-list/.saves-4325-warning~ diff --git a/emacs/.emacs.d/auto-save-list/.saves-4396-warning~ b/emacs/.emacs.d/auto-save-list/.saves-4396-warning~ diff --git a/emacs/.emacs.d/auto-save-list/.saves-4657-warning.home~ b/emacs/.emacs.d/auto-save-list/.saves-4657-warning.home~ diff --git a/emacs/.emacs.d/auto-save-list/.saves-5180-home~ b/emacs/.emacs.d/auto-save-list/.saves-5180-home~ diff --git a/emacs/.emacs.d/auto-save-list/.saves-6206-warning~ b/emacs/.emacs.d/auto-save-list/.saves-6206-warning~ @@ -0,0 +1,6 @@ +/home/paul/.chrome-ext/noflash/script.js +/home/paul/.chrome-ext/noflash/#script.js# +/home/paul/.chrome-ext/noflash/manifest.json +/home/paul/.chrome-ext/noflash/#manifest.json# +/home/paul/.i3/config +/home/paul/.i3/#config# diff --git a/emacs/.emacs.d/auto-save-list/.saves-7875-home~ b/emacs/.emacs.d/auto-save-list/.saves-7875-home~ diff --git a/emacs/.emacs.d/auto-save-list/.saves-7906-warning~ b/emacs/.emacs.d/auto-save-list/.saves-7906-warning~ @@ -0,0 +1,2 @@ +/home/paul/.conkyrc +/home/paul/#.conkyrc# diff --git a/emacs/.emacs.d/auto-save-list/.saves-8433-warning~ b/emacs/.emacs.d/auto-save-list/.saves-8433-warning~ @@ -0,0 +1,4 @@ +/home/paul/.i3/config +/home/paul/.i3/#config# +/home/paul/.i3status.conf +/home/paul/#.i3status.conf# diff --git a/emacs/.emacs.d/auto-save-list/.saves-8788-warning~ b/emacs/.emacs.d/auto-save-list/.saves-8788-warning~ @@ -0,0 +1,2 @@ +/home/paul/.i3/config +/home/paul/.i3/#config# diff --git a/emacs/.emacs.d/auto-save-list/.saves-9494-warning~ b/emacs/.emacs.d/auto-save-list/.saves-9494-warning~ diff --git a/emacs/.emacs.d/auto-save-list/.saves-9918-warning.home~ b/emacs/.emacs.d/auto-save-list/.saves-9918-warning.home~ diff --git a/emacs/.emacs.d/auto-save-list/.saves-9969-warning~ b/emacs/.emacs.d/auto-save-list/.saves-9969-warning~ @@ -0,0 +1,6 @@ +/home/paul/desktop/pnbp/compile.py +/home/paul/desktop/pnbp/#compile.py# +/home/paul/desktop/pnbp/includes/header.html +/home/paul/desktop/pnbp/includes/#header.html# +/home/paul/desktop/pnbp/templates/post.html +/home/paul/desktop/pnbp/templates/#post.html# diff --git a/emacs/.emacs.d/autopair.el b/emacs/.emacs.d/autopair.el @@ -0,0 +1,1126 @@ +;;; autopair.el --- Automagically pair braces and quotes like TextMate + +;; Copyright (C) 2009,2010 Joao Tavora + +;; Author: Joao Tavora <joaotavora [at] gmail.com> +;; Keywords: convenience, emulations +;; X-URL: http://autopair.googlecode.com +;; URL: http://autopair.googlecode.com +;; EmacsWiki: AutoPairs +;; Package-Requires: ((cl-lib "0.3")) +;; Version: 0.6.1 + +;; 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: +;; +;; Another stab at making braces and quotes pair like in +;; TextMate: +;; +;; * Opening braces/quotes are autopaired; +;; * Closing braces/quotes are autoskipped; +;; * Backspacing an opening brace/quote autodeletes its adjacent pair. +;; * Newline between newly-opened brace pairs open an extra indented line. +;; +;; Autopair deduces from the current syntax table which characters to +;; pair, skip or delete. +;; +;;; Installation: +;; +;; (require 'autopair) +;; (autopair-global-mode) ;; to enable in all buffers +;; +;; To enable autopair in just some types of buffers, comment out the +;; `autopair-global-mode' and put autopair-mode in some major-mode +;; hook, like: +;; +;; (add-hook 'c-mode-common-hook #'(lambda () (autopair-mode))) +;; +;; Alternatively, do use `autopair-global-mode' and create +;; *exceptions* using the `autopair-dont-activate' local variable (for +;; emacs < 24), or just using (autopair-mode -1) (for emacs >= 24) +;; like: +;; +;; (add-hook 'c-mode-common-hook +;; #'(lambda () +;; (setq autopair-dont-activate t) +;; (autopair-mode -1))) +;; +;; +;;; Use: +;; +;; The extension works by rebinding the braces and quotes keys, but +;; can still be minimally intrusive, since the original binding is +;; always called as if autopair did not exist. +;; +;; The decision of which keys to actually rebind is taken at +;; minor-mode activation time, based on the current major mode's +;; syntax tables. To achieve this kind of behaviour, an emacs +;; variable `emulation-mode-map-alists' was used. +;; +;; If you set `autopair-pair-criteria' and `autopair-skip-criteria' to +;; 'help-balance (which, by the way, is the default), braces are not +;; autopaired/autoskiped in all situations; the decision to autopair +;; or autoskip a brace is taken according to the following table: +;; +;; +---------+------------+-----------+-------------------+ +;; | 1234567 | autopair? | autoskip? | notes | +;; +---------+------------+-----------+-------------------+ +;; | (()) | yyyyyyy | ---yy-- | balanced | +;; +---------+------------+-----------+-------------------+ +;; | (())) | ------y | ---yyy- | too many closings | +;; +---------+------------+-----------+-------------------+ +;; | ((()) | yyyyyyy | ------- | too many openings | +;; +---------+------------+-----------+-------------------+ +;; +;; The table is read like this: in a buffer with 7 characters laid out +;; like the first column, an "y" marks points where an opening brace +;; is autopaired and in which places would a closing brace be +;; autoskipped. +;; +;; Quote pairing tries to support similar "intelligence", but is less +;; deterministic. Some inside-string or inside-comment situations may +;; not always behave how you intend them to. +;; +;; The variable `autopair-autowrap' tells autopair to automatically +;; wrap the selection region with the delimiters you're trying to +;; insert. This is done conditionally based of syntaxes of the two +;; ends of the selection region. It is compatible with `cua-mode's +;; typing-deletes-selection behaviour. +;; +;; If you find the paren-blinking annoying, turn `autopair-blink' to +;; nil. +;; +;; For lisp-programming you might also like `autopair-skip-whitespace'. +;; +;; For further customization have a look at `autopair-dont-pair', +;; `autopair-handle-action-fns' and `autopair-extra-pairs'. +;; +;; `autopair-dont-pair' lets you define special cases of characters +;; you don't want paired. Its default value skips pairing +;; single-quote characters when inside a comment literal, even if the +;; language syntax tables does pair these characters. +;; +;; (defvar autopair-dont-pair `(:string (?') :comment (?')) +;; +;; As a further example, to also prevent the '{' (opening brace) +;; character from being autopaired in C++ comments use this in your +;; .emacs. +;; +;; (add-hook 'c++-mode-hook +;; #'(lambda () +;; (push ?{ +;; (cl-getf autopair-dont-pair :comment)))) +;; +;; `autopair-handle-action-fns' lets you override/extend the actions +;; taken by autopair after it decides something must be paired,skipped +;; or deleted. To work with triple quoting in python mode, you can use +;; this for example: +;; +;; (add-hook 'python-mode-hook +;; #'(lambda () +;; (setq autopair-handle-action-fns +;; (list #'autopair-default-handle-action +;; #'autopair-python-triple-quote-action)))) +;; +;; It's also useful to deal with latex's mode use of the "paired +;; delimiter" syntax class. +;; +;; (add-hook 'latex-mode-hook +;; #'(lambda () +;; (set (make-local-variable 'autopair-handle-action-fns) +;; (list #'autopair-default-handle-action +;; #'autopair-latex-mode-paired-delimiter-action)))) +;; +;; `autopair-extra-pairs' lets you define extra pairing and skipping +;; behaviour for pairs not programmed into the syntax table. Watch +;; out, this is work-in-progress, a little unstable and does not help +;; balancing at all. To have '<' and '>' pair in c++-mode buffers, but +;; only in code, use: +;; +;; (add-hook 'c++-mode-hook +;; #'(lambda () +;; (push '(?< . ?>) +;; (cl-getf autopair-extra-pairs :code)))) +;; +;; if you program in emacs-lisp you might also like the following to +;; pair backtick and quote +;; +;; (add-hook 'emacs-lisp-mode-hook +;; #'(lambda () +;; (push '(?` . ?') +;; (cl-getf autopair-extra-pairs :comment)) +;; (push '(?` . ?') +;; (cl-getf autopair-extra-pairs :string)))) +;; +;;; Bugs: +;; +;; * Quote pairing/skipping inside comments is not perfect... +;; +;; * See the last section on monkey-patching for the `defadvice' +;; tricks used to make `autopair-autowrap' work with `cua-mode' and +;; `delete-selection-mode'. +;; +;;; Credit: +;; +;; Thanks Ed Singleton for early testing. +;; +;;; Code: + +;; requires +(require 'cl-lib) +(require 'paren) + +(defgroup autopair nil + "Automagically pair braces and quotes" + :group 'convenience) + +;; variables +(defcustom autopair-pair-criteria 'help-balance + "How to decide whether to pair opening brackets or quotes. + +Set this to 'always to always pair, or 'help-balance to be more +criterious when pairing." + :group 'autopair + :type '(choice (const :tag "Help balance" help-balance) + (const :tag "Always pair" always))) + +(defcustom autopair-skip-criteria 'help-balance + "How to decide whether to skip closing brackets or quotes. + +Set this to 'always to always skip, or 'help-balance to be more +criterious when skipping." + :group 'autopair + :type '(choice (const :tag "Help balance" help-balance) + (const :tag "Always skip" always))) + +(defcustom autopair-autowrap 'help-balance + "If non-nil autopair attempts to wrap the selected region. + +This is also done in an optimistic \"try-to-balance\" fashion. +Set this to to 'help-balance to be more criterious when +wrapping." + :group 'autopair + :type '(choice (const :tag "Do wrap" t) + (const :tag "Do not wrap" nil) + (const :tag "Help Balance" 'help-balance))) + +(defvar autopair--emulation-alist nil + "A keymap alist for adding to `emulation-mode-map-alists'. + +The alist contains single (t MAP) association, where MAP is a +dynamic keymap set mostly from the major mode's syntax table.") + +(unless (eval-when-compile (> emacs-major-version 23)) + (defvar autopair-dont-activate nil + "Control activation of `autopair-global-mode'. + +Set this to a non-nil value to skip activation of `autopair-mode' +in certain contexts. If however the value satisfies `functionp' +and is a function of no arguments, the function is called and it is +the return value that decides.") + (make-variable-buffer-local 'autopair-dont-activate)) + +(defvar autopair-extra-pairs nil + "Extra pairs for which to use pairing. + +It's a Common-lisp-style even-numbered property list, each pair +of elements being of the form (TYPE , PAIRS). PAIRS is a mixed +list whose elements are cons cells, which look like cells look +like (OPENING . CLOSING). Autopair pairs these like +parenthesis. + +TYPE can be one of: + +:string : whereby PAIRS will be considered only when inside a + string literal + +:comment : whereby PAIRS will be considered only when inside a comment + +:code : whereby PAIRS will be considered only when outisde a + string and a comment. + +:everywhere : whereby PAIRS will be considered in all situations + +In Emacs-lisp, this might be useful + +(add-hook 'emacs-lisp-mode-hook + #'(lambda () + (setq autopair-extra-pairs `(:comment ((?`. ?')))))) + + +Note that this does *not* work for single characters, +e.x. characters you want to behave as quotes. See the +docs/source comments for more details.") + +(make-variable-buffer-local 'autopair-extra-pairs) + +(defvar autopair-dont-pair `(:string (?') :comment (?')) + "Characters for which to skip any pairing behaviour. + +This variable overrides `autopair-pair-criteria' and +`autopair-extra-pairs'. It does not + (currently) affect the skipping behaviour. + +It's a Common-lisp-style even-numbered property list, each pair +of elements being of the form (TYPE , CHARS). CHARS is a list of +characters and TYPE can be one of: + +:string : whereby characters in CHARS will not be autopaired when + inside a string literal + +:comment : whereby characters in CHARS will not be autopaired when + inside a comment + +:never : whereby characters in CHARS won't even have their + bindings replaced by autopair's. This particular option + should be used for troubleshooting and requires + `autopair-mode' to be restarted to have any effect.") +(make-variable-buffer-local 'autopair-dont-pair) + +(defvar autopair-action nil + "Autopair action decided on by last interactive autopair command, or nil. + +When autopair decides on an action this is a list whose first +three elements are (ACTION PAIR POS-BEFORE). + +ACTION is one of `opening', `insert-quote', `skip-quote', +`backspace', `newline' or `paired-delimiter'. PAIR is the pair of +the `autopair--inserted' character, if applicable. POS-BEFORE is +value of point before action command took place .") + + +(defvar autopair-wrap-action nil + "Autowrap action decided on by autopair, if any. + +When autopair decides on an action this is a list whose first +three elements are (ACTION PAIR POS-BEFORE REGION-BEFORE). + +ACTION can only be `wrap' currently. PAIR and POS-BEFORE +delimiter are as in `autopair-action'. REGION-BEFORE is a cons +cell with the bounds of the region before the command takes +place") + +(defvar autopair-handle-action-fns '() + "Autopair handlers to run *instead* of the default handler. + +Each element is a function taking three arguments (ACTION, PAIR +and POS-BEFORE), which are the three elements of the +`autopair-action' variable, which see. + +If non-nil, these functions are called *instead* of the single +function `autopair-default-handle-action', so use this variable +to specify special behaviour. To also run the default behaviour, +be sure to include `autopair-default-handle-action' in the +list, or call it from your handlers.") +(make-variable-buffer-local 'autopair-handle-action-fns) + +(defvar autopair-handle-wrap-action-fns '() + "Autopair wrap handlers to run *instead* of the default handler. + +Each element is a function taking four arguments (ACTION, PAIR, +POS-BEFORE and REGION-BEFORE), which are the three elements of the +`autopair-wrap-action' variable, which see. + +If non-nil, these functions are called *instead* of the single +function `autopair-default-handle-wrap-action', so use this +variable to specify special behaviour. To also run the default +behaviour, be sure to include `autopair-default-handle-wrap-action' in +the list, or call it in your handlers.") +(make-variable-buffer-local 'autopair-handle-wrap-action-fns) + +(defvar autopair-inserted nil + "Delimiter inserted by last interactive autopair command. + +This is calculated with `autopair-calculate-inserted', which see.") + +(defun autopair--calculate-inserted () + "Attempts to guess the delimiter the current command is inserting. + +For now, simply returns `last-command-event'" + last-command-event) + +;; minor mode and global mode +;; +;;;###autoload +(define-minor-mode autopair-mode + "Automagically pair braces and quotes like in TextMate." + nil " pair" nil + (cond (autopair-mode + ;; Setup the dynamic emulation keymap, i.e. sets `autopair--emulation-alist' + ;; + (autopair--set-emulation-bindings) + (add-to-list 'emulation-mode-map-alists 'autopair--emulation-alist 'append) + ;; Init important vars + ;; + (setq autopair-action nil) + (setq autopair-wrap-action nil) + ;; Add the post command handler + ;; + (add-hook 'post-command-hook 'autopair--post-command-handler nil 'local)) + (t + (set (make-local-variable 'autopair--emulation-alist) nil) + (remove-hook 'post-command-hook 'autopair--post-command-handler 'local)))) + +;;;###autoload +(define-globalized-minor-mode autopair-global-mode autopair-mode autopair-on) + +(when (eval-when-compile (>= emacs-major-version 24)) + (defvar autopair--global-mode-emacs24-hack-flag nil) + (defadvice autopair-global-mode-enable-in-buffers (before autopairs-global-mode-emacs24-hack activate) + "Monkey patch for recent emacsen 24. + +It's impossible for a globalized minor-mode to see variables set +by major-mode-hooks. However, the auto-generated +`autopair-global-mode-enable-in-buffers' does run after the +major-mode-hooks. + +This advice makes sure the emulation keybindings are (re)set +there. It relies on the fact that +`autopair-global-mode-enable-in-buffers' is still called again in +`after-change-major-mode-hook' (but the autopair-mode has already +been turned on before the major-mode hooks kicked in). + +We want this advice to only kick in the *second* call to +`autopair-global-mode-enable-in-buffers'." + (dolist (buf autopair-global-mode-buffers) + (when (buffer-live-p buf) + (with-current-buffer buf + (when (and autopair-mode + (not autopair--global-mode-emacs24-hack-flag)) + (autopair--set-emulation-bindings) + (set (make-local-variable 'autopair--global-mode-emacs24-hack-flag) t))))))) + +(defun autopair-on () + (unless (or buffer-read-only + (and (not (minibufferp)) + (string-match "^ \\*" (buffer-name))) + (eq major-mode 'sldb-mode) + (and (eval-when-compile (< emacs-major-version 24)) + (boundp 'autopair-dont-activate) + autopair-dont-activate) + (autopair-mode 1)))) + +(defun autopair--set-emulation-bindings () + "Setup keymap MAP with keybindings based on the major-mode's +syntax table and the local value of `autopair-extra-pairs'." + (let ((map (make-sparse-keymap))) + (define-key map [remap delete-backward-char] 'autopair-backspace) + (define-key map [remap backward-delete-char-untabify] 'autopair-backspace) + (define-key map "\177" 'autopair-backspace) + (define-key map "\r" 'autopair-newline) + (dotimes (char 256) ;; only searches the first 256 chars, + ;; TODO: is this enough/toomuch/stupid? + (unless (member char + (cl-getf autopair-dont-pair :never)) + (let* ((syntax-entry (aref (syntax-table) char)) + (class (and syntax-entry + (syntax-class syntax-entry))) + (pair (and syntax-entry + (cdr syntax-entry)))) + (cond ((and (eq class (car (string-to-syntax "("))) + pair) + ;; syntax classes "opening parens" and "close parens" + (define-key map (string char) 'autopair-insert-opening) + (define-key map (string pair) 'autopair-skip-close-maybe)) + ((eq class (car (string-to-syntax "\""))) + ;; syntax class "string quote + (define-key map (string char) 'autopair-insert-or-skip-quote)) + ((eq class (car (string-to-syntax "$"))) + ;; syntax class "paired-delimiter" + ;; + ;; Apropos this class, see Issues 18, 25 and + ;; elisp info node "35.2.1 Table of Syntax + ;; Classes". The fact that it supresses + ;; syntatic properties in the delimited region + ;; dictates that deciding to autopair/autoskip + ;; can't really be as clean as the string + ;; delimiter. + ;; + ;; Apparently, only `TeX-mode' uses this, so + ;; the best is to bind this to + ;; `autopair-insert-or-skip-paired-delimiter' + ;; which defers any decision making to + ;; mode-specific post-command handler + ;; functions. + ;; + (define-key map (string char) 'autopair-insert-or-skip-paired-delimiter)))))) + ;; read `autopair-extra-pairs' + ;; + (dolist (pairs-list (cl-remove-if-not #'listp autopair-extra-pairs)) + (dolist (pair pairs-list) + (define-key map (string (car pair)) 'autopair-extra-insert-opening) + (define-key map (string (cdr pair)) 'autopair-extra-skip-close-maybe))) + + (set (make-local-variable 'autopair--emulation-alist) (list (cons t map))))) + +;; helper functions +;; +(defun autopair--syntax-ppss () + "Calculate syntax info relevant to autopair. + +A list of four elements is returned: + +- SYNTAX-INFO is either the result `syntax-ppss' or the result of + calling `parse-partial-sexp' with the appropriate + bounds (previously calculated with `syntax-ppss'. + +- WHERE-SYM can be one of the symbols :string, :comment or :code. + +- QUICK-SYNTAX-INFO is always the result returned by `syntax-ppss'. + +- BOUNDS are the boudaries of the current string or comment if + we're currently inside one." + (let* ((quick-syntax-info (syntax-ppss)) + (string-or-comment-start (nth 8 quick-syntax-info))) + (cond (;; inside a string, recalculate + (nth 3 quick-syntax-info) + (list (parse-partial-sexp (1+ string-or-comment-start) (point)) + :string + quick-syntax-info + (cons string-or-comment-start + (condition-case nil + (scan-sexps string-or-comment-start 1) + (scan-error nil))))) + ((nth 4 quick-syntax-info) + (list (parse-partial-sexp (1+ (nth 8 quick-syntax-info)) (point)) + :comment + quick-syntax-info)) + (t + (list quick-syntax-info + :code + quick-syntax-info))))) + +(defun autopair--pair-of (delim &optional closing) + (when (and delim + (integerp delim)) + (let ((syntax-entry (aref (syntax-table) delim))) + (cond ((eq (syntax-class syntax-entry) (car (string-to-syntax "("))) + (cdr syntax-entry)) + ((or (eq (syntax-class syntax-entry) (car (string-to-syntax "\""))) + (eq (syntax-class syntax-entry) (car (string-to-syntax "$")))) + delim) + ((and (not closing) + (eq (syntax-class syntax-entry) (car (string-to-syntax ")")))) + (cdr syntax-entry)) + (autopair-extra-pairs + (cl-some #'(lambda (pair-list) + (cl-some #'(lambda (pair) + (cond ((eq (cdr pair) delim) (car pair)) + ((eq (car pair) delim) (cdr pair)))) + pair-list)) + (cl-remove-if-not #'listp autopair-extra-pairs))))))) + +(defun autopair--calculate-wrap-action () + (when (and transient-mark-mode mark-active) + (when (> (point) (mark)) + (exchange-point-and-mark)) + (save-excursion + (let* ((region-before (cons (region-beginning) + (region-end))) + (point-before (point)) + (start-syntax (syntax-ppss (car region-before))) + (end-syntax (syntax-ppss (cdr region-before)))) + (when (or (not (eq autopair-autowrap 'help-balance)) + (and (eq (nth 0 start-syntax) (nth 0 end-syntax)) + (eq (nth 3 start-syntax) (nth 3 end-syntax)))) + (list 'wrap (or (cl-second autopair-action) + (autopair--pair-of autopair-inserted)) + point-before + region-before)))))) + +(defun autopair--original-binding (fallback-keys) + (or (key-binding `[,autopair-inserted]) + (key-binding (this-single-command-keys)) + (key-binding fallback-keys))) + +(defvar autopair--this-command nil) +(defun autopair--fallback (&optional fallback-keys) + (let* ((autopair--emulation-alist nil) + (beyond-cua (let ((cua--keymap-alist nil)) + (autopair--original-binding fallback-keys))) + (beyond-autopair (autopair--original-binding fallback-keys))) + (when autopair-autowrap + (setq autopair-wrap-action (autopair--calculate-wrap-action))) + + (setq autopair--this-command this-command) + (setq this-original-command beyond-cua) + ;; defer to "paredit-mode" if that is installed and running + (when (and (featurep 'paredit) + (symbolp beyond-cua) + (string-match "paredit" (symbol-name beyond-cua))) + (setq autopair-action nil)) + (let ((cua-delete-selection (not autopair-autowrap)) + (blink-matching-paren (not autopair-action))) + (call-interactively beyond-autopair)))) + +(defcustom autopair-skip-whitespace nil + "If non-nil also skip over whitespace when skipping closing delimiters. + +If set to 'chomp, this will be most useful in lisp-like languages +where you want lots of )))))...." + :group 'autopair + :type 'boolean) + +(defcustom autopair-blink (if (boundp 'blink-matching-paren) + blink-matching-paren + t) + "If non-nil autopair blinks matching delimiters." + :group 'autopair + :type 'boolean) + +(defcustom autopair-blink-delay 0.1 + "Autopair's blink-the-delimiter delay." + :group 'autopair + :type 'float) + +(defun autopair--document-bindings (&optional fallback-keys) + (concat + "Works by scheduling possible autopair behaviour, then calls +original command as if autopair didn't exist" + (when (eq this-command 'describe-key) + (let* ((autopair--emulation-alist nil) + (command (or (key-binding (this-single-command-keys)) + (key-binding fallback-keys)))) + (when command + (format ", which in this case is `%s'" command)))) + ".")) + +(defun autopair--escaped-p (syntax-info) + (nth 5 syntax-info)) + +(defun autopair--exception-p (where-sym exception-where-sym blacklist &optional fn) + (and (or (eq exception-where-sym :everywhere) + (eq exception-where-sym where-sym)) + (member autopair-inserted + (if fn + (mapcar fn (cl-getf blacklist exception-where-sym)) + (cl-getf blacklist exception-where-sym))))) + +(defun autopair--find-pair (direction) + "Compute (MATCHED START END) for the pair of the delimiter at point. + +With positive DIRECTION consider the delimiter after point and +travel forward, otherwise consider the delimiter is just before +point and travel backward." + (let* ((show-paren-data (and nil + (funcall show-paren-data-function))) + (here (point))) + (cond (show-paren-data + (cl-destructuring-bind (here-beg here-end there-beg there-end mismatch) + show-paren-data + (if (cl-plusp direction) + (list (not mismatch) there-end here-beg) + (list (not mismatch) there-beg here-end)))) + (t + (condition-case move-err + (save-excursion + (forward-sexp (if (cl-plusp direction) 1 -1)) + (list (if (cl-plusp direction) + (eq (char-after here) + (autopair--pair-of (char-before (point)))) + (eq (char-before here) + (autopair--pair-of (char-after (point))))) + (point) here)) + (scan-error + (list nil (nth 2 move-err) here))))))) + +(defun autopair--up-list (&optional n) + "Try to up-list forward as much as N lists. + +With negative N, up-list backward. + +Return a cons of two descritions (MATCHED START END) for the +innermost and outermost lists that enclose point. The outermost +list enclosing point is either the first top-level or mismatched +list found by uplisting." + (save-excursion + (cl-loop with n = (or n (point-max)) + for i from 0 below (abs n) + with outermost + with innermost + until outermost + do + (condition-case forward-err + (progn + (scan-sexps (point) (if (cl-plusp n) + (point-max) + (- (point-max)))) + (unless innermost + (setq innermost (list t))) + (setq outermost (list t))) + (scan-error + (goto-char + (if (cl-plusp n) + ;; HACK: the reason for this `max' is that some + ;; modes like ruby-mode sometimes mis-report the + ;; scan error when `forward-sexp'eeing too-much, its + ;; (nth 3) should at least one greater than its (nth + ;; 2). We really need to move out of the sexp so + ;; detect this and add 1. If this were fixed we + ;; could move to (nth 3 forward-err) in all + ;; situations. + ;; + (max (1+ (nth 2 forward-err)) + (nth 3 forward-err)) + (nth 3 forward-err))) + (let ((pair-data (autopair--find-pair (- n)))) + (unless innermost + (setq innermost pair-data)) + (unless (cl-first pair-data) + (setq outermost pair-data))))) + finally (return (cons innermost outermost))))) + +;; interactive commands and their associated predicates +;; +(defun autopair-insert-or-skip-quote () + (interactive) + (setq autopair-inserted (autopair--calculate-inserted)) + (let* ((syntax-triplet (autopair--syntax-ppss)) + (syntax-info (cl-first syntax-triplet)) + (where-sym (cl-second syntax-triplet)) + (orig-info (cl-third syntax-triplet)) + ;; inside-string may the quote character itself or t if this + ;; is a "generically terminated string" + (inside-string (and (eq where-sym :string) + (cl-fourth orig-info))) + (escaped-p (autopair--escaped-p syntax-info)) + + ) + (cond (;; decides whether to skip the quote... + ;; + (and (not escaped-p) + (eq autopair-inserted (char-after (point))) + (or + ;; ... if we're already inside a string and the + ;; string starts with the character just inserted, + ;; or it's a generically terminated string + (and inside-string + (or (eq inside-string t) + (eq autopair-inserted inside-string))) + ;; ... if we're in a comment and ending a string + ;; (the inside-string criteria does not work + ;; here...) + (and (eq where-sym :comment) + (condition-case nil + (eq autopair-inserted (char-after (scan-sexps (1+ (point)) -1))) + (scan-error nil))))) + (setq autopair-action (list 'skip-quote autopair-inserted (point)))) + (;; decides whether to pair, i.e do *not* pair the quote if... + ;; + (not + (or + escaped-p + ;; ... inside a generic string + (eq inside-string t) + ;; ... inside an unterminated string started by this char + (autopair--in-unterminated-string-p syntax-triplet) + ;; ... the position at the end of buffer is inside an + ;; unterminated string + (autopair--in-unterminated-string-p (save-excursion + (goto-char (point-max)) + (autopair--syntax-ppss))) + ;; ... comment-disable or string-disable are true at + ;; point. The latter is only useful if we're in a string + ;; terminated by a character other than + ;; `autopair-inserted'. + (cl-some #'(lambda (sym) + (autopair--exception-p where-sym sym autopair-dont-pair)) + '(:comment :string)))) + (setq autopair-action (list 'insert-quote autopair-inserted (point))))) + (autopair--fallback))) + +(put 'autopair-insert-or-skip-quote 'function-documentation + '(concat "Insert or possibly skip over a quoting character.\n\n" + (autopair--document-bindings))) + +(defun autopair--in-unterminated-string-p (autopair-triplet) + (let* ((relevant-ppss (cl-third autopair-triplet)) + (string-delim (cl-fourth relevant-ppss))) + (and (or (eq t string-delim) + (eq autopair-inserted string-delim)) + (condition-case nil (progn (scan-sexps (cl-ninth relevant-ppss) 1) nil) (scan-error t))))) + + +(defun autopair-insert-opening () + (interactive) + (setq autopair-inserted (autopair--calculate-inserted)) + (when (autopair--pair-p) + (setq autopair-action (list 'opening (autopair--pair-of autopair-inserted) (point)))) + (autopair--fallback)) +(put 'autopair-insert-opening 'function-documentation + '(concat "Insert opening delimiter and possibly automatically close it.\n\n" + (autopair--document-bindings))) + +(defun autopair-skip-close-maybe () + (interactive) + (setq autopair-inserted (autopair--calculate-inserted)) + (when (autopair--skip-p) + (setq autopair-action (list 'closing (autopair--pair-of autopair-inserted) (point)))) + (autopair--fallback)) +(put 'autopair-skip-close-maybe 'function-documentation + '(concat "Insert or possibly skip over a closing delimiter.\n\n" + (autopair--document-bindings))) + +(defun autopair-backspace () + (interactive) + (setq autopair-inserted (autopair--calculate-inserted)) + (when (char-before) + (setq autopair-action (list 'backspace (autopair--pair-of (char-before) 'closing) (point)))) + (autopair--fallback (kbd "DEL"))) +(put 'autopair-backspace 'function-documentation + '(concat "Possibly delete a pair of paired delimiters.\n\n" + (autopair--document-bindings (kbd "DEL")))) + +(defun autopair-newline () + (interactive) + (setq autopair-inserted (autopair--calculate-inserted)) + (let ((pair (autopair--pair-of (char-before)))) + (when (and pair + (eq (char-syntax pair) ?\)) + (eq (char-after) pair)) + (setq autopair-action (list 'newline pair (point)))) + (autopair--fallback (kbd "RET")))) +(put 'autopair-newline 'function-documentation + '(concat "Do a smart newline when right between parenthesis.\n +In other words, insert an extra newline along with the one inserted normally +by this command. Then place point after the first, indented.\n\n" + (autopair--document-bindings (kbd "RET")))) + +(defun autopair--skip-p () + (let* ((syntax-triplet (autopair--syntax-ppss)) + (syntax-info (cl-first syntax-triplet)) + (orig-point (point))) + (cond ((eq autopair-skip-criteria 'help-balance) + (cl-destructuring-bind (innermost . outermost) + (autopair--up-list (- (point-max))) + (cond ((cl-first outermost) + (cl-first innermost)) + ((cl-first innermost) + (not (eq (autopair--pair-of (char-after (cl-third outermost))) + autopair-inserted)))))) + ((eq autopair-skip-criteria 'need-opening) + (save-excursion + (condition-case err + (progn + (backward-list) + t) + (scan-error nil)))) + (t + t)))) + +(defun autopair--pair-p () + (let* ((syntax-triplet (autopair--syntax-ppss)) + (syntax-info (cl-first syntax-triplet)) + (where-sym (cl-second syntax-triplet)) + (orig-point (point))) + (and (not (cl-some #'(lambda (sym) + (autopair--exception-p where-sym sym autopair-dont-pair)) + '(:string :comment :code :everywhere))) + (cond ((eq autopair-pair-criteria 'help-balance) + (and (not (autopair--escaped-p syntax-info)) + (cl-destructuring-bind (innermost . outermost) + (autopair--up-list (point-max)) + (cond ((cl-first outermost) + t) + ((not (cl-first innermost)) + (not (eq (autopair--pair-of (char-before (cl-third outermost))) + autopair-inserted))))))) + ((eq autopair-pair-criteria 'always) + t) + (t + (not (autopair--escaped-p syntax-info))))))) + +;; post-command-hook stuff +;; +(defun autopair--post-command-handler () + "Performs pairing and wrapping based on `autopair-action' and +`autopair-wrap-action'. " + (when (and autopair-wrap-action + (cl-notany #'null autopair-wrap-action)) + + (if autopair-handle-wrap-action-fns + (condition-case err + (mapc #'(lambda (fn) + (apply fn autopair-wrap-action)) + autopair-handle-wrap-action-fns) + (scan-error (progn + (message "[autopair] error running custom `autopair-handle-wrap-action-fns', switching autopair off") + (autopair-mode -1)))) + (apply #'autopair-default-handle-wrap-action autopair-wrap-action)) + (setq autopair-wrap-action nil)) + + (when (and autopair-action + (cl-notany #'null autopair-action)) + (if autopair-handle-action-fns + (condition-case err + (mapc #'(lambda (fn) + (funcall fn (cl-first autopair-action) (cl-second autopair-action) (cl-third autopair-action))) + autopair-handle-action-fns) + (scan-error (progn + (message "[autopair] error running custom `autopair-handle-action-fns', switching autopair off") + (autopair-mode -1)))) + (apply #'autopair-default-handle-action autopair-action)) + (setq autopair-action nil))) + +(defun autopair--blink-matching-open () + (let ((blink-matching-paren autopair-blink) + (show-paren-mode nil) + (blink-matching-delay autopair-blink-delay)) + (blink-matching-open))) + +(defun autopair--blink (&optional pos) + (when autopair-blink + (if pos + (save-excursion + (goto-char pos) + (sit-for autopair-blink-delay)) + (sit-for autopair-blink-delay)))) + +(defun autopair-default-handle-action (action pair pos-before) + ;;(message "action is %s" action) + (condition-case err + (cond (;; automatically insert closing delimiter + (and (eq 'opening action) + (not (eq pair (char-before)))) + (insert pair) + (autopair--blink) + (backward-char 1)) + (;; automatically insert closing quote delimiter + (eq 'insert-quote action) + (insert pair) + (autopair--blink) + (backward-char 1)) + (;; automatically skip oper closer quote delimiter + (and (eq 'skip-quote action) + (eq pair (char-after (point)))) + (delete-char 1) + (autopair--blink-matching-open)) + (;; skip over newly-inserted-but-existing closing delimiter + ;; (normal case) + (eq 'closing action) + (let ((skipped 0)) + (when autopair-skip-whitespace + (setq skipped (save-excursion (skip-chars-forward "\s\n\t")))) + (when (eq autopair-inserted (char-after (+ (point) skipped))) + (backward-delete-char 1) + (unless (zerop skipped) (autopair--blink (+ (point) skipped))) + (if (eq autopair-skip-whitespace 'chomp) + (delete-char skipped) + (forward-char skipped)) + (forward-char)) + (autopair--blink-matching-open))) + (;; autodelete closing delimiter + (and (eq 'backspace action) + (eq pair (char-after (point)))) + (delete-char 1)) + (;; opens an extra line after point, then indents + (and (eq 'newline action) + (eq pair (char-after (point)))) + (save-excursion + (newline-and-indent)) + (indent-according-to-mode))) + (error + (message "[autopair] Ignored error in `autopair-default-handle-action'")))) + + +(defun autopair-default-handle-wrap-action (action pair pos-before region-before) + "Default handler for the wrapping action in `autopair-wrap'" + (condition-case err + (when (eq 'wrap action) + (let ((delete-active-region nil)) + (cond + ((member autopair--this-command '(autopair-insert-opening + autopair-extra-insert-opening)) + (goto-char (1+ (cdr region-before))) + (insert pair) + (autopair--blink) + (goto-char (1+ (car region-before)))) + (;; wraps + (member autopair--this-command '(autopair-skip-close-maybe + autopair-extra-skip-close-maybe)) + (delete-char -1) + (insert pair) + (goto-char (1+ (cdr region-before))) + (insert autopair-inserted)) + ((member autopair--this-command '(autopair-insert-or-skip-quote + autopair-insert-or-skip-paired-delimiter)) + (goto-char (1+ (cdr region-before))) + (insert pair) + (autopair--blink)) + (t + (delete-char -1) + (goto-char (cdr region-before)) + (insert autopair-inserted))) + (setq autopair-action nil))) + (error + (message "[autopair] Ignored error in `autopair-default-handle-wrap-action'")))) + + +;; example python triple quote helper +;; +(defun autopair-python-triple-quote-action (action pair pos-before) + (cond ((and (eq 'insert-quote action) + (>= (point) 3) + (string= (buffer-substring (- (point) 3) + (point)) + (make-string 3 pair))) + (save-excursion (insert (make-string 2 pair)))) + ((and (eq 'backspace action) + (>= (point) 2) + (<= (point) (- (point-max) 2)) + (string= (buffer-substring (- (point) 2) + (+ (point) 2)) + (make-string 4 pair))) + (delete-region (- (point) 2) + (+ (point) 2))) + ((and (eq 'skip-quote action) + (<= (point) (- (point-max) 2)) + (string= (buffer-substring (point) + (+ (point) 2)) + (make-string 2 pair))) + (forward-char 2)) + (t + t))) + +;; example latex paired-delimiter helper +;; +(defun autopair-latex-mode-paired-delimiter-action (action pair pos-before) + "Pair or skip latex's \"paired delimiter\" syntax in math mode. Added AucText support, thanks Massimo Lauria" + (when (eq action 'paired-delimiter) + (when (eq (char-before) pair) + (if (and (or + (eq (get-text-property pos-before 'face) 'tex-math) + (eq (get-text-property (- pos-before 1) 'face) 'font-latex-math-face) + (member 'font-latex-math-face (get-text-property (- pos-before 1) 'face))) + (eq (char-after) pair)) + (cond ((and (eq (char-after) pair) + (eq (char-after (1+ (point))) pair)) + ;; double skip + (delete-char 1) + (forward-char)) + ((eq (char-before pos-before) pair) + ;; doube insert + (insert pair) + (backward-char)) + (t + ;; simple skip + (delete-char 1))) + (insert pair) + (backward-char))))) + +;; Commands and predicates for the autopair-extra* feature +;; + +(defun autopair-extra-insert-opening () + (interactive) + (setq autopair-inserted (autopair--calculate-inserted)) + (when (autopair--extra-pair-p) + (setq autopair-action (list 'opening (autopair--pair-of autopair-inserted) (point)))) + (autopair--fallback)) +(put 'autopair-extra-insert-opening 'function-documentation + '(concat "Insert (an extra) opening delimiter and possibly automatically close it.\n\n" + (autopair--document-bindings))) + +(defun autopair-extra-skip-close-maybe () + (interactive) + (setq autopair-inserted (autopair--calculate-inserted)) + (when (autopair--extra-skip-p) + (setq autopair-action (list 'closing autopair-inserted (point)))) + (autopair--fallback)) +(put 'autopair-extra-skip-close-maybe 'function-documentation + '(concat "Insert or possibly skip over a (and extra) closing delimiter.\n\n" + (autopair--document-bindings))) + +(defun autopair--extra-pair-p () + (let* ((syntax-triplet (autopair--syntax-ppss)) + (syntax-info (cl-first syntax-triplet)) + (where-sym (cl-second syntax-triplet))) + (cl-some #'(lambda (sym) + (autopair--exception-p where-sym sym autopair-extra-pairs #'car)) + '(:everywhere :comment :string :code)))) + +(defun autopair--extra-skip-p () + (let* ((syntax-triplet (autopair--syntax-ppss)) + (syntax-info (cl-first syntax-triplet)) + (where-sym (cl-second syntax-triplet)) + (orig-point (point))) + (and (eq (char-after (point)) autopair-inserted) + (cl-some #'(lambda (sym) + (autopair--exception-p where-sym sym autopair-extra-pairs #'cdr)) + '(:comment :string :code :everywhere)) + (save-excursion + (condition-case err + (backward-sexp (point-max)) + (scan-error + (goto-char (cl-third err)))) + (search-forward (make-string 1 (autopair--pair-of autopair-inserted)) + orig-point + 'noerror))))) + +;; Commands and tex-mode specific handler functions for the "paired +;; delimiter" syntax class. +;; +(defun autopair-insert-or-skip-paired-delimiter () + " insert or skip a character paired delimiter" + (interactive) + (setq autopair-inserted (autopair--calculate-inserted)) + (setq autopair-action (list 'paired-delimiter autopair-inserted (point))) + (autopair--fallback)) + +(put 'autopair-insert-or-skip-paired-delimiter 'function-documentation + '(concat "Insert or possibly skip over a character with a syntax-class of \"paired delimiter\"." + (autopair--document-bindings))) + + + +;; monkey-patching: Compatibility with delete-selection-mode and cua-mode +;; +;; Ideally one would be able to use functions as the value of the +;; 'delete-selection properties of the autopair commands. The function +;; would return non-nil when no wrapping should/could be performed. +;; +;; Until then use some `defadvice' i.e. monkey-patching, which relies +;; on these features' implementation details. +;; +(put 'autopair-insert-opening 'delete-selection t) +(put 'autopair-skip-close-maybe 'delete-selection t) +(put 'autopair-insert-or-skip-quote 'delete-selection t) +(put 'autopair-extra-insert-opening 'delete-selection t) +(put 'autopair-extra-skip-close-maybe 'delete-selection t) +(put 'autopair-backspace 'delete-selection 'supersede) +(put 'autopair-newline 'delete-selection t) + +(defun autopair--should-autowrap () + (and autopair-mode + (not (eq this-command 'autopair-backspace)) + (symbolp this-command) + (string-match "^autopair" (symbol-name this-command)) + (autopair--calculate-wrap-action))) + +(defadvice cua--pre-command-handler-1 (around autopair-override activate) + "Don't actually do anything if autopair is about to autowrap. " + (unless (autopair--should-autowrap) ad-do-it)) + +(defadvice delete-selection-pre-hook (around autopair-override activate) + "Don't actually do anything if autopair is about to autowrap. " + (unless (autopair--should-autowrap) ad-do-it)) + +(provide 'autopair) + + +;; Local Variables: +;; coding: utf-8 +;; End: +;;; autopair.el ends here diff --git a/emacs/.emacs.d/master.zip b/emacs/.emacs.d/master.zip Binary files differ diff --git a/emacs/.emacs.d/multiple-cursors/.gitignore b/emacs/.emacs.d/multiple-cursors/.gitignore @@ -0,0 +1,2 @@ +elpa +*.elc diff --git a/emacs/.emacs.d/multiple-cursors/.travis.yml b/emacs/.emacs.d/multiple-cursors/.travis.yml @@ -0,0 +1,21 @@ +language: emacs-lisp +before_install: + - if [ "$EMACS" = 'emacs-snapshot' ]; then + sudo add-apt-repository -y ppa:cassou/emacs && + sudo apt-get update -qq && + sudo apt-get install -qq + emacs-snapshot-el emacs-snapshot-gtk emacs-snapshot; + fi + - if [ "$EMACS" = 'emacs24' ]; then + sudo add-apt-repository -y ppa:cassou/emacs && + sudo apt-get update -qq && + sudo apt-get install -qq + emacs24 emacs24-el emacs24-common-non-dfsg; + fi + - curl -fsSkL https://raw.github.com/cask/cask/master/go | python + - export PATH="/home/travis/.cask/bin:$PATH" + - cask +env: + - EMACS=emacs24 TAGS="" +script: + ./run-travis-ci.sh diff --git a/emacs/.emacs.d/multiple-cursors/Cask b/emacs/.emacs.d/multiple-cursors/Cask @@ -0,0 +1,9 @@ +(source gnu) +(source melpa) + +(package-file "multiple-cursors.el") + +(development + (depends-on "ecukes") + (depends-on "espuds") + (depends-on "wrap-region")) diff --git a/emacs/.emacs.d/multiple-cursors/README.md b/emacs/.emacs.d/multiple-cursors/README.md @@ -0,0 +1,199 @@ +# multiple-cursors.el [![Build Status](https://secure.travis-ci.org/magnars/multiple-cursors.el.png)](http://travis-ci.org/magnars/multiple-cursors.el) + +Multiple cursors for Emacs. This is some pretty crazy functionality, so yes, +there are kinks. Don't be afraid tho, I've been using it since 2011 with +great success and much merriment. + +## Basic usage + +Start out with: + + (require 'multiple-cursors) + +Then you have to set up your keybindings - multiple-cursors doesn't presume to +know how you'd like them laid out. Here are some examples: + +When you have an active region that spans multiple lines, the following will +add a cursor to each line: + + (global-set-key (kbd "C-S-c C-S-c") 'mc/edit-lines) + +When you want to add multiple cursors not based on continuous lines, but based on +keywords in the buffer, use: + + (global-set-key (kbd "C->") 'mc/mark-next-like-this) + (global-set-key (kbd "C-<") 'mc/mark-previous-like-this) + (global-set-key (kbd "C-c C-<") 'mc/mark-all-like-this) + +First mark the word, then add more cursors. + +To get out of multiple-cursors-mode, press `<return>` or `C-g`. The latter will +first disable multiple regions before disabling multiple cursors. If you want to +insert a newline in multiple-cursors-mode, use `C-j`. + +## Video + +You can [watch an intro to multiple-cursors at Emacs Rocks](http://emacsrocks.com/e13.html). + +## Command overview + +### Mark one more occurrence + + - `mc/mark-next-like-this`: Adds a cursor and region at the next part of the buffer forwards that matches the current region. + - `mc/mark-next-word-like-this`: Like `mc/mark-next-like-this` but only for whole words. + - `mc/mark-next-symbol-like-this`: Like `mc/mark-next-like-this` but only for whole symbols. + - `mc/mark-previous-like-this`: Adds a cursor and region at the next part of the buffer backwards that matches the current region. + - `mc/mark-previous-word-like-this`: Like `mc/mark-previous-like-this` but only for whole words. + - `mc/mark-previous-symbol-like-this`: Like `mc/mark-previous-like-this` but only for whole symbols. + - `mc/mark-more-like-this-extended`: Use arrow keys to quickly mark/skip next/previous occurances. + - `mc/add-cursor-on-click`: Bind to a mouse event to add cursors by clicking. See tips-section. + - `mc/mark-pop`: Set a cursor at the current point and move to the next (different) position on the mark stack. This allows for fine grained control over the placement of cursors. + +### Juggle around with the current cursors + + - `mc/unmark-next-like-this`: Remove the cursor furthest down in the buffer. + - `mc/unmark-previous-like-this`: Remove the cursor furthest up in the buffer. + - `mc/skip-to-next-like-this`: Remove the cursor furthest down, marking the next occurance down. + - `mc/skip-to-previous-like-this`: Remove the cursor furthest up, marking the next occurance up. + - `mc/mark-next-like-this-extended`: Temporarily bind the arrow keys to mark/unmark/skip cursors. + +### Mark many occurrences + + - `mc/edit-lines`: Adds one cursor to each line in the current region. + - `mc/edit-beginnings-of-lines`: Adds a cursor at the start of each line in the current region. + - `mc/edit-ends-of-lines`: Adds a cursor at the end of each line in the current region. + - `mc/mark-all-like-this`: Marks all parts of the buffer that matches the current region. + - `mc/mark-all-words-like-this`: Like `mc/mark-all-like-this` but only for whole words. + - `mc/mark-all-symbols-like-this`: Like `mc/mark-all-like-this` but only for whole symbols. + - `mc/mark-all-in-region`: Prompts for a string to match in the region, adding cursors to all of them. + - `mc/mark-all-like-this-in-defun`: Marks all parts of the current defun that matches the current region. + - `mc/mark-all-words-like-this-in-defun`: Like `mc/mark-all-like-this-in-defun` but only for whole words. + - `mc/mark-all-symbols-like-this-in-defun`: Like `mc/mark-all-like-this-in-defun` but only for whole symbols. + - `mc/mark-all-dwim`: Tries to be smart about marking everything you want. Can be pressed multiple times. + +### Special + + - `set-rectangular-region-anchor`: Think of this one as `set-mark` except you're marking a rectangular region. + - `mc/mark-sgml-tag-pair`: Mark the current opening and closing tag. + - `mc/insert-numbers`: Insert increasing numbers for each cursor, top to bottom. + - `mc/sort-regions`: Sort the marked regions alphabetically. + - `mc/reverse-regions`: Reverse the order of the marked regions. + +## Tips and tricks + +- To get out of multiple-cursors-mode, press `<return>` or `C-g`. The latter will + first disable multiple regions before disabling multiple cursors. If you want to + insert a newline in multiple-cursors-mode, use `C-j`. + +- Sometimes you end up with cursors outside of your view. You can + scroll the screen to center on each cursor with `C-v` and `M-v`. + +- Try pressing `mc/mark-next-like-this` with no region selected. It + will just add a cursor on the next line. + +- Try pressing `mc/mark-all-like-this-dwim` on a tagname in html-mode. + +- Notice that the number of cursors active can be seen in the modeline. + +- If you get out of multiple-cursors-mode and yank - it will yank only + from the kill-ring of main cursor. To yank from the kill-rings of + every cursor use yank-rectangle, normally found at C-x r y. + +- You can use `mc/reverse-regions` with nothing selected and just one cursor. + It will then flip the sexp at point and the one below it. + +- When you use `mc/edit-lines`, you can give it a positive or negative + prefix to change how it behaves on too short lines. + +- If you would like to keep the global bindings clean, and get custom keybindings + when the region is active, you can try [region-bindings-mode](https://github.com/fgallina/region-bindings-mode). + +BTW, I highly recommend adding `mc/mark-next-like-this` to a key binding that's +right next to the key for `er/expand-region`. + +### Binding mouse events + +To override a mouse event, you will likely have to also unbind the +`down-mouse` part of the event. Like this: + + (global-unset-key (kbd "M-<down-mouse-1>")) + (global-set-key (kbd "M-<mouse-1>") 'mc/add-cursor-on-click) + +Or you can do like me and find an unused, but less convenient, binding: + + (global-set-key (kbd "C-S-<mouse-1>") 'mc/add-cursor-on-click) + +## Unknown commands + +Multiple-cursors uses two lists of commands to know what to do: the run-once list +and the run-for-all list. It comes with a set of defaults, but it would be beyond silly +to try and include all the known Emacs commands. + +So that's why multiple-cursors occasionally asks what to do about a command. It will +then remember your choice by saving it in `~/.emacs.d/.mc-lists.el`. You can change +the location with: + + (setq mc/list-file "/my/preferred/file") + +NB! Make sure to do so before requiring multiple-cursors. + +## Known limitations + +* isearch-forward and isearch-backward aren't supported with multiple cursors. + If you want this functionality, you can use [phi-search](https://github.com/zk-phi/phi-search). +* Commands run with `M-x` won't be repeated for all cursors. +* All key bindings that refer to lambdas are always run for all cursors. If you + need to limit it, you will have to give it a name. +* Redo might screw with your cursors. Undo works very well. + + +## Contribute + +Yes, please do. There's a suite of tests, so remember to add tests for your +specific feature, or I might break it later. + +You'll find the repo at: + + https://github.com/magnars/multiple-cursors.el + +To fetch the test dependencies, install +[cask](https://github.com/rejeep/cask.el) if you haven't already, +then: + + $ cd /path/to/multiple-cursors + $ cask + +Run the tests with: + + $ ./run-tests.sh + +## Contributors + +* [Takafumi Arakaki](https://github.com/tkf) has contributed several small improvements +* [Marco Baringer](https://github.com/segv) contributed looping to `mc/cycle` and adding cursors without region for mark-more. +* [Ivan Andrus](https://github.com/gvol) added showing number of cursors in mode-line, and different options for how to handle short lines in `mc/edit-lines`. +* [Fuco](https://github.com/Fuco1) added the first version of `mc/mark-all-like-this-dwim` +* [Zach Kost-Smith](https://github.com/smithzvk) added `mc/mark-pop` +* [Maciej Katafiasz](https://github.com/mathrick) added `mc/mark-all-dwim` + +Thanks! + +## License + +Copyright (C) 2012 Magnar Sveen + +Author: Magnar Sveen <magnars@gmail.com> +Keywords: editing cursors + +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/>. diff --git a/emacs/.emacs.d/multiple-cursors/features/edit-lines.feature b/emacs/.emacs.d/multiple-cursors/features/edit-lines.feature @@ -0,0 +1,140 @@ +Feature: Switching from a multiline region to multiple cursors + + Scenario: Single line region + When I insert "hello there" + And I select "there" + And I press "C-S-c C-S-c" + Then I should have one cursor + + Scenario: Edit lines + When I insert: + """ + hello + there + """ + And I go to the front of the word "hello" + And I set the mark + And I go to the front of the word "there" + And I press "C-S-c C-S-c" + Then I should have 2 cursors + + Scenario: Edit lines from bottom up + When I insert: + """ + hello + there + """ + And I go to the front of the word "there" + And I set the mark + And I go to the front of the word "hello" + And I press "C-S-c C-S-c" + Then I should have one cursor + + Scenario: Edit only real lines, even in visual-line-mode + Given I turn on visual-line-mode + And I insert: + """ + some very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very + long text + """ + And I go to the front of the word "some" + And I set the mark + And I go to the front of the word "long" + And I press "C-S-c C-S-c" + Then I should have 2 cursors + + Scenario: Edit without using transient mark mode + Given I turn off transient-mark-mode + And I insert: + """ + hello + there + """ + And I go to the front of the word "hello" + And I set the mark + And I go to the front of the word "there" + And I press "C-S-c C-S-c" + Then I should have 2 cursors + + Scenario: Edit default short lines + When I insert: + """ + hello + + there + """ + And I go to the end of the word "hello" + And I set the mark + And I go to the end of the word "there" + And I press "C-S-c C-S-c" + And I press "you" + Then I should see: + """ + helloyou + you + thereyou + """ + + Scenario: Pad short lines + When I insert: + """ + hello + + there + """ + And I go to the end of the word "hello" + And I set the mark + And I go to the end of the word "there" + And I press "M-1 C-S-c C-S-c" + Then I should have 3 cursors + + Scenario: Edit padding short lines + When I insert: + """ + hello + + there + """ + And I go to the end of the word "hello" + And I set the mark + And I go to the end of the word "there" + And I press "M-1 C-S-c C-S-c" + And I press "you" + Then I should see: + """ + helloyou + you + thereyou + """ + + Scenario: Skip short lines + When I insert: + """ + hello + + there + """ + And I go to the end of the word "hello" + And I set the mark + And I go to the end of the word "there" + And I press "M-- M-1 C-S-c C-S-c" + Then I should have 2 cursors + + Scenario: Edit skipping short lines + When I insert: + """ + hello + + there + """ + And I go to the end of the word "hello" + And I set the mark + And I go to the end of the word "there" + And I press "M-- M-1 C-S-c C-S-c" + And I press "you" + Then I should see: + """ + helloyou + + thereyou + """ diff --git a/emacs/.emacs.d/multiple-cursors/features/insert-numbers.feature b/emacs/.emacs.d/multiple-cursors/features/insert-numbers.feature @@ -0,0 +1,13 @@ +Feature: Insert increasing numbers + + Scenario: Three cursors, 0-1-2 + Given I have cursors at "text" in "This text contains the word text thrice (text)" + When I press "H-0" + And I press "SPC" + Then I should see "This 0 text contains the word 1 text thrice (2 text)" + + Scenario: Three cursors, 9-10-11 + Given I have cursors at "text" in "This text contains the word text thrice (text)" + When I press "C-9 H-0" + And I press "SPC" + Then I should see "This 9 text contains the word 10 text thrice (11 text)" diff --git a/emacs/.emacs.d/multiple-cursors/features/mark-all-dwim-html.feature b/emacs/.emacs.d/multiple-cursors/features/mark-all-dwim-html.feature @@ -0,0 +1,94 @@ +Feature: Mark all do-what-I-mean (html) + + Background: + Given I turn on html-mode + And I turn on delete-selection-mode + And I insert: + """ + <body> + <div class="abc"> def </div> + <div class="ghi"> jkl </div> + </body> + """ + + Scenario: Marks tags in html-mode, from front + When I go to the front of the word "abc" + And I press "M-b" + And I press "M-b" + And I press "M-$" + And I type "h1" + Then I should see: + """ + <body> + <h1 class="abc"> def </h1> + <div class="ghi"> jkl </div> + </body> + """ + + Scenario: Marks tags in html-mode, from back + When I go to the end of the word "jkl" + And I press "M-f" + And I press "M-$" + And I type "h1" + Then I should see: + """ + <body> + <div class="abc"> def </div> + <h1 class="ghi"> jkl </h1> + </body> + """ + + Scenario: Marks tags in html-mode, from outside front + When I go to the front of the word "abc" + And I press "M-b" + And I press "M-b" + And I press "C-b" + And I press "M-$" + And I type "h1" + Then I should see: + """ + <body> + <h1 class="abc"> def </h1> + <div class="ghi"> jkl </div> + </body> + """ + + Scenario: Marks tags in html-mode, from outside back + When I go to the end of the word "jkl" + And I press "M-f" + And I press "C-f" + And I press "M-$" + And I type "h1" + Then I should see: + """ + <body> + <div class="abc"> def </div> + <h1 class="ghi"> jkl </h1> + </body> + """ + + Scenario: Marks words in html-mode + When I go to the front of the word "abc" + And I press "M-$" + And I type "def" + Then I should see: + """ + <body> + <div class="def"> def </div> + <div class="ghi"> jkl </div> + </body> + """ + + Scenario: Marks words in html-mode + When I go to the front of the word "abc" + And I press "M-$" + And I type "def" + And I press "M-$" + And I type "hah" + Then I should see: + """ + <body> + <div class="hah"> hah </div> + <div class="ghi"> jkl </div> + </body> + """ diff --git a/emacs/.emacs.d/multiple-cursors/features/mark-all-dwim.feature b/emacs/.emacs.d/multiple-cursors/features/mark-all-dwim.feature @@ -0,0 +1,90 @@ +Feature: Mark all do-what-I-mean + + Background: + Given I turn on emacs-lisp-mode + And I turn on delete-selection-mode + And I insert: + """ + (defun abc (ghi) (message ghi)) + (defun def (ghi) (message some-other-ghi)) + + """ + + Scenario: Mark symbols in defun + When I go to the end of the word "abc" + And I press "M-f" + And I press "M-$" + And I type "hmm" + Then I should see: + """ + (defun abc (hmm) (message hmm)) + (defun def (ghi) (message some-other-ghi)) + """ + When I press "C-g" + And I go to the front of the word "hmm" + And I press "C-$" + And I type "foo" + Then I should see: + """ + (defun abc (foo) (message foo)) + (defun def (ghi) (message some-other-ghi)) + """ + + Scenario: Mark all symbols by pressing twice + When I go to the end of the word "abc" + And I press "M-f" + And I press "M-$" + And I press "M-$" + And I type "hmm" + Then I should see: + """ + (defun abc (hmm) (message hmm)) + (defun def (hmm) (message some-other-hmm)) + """ + When I press "C-g" + And I press "M->" + And I insert: + """ + (defun def (hmm-hmm) (message hmm)) + """ + And I go to the front of the word "hmm" + And I press "C-$" + And I press "C-$" + And I type "humm" + Then I should see: + """ + (defun abc (humm) (message humm)) + (defun def (humm) (message some-other-humm)) + (defun def (humm-humm) (message humm)) + """ + + Scenario: Mark dwim from selection + When I press "M-<" + And I press "S-M->" + And I press "C-$ ghi RET" + And I type "xyz" + Then I should see: + """ + (defun abc (xyz) (message xyz)) + (defun def (xyz) (message some-other-xyz)) + """ + When I press "C-g" + And I go to the front of the word "xyz" + And I press "C-M-SPC" + And I press "C-$" + And I type "foo" + Then I should see: + """ + (defun abc (foo) (message foo)) + (defun def (xyz) (message some-other-xyz)) + """ + When I press "C-g" + And I press "M-<" + And I press "S-M->" + And I press "C-u C-$" + And I type ";;" + Then I should see: + """ + ;;(defun abc (foo) (message foo)) + ;;(defun def (xyz) (message some-other-xyz)) + """ diff --git a/emacs/.emacs.d/multiple-cursors/features/mark-more.feature b/emacs/.emacs.d/multiple-cursors/features/mark-more.feature @@ -0,0 +1,144 @@ +Feature: Marking multiple parts of the buffer + + Scenario: Marking next like this, cursors + When I insert "This text has the word text in it" + And I select "text" + And I press "C->" + Then I should have 2 cursors + + Scenario: Marking next like this, region + Given I turn on delete-selection-mode + When I insert "This text has the word text in it" + And I select "text" + And I press "C->" + And I type "sentence" + Then I should see "This sentence has the word sentence in it" + + Scenario: Skipping a mark + Given I turn on delete-selection-mode + When I insert "Here's text, text and text" + And I select "text" + And I press "C->" + And I press "C-0 C->" + And I type "more" + Then I should see "Here's more, text and more" + + Scenario: Removing last fake + When I insert "Here's text, text and text" + And I select "text" + And I press "C->" + And I press "C-- C->" + Then I should have one cursor + + Scenario: Removing furthest mark + Given I turn on delete-selection-mode + When I insert "Here's text, text and text" + And I select "text" + And I press "C->" + And I press "C->" + And I press "C-- C->" + And I type "more" + Then I should see "Here's more, more and text" + + Scenario: Marking prev like this, cursors + When I insert "This text has the word text in it" + And I select the last "text" + And I press "C-<" + Then I should have 2 cursors + + Scenario: Marking prev like this, region + Given I turn on delete-selection-mode + When I insert "This text has the word text in it" + And I select the last "text" + And I press "C-<" + And I type "sentence" + Then I should see "This sentence has the word sentence in it" + + Scenario: Skipping a prev mark + Given I turn on delete-selection-mode + When I insert "Here's text, text and text" + And I select the last "text" + And I press "C-<" + And I press "C-0 C-<" + And I type "more" + Then I should see "Here's more, text and more" + + Scenario: Removing first fake + When I insert "Here's text, text and text" + And I select the last "text" + And I press "C-<" + And I press "C-- C-<" + Then I should have one cursor + + Scenario: Removing first mark + Given I turn on delete-selection-mode + When I insert "Here's text, text and text" + And I select the last "text" + And I press "C-<" + And I press "C-<" + And I press "C-- C-<" + And I type "more" + Then I should see "Here's text, more and more" + + Scenario: Marking all + When I insert "Here's text, text and text" + And I select "text" + And I press "M-!" + Then I should have 3 cursors + + Scenario: Marking in region + Given I turn on delete-selection-mode + When I insert "Here's text, text and text" + And I select "text, text" + And I press "M-# text <return>" + And I type "more" + Then I should have 2 cursors + And I should see "Here's more, more and text" + + Scenario: Marking without an active region + When I insert: + """ + aaa + bbb + ccc + """ + And I go to the front of the word "bbb" + And I press "C->" + And I type "_" + Then I should have 2 cursors + And I should see: + """ + aaa + _bbb + _ccc + """ + + Scenario: Increasing number of cursors without an active region + When I insert: + """ + aaa + bbb + ccc + """ + And I go to the front of the word "bbb" + And I press "C->" + And I press "C-<" + And i press "C-f" + And I type "_" + Then I should have 3 cursors + And I should see: + """ + a_aa + b_bb + c_cc + """ + + Scenario: Multiple cursor with shift selection + When I insert "This text contains the word text twice" + And I go to the front of the word "text" + And I press "M-S-f" + And I press "C->" + And I press "C-f" + And I press "<deletechar>" + Then I should see "This text ontains the word text wice" + diff --git a/emacs/.emacs.d/multiple-cursors/features/mark-pop.feature b/emacs/.emacs.d/multiple-cursors/features/mark-pop.feature @@ -0,0 +1,88 @@ +Feature: Popping cursors off of the mark stack + + Scenario: Single pop + Given I turn off transient-mark-mode + And I insert: + """ + hello + there + """ + And I go to the front of the word "hello" + And I set the mark + And I go to the front of the word "there" + And I press "M-x mc/mark-pop" + Then I should have 2 cursors + + Scenario: Multiple pops + Given I turn off transient-mark-mode + And I insert: + """ + hello + there, my friend + """ + And I go to the front of the word "hello" + And I set the mark + And I go to the front of the word "my" + And I set the mark + And I go to the front of the word "friend" + And I press "M-x mc/mark-pop" + And I press "M-x mc/mark-pop" + Then I should have 3 cursors + + Scenario: Discard identical mark and point + Given I turn off transient-mark-mode + And I insert: + """ + hello + there, my friend + """ + And I go to the front of the word "hello" + And I set the mark + And I go to the front of the word "my" + And I set the mark + And I go to the front of the word "friend" + And I set the mark + And I press "M-x mc/mark-pop" + And I press "M-x mc/mark-pop" + Then I should have 3 cursors + + Scenario: Changing the text + Given I turn off transient-mark-mode + And I insert: + """ + hello + there, my friend + """ + And I go to the front of the word "hello" + And I set the mark + And I go to the front of the word "my" + And I set the mark + And I go to the front of the word "friend" + And I press "M-x mc/mark-pop" + And I press "M-x mc/mark-pop" + And I type "!" + Then I should see: + """ + !hello + there, !my !friend + """ + + Scenario: With transient-mark-mode + And I insert: + """ + hello + there, my friend + """ + And I go to the front of the word "hello" + And I press "C-@ C-@" + And I go to the front of the word "my" + And I press "C-@ C-@" + And I go to the front of the word "friend" + And I press "M-x mc/mark-pop" + And I press "M-x mc/mark-pop" + And I type "!" + Then I should see: + """ + !hello + there, !my !friend + """ diff --git a/emacs/.emacs.d/multiple-cursors/features/mark-things.feature b/emacs/.emacs.d/multiple-cursors/features/mark-things.feature @@ -0,0 +1,137 @@ +Feature: Mark things + + Scenario: Mark all symbols like this with select + Given I turn on emacs-lisp-mode + And I turn on delete-selection-mode + And I insert: + """ + (defun abc (ghi) (message ghi)) + (defun def (ghi) (message some-other-ghi)) + """ + When I select "ghi" + And I mark all symbols like this + And I type "hmm" + Then I should see: + """ + (defun abc (hmm) (message hmm)) + (defun def (hmm) (message some-other-ghi)) + """ + + Scenario: Mark all words like this with select + Given I turn on emacs-lisp-mode + And I turn on delete-selection-mode + And I insert: + """ + (defun abc (ghi) (message ghi)) + (defun def (ghi) (message some-other-ghi)) + """ + When I select "ghi" + And I mark all words like this + And I type "hmm" + Then I should see: + """ + (defun abc (hmm) (message hmm)) + (defun def (hmm) (message some-other-hmm)) + """ + + Scenario: Mark all symbols like this in defun with select + Given I turn on emacs-lisp-mode + And I turn on delete-selection-mode + And I insert: + """ + (defun abc (ghi) (message ghi)) + (defun def (ghi) (message some-other-ghi)) + """ + When I select "ghi" + And I mark all symbols like this in defun + And I type "hmm" + Then I should see: + """ + (defun abc (hmm) (message hmm)) + (defun def (ghi) (message some-other-ghi)) + """ + + Scenario: Mark all words like this in defun with select + Given I turn on emacs-lisp-mode + And I turn on delete-selection-mode + And I insert: + """ + (defun abc (ghi) (message ghi)) + (defun def (ghi) (message some-other-ghi)) + """ + When I select "ghi" + And I mark all words like this in defun + And I type "hmm" + Then I should see: + """ + (defun abc (hmm) (message hmm)) + (defun def (ghi) (message some-other-ghi)) + """ + + Scenario: Mark all symbols like this with no select + Given I turn on emacs-lisp-mode + And I turn on delete-selection-mode + And I insert: + """ + (defun abc (ghi) (message ghi)) + (defun def (ghi) (message some-other-ghi)) + """ + When I go to word "ghi" + And I mark all symbols like this + And I type "hmm" + Then I should see: + """ + (defun abc (hmm) (message hmm)) + (defun def (hmm) (message some-other-ghi)) + """ + + Scenario: Mark all words like this with no select + Given I turn on emacs-lisp-mode + And I turn on delete-selection-mode + And I insert: + """ + (defun abc (ghi) (message ghi)) + (defun def (ghi) (message some-other-ghi)) + """ + When I go to word "ghi" + And I mark all words like this + And I type "hmm" + Then I should see: + """ + (defun abc (hmm) (message hmm)) + (defun def (hmm) (message some-other-hmm)) + """ + + Scenario: Mark all symbols like this in defun with no select + Given I turn on emacs-lisp-mode + And I turn on delete-selection-mode + And I insert: + """ + (defun abc (ghi) (message ghi)) + (defun def (ghi) (message some-other-ghi)) + """ + When I go to word "ghi" + And I mark all symbols like this in defun + And I type "hmm" + Then I should see: + """ + (defun abc (hmm) (message hmm)) + (defun def (ghi) (message some-other-ghi)) + """ + + Scenario: Mark all words like this in defun with no select + Given I turn on emacs-lisp-mode + And I turn on delete-selection-mode + And I insert: + """ + (defun abc (ghi) (message ghi)) + (defun def (ghi) (message some-other-ghi)) + """ + When I go to word "ghi" + And I mark all words like this in defun + And I type "hmm" + Then I should see: + """ + (defun abc (hmm) (message hmm)) + (defun def (ghi) (message some-other-ghi)) + """ diff --git a/emacs/.emacs.d/multiple-cursors/features/multiple-cursors-core.feature b/emacs/.emacs.d/multiple-cursors/features/multiple-cursors-core.feature @@ -0,0 +1,188 @@ +Feature: Multiple cursors core + In order to make efficient changes + As an Emacs user with multiple-cursors + I want to change multiple parts of the buffer at once + + Scenario: Exiting multiple-cursors mode with return + Given I have cursors at "text" in "This text contains the word text twice" + And I press "<return>" + Then I should have one cursor + + Scenario: Exiting multiple-cursors mode with C-g + Given I have cursors at "text" in "This text contains the word text twice" + And I press "C-g" + Then I should have one cursor + + Scenario: Separate kill-rings + Given I have cursors at "text" in "This text contains the word text twice" + When I press "M-f" + And I press "M-d" + And I press "M-b" + And I press "C-y" + Then I should see "This containstext the word twicetext" + + Scenario: Separate kill-rings, yank-pop + Given I have cursors at "text" in "This text contains the word text twice" + When I press "M-d" + And I press "C-f" + And I press "M-d" + And I press "C-y M-y" + Then I should see "This text the word text" + + Scenario: Multiple lambdas + Given I have bound C-! to a lambda that inserts "a" + And I have cursors at "text" in "This text contains the word text twice" + When I press "C-!" + Then I should see "This atext contains the word atext twice" + + Scenario: Multiple supported command (forward-word in this case) + Given I have cursors at "text" in "This text contains the word text twice" + And I type "(" + And I press "M-f" + And I press "M-f" + And I type ")" + Then I should see "This (text contains) the word (text twice)" + + Scenario: Unknown command: yes, do for all + Given I have bound C-! to a new command that inserts "a" + And I have cursors at "text" in "This text contains the word text twice" + When I press "C-! y" + And I press "C-!" + Then I should see "This aatext contains the word aatext twice" + + Scenario: Unknown command: no, don't do for all + Given I have bound C-! to another new command that inserts "a" + And I have cursors at "text" in "This text contains the word text twice" + When I press "C-! n" + And I press "C-!" + Then I should see "This aatext contains the word text twice" + + Scenario: Undo + Given I have cursors at "text" in "This text contains the word text twice" + When I press "M-f" + And I press "M-DEL" + And I press "C-_" + And I type "!" + Then I should see "This text! contains the word text! twice" + + Scenario: Setting and popping mark + Given I have cursors at "text" in "This text contains the word text twice" + And I press "C-SPC" + And I press "M-f" + And I press "C-u C-SPC" + And I type "!" + Then I should see "This !text contains the word !text twice" + + Scenario: delete-selection-mode (self-insert-command) + Given I turn on delete-selection-mode + And I have cursors at "text" in "This text contains the word text twice" + And I press "C-SPC" + And I press "M-f" + And I type "!" + Then I should see "This ! contains the word ! twice" + + Scenario: delete-selection-mode (delete-char) + Given I turn on delete-selection-mode + And I have cursors at "text" in "This text contains the word text twice" + And I press "C-SPC" + And I press "M-f" + And I press "C-d" + Then I should see "This contains the word twice" + + Scenario: delete-selection-mode (yank) + Given I turn on delete-selection-mode + And I have cursors at "text" in "This text contains the word text twice" + And I press "M-b" + And I press "C-SPC" + And I press "M-f" + And I press "M-w" + And I press "C-SPC" + And I press "M-f" + And I press "C-y" + Then I should see "ThisThis contains the wordword twice" + + Scenario: subword-mode + Given I turn on subword-mode + And I have cursors at "textSnippet" in "This textSnippet contains the word textSnippet twice" + And I press "M-f" + And I type "_" + And I press "M-l" + Then I should see "This text_snippet contains the word text_snippet twice" + + Scenario: cua-mode + Given I turn on cua-mode + And I insert "This text contains the word text twice" + And I go to the front of the word "text" + And I press "C-SPC" + And I press "M-f" + And I mark next like this + And I type "!" + Then I should see "This ! contains the word ! twice" + + Scenario: wrap-region (function turns to keyboard macros) + Given I turn on wrap-region-mode + And I insert "This text contains the word text twice" + And I go to the front of the word "text" + And I press "C-M-SPC" + And I mark next like this + And I press "C-g" + And I type "(" + Then I should see "This (text contains the word (text twice" + + Scenario: Bound keyboard macros + Given I have bound C-! to a keyboard macro that insert "_" + And I have cursors at "text" in "This text contains the word text twice" + When I press "C-!" + When I press "C-!" + Then I should see "This __text contains the word __text twice" + + Scenario: Interprogram paste + Given I have cursors at "text" in "This text contains the word text twice" + When I copy "external" in another program + And I press "C-y" + Then I should see "This externaltext contains the word externaltext twice" + + Scenario: Added to killed-rectangle after exiting multiple-cursors-mode + Given I have cursors at "text" in "This text contains the word text twice" + When I press "M-f" + And I press "C-f" + And I press "C-SPC" + And I press "M-f" + And I press "M-w" + And I press "<return>" + And I press "C-a" + And I press "C-k" + And I press "C-x r y" + Then I should see: + """ + contains + twice + """ + + Scenario: Looping forwards around cursors + Given I have cursors at "_" in "1_34567_9" + And I press "C-v" + And I press "C-v" + And I press "C-v" + Then the cursor should be at point "8" + + Scenario: Looping forwards around cursors including one at point-max + Given I have cursors at "_" in "1_34_67_" + And I press "C-f" + And I press "C-v" + And I press "C-v" + And I press "C-v" + Then the cursor should be at point "3" + + Scenario: Looping backwards around cursors + Given I have cursors at "_" in "1_34567_9" + And I press "M-v" + And I press "M-v" + Then the cursor should be at point "2" + + Scenario: Looping backwards around cursors including one at point-min + Given I have cursors at "_" in "_234_67_9" + And I press "M-v" + And I press "M-v" + And I press "M-v" + Then the cursor should be at point "1" diff --git a/emacs/.emacs.d/multiple-cursors/features/rectangular-region.feature b/emacs/.emacs.d/multiple-cursors/features/rectangular-region.feature @@ -0,0 +1,73 @@ +Feature: Rectangular region + + Scenario: Works like regular region when on one line + When I insert "some text" + And I press "H-SPC" + And I press "M-b" + Then the region should be "text" + And rectangular-region-mode should be on + + Scenario: Works like regular region when on one line, insert + Given I turn on delete-selection-mode + When I insert "some text" + And I press "H-SPC" + And I press "M-b" + And I type "replacement" + Then I should see "some replacement" + And rectangular-region-mode should be off + + Scenario: Works like regular region when on one line, copy 1 + Given I turn on delete-selection-mode + When I insert "some text" + And I press "H-SPC" + And I press "M-b" + And I press "M-w" + Then rectangular-region-mode should be off + + Scenario: Works like regular region when on one line, copy 2 + Given I turn on delete-selection-mode + When I insert "some text" + And I press "H-SPC" + And I press "M-b" + And I press "M-w" + And I press "C-y" + Then I should see "some texttext" + + Scenario: Changing multiple lines + Given I turn on delete-selection-mode + When I insert: + """ + This is some text + This is more text + """ + And I go to point "6" + And I press "H-SPC" + And I press "M-f" + And I press "C-n" + And I type "was" + Then I should see: + """ + This was some text + This was more text + """ + And I should have 2 cursors + + Scenario: Changing multiple lines with gaps + Given I turn on delete-selection-mode + When I insert: + """ + This is some text + + This is more text + """ + And I go to point "6" + And I press "H-SPC" + And I go to the end of the word "more" + And I type "was" + Then I should see: + """ + This was text + + This was text + """ + And I should have 2 cursors diff --git a/emacs/.emacs.d/multiple-cursors/features/sort-and-reverse.feature b/emacs/.emacs.d/multiple-cursors/features/sort-and-reverse.feature @@ -0,0 +1,19 @@ +Feature: Sorting and reversing cursor regions + + Scenario: Reversing regions + Given I have cursors at "text" in "This text contains the word text thrice (text here)" + When I press "M-f" + And I press "C-f" + And I press "C-SPC" + And I press "M-f" + And I press "H-1" + Then I should see "This text here the word text thrice (text contains)" + + Scenario: Sorting regions + Given I have cursors at "text" in "This text contains the word text thrice (text here)" + When I press "M-f" + And I press "C-f" + And I press "C-SPC" + And I press "M-f" + And I press "H-2" + Then I should see "This text contains the word text here (text thrice)" diff --git a/emacs/.emacs.d/multiple-cursors/features/step-definitions/multiple-cursors-steps.el b/emacs/.emacs.d/multiple-cursors/features/step-definitions/multiple-cursors-steps.el @@ -0,0 +1,139 @@ +(When "^I mark next like this$" + (lambda () (call-interactively 'mc/mark-next-like-this))) + +(When "^I mark previous like this$" + (lambda () (call-interactively 'mc/mark-previous-like-this))) + +(When "^I mark all like this$" + (lambda () (call-interactively 'mc/mark-all-like-this))) + +(When "^I mark all like this dwim$" + (lambda () (call-interactively 'mc/mark-all-like-this-dwim))) + +(When "^I mark all in region$" + (lambda () (call-interactively 'mc/mark-all-in-region))) + +(When "^I insert numbers$" + (lambda () (call-interactively 'mc/insert-numbers))) + +(When "^I reverse regions$" + (lambda () (call-interactively 'mc/reverse-regions))) + +(When "^I sort regions$" + (lambda () (call-interactively 'mc/sort-regions))) + +(When "^I edit lines$" + (lambda () (call-interactively 'mc/edit-lines))) + +(When "^I set rectangular region anchor$" + (lambda () (call-interactively 'set-rectangular-region-anchor))) + +(And "^delete-selection-mode is active$" + (lambda () + (delete-selection-mode 1))) + +(Given "^I turn off transient-mark-mode$" + (lambda () + (transient-mark-mode -1))) + +(Then "^I should have \\([0-9]+\\) cursors$" + (lambda (num) + (let ((actual (mc/num-cursors))) + (assert (eq (string-to-number num) actual) nil + "Expected to have %s cursors, but was %d." num actual)))) + +(Then "^I should have one cursor$" + (lambda () + (assert (not multiple-cursors-mode) nil + "Expected to have one cursor, but multiple-cursors-mode is still active.") + (assert (eq 1 (mc/num-cursors)) nil + "Expected to have one cursor, but there are still fake cursor overlays."))) + +(Then "^rectangular-region-mode should be off$" + (lambda () + (assert (not rectangular-region-mode) nil + "Expected rectangular-region-mode mode to be off, but wasn't."))) + +(Then "^rectangular-region-mode should be on$" + (lambda () + (assert rectangular-region-mode nil + "Expected rectangular-region-mode mode to be on, but wasn't."))) + +(When "^I press \"\\(.+\\)\"$" + (lambda (keybinding) + (let ((macro (edmacro-parse-keys keybinding))) + (if espuds-chain-active + (setq espuds-action-chain (vconcat espuds-action-chain macro)) + (if (and (equal keybinding "C-g") + (eq (key-binding (kbd "C-g")) 'keyboard-quit)) + (espuds-quit) + (execute-kbd-macro macro)))))) + +(Given "^I have cursors at \"\\(.+\\)\" in \"\\(.+\\)\"$" + (lambda (needle haystack) + (insert haystack) + (goto-char (point-min)) + (search-forward needle) + (set-mark (point)) + (goto-char (match-beginning 0)) + (mc/mark-all-like-this) + (mc/keyboard-quit))) + +(When "^I copy \"\\(.+\\)\" in another program$" + (lambda (text) + (lexical-let ((text text)) + (setq interprogram-paste-function + #'(lambda () (let ((r text)) (setq text nil) r)))))) + +(Given "^I have bound C-! to a lambda that inserts \"\\(.+\\)\"$" + (lambda (ins) + (lexical-let ((ins ins)) + (global-set-key (kbd "C-!") #'(lambda () (interactive) (insert ins)))))) + +(Given "^I have bound C-! to a new command that inserts \"\\(.+\\)\"$" + (lambda (ins) + (lexical-let ((ins ins)) + (defun mc-test-temp-command () (interactive) (insert ins)) + (global-set-key (kbd "C-!") 'mc-test-temp-command)))) + +(Given "^I have bound C-! to another new command that inserts \"\\(.+\\)\"$" + (lambda (ins) + (lexical-let ((ins ins)) + (defun mc-test-temp-command-2 () (interactive) (insert ins)) + (global-set-key (kbd "C-!") 'mc-test-temp-command-2)))) + +(Given "^I have bound C-! to a keyboard macro that insert \"_\"$" + (lambda () + (fset 'mc-test-temp-kmacro "\C-q_") + (global-set-key (kbd "C-!") 'mc-test-temp-kmacro))) + +(When "^I go to character \"\\(.+\\)\"$" + (lambda (char) + (goto-char (point-min)) + (let ((search (re-search-forward (format "%s" char) nil t)) + (message "Can not go to character '%s' since it does not exist in the current buffer: %s")) + (assert search nil message char (espuds-buffer-contents))))) + +(When "^I go to the \\(front\\|end\\) of the word \"\\(.+\\)\"$" + (lambda (pos word) + (goto-char (point-min)) + (let ((search (re-search-forward (format "%s" word) nil t)) + (message "Can not go to character '%s' since it does not exist in the current buffer: %s")) + (assert search nil message word (espuds-buffer-contents)) + (if (string-equal "front" pos) (backward-word))))) + +(When "^I select the last \"\\(.+\\)\"$" + (lambda (text) + (goto-char (point-max)) + (let ((search (re-search-backward text nil t))) + (assert search nil "The text '%s' was not found in the current buffer." text)) + (set-mark (point)) + (re-search-forward text))) + +(When "^I mark all \\(.+\\)$" + (lambda (rest) + (let ((func (intern (mapconcat 'identity + (cons "mc/mark-all" + (split-string rest)) + "-")))) + (call-interactively func)))) diff --git a/emacs/.emacs.d/multiple-cursors/features/support/env.el b/emacs/.emacs.d/multiple-cursors/features/support/env.el @@ -0,0 +1,45 @@ +(let* ((current-directory (file-name-directory load-file-name)) + (features-directory (expand-file-name ".." current-directory)) + (project-directory (expand-file-name ".." features-directory))) + (setq multiple-cursors-root-path project-directory) + (setq multiple-cursors-util-path (expand-file-name "util" project-directory))) + +(add-to-list 'load-path multiple-cursors-root-path) +(add-to-list 'load-path multiple-cursors-util-path) +(add-to-list 'load-path (expand-file-name "espuds" multiple-cursors-util-path)) +(add-to-list 'load-path (expand-file-name "vendor" multiple-cursors-util-path)) + +(require 'multiple-cursors) +(require 'espuds) +(require 'ert) +(require 'wrap-region) + +(defun mc/save-lists ()) ;; redefine to do nothing when running tests + +(Before + (cua-mode 0) + (multiple-cursors-mode 0) + (rectangular-region-mode 0) + (global-set-key (kbd "C->") 'mc/mark-next-like-this) + (global-set-key (kbd "C-<") 'mc/mark-previous-like-this) + (global-set-key (kbd "M-!") 'mc/mark-all-like-this) + (global-set-key (kbd "M-$") 'mc/mark-all-like-this-dwim) + (global-set-key (kbd "C-$") 'mc/mark-all-dwim) + (global-set-key (kbd "M-#") 'mc/mark-all-in-region) + (global-set-key (kbd "H-0") 'mc/insert-numbers) + (global-set-key (kbd "H-1") 'mc/reverse-regions) + (global-set-key (kbd "H-2") 'mc/sort-regions) + (global-set-key (kbd "C-S-c C-S-c") 'mc/edit-lines) + (global-set-key (kbd "H-SPC") 'set-rectangular-region-anchor) + (switch-to-buffer + (get-buffer-create "*multiple-cursors*")) + (erase-buffer) + (transient-mark-mode 1) + (cua-mode 0) + (delete-selection-mode 0) + (subword-mode 0) + (wrap-region-mode 0) + (setq set-mark-default-inactive nil) + (deactivate-mark)) + +(After) diff --git a/emacs/.emacs.d/multiple-cursors/mc-cycle-cursors.el b/emacs/.emacs.d/multiple-cursors/mc-cycle-cursors.el @@ -0,0 +1,122 @@ +;;; mc-cycle-cursors.el + +;; Copyright (C) 2012 Magnar Sveen + +;; Author: Magnar Sveen <magnars@gmail.com> +;; Keywords: editing cursors + +;; 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 scrolls the buffer to center each cursor in turn. +;; Scroll down with C-v, scroll up with M-v +;; This is nice when you have cursors that's outside of your view. + +;;; Code: + +(require 'multiple-cursors-core) + +(eval-when-compile (require 'cl)) + +(defun mc/next-fake-cursor-after-point () + (let ((pos (point)) + (next-pos (1+ (point-max))) + next) + (mc/for-each-fake-cursor + (let ((cursor-pos (overlay-get cursor 'point))) + (when (and (< pos cursor-pos) + (< cursor-pos next-pos)) + (setq next-pos cursor-pos) + (setq next cursor)))) + next)) + +(defun mc/prev-fake-cursor-before-point () + (let ((pos (point)) + (prev-pos (1- (point-min))) + prev) + (mc/for-each-fake-cursor + (let ((cursor-pos (overlay-get cursor 'point))) + (when (and (> pos cursor-pos) + (> cursor-pos prev-pos)) + (setq prev-pos cursor-pos) + (setq prev cursor)))) + prev)) + +(defcustom mc/cycle-looping-behaviour 'continue + "What to do if asked to cycle beyond the last cursor or before the first cursor." + :type '(radio (const :tag "Loop around to beginning/end of document." continue) + (const :tag "Warn and then loop around." warn) + (const :tag "Signal an error." error) + (const :tag "Don't loop." stop)) + :group 'multiple-cursors) + +(defun mc/handle-loop-condition (error-message) + (ecase mc/cycle-looping-behaviour + (error (error error-message)) + (warn (message error-message)) + (continue 'continue) + (stop 'stop))) + +(defun mc/first-fake-cursor-after (point) + "Very similar to mc/furthest-cursor-before-point, but ignores (mark) and (point)." + (let* ((cursors (mc/all-fake-cursors)) + (cursors-after-point (remove-if (lambda (cursor) + (< (mc/cursor-beg cursor) point)) + cursors)) + (cursors-in-order (sort* cursors-after-point '< :key 'mc/cursor-beg))) + (first cursors-in-order))) + +(defun mc/last-fake-cursor-before (point) + "Very similar to mc/furthest-cursor-before-point, but ignores (mark) and (point)." + (let* ((cursors (mc/all-fake-cursors)) + (cursors-before-point (remove-if (lambda (cursor) + (> (mc/cursor-end cursor) point)) + cursors)) + (cursors-in-order (sort* cursors-before-point '> :key 'mc/cursor-end))) + (first cursors-in-order))) + +(defun* mc/cycle (next-cursor fallback-cursor loop-message) + (when (null next-cursor) + (when (eql 'stop (mc/handle-loop-condition loop-message)) + (return-from mc/cycle nil)) + (setf next-cursor fallback-cursor)) + (mc/create-fake-cursor-at-point) + (mc/pop-state-from-overlay next-cursor) + (recenter)) + +(defun mc/cycle-forward () + (interactive) + (mc/cycle (mc/next-fake-cursor-after-point) + (mc/first-fake-cursor-after (point-min)) + "We're already at the last cursor.")) + +(defun mc/cycle-backward () + (interactive) + (mc/cycle (mc/prev-fake-cursor-before-point) + (mc/last-fake-cursor-before (point-max)) + "We're already at the last cursor")) + +(define-key mc/keymap (kbd "C-v") 'mc/cycle-forward) +(define-key mc/keymap (kbd "M-v") 'mc/cycle-backward) + +(provide 'mc-cycle-cursors) + + +;; Local Variables: +;; coding: utf-8 +;; byte-compile-warnings: (not cl-functions) +;; End: + +;;; mc-cycle-cursors.el ends here diff --git a/emacs/.emacs.d/multiple-cursors/mc-edit-lines.el b/emacs/.emacs.d/multiple-cursors/mc-edit-lines.el @@ -0,0 +1,110 @@ +;;; mc-edit-lines.el + +;; Copyright (C) 2012 Magnar Sveen + +;; Author: Magnar Sveen <magnars@gmail.com> +;; Keywords: editing cursors + +;; 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 contains functions to add multiple cursors to consecutive lines +;; given an active region. + +;; Please see multiple-cursors.el for more commentary. + +;;; Code: + +(require 'multiple-cursors-core) + +(defcustom mc/edit-lines-empty-lines nil + "What should be done by `mc/edit-lines' when a line is not long enough." + :type '(radio (const :tag "Pad the line with spaces." pad) + (const :tag "Ignore the line." ignore) + (const :tag "Signal an error." error) + (const :tag "Nothing. Cursor is at end of line." nil)) + :group 'multiple-cursors) + +;;;###autoload +(defun mc/edit-lines (&optional arg) + "Add one cursor to each line of the active region. +Starts from mark and moves in straight down or up towards the +line point is on. + +What is done with lines which are not long enough is governed by +`mc/edit-lines-empty-lines'. The prefix argument ARG can be used +to override this. If ARG is a symbol (when called from Lisp), +that symbol is used instead of `mc/edit-lines-empty-lines'. +Otherwise, if ARG negative, short lines will be ignored. Any +other non-nil value will cause short lines to be padded." + (interactive "P") + (when (not (and mark-active (/= (point) (mark)))) + (error "Mark a set of lines first")) + (mc/remove-fake-cursors) + (let* ((col (current-column)) + (point-line (line-number-at-pos)) + (mark-line (progn (exchange-point-and-mark) (line-number-at-pos))) + (direction (if (< point-line mark-line) :up :down)) + (style (cond + ;; called from lisp + ((and arg (symbolp arg)) + arg) + ;; negative argument + ((< (prefix-numeric-value arg) 0) + 'ignore) + (arg 'pad) + (t mc/edit-lines-empty-lines)))) + (deactivate-mark) + (when (and (eq direction :up) (bolp)) + (previous-logical-line 1 nil) + (move-to-column col)) + ;; Add the cursors + (while (not (eq (line-number-at-pos) point-line)) + ;; Pad the line + (when (eq style 'pad) + (while (< (current-column) col) + (insert " "))) + ;; Error + (when (and (eq style 'error) + (not (equal col (current-column)))) + (error "Short line encountered in `mc/edit-lines'")) + ;; create the cursor + (unless (and (eq style 'ignore) + (not (equal col (current-column)))) + (mc/create-fake-cursor-at-point)) + ;; proceed to next + (if (eq direction :up) + (previous-logical-line 1 nil) + (next-logical-line 1 nil)) + (move-to-column col)) + (multiple-cursors-mode))) + +;;;###autoload +(defun mc/edit-ends-of-lines () + "Add one cursor to the end of each line in the active region." + (interactive) + (mc/edit-lines) + (mc/execute-command-for-all-cursors 'end-of-line)) + +;;;###autoload +(defun mc/edit-beginnings-of-lines () + "Add one cursor to the beginning of each line in the active region." + (interactive) + (mc/edit-lines) + (mc/execute-command-for-all-cursors 'beginning-of-line)) + +(provide 'mc-edit-lines) + +;;; mc-edit-lines.el ends here diff --git a/emacs/.emacs.d/multiple-cursors/mc-mark-more.el b/emacs/.emacs.d/multiple-cursors/mc-mark-more.el @@ -0,0 +1,561 @@ +;;; mc-mark-more.el + +;; Copyright (C) 2012 Magnar Sveen + +;; Author: Magnar Sveen <magnars@gmail.com> +;; Keywords: editing cursors + +;; 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 contains functions to mark more parts of the buffer. +;; See ./features/mark-more.feature for examples. + +;; Please see multiple-cursors.el for more commentary. + +;;; Code: + +(require 'multiple-cursors-core) +(require 'thingatpt) + +(defun mc/cursor-end (cursor) + (if (overlay-get cursor 'mark-active) + (max (overlay-get cursor 'point) + (overlay-get cursor 'mark)) + (overlay-get cursor 'point))) + +(defun mc/cursor-beg (cursor) + (if (overlay-get cursor 'mark-active) + (min (overlay-get cursor 'point) + (overlay-get cursor 'mark)) + (overlay-get cursor 'point))) + +(defun mc/furthest-region-end () + (let ((end (max (mark) (point)))) + (mc/for-each-fake-cursor + (setq end (max end (mc/cursor-end cursor)))) + end)) + +(defun mc/first-region-start () + (let ((beg (min (mark) (point)))) + (mc/for-each-fake-cursor + (setq beg (min beg (mc/cursor-beg cursor)))) + beg)) + +(defun mc/furthest-cursor-before-point () + (let ((beg (min (mark) (point))) + furthest) + (mc/for-each-fake-cursor + (when (< (mc/cursor-beg cursor) beg) + (setq beg (mc/cursor-beg cursor)) + (setq furthest cursor))) + furthest)) + +(defun mc/furthest-cursor-after-point () + (let ((end (max (mark) (point))) + furthest) + (mc/for-each-fake-cursor + (when (> (mc/cursor-end cursor) end) + (setq end (mc/cursor-end cursor)) + (setq furthest cursor))) + furthest)) + +(defun mc/region-strings () + (let ((strings (list (buffer-substring-no-properties (point) (mark))))) + (mc/for-each-fake-cursor + (add-to-list 'strings (buffer-substring-no-properties + (mc/cursor-beg cursor) + (mc/cursor-end cursor)))) + strings)) + +(defvar mc/enclose-search-term nil + "How should mc/mark-more-* search for more matches? + +Match everything: nil +Match only whole words: 'words +Match only whole symbols: 'symbols + +Use like case-fold-search, don't recommend setting it globally.") + +(defun mc/mark-more-like-this (skip-last direction) + (let ((case-fold-search nil) + (re (regexp-opt (mc/region-strings) mc/enclose-search-term)) + (point-out-of-order (ecase direction + (forwards (< (point) (mark))) + (backwards (not (< (point) (mark)))))) + (furthest-cursor (ecase direction + (forwards (mc/furthest-cursor-after-point)) + (backwards (mc/furthest-cursor-before-point)))) + (start-char (ecase direction + (forwards (mc/furthest-region-end)) + (backwards (mc/first-region-start)))) + (search-function (ecase direction + (forwards 'search-forward-regexp) + (backwards 'search-backward-regexp))) + (match-point-getter (ecase direction + (forwards 'match-beginning) + (backwards 'match-end)))) + (if (and skip-last (not furthest-cursor)) + (error "No cursors to be skipped") + (mc/save-excursion + (goto-char start-char) + (when skip-last + (mc/remove-fake-cursor furthest-cursor)) + (if (funcall search-function re nil t) + (progn + (push-mark (funcall match-point-getter 0)) + (when point-out-of-order + (exchange-point-and-mark)) + (mc/create-fake-cursor-at-point)) + (error "no more matches found.")))))) + +;;;###autoload +(defun mc/mark-next-like-this (arg) + "Find and mark the next part of the buffer matching the currently active region +With negative ARG, delete the last one instead. +With zero ARG, skip the last one and mark next." + (interactive "p") + (if (region-active-p) + (if (< arg 0) + (let ((cursor (mc/furthest-cursor-after-point))) + (if cursor + (mc/remove-fake-cursor cursor) + (error "No cursors to be unmarked"))) + (mc/mark-more-like-this (= arg 0) 'forwards)) + (mc/mark-lines arg 'forwards)) + (mc/maybe-multiple-cursors-mode)) + +;;;###autoload +(defun mc/mark-next-word-like-this (arg) + (interactive "p") + (let ((mc/enclose-search-term 'words)) + (mc/mark-next-like-this arg))) + +;;;###autoload +(defun mc/mark-next-symbol-like-this (arg) + (interactive "p") + (let ((mc/enclose-search-term 'symbols)) + (mc/mark-next-like-this arg))) + +;;;###autoload +(defun mc/mark-previous-like-this (arg) + "Find and mark the previous part of the buffer matching the currently active region +With negative ARG, delete the last one instead. +With zero ARG, skip the last one and mark next." + (interactive "p") + (if (region-active-p) + (if (< arg 0) + (let ((cursor (mc/furthest-cursor-before-point))) + (if cursor + (mc/remove-fake-cursor cursor) + (error "No cursors to be unmarked"))) + (mc/mark-more-like-this (= arg 0) 'backwards)) + (mc/mark-lines arg 'backwards)) + (mc/maybe-multiple-cursors-mode)) + +;;;###autoload +(defun mc/mark-previous-word-like-this (arg) + (interactive "p") + (let ((mc/enclose-search-term 'words)) + (mc/mark-previous-like-this arg))) + +;;;###autoload +(defun mc/mark-previous-symbol-like-this (arg) + (interactive "p") + (let ((mc/enclose-search-term 'symbols)) + (mc/mark-previous-like-this arg))) + +(defun mc/mark-lines (num-lines direction) + (dotimes (i num-lines) + (mc/create-fake-cursor-at-point) + (ecase direction + (forwards (loop do (next-logical-line 1 nil) + while (mc/all-fake-cursors (point) (1+ (point))))) + (backwards (loop do (previous-logical-line 1 nil) + while (mc/all-fake-cursors (point) (1+ (point)))))))) + +;;;###autoload +(defun mc/mark-next-lines (arg) + (interactive "p") + (mc/mark-lines arg 'forwards) + (mc/maybe-multiple-cursors-mode)) + +;;;###autoload +(defun mc/mark-previous-lines (arg) + (interactive "p") + (mc/mark-lines arg 'backwards) + (mc/maybe-multiple-cursors-mode)) + +;;;###autoload +(defun mc/unmark-next-like-this () + "Deselect next part of the buffer matching the currently active region." + (interactive) + (mc/mark-next-like-this -1)) + +;;;###autoload +(defun mc/unmark-previous-like-this () + "Deselect prev part of the buffer matching the currently active region." + (interactive) + (mc/mark-previous-like-this -1)) + +;;;###autoload +(defun mc/skip-to-next-like-this () + "Skip the current one and select the next part of the buffer matching the currently active region." + (interactive) + (mc/mark-next-like-this 0)) + +;;;###autoload +(defun mc/skip-to-previous-like-this () + "Skip the current one and select the prev part of the buffer matching the currently active region." + (interactive) + (mc/mark-previous-like-this 0)) + +;;;###autoload +(defun mc/mark-all-like-this () + "Find and mark all the parts of the buffer matching the currently active region" + (interactive) + (unless (region-active-p) + (error "Mark a region to match first.")) + (mc/remove-fake-cursors) + (let ((master (point)) + (case-fold-search nil) + (point-first (< (point) (mark))) + (re (regexp-opt (mc/region-strings) mc/enclose-search-term))) + (mc/save-excursion + (goto-char 0) + (while (search-forward-regexp re nil t) + (push-mark (match-beginning 0)) + (when point-first (exchange-point-and-mark)) + (unless (= master (point)) + (mc/create-fake-cursor-at-point)) + (when point-first (exchange-point-and-mark))))) + (if (> (mc/num-cursors) 1) + (multiple-cursors-mode 1) + (multiple-cursors-mode 0))) + +(defun mc--select-thing-at-point (thing) + (let ((bound (bounds-of-thing-at-point thing))) + (when bound + (set-mark (car bound)) + (goto-char (cdr bound)) + bound))) + +(defun mc--select-thing-at-point-or-bark (thing) + (unless (or (region-active-p) (mc--select-thing-at-point thing)) + (error "Mark a region or set cursor on a %s." thing))) + +;;;###autoload +(defun mc/mark-all-words-like-this () + (interactive) + (mc--select-thing-at-point-or-bark 'word) + (let ((mc/enclose-search-term 'words)) + (mc/mark-all-like-this))) + +;;;###autoload +(defun mc/mark-all-symbols-like-this () + (interactive) + (mc--select-thing-at-point-or-bark 'symbol) + (let ((mc/enclose-search-term 'symbols)) + (mc/mark-all-like-this))) + +;;;###autoload +(defun mc/mark-all-in-region (beg end) + "Find and mark all the parts in the region matching the given search" + (interactive "r") + (let ((search (read-from-minibuffer "Mark all in region: ")) + (case-fold-search nil)) + (if (string= search "") + (message "Mark aborted") + (progn + (mc/remove-fake-cursors) + (goto-char beg) + (while (search-forward search end t) + (push-mark (match-beginning 0)) + (mc/create-fake-cursor-at-point)) + (let ((first (mc/furthest-cursor-before-point))) + (if (not first) + (error "Search failed for %S" search) + (mc/pop-state-from-overlay first))) + (if (> (mc/num-cursors) 1) + (multiple-cursors-mode 1) + (multiple-cursors-mode 0)))))) + +(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)))) + +;;;###autoload +(defun mc/mark-more-like-this-extended () + "Like mark-more-like-this, but then lets you adjust with arrows key. +The adjustments work like this: + + <up> Mark previous like this and set direction to 'up + <down> Mark next like this and set direction to 'down + +If direction is 'up: + + <left> Skip past the cursor furthest up + <right> Remove the cursor furthest up + +If direction is 'down: + + <left> Remove the cursor furthest down + <right> Skip past the cursor furthest down + +The bindings for these commands can be changed. See `mc/mark-more-like-this-extended-keymap'." + (interactive) + (mc/mmlte--down) + (set-temporary-overlay-map mc/mark-more-like-this-extended-keymap t)) + +(defvar mc/mark-more-like-this-extended-direction nil + "When using mc/mark-more-like-this-extended are we working on the next or previous cursors?") + +(make-variable-buffer-local 'mc/mark-more-like-this-extended) + +(defun mc/mmlte--message () + (if (eq mc/mark-more-like-this-extended-direction 'up) + (message "<up> to mark previous, <left> to skip, <right> to remove, <down> to mark next") + (message "<down> to mark next, <right> to skip, <left> to remove, <up> to mark previous"))) + +(defun mc/mmlte--up () + (interactive) + (mc/mark-previous-like-this 1) + (setq mc/mark-more-like-this-extended-direction 'up) + (mc/mmlte--message)) + +(defun mc/mmlte--down () + (interactive) + (mc/mark-next-like-this 1) + (setq mc/mark-more-like-this-extended-direction 'down) + (mc/mmlte--message)) + +(defun mc/mmlte--left () + (interactive) + (if (eq mc/mark-more-like-this-extended-direction 'down) + (mc/unmark-next-like-this) + (mc/skip-to-previous-like-this)) + (mc/mmlte--message)) + +(defun mc/mmlte--right () + (interactive) + (if (eq mc/mark-more-like-this-extended-direction 'up) + (mc/unmark-previous-like-this) + (mc/skip-to-next-like-this)) + (mc/mmlte--message)) + +(defvar mc/mark-more-like-this-extended-keymap (make-sparse-keymap)) + +(define-key mc/mark-more-like-this-extended-keymap (kbd "<up>") 'mc/mmlte--up) +(define-key mc/mark-more-like-this-extended-keymap (kbd "<down>") 'mc/mmlte--down) +(define-key mc/mark-more-like-this-extended-keymap (kbd "<left>") 'mc/mmlte--left) +(define-key mc/mark-more-like-this-extended-keymap (kbd "<right>") 'mc/mmlte--right) + +(defvar mc--restrict-mark-all-to-symbols nil) + +;;;###autoload +(defun mc/mark-all-like-this-dwim (arg) + "Tries to guess what you want to mark all of. +Can be pressed multiple times to increase selection. + +With prefix, it behaves the same as original `mc/mark-all-like-this'" + (interactive "P") + (if arg + (mc/mark-all-like-this) + (if (and (not (use-region-p)) + (derived-mode-p 'sgml-mode) + (mc--on-tag-name-p)) + (mc/mark-sgml-tag-pair) + (let ((before (mc/num-cursors))) + (unless (eq last-command 'mc/mark-all-like-this-dwim) + (setq mc--restrict-mark-all-to-symbols nil)) + (unless (use-region-p) + (mc--mark-symbol-at-point) + (setq mc--restrict-mark-all-to-symbols t)) + (if mc--restrict-mark-all-to-symbols + (mc/mark-all-symbols-like-this-in-defun) + (mc/mark-all-like-this-in-defun)) + (when (<= (mc/num-cursors) before) + (if mc--restrict-mark-all-to-symbols + (mc/mark-all-symbols-like-this) + (mc/mark-all-like-this))) + (when (<= (mc/num-cursors) before) + (mc/mark-all-like-this)))))) + +;;;###autoload +(defun mc/mark-all-dwim (arg) + "Tries even harder to guess what you want to mark all of. + +If the region is active and spans multiple lines, it will behave +as if `mc/mark-all-in-region'. With the prefix ARG, it will call +`mc/edit-lines' instead. + +If the region is inactive or on a single line, it will behave like +`mc/mark-all-like-this-dwim'." + (interactive "P") + (if (and (use-region-p) + (not (> (mc/num-cursors) 1)) + (not (= (line-number-at-pos (region-beginning)) + (line-number-at-pos (region-end))))) + (if arg + (call-interactively 'mc/edit-lines) + (call-interactively 'mc/mark-all-in-region)) + (progn + (setq this-command 'mc/mark-all-like-this-dwim) + (mc/mark-all-like-this-dwim arg)))) + +(defun mc--in-defun () + (bounds-of-thing-at-point 'defun)) + +;;;###autoload +(defun mc/mark-all-like-this-in-defun () + "Mark all like this in defun." + (interactive) + (if (mc--in-defun) + (save-restriction + (widen) + (narrow-to-defun) + (mc/mark-all-like-this)) + (mc/mark-all-like-this))) + +;;;###autoload +(defun mc/mark-all-words-like-this-in-defun () + "Mark all words like this in defun." + (interactive) + (mc--select-thing-at-point-or-bark 'word) + (if (mc--in-defun) + (save-restriction + (widen) + (narrow-to-defun) + (mc/mark-all-words-like-this)) + (mc/mark-all-words-like-this))) + +;;;###autoload +(defun mc/mark-all-symbols-like-this-in-defun () + "Mark all symbols like this in defun." + (interactive) + (mc--select-thing-at-point-or-bark 'symbol) + (if (mc--in-defun) + (save-restriction + (widen) + (narrow-to-defun) + (mc/mark-all-symbols-like-this)) + (mc/mark-all-symbols-like-this))) + +(defun mc--mark-symbol-at-point () + "Select the symbol under cursor" + (interactive) + (when (not (use-region-p)) + (let ((b (bounds-of-thing-at-point 'symbol))) + (goto-char (car b)) + (set-mark (cdr b))))) + +(defun mc--get-nice-sgml-context () + (car + (last + (progn + (when (looking-at "<") (forward-char 1)) + (when (looking-back ">") (forward-char -1)) + (sgml-get-context))))) + +(defun mc--on-tag-name-p () + (let* ((context (save-excursion (mc--get-nice-sgml-context))) + (tag-name-len (length (aref context 4))) + (beg (aref context 2)) + (end (+ beg tag-name-len (if (eq 'open (aref context 1)) 1 3)))) + (and context + (>= (point) beg) + (<= (point) end)))) + +;;;###autoload +(defun mc/add-cursor-on-click (event) + "Add a cursor where you click." + (interactive "e") + (mouse-minibuffer-check event) + ;; Use event-end in case called from mouse-drag-region. + ;; If EVENT is a click, event-end and event-start give same value. + (let ((position (event-end event))) + (if (not (windowp (posn-window position))) + (error "Position not in text area of window")) + (select-window (posn-window position)) + (if (numberp (posn-point position)) + (save-excursion + (goto-char (posn-point position)) + (mc/create-fake-cursor-at-point))) + (mc/maybe-multiple-cursors-mode))) + +;;;###autoload +(defun mc/mark-sgml-tag-pair () + "Mark the tag we're in and its pair for renaming." + (interactive) + (when (not (mc--inside-tag-p)) + (error "Place point inside tag to rename.")) + (let ((context (mc--get-nice-sgml-context))) + (if (looking-at "</") + (setq context (car (last (sgml-get-context))))) + (goto-char (aref context 2)) + (let* ((tag-name (aref context 4)) + (num-chars (length tag-name)) + (master-start (1+ (point))) + (mirror-end (save-excursion + (sgml-skip-tag-forward 1) + (1- (point))))) + (goto-char (- mirror-end num-chars)) + (set-mark mirror-end) + (mc/create-fake-cursor-at-point) + (goto-char master-start) + (set-mark (+ (point) num-chars)))) + (mc/maybe-multiple-cursors-mode)) + +(defun mc--inside-tag-p () + (save-excursion + (not (null (sgml-get-context))))) + +(provide 'mc-mark-more) + +;;; mc-mark-more.el ends here diff --git a/emacs/.emacs.d/multiple-cursors/mc-mark-pop.el b/emacs/.emacs.d/multiple-cursors/mc-mark-pop.el @@ -0,0 +1,22 @@ +;;; mc-mark-pop.el --- Pop cursors off of the mark stack + +(require 'multiple-cursors-core) + +;;;###autoload +(defun mc/mark-pop () + "Add a cursor at the current point, pop off mark ring and jump +to the popped mark." + (interactive) + ;; If the mark happens to be at the current point, just pop that one off. + (while (eql (mark) (point)) + (pop-mark)) + (mc/create-fake-cursor-at-point) + (exchange-point-and-mark) + (pop-mark) + (mc/maybe-multiple-cursors-mode)) + +;; A good key binding for this feature is perhaps "C-S-p" ('p' for pop). + +(provide 'mc-mark-pop) + +;;; mc-mark-pop.el ends here diff --git a/emacs/.emacs.d/multiple-cursors/mc-separate-operations.el b/emacs/.emacs.d/multiple-cursors/mc-separate-operations.el @@ -0,0 +1,90 @@ +;;; mc-separate-operations.el - functions that work differently on each cursor + +;; Copyright (C) 2012 Magnar Sveen + +;; Author: Magnar Sveen <magnars@gmail.com> +;; Keywords: editing cursors + +;; 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 contains functions that work differently on each cursor, +;; instead of treating all of them the same. + +;; Please see multiple-cursors.el for more commentary. + +;;; Code: + +(require 'multiple-cursors-core) + +;;;###autoload +(defun mc/insert-numbers (arg) + "Insert increasing numbers for each cursor, starting at 0 or ARG." + (interactive "P") + (setq mc--insert-numbers-number (or arg 0)) + (mc/for-each-cursor-ordered + (mc/execute-command-for-fake-cursor 'mc--insert-number-and-increase cursor))) + +(defvar mc--insert-numbers-number 0) + +(defun mc--insert-number-and-increase () + (interactive) + (insert (number-to-string mc--insert-numbers-number)) + (setq mc--insert-numbers-number (1+ mc--insert-numbers-number))) + +(defun mc--ordered-region-strings () + (let (strings) + (save-excursion + (mc/for-each-cursor-ordered + (setq strings (cons (buffer-substring-no-properties + (mc/cursor-beg cursor) + (mc/cursor-end cursor)) strings)))) + (nreverse strings))) + +(defvar mc--strings-to-replace nil) + +(defun mc--replace-region-strings-1 () + (interactive) + (delete-region (region-beginning) (region-end)) + (save-excursion (insert (car mc--strings-to-replace))) + (setq mc--strings-to-replace (cdr mc--strings-to-replace))) + +(defun mc--replace-region-strings () + (mc/for-each-cursor-ordered + (mc/execute-command-for-fake-cursor 'mc--replace-region-strings-1 cursor))) + +;;;###autoload +(defun mc/reverse-regions () + (interactive) + (if (not multiple-cursors-mode) + (progn + (mc/mark-next-lines 1) + (mc/reverse-regions) + (multiple-cursors-mode 0)) + (unless (use-region-p) + (mc/execute-command-for-all-cursors 'mark-sexp)) + (setq mc--strings-to-replace (nreverse (mc--ordered-region-strings))) + (mc--replace-region-strings))) + +;;;###autoload +(defun mc/sort-regions () + (interactive) + (unless (use-region-p) + (mc/execute-command-for-all-cursors 'mark-sexp)) + (setq mc--strings-to-replace (sort (mc--ordered-region-strings) 'string<)) + (mc--replace-region-strings)) + +(provide 'mc-separate-operations) +;;; mc-separate-operations.el ends here diff --git a/emacs/.emacs.d/multiple-cursors/multiple-cursors-core.el b/emacs/.emacs.d/multiple-cursors/multiple-cursors-core.el @@ -0,0 +1,729 @@ +;;; multiple-cursors-core.el --- An experiment in multiple cursors for emacs. + +;; Copyright (C) 2012 Magnar Sveen + +;; Author: Magnar Sveen <magnars@gmail.com> +;; Keywords: editing cursors + +;; 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 contains the core functionality of multiple-cursors. +;; Please see multiple-cursors.el for more commentary. + +;;; Code: + +(require 'cl) + +(require 'rect) + +(defvar mc--read-char) + +(defface mc/cursor-face + '((t (:inverse-video t))) + "The face used for fake cursors" + :group 'multiple-cursors) + +(defface mc/region-face + '((t :inherit region)) + "The face used for fake regions" + :group 'multiple-cursors) + +(defmacro mc/add-fake-cursor-to-undo-list (&rest forms) + "Make sure point is in the right place when undoing" + (let ((uc (make-symbol "undo-cleaner"))) + `(let ((,uc (cons 'apply (cons 'deactivate-cursor-after-undo (list id))))) + (setq buffer-undo-list (cons ,uc buffer-undo-list)) + ,@forms + (if (eq ,uc (car buffer-undo-list)) ;; if nothing has been added to the undo-list + (setq buffer-undo-list (cdr buffer-undo-list)) ;; then pop the cleaner right off again + (setq buffer-undo-list ;; otherwise add a function to activate this cursor + (cons (cons 'apply (cons 'activate-cursor-for-undo (list id))) buffer-undo-list)))))) + +(defun mc/all-fake-cursors (&optional start end) + (remove-if-not 'mc/fake-cursor-p + (overlays-in (or start (point-min)) + (or end (point-max))))) + +(defmacro mc/for-each-fake-cursor (&rest forms) + "Runs the body for each fake cursor, bound to the name cursor" + `(mapc #'(lambda (cursor) ,@forms) + (mc/all-fake-cursors))) + +(defmacro mc/save-excursion (&rest forms) + "Saves and restores all the state that multiple-cursors cares about." + (let ((cs (make-symbol "current-state"))) + `(let ((,cs (mc/store-current-state-in-overlay + (make-overlay (point) (point) nil nil t)))) + (overlay-put ,cs 'type 'original-cursor) + (save-excursion ,@forms) + (mc/pop-state-from-overlay ,cs)))) + +(defun mc--compare-by-overlay-start (o1 o2) + (< (overlay-start o1) (overlay-start o2))) + +(defmacro mc/for-each-cursor-ordered (&rest forms) + "Runs the body for each cursor, fake and real, bound to the name cursor" + (let ((rci (make-symbol "real-cursor-id"))) + `(let ((,rci (overlay-get (mc/create-fake-cursor-at-point) 'mc-id))) + (mapc #'(lambda (cursor) + (when (mc/fake-cursor-p cursor) + ,@forms)) + (sort (overlays-in (point-min) (point-max)) 'mc--compare-by-overlay-start)) + (mc/pop-state-from-overlay (mc/cursor-with-id ,rci))))) + +(defmacro mc/save-window-scroll (&rest forms) + "Saves and restores the window scroll position" + (let ((p (make-symbol "p")) + (s (make-symbol "start")) + (h (make-symbol "hscroll"))) + `(let ((,p (set-marker (make-marker) (point))) + (,s (set-marker (make-marker) (window-start))) + (,h (window-hscroll))) + ,@forms + (goto-char ,p) + (set-window-start nil ,s t) + (set-window-hscroll nil ,h) + (set-marker ,p nil) + (set-marker ,s nil)))) + +(defun mc/make-cursor-overlay-at-eol (pos) + "Create overlay to look like cursor at end of line." + (let ((overlay (make-overlay pos pos nil nil nil))) + (overlay-put overlay 'after-string (propertize " " 'face 'mc/cursor-face)) + overlay)) + +(defun mc/make-cursor-overlay-inline (pos) + "Create overlay to look like cursor inside text." + (let ((overlay (make-overlay pos (1+ pos) nil nil nil))) + (overlay-put overlay 'face 'mc/cursor-face) + overlay)) + +(defun mc/make-cursor-overlay-at-point () + "Create overlay to look like cursor. +Special case for end of line, because overlay over a newline +highlights the entire width of the window." + (if (eolp) + (mc/make-cursor-overlay-at-eol (point)) + (mc/make-cursor-overlay-inline (point)))) + +(defun mc/make-region-overlay-between-point-and-mark () + "Create overlay to look like active region." + (let ((overlay (make-overlay (mark) (point) nil nil t))) + (overlay-put overlay 'face 'mc/region-face) + (overlay-put overlay 'type 'additional-region) + overlay)) + +(defvar mc/cursor-specific-vars '(transient-mark-mode + kill-ring + kill-ring-yank-pointer + mark-ring + mark-active + yank-undo-function + autopair-action + autopair-wrap-action + er/history) + "A list of vars that need to be tracked on a per-cursor basis.") + +(defun mc/store-current-state-in-overlay (o) + "Store relevant info about point and mark in the given overlay." + (overlay-put o 'point (set-marker (make-marker) (point))) + (overlay-put o 'mark (set-marker (make-marker) (mark))) + (dolist (var mc/cursor-specific-vars) + (when (boundp var) (overlay-put o var (symbol-value var)))) + o) + +(defun mc/restore-state-from-overlay (o) + "Restore point and mark from stored info in the given overlay." + (goto-char (overlay-get o 'point)) + (set-marker (mark-marker) (overlay-get o 'mark)) + (dolist (var mc/cursor-specific-vars) + (when (boundp var) (set var (overlay-get o var))))) + +(defun mc/remove-fake-cursor (o) + "Delete overlay with state, including dependent overlays and markers." + (set-marker (overlay-get o 'point) nil) + (set-marker (overlay-get o 'mark) nil) + (mc/delete-region-overlay o) + (delete-overlay o)) + +(defun mc/pop-state-from-overlay (o) + "Restore the state stored in given overlay and then remove the overlay." + (mc/restore-state-from-overlay o) + (mc/remove-fake-cursor o)) + +(defun mc/delete-region-overlay (o) + "Remove the dependent region overlay for a given cursor overlay." + (ignore-errors + (delete-overlay (overlay-get o 'region-overlay)))) + +(defvar mc--current-cursor-id 0 + "Var to store increasing id of fake cursors, used to keep track of them for undo.") + +(defun mc/create-cursor-id () + "Returns a unique cursor id" + (incf mc--current-cursor-id)) + +(defun mc/create-fake-cursor-at-point (&optional id) + "Add a fake cursor and possibly a fake active region overlay based on point and mark. +Saves the current state in the overlay to be restored later." + (let ((overlay (mc/make-cursor-overlay-at-point))) + (overlay-put overlay 'mc-id (or id (mc/create-cursor-id))) + (overlay-put overlay 'type 'fake-cursor) + (overlay-put overlay 'priority 100) + (mc/store-current-state-in-overlay overlay) + (when (use-region-p) + (overlay-put overlay 'region-overlay + (mc/make-region-overlay-between-point-and-mark))) + overlay)) + +(defun mc/execute-command (cmd) + "Run command, simulating the parts of the command loop that makes sense for fake cursors." + (setq this-command cmd) + (run-hooks 'pre-command-hook) + (unless (eq this-command 'ignore) + (call-interactively cmd)) + (run-hooks 'post-command-hook) + (when deactivate-mark (deactivate-mark))) + +(defvar mc--executing-command-for-fake-cursor nil) + +(defun mc/execute-command-for-fake-cursor (cmd cursor) + (let ((mc--executing-command-for-fake-cursor t) + (id (overlay-get cursor 'mc-id)) + (annoying-arrows-mode nil) + (smooth-scroll-margin 0)) + (mc/add-fake-cursor-to-undo-list + (mc/pop-state-from-overlay cursor) + (ignore-errors + (mc/execute-command cmd) + (mc/create-fake-cursor-at-point id))))) + +(defun mc/execute-command-for-all-fake-cursors (cmd) + "Calls CMD interactively for each cursor. +It works by moving point to the fake cursor, setting +up the proper environment, and then removing the cursor. +After executing the command, it sets up a new fake +cursor with updated info." + (mc/save-excursion + (mc/save-window-scroll + (mc/for-each-fake-cursor + (save-excursion + (mc/execute-command-for-fake-cursor cmd cursor))))) + (mc--reset-read-prompts)) + +(defun mc/execute-command-for-all-cursors (cmd) + "Calls CMD interactively for the real cursor and all fakes." + (call-interactively cmd) + (mc/execute-command-for-all-fake-cursors cmd)) + +;; Intercept some reading commands so you won't have to +;; answer them for every single cursor + +(defvar mc--read-char nil) +(defvar multiple-cursors-mode nil) +(defadvice read-char (around mc-support activate) + (if (not multiple-cursors-mode) + ad-do-it + (unless mc--read-char + (setq mc--read-char ad-do-it)) + (setq ad-return-value mc--read-char))) + +(defvar mc--read-quoted-char nil) +(defadvice read-quoted-char (around mc-support activate) + (if (not multiple-cursors-mode) + ad-do-it + (unless mc--read-quoted-char + (setq mc--read-quoted-char ad-do-it)) + (setq ad-return-value mc--read-quoted-char))) + +(defun mc--reset-read-prompts () + (setq mc--read-char nil) + (setq mc--read-quoted-char nil)) + +(mc--reset-read-prompts) + +(defun mc/fake-cursor-p (o) + "Predicate to check if an overlay is a fake cursor" + (eq (overlay-get o 'type) 'fake-cursor)) + +(defun mc/cursor-with-id (id) + "Find the first cursor with the given id, or nil" + (find-if #'(lambda (o) (and (mc/fake-cursor-p o) + (= id (overlay-get o 'mc-id)))) + (overlays-in (point-min) (point-max)))) + +(defvar mc--stored-state-for-undo nil + "Variable to keep the state of the real cursor while undoing a fake one") + +(defun activate-cursor-for-undo (id) + "Called when undoing to temporarily activate the fake cursor which action is being undone." + (let ((cursor (mc/cursor-with-id id))) + (when cursor + (setq mc--stored-state-for-undo (mc/store-current-state-in-overlay + (make-overlay (point) (point) nil nil t))) + (mc/pop-state-from-overlay cursor)))) + +(defun deactivate-cursor-after-undo (id) + "Called when undoing to reinstate the real cursor after undoing a fake one." + (when mc--stored-state-for-undo + (mc/create-fake-cursor-at-point id) + (mc/pop-state-from-overlay mc--stored-state-for-undo) + (setq mc--stored-state-for-undo nil))) + +(defun mc/prompt-for-inclusion-in-whitelist (original-command) + "Asks the user, then adds the command either to the once-list or the all-list." + (let ((all-p (y-or-n-p (format "Do %S for all cursors?" original-command)))) + (if all-p + (add-to-list 'mc/cmds-to-run-for-all original-command) + (add-to-list 'mc/cmds-to-run-once original-command)) + (mc/save-lists) + all-p)) + +(defun mc/num-cursors () + "The number of cursors (real and fake) in the buffer." + (1+ (count-if 'mc/fake-cursor-p + (overlays-in (point-min) (point-max))))) + +(defvar mc--this-command nil + "Used to store the original command being run.") +(make-variable-buffer-local 'mc--this-command) + +(defun mc/make-a-note-of-the-command-being-run () + "Used with pre-command-hook to store the original command being run. +Since that cannot be reliably determined in the post-command-hook. + +Specifically, this-original-command isn't always right, because it could have +been remapped. And certain modes (cua comes to mind) will change their +remapping based on state. So a command that changes the state will afterwards +not be recognized through the command-remapping lookup." + (unless mc--executing-command-for-fake-cursor + (let ((cmd (or (command-remapping this-original-command) + this-original-command))) + (setq mc--this-command (and (not (eq cmd 'god-mode-self-insert)) + cmd))))) + +(defun mc/execute-this-command-for-all-cursors () + "Wrap around `mc/execute-this-command-for-all-cursors-1' to protect hook." + (condition-case error + (mc/execute-this-command-for-all-cursors-1) + (error + (message "[mc] problem in `mc/execute-this-command-for-all-cursors': %s" + (error-message-string error))))) + +;; execute-kbd-macro should never be run for fake cursors. The real cursor will +;; execute the keyboard macro, resulting in new commands in the command loop, +;; and the fake cursors can pick up on those instead. +(defadvice execute-kbd-macro (around skip-fake-cursors activate) + (unless mc--executing-command-for-fake-cursor + ad-do-it)) + +(defun mc/execute-this-command-for-all-cursors-1 () + "Used with post-command-hook to execute supported commands for all cursors. + +It uses two lists of commands to know what to do: the run-once +list and the run-for-all list. If a command is in neither of these lists, +it will prompt for the proper action and then save that preference. + +Some commands are so unsupported that they are even prevented for +the original cursor, to inform about the lack of support." + (unless mc--executing-command-for-fake-cursor + + (if (eq 1 (mc/num-cursors)) ;; no fake cursors? disable mc-mode + (multiple-cursors-mode 0) + (when this-original-command + (let ((original-command (or mc--this-command + (command-remapping this-original-command) + this-original-command))) + + ;; skip keyboard macros, since they will generate actual commands that are + ;; also run in the command loop - we'll handle those later instead. + (when (functionp original-command) + + ;; if it's a lambda, we can't know if it's supported or not + ;; - so go ahead and assume it's ok, because we're just optimistic like that + (if (or (not (symbolp original-command)) + ;; lambda registered by smartrep + (string-prefix-p "(" (symbol-name original-command))) + (mc/execute-command-for-all-fake-cursors original-command) + + ;; smartrep `intern's commands into own obarray to help + ;; `describe-bindings'. So, let's re-`intern' here to + ;; make the command comparable by `eq'. + (setq original-command (intern (symbol-name original-command))) + + ;; otherwise it's a symbol, and we can be more thorough + (if (get original-command 'mc--unsupported) + (message "%S is not supported with multiple cursors%s" + original-command + (get original-command 'mc--unsupported)) + (when (and original-command + (not (memq original-command mc--default-cmds-to-run-once)) + (not (memq original-command mc/cmds-to-run-once)) + (or (memq original-command mc--default-cmds-to-run-for-all) + (memq original-command mc/cmds-to-run-for-all) + (mc/prompt-for-inclusion-in-whitelist original-command))) + (mc/execute-command-for-all-fake-cursors original-command)))))))))) + +(defun mc/remove-fake-cursors () + "Remove all fake cursors. +Do not use to conclude editing with multiple cursors. For that +you should disable multiple-cursors-mode." + (mc/for-each-fake-cursor + (mc/remove-fake-cursor cursor))) + +(defun mc/keyboard-quit () + "Deactivate mark if there are any active, otherwise exit multiple-cursors-mode." + (interactive) + (if (not (use-region-p)) + (multiple-cursors-mode 0) + (deactivate-mark))) + +(defvar mc/keymap nil + "Keymap while multiple cursors are active. +Main goal of the keymap is to rebind C-g and <return> to conclude +multiple cursors editing.") +(unless mc/keymap + (setq mc/keymap (make-sparse-keymap)) + (define-key mc/keymap (kbd "C-g") 'mc/keyboard-quit) + (define-key mc/keymap (kbd "<return>") 'multiple-cursors-mode) + (when (fboundp 'phi-search) + (define-key mc/keymap (kbd "C-s") 'phi-search)) + (when (fboundp 'phi-search-backward) + (define-key mc/keymap (kbd "C-r") 'phi-search-backward))) + +(defun mc--all-equal (list) + "Are all the items in LIST equal?" + (let ((first (car list)) + (all-equal t)) + (while (and all-equal list) + (setq all-equal (equal first (car list))) + (setq list (cdr list))) + all-equal)) + +(defun mc--kill-ring-entries () + "Return the latest kill-ring entry for each cursor. +The entries are returned in the order they are found in the buffer." + (let (entries) + (mc/for-each-cursor-ordered + (setq entries (cons (car (overlay-get cursor 'kill-ring)) entries))) + (reverse entries))) + +(defun mc--maybe-set-killed-rectangle () + "Add the latest kill-ring entry for each cursor to killed-rectangle. +So you can paste it in later with `yank-rectangle'." + (let ((entries (mc--kill-ring-entries))) + (unless (mc--all-equal entries) + (setq killed-rectangle entries)))) + +(defvar mc/unsupported-minor-modes '(auto-complete-mode flyspell-mode) + "List of minor-modes that does not play well with multiple-cursors. +They are temporarily disabled when multiple-cursors are active.") + +(defvar mc/temporarily-disabled-minor-modes nil + "The list of temporarily disabled minor-modes.") +(make-variable-buffer-local 'mc/temporarily-disabled-minor-modes) + +(defun mc/temporarily-disable-minor-mode (mode) + "If MODE is available and turned on, remember that and turn it off." + (when (and (boundp mode) (eval mode)) + (add-to-list 'mc/temporarily-disabled-minor-modes mode) + (funcall mode -1))) + +(defun mc/temporarily-disable-unsupported-minor-modes () + (mapc 'mc/temporarily-disable-minor-mode mc/unsupported-minor-modes)) + +(defun mc/enable-minor-mode (mode) + (funcall mode 1)) + +(defun mc/enable-temporarily-disabled-minor-modes () + (mapc 'mc/enable-minor-mode mc/temporarily-disabled-minor-modes) + (setq mc/temporarily-disabled-minor-modes nil)) + +(defcustom mc/mode-line + `(" mc:" (:eval (format ,(propertize "%d" 'face 'font-lock-warning-face) + (mc/num-cursors)))) + "What to display in the mode line while multiple-cursors-mode is active." + :group 'multiple-cursors) +(put 'mc/mode-line 'risky-local-variable t) + +(define-minor-mode multiple-cursors-mode + "Mode while multiple cursors are active." + nil mc/mode-line mc/keymap + (if multiple-cursors-mode + (progn + (mc/temporarily-disable-unsupported-minor-modes) + (add-hook 'pre-command-hook 'mc/make-a-note-of-the-command-being-run nil t) + (add-hook 'post-command-hook 'mc/execute-this-command-for-all-cursors t t) + (run-hooks 'multiple-cursors-mode-enabled-hook)) + (remove-hook 'post-command-hook 'mc/execute-this-command-for-all-cursors t) + (remove-hook 'pre-command-hook 'mc/make-a-note-of-the-command-being-run t) + (setq mc--this-command nil) + (mc--maybe-set-killed-rectangle) + (mc/remove-fake-cursors) + (mc/enable-temporarily-disabled-minor-modes) + (run-hooks 'multiple-cursors-mode-disabled-hook))) + +(add-hook 'after-revert-hook #'(lambda () (multiple-cursors-mode 0))) + +(defun mc/maybe-multiple-cursors-mode () + "Enable multiple-cursors-mode if there is more than one currently active cursor." + (if (> (mc/num-cursors) 1) + (multiple-cursors-mode 1) + (multiple-cursors-mode 0))) + +(defmacro unsupported-cmd (cmd msg) + "Adds command to list of unsupported commands and prevents it +from being executed if in multiple-cursors-mode." + `(progn + (put (quote ,cmd) 'mc--unsupported ,msg) + (defadvice ,cmd (around unsupported-advice activate) + "command isn't supported with multiple cursors" + (unless (and multiple-cursors-mode (called-interactively-p 'any)) + ad-do-it)))) + +;; Commands that does not work with multiple-cursors +(unsupported-cmd isearch-forward ". Feel free to add a compatible version.") +(unsupported-cmd isearch-backward ". Feel free to add a compatible version.") + +;; Make sure pastes from other programs are added to all kill-rings when yanking +(defadvice current-kill (before interprogram-paste-for-all-cursors activate) + (let ((interprogram-paste (and (= n 0) + interprogram-paste-function + (funcall interprogram-paste-function)))) + (when interprogram-paste + ;; Add interprogram-paste to normal kill ring, just + ;; like current-kill usually does for itself. + ;; We have to do the work for it tho, since the funcall only returns + ;; something once. It is not a pure function. + (let ((interprogram-cut-function nil)) + (if (listp interprogram-paste) + (mapc 'kill-new (nreverse interprogram-paste)) + (kill-new interprogram-paste)) + ;; And then add interprogram-paste to the kill-rings + ;; of all the other cursors too. + (mc/for-each-fake-cursor + (let ((kill-ring (overlay-get cursor 'kill-ring)) + (kill-ring-yank-pointer (overlay-get cursor 'kill-ring-yank-pointer))) + (if (listp interprogram-paste) + (mapc 'kill-new (nreverse interprogram-paste)) + (kill-new interprogram-paste)) + (overlay-put cursor 'kill-ring kill-ring) + (overlay-put cursor 'kill-ring-yank-pointer kill-ring-yank-pointer))))))) + +(defvar mc/list-file "~/.emacs.d/.mc-lists.el" + "The position of the file that keeps track of your preferences +for running commands with multiple cursors.") + +(defun mc/dump-list (list-symbol) + "Insert (setq 'LIST-SYMBOL LIST-VALUE) to current buffer." + (symbol-macrolet ((value (symbol-value list-symbol))) + (insert "(setq " (symbol-name list-symbol) "\n" + " '(") + (newline-and-indent) + (set list-symbol + (sort value (lambda (x y) (string-lessp (symbol-name x) + (symbol-name y))))) + (mapc #'(lambda (cmd) (insert (format "%S" cmd)) (newline-and-indent)) + value) + (insert "))") + (newline))) + +(defun mc/save-lists () + "Saves preferences for running commands with multiple cursors to `mc/list-file'" + (with-temp-file mc/list-file + (emacs-lisp-mode) + (insert ";; This file is automatically generated by the multiple-cursors extension.") + (newline) + (insert ";; It keeps track of your preferences for running commands with multiple cursors.") + (newline) + (newline) + (mc/dump-list 'mc/cmds-to-run-for-all) + (newline) + (mc/dump-list 'mc/cmds-to-run-once))) + +(defvar mc/cmds-to-run-once nil + "Commands to run only once in multiple-cursors-mode.") + +(defvar mc--default-cmds-to-run-once nil + "Default set of commands to run only once in multiple-cursors-mode.") + +(setq mc--default-cmds-to-run-once '(mc/edit-lines + mc/edit-ends-of-lines + mc/edit-beginnings-of-lines + mc/mark-next-like-this + mc/mark-next-word-like-this + mc/mark-next-symbol-like-this + mc/mark-previous-like-this + mc/mark-previous-word-like-this + mc/mark-previous-symbol-like-this + mc/mark-all-like-this + mc/mark-all-words-like-this + mc/mark-all-symbols-like-this + mc/mark-more-like-this-extended + mc/mark-all-like-this-in-defun + mc/mark-all-words-like-this-in-defun + mc/mark-all-symbols-like-this-in-defun + mc/mark-all-like-this-dwim + mc/mark-all-dwim + mc/mark-sgml-tag-pair + mc/insert-numbers + mc/sort-regions + mc/reverse-regions + mc/cycle-forward + mc/cycle-backward + mc/add-cursor-on-click + mc/mark-pop + mc/add-cursors-to-all-matches + mc/mmlte--left + mc/mmlte--right + mc/mmlte--up + mc/mmlte--down + mc/unmark-next-like-this + mc/unmark-previous-like-this + mc/skip-to-next-like-this + mc/skip-to-previous-like-this + rrm/switch-to-multiple-cursors + save-buffer + ido-exit-minibuffer + exit-minibuffer + minibuffer-complete-and-exit + execute-extended-command + undo + redo + undo-tree-undo + undo-tree-redo + universal-argument + universal-argument-more + universal-argument-other-key + negative-argument + digit-argument + top-level + recenter-top-bottom + describe-mode + describe-key-1 + describe-function + describe-bindings + describe-prefix-bindings + view-echo-area-messages + other-window + kill-buffer-and-window + split-window-right + split-window-below + delete-other-windows + toggle-window-split + mwheel-scroll + scroll-up-command + scroll-down-command + mouse-set-point + mouse-drag-region + quit-window + toggle-read-only + windmove-left + windmove-right + windmove-up + windmove-down)) + +(defvar mc--default-cmds-to-run-for-all nil + "Default set of commands that should be mirrored by all cursors") + +(setq mc--default-cmds-to-run-for-all '(mc/keyboard-quit + self-insert-command + quoted-insert + previous-line + next-line + newline + newline-and-indent + open-line + delete-blank-lines + transpose-chars + transpose-lines + transpose-paragraphs + transpose-regions + join-line + right-char + right-word + forward-char + forward-word + left-char + left-word + backward-char + backward-word + forward-paragraph + backward-paragraph + upcase-word + downcase-word + capitalize-word + forward-list + backward-list + hippie-expand + hippie-expand-lines + yank + yank-pop + append-next-kill + kill-word + kill-line + kill-whole-line + backward-kill-word + backward-delete-char-untabify + delete-char delete-forward-char + delete-backward-char + py-electric-backspace + c-electric-backspace + org-delete-backward-char + python-indent-dedent-line-backspace + paredit-backward-delete + autopair-backspace + just-one-space + zap-to-char + end-of-line + set-mark-command + exchange-point-and-mark + cua-set-mark + cua-replace-region + move-end-of-line + beginning-of-line + move-beginning-of-line + kill-ring-save + back-to-indentation + subword-forward + subword-backward + subword-mark + subword-kill + subword-backward-kill + subword-transpose + subword-capitalize + subword-upcase + subword-downcase + er/expand-region + er/contract-region + smart-forward + smart-backward + smart-up + smart-down)) + +(defvar mc/cmds-to-run-for-all nil + "Commands to run for all cursors in multiple-cursors-mode") + +(load mc/list-file t) ;; load, but no errors if it does not exist yet please + +(provide 'multiple-cursors-core) + +;; Local Variables: +;; coding: utf-8 +;; byte-compile-warnings: (not cl-functions) +;; End: + +;;; multiple-cursors-core.el ends here diff --git a/emacs/.emacs.d/multiple-cursors/multiple-cursors-pkg.el b/emacs/.emacs.d/multiple-cursors/multiple-cursors-pkg.el @@ -0,0 +1,2 @@ +(define-package "multiple-cursors" "1.3.0" + "Multiple cursors for Emacs.") diff --git a/emacs/.emacs.d/multiple-cursors/multiple-cursors.el b/emacs/.emacs.d/multiple-cursors/multiple-cursors.el @@ -0,0 +1,191 @@ +;;; multiple-cursors.el --- Multiple cursors for emacs. + +;; Copyright (C) 2012-2013 Magnar Sveen + +;; Author: Magnar Sveen <magnars@gmail.com> +;; Version: 1.2.2 +;; Keywords: editing cursors + +;; 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: + +;; Multiple cursors for Emacs. This is some pretty crazy functionality, so yes, +;; there are kinks. Don't be afraid tho, I've been using it since 2011 with +;; great success and much merriment. + +;; ## Basic usage + +;; Start out with: + +;; (require 'multiple-cursors) + +;; Then you have to set up your keybindings - multiple-cursors doesn't presume to +;; know how you'd like them laid out. Here are some examples: + +;; When you have an active region that spans multiple lines, the following will +;; add a cursor to each line: + +;; (global-set-key (kbd "C-S-c C-S-c") 'mc/edit-lines) + +;; When you want to add multiple cursors not based on continuous lines, but based on +;; keywords in the buffer, use: + +;; (global-set-key (kbd "C->") 'mc/mark-next-like-this) +;; (global-set-key (kbd "C-<") 'mc/mark-previous-like-this) +;; (global-set-key (kbd "C-c C-<") 'mc/mark-all-like-this) + +;; First mark the word, then add more cursors. + +;; To get out of multiple-cursors-mode, press `<return>` or `C-g`. The latter will +;; first disable multiple regions before disabling multiple cursors. If you want to +;; insert a newline in multiple-cursors-mode, use `C-j`. + +;; ## Video + +;; You can [watch an intro to multiple-cursors at Emacs Rocks](http://emacsrocks.com/e13.html). + +;; ## Command overview + +;; ### Mark one more occurrence + +;; - `mc/mark-next-like-this`: Adds a cursor and region at the next part of the buffer forwards that matches the current region. +;; - `mc/mark-next-word-like-this`: Like `mc/mark-next-like-this` but only for whole words. +;; - `mc/mark-next-symbol-like-this`: Like `mc/mark-next-like-this` but only for whole symbols. +;; - `mc/mark-previous-like-this`: Adds a cursor and region at the next part of the buffer backwards that matches the current region. +;; - `mc/mark-previous-word-like-this`: Like `mc/mark-previous-like-this` but only for whole words. +;; - `mc/mark-previous-symbol-like-this`: Like `mc/mark-previous-like-this` but only for whole symbols. +;; - `mc/mark-more-like-this-extended`: Use arrow keys to quickly mark/skip next/previous occurances. +;; - `mc/add-cursor-on-click`: Bind to a mouse event to add cursors by clicking. See tips-section. + +;; ### Mark many occurrences + +;; - `mc/mark-all-like-this`: Marks all parts of the buffer that matches the current region. +;; - `mc/mark-all-words-like-this`: Like `mc/mark-all-like-this` but only for whole words. +;; - `mc/mark-all-symbols-like-this`: Like `mc/mark-all-like-this` but only for whole symbols. +;; - `mc/mark-all-in-region`: Prompts for a string to match in the region, adding cursors to all of them. +;; - `mc/mark-all-like-this-in-defun`: Marks all parts of the current defun that matches the current region. +;; - `mc/mark-all-words-like-this-in-defun`: Like `mc/mark-all-like-this-in-defun` but only for whole words. +;; - `mc/mark-all-symbols-like-this-in-defun`: Like `mc/mark-all-like-this-in-defun` but only for whole symbols. +;; - `mc/mark-all-like-this-dwim`: Tries to be smart about marking everything you want. Can be pressed multiple times. + +;; ### Special + +;; - `set-rectangular-region-anchor`: Think of this one as `set-mark` except you're marking a rectangular region. +;; - `mc/mark-sgml-tag-pair`: Mark the current opening and closing tag. +;; - `mc/insert-numbers`: Insert increasing numbers for each cursor, top to bottom. +;; - `mc/sort-regions`: Sort the marked regions alphabetically. +;; - `mc/reverse-regions`: Reverse the order of the marked regions. + +;; ## Tips and tricks + +;; - To get out of multiple-cursors-mode, press `<return>` or `C-g`. The latter will +;; first disable multiple regions before disabling multiple cursors. If you want to +;; insert a newline in multiple-cursors-mode, use `C-j`. +;; +;; - Sometimes you end up with cursors outside of your view. You can +;; scroll the screen to center on each cursor with `C-v` and `M-v`. +;; +;; - Try pressing `mc/mark-next-like-this` with no region selected. It will just add a cursor +;; on the next line. +;; +;; - Try pressing `mc/mark-all-like-this-dwim` on a tagname in html-mode. +;; +;; - Notice that the number of cursors active can be seen in the modeline. +;; +;; - If you get out of multiple-cursors-mode and yank - it will yank only +;; from the kill-ring of main cursor. To yank from the kill-rings of +;; every cursor use yank-rectangle, normally found at C-x r y. +;; +;; - You can use `mc/reverse-regions` with nothing selected and just one cursor. +;; It will then flip the sexp at point and the one below it. +;; +;; - If you would like to keep the global bindings clean, and get custom keybindings +;; when the region is active, you can try [region-bindings-mode](https://github.com/fgallina/region-bindings-mode). +;; +;; BTW, I highly recommend adding `mc/mark-next-like-this` to a key binding that's +;; right next to the key for `er/expand-region`. + +;; ### Binding mouse events + +;; To override a mouse event, you will likely have to also unbind the +;; `down-mouse` part of the event. Like this: +;; +;; (global-unset-key (kbd "M-<down-mouse-1>")) +;; (global-set-key (kbd "M-<mouse-1>") 'mc/add-cursor-on-click) +;; +;; Or you can do like me and find an unused, but less convenient, binding: +;; +;; (global-set-key (kbd "C-S-<mouse-1>") 'mc/add-cursor-on-click) + +;; ## Unknown commands + +;; Multiple-cursors uses two lists of commands to know what to do: the run-once list +;; and the run-for-all list. It comes with a set of defaults, but it would be beyond silly +;; to try and include all the known Emacs commands. + +;; So that's why multiple-cursors occasionally asks what to do about a command. It will +;; then remember your choice by saving it in `~/.emacs.d/.mc-lists.el`. You can change +;; the location with: + +;; (setq mc/list-file "/my/preferred/file") + +;; ## Known limitations + +;; * isearch-forward and isearch-backward aren't supported with multiple cursors. +;; You should feel free to add a simplified version that can work with it. +;; * Commands run with `M-x` won't be repeated for all cursors. +;; * All key bindings that refer to lambdas are always run for all cursors. If you +;; need to limit it, you will have to give it a name. +;; * Redo might screw with your cursors. Undo works very well. + +;; ## Contribute + +;; Yes, please do. There's a suite of tests, so remember to add tests for your +;; specific feature, or I might break it later. + +;; You'll find the repo at: + +;; https://github.com/magnars/multiple-cursors.el + +;; To fetch the test dependencies: + +;; $ cd /path/to/multiple-cursors +;; $ git submodule update --init + +;; Run the tests with: + +;; $ ./util/ecukes/ecukes --graphical + +;; ## Contributors + +;; * [Takafumi Arakaki](https://github.com/tkf) made .mc-lists.el diff friendly +;; * [Marco Baringer](https://github.com/segv) contributed looping to mc/cycle and adding cursors without region for mark-more. +;; * [Ivan Andrus](https://github.com/gvol) added showing number of cursors in mode-line +;; * [Fuco](https://github.com/Fuco1) added the first version of `mc/mark-all-like-this-dwim` + +;; Thanks! + +;;; Code: + +(require 'mc-edit-lines) +(require 'mc-cycle-cursors) +(require 'mc-mark-more) +(require 'mc-mark-pop) +(require 'rectangular-region-mode) +(require 'mc-separate-operations) + +(provide 'multiple-cursors) + +;;; multiple-cursors.el ends here diff --git a/emacs/.emacs.d/multiple-cursors/rectangular-region-mode.el b/emacs/.emacs.d/multiple-cursors/rectangular-region-mode.el @@ -0,0 +1,124 @@ +;;; rectangular-region-mode.el + +;; Copyright (C) 2012 Magnar Sveen + +;; Author: Magnar Sveen <magnars@gmail.com> +;; Keywords: editing cursors + +;; 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: + +;; (global-set-key (kbd "H-SPC") 'set-rectangular-region-anchor) + +;; Think of this one as `set-mark` except you're marking a rectangular region. It is +;; an exceedingly quick way of adding multiple cursors to multiple lines. + +;;; Code: + +(require 'multiple-cursors-core) + +(defvar rrm/anchor (make-marker) + "The position in the buffer that anchors the rectangular region.") + +(defvar rectangular-region-mode-map (make-sparse-keymap) + "Keymap for rectangular region is mainly for rebinding C-g") + +(define-key rectangular-region-mode-map (kbd "C-g") 'rrm/keyboard-quit) +(define-key rectangular-region-mode-map (kbd "<return>") 'rrm/switch-to-multiple-cursors) + +(defvar rectangular-region-mode nil) + +(defun rrm/keyboard-quit () + "Exit rectangular-region-mode." + (interactive) + (rectangular-region-mode 0) + (rrm/remove-rectangular-region-overlays) + (deactivate-mark)) + +;; Bind this to a key (for instance H-SPC) to start rectangular-region-mode +;;;###autoload +(defun set-rectangular-region-anchor () + "Anchors the rectangular region at point. + +Think of this one as `set-mark' except you're marking a rectangular region. It is +an exceedingly quick way of adding multiple cursors to multiple lines." + (interactive) + (set-marker rrm/anchor (point)) + (push-mark (point)) + (rectangular-region-mode 1)) + +(defun rrm/remove-rectangular-region-overlays () + "Remove all rectangular-region overlays." + (mc/remove-fake-cursors) + (mapc #'(lambda (o) + (when (eq (overlay-get o 'type) 'additional-region) + (delete-overlay o))) + (overlays-in (point-min) (point-max)))) + +(defun rrm/repaint () + "Start from the anchor and draw a rectangle between it and point." + (if (not rectangular-region-mode) + (remove-hook 'post-command-hook 'rrm/repaint t) + ;; else + (rrm/remove-rectangular-region-overlays) + (let* ((annoying-arrows-mode nil) + (point-column (current-column)) + (point-line (line-number-at-pos)) + (anchor-column (save-excursion (goto-char rrm/anchor) (current-column))) + (anchor-line (save-excursion (goto-char rrm/anchor) (line-number-at-pos))) + (left-column (if (< point-column anchor-column) point-column anchor-column)) + (right-column (if (> point-column anchor-column) point-column anchor-column)) + (navigation-step (if (< point-line anchor-line) 1 -1))) + (move-to-column anchor-column) + (set-mark (point)) + (move-to-column point-column) + (mc/save-excursion + (while (not (= anchor-line (line-number-at-pos))) + (forward-line navigation-step) + (move-to-column anchor-column) + (when (= anchor-column (current-column)) + (set-mark (point)) + (move-to-column point-column) + (when (= point-column (current-column)) + (mc/create-fake-cursor-at-point)))))))) + +(defun rrm/switch-to-multiple-cursors (&rest forms) + "Switch from rectangular-region-mode to multiple-cursors-mode." + (interactive) + (rectangular-region-mode 0) + (multiple-cursors-mode 1)) + +(defadvice er/expand-region (before switch-from-rrm-to-mc activate) + (when rectangular-region-mode + (rrm/switch-to-multiple-cursors))) + +(defadvice kill-ring-save (before switch-from-rrm-to-mc activate) + (when rectangular-region-mode + (rrm/switch-to-multiple-cursors))) + +(define-minor-mode rectangular-region-mode + "A mode for creating a rectangular region to edit" + nil " rr" rectangular-region-mode-map + (if rectangular-region-mode + (progn + (add-hook 'after-change-functions 'rrm/switch-to-multiple-cursors t t) + (add-hook 'post-command-hook 'rrm/repaint t t)) + (remove-hook 'after-change-functions 'rrm/switch-to-multiple-cursors t) + (remove-hook 'post-command-hook 'rrm/repaint t) + (set-marker rrm/anchor nil))) + +(provide 'rectangular-region-mode) + +;;; rectangular-region-mode.el ends here diff --git a/emacs/.emacs.d/multiple-cursors/run-tests.sh b/emacs/.emacs.d/multiple-cursors/run-tests.sh @@ -0,0 +1,2 @@ +#!/bin/sh -e +cask exec ecukes "$@" --no-win diff --git a/emacs/.emacs.d/multiple-cursors/run-travis-ci.sh b/emacs/.emacs.d/multiple-cursors/run-travis-ci.sh @@ -0,0 +1,13 @@ +#!/bin/sh -e + +cd "$(dirname "$0")" + +ECUKES_EMACS=${EMACS:-$(which emacs)} +export ECUKES_EMACS + +echo "*** Emacs version ***" +echo "ECUKES_EMACS = $ECUKES_EMACS" +"$ECUKES_EMACS" --version +echo + +exec ./run-tests.sh $TAGS diff --git a/emacs/.emacs.d/multiple-cursors/watch-tests.watchr b/emacs/.emacs.d/multiple-cursors/watch-tests.watchr @@ -0,0 +1,45 @@ +ENV["WATCHR"] = "1" +system 'clear' + +def run(cmd) + `#{cmd}` +end + +def run_all_tests + system('clear') + result = run "./run-tests.sh" + puts result +end + +def run_test(file) + system('clear') + result = run "./run-tests.sh #{file} --verbose" + puts result +end + +run_all_tests +watch('.*.feature') { |file| run_test file } +watch('.*.el') { run_all_tests } + +# Ctrl-\ +Signal.trap 'QUIT' do + puts " --- Running all tests ---\n\n" + run_all_tests +end + +@interrupted = false + +# Ctrl-C +Signal.trap 'INT' do + if @interrupted then + @wants_to_quit = true + abort("\n") + else + puts "Interrupt a second time to quit" + @interrupted = true + Kernel.sleep 1.5 + # raise Interrupt, nil # let the run loop catch it + run_all_tests + @interrupted = false + end +end diff --git a/emacs/.emacs.d/php-mode.el b/emacs/.emacs.d/php-mode.el @@ -0,0 +1,1103 @@ +;;; php-mode.el --- major mode for editing PHP code + +;; Copyright (C) 1999, 2000, 2001, 2003, 2004 Turadg Aleahmad +;; 2008 Aaron S. Hawley + +;; Maintainer: Aaron S. Hawley <ashawley at users.sourceforge.net> +;; Author: Turadg Aleahmad, 1999-2004 +;; Keywords: php languages oop +;; Created: 1999-05-17 +;; Modified: 2008-11-04 +;; X-URL: http://php-mode.sourceforge.net/ + +(defconst php-mode-version-number "1.5.0" + "PHP Mode version number.") + +;;; License + +;; This file 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 file 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 file; if not, write to the Free Software +;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +;; 02110-1301, USA. + +;;; Usage + +;; Put this file in your Emacs lisp path (eg. site-lisp) and add to +;; your .emacs file: +;; +;; (require 'php-mode) + +;; To use abbrev-mode, add lines like this: +;; (add-hook 'php-mode-hook +;; '(lambda () (define-abbrev php-mode-abbrev-table "ex" "extends"))) + +;; To make php-mode compatible with html-mode, see http://php-mode.sf.net + +;; Many options available under Help:Customize +;; Options specific to php-mode are in +;; Programming/Languages/Php +;; Since it inherits much functionality from c-mode, look there too +;; Programming/Languages/C + +;;; Commentary: + +;; PHP mode is a major mode for editing PHP 3 and 4 source code. It's +;; an extension of C mode; thus it inherits all C mode's navigation +;; functionality. But it colors according to the PHP grammar and indents +;; according to the PEAR coding guidelines. It also includes a couple +;; handy IDE-type features such as documentation search and a source +;; and class browser. + +;;; Contributors: (in chronological order) + +;; Juanjo, Torsten Martinsen, Vinai Kopp, Sean Champ, Doug Marcey, +;; Kevin Blake, Rex McMaster, Mathias Meyer, Boris Folgmann, Roland +;; Rosenfeld, Fred Yankowski, Craig Andrews, John Keller, Ryan +;; Sammartino, ppercot, Valentin Funk, Stig Bakken, Gregory Stark, +;; Chris Morris, Nils Rennebarth, Gerrit Riessen, Eric Mc Sween, +;; Ville Skytta, Giacomo Tesio, Lennart Borgman, Stefan Monnier, +;; Aaron S. Hawley, Ian Eure, Bill Lovett, Dias Badekas, David House + +;;; Changelog: + +;; 1.5 +;; Support function keywords like public, private and the ampersand +;; character for function-based commands. Support abstract, final, +;; static, public, private and protected keywords in Imenu. Fix +;; reversed order of Imenu entries. Use font-lock-preprocessor-face +;; for PHP and ASP tags. Make php-mode-modified a literal value +;; rather than a computed string. Add date and time constants of +;; PHP. (Dias Badekas) Fix false syntax highlighting of keywords +;; because of underscore character. Change HTML indentation warning +;; to match only HTML at the beginning of the line. Fix +;; byte-compiler warnings. Clean-up whitespace and audited style +;; consistency of code. Remove conditional bindings and XEmacs code +;; that likely does nothing. +;; +;; 1.4 +;; Updated GNU GPL to version 3. Ported to Emacs 22 (CC mode +;; 5.31). M-x php-mode-version shows version. Provide end-of-defun +;; beginning-of-defun functionality. Support add-log library. +;; Fix __CLASS__ constant (Ian Eure). Allow imenu to see visibility +;; declarations -- "private", "public", "protected". (Bill Lovett) +;; +;; 1.3 +;; Changed the definition of # using a tip from Stefan +;; Monnier to correct highlighting and indentation. (Lennart Borgman) +;; Changed the highlighting of the HTML part. (Lennart Borgman) +;; +;; See the ChangeLog file included with the source package. + + +;;; Code: + +(require 'speedbar) +(require 'font-lock) +(require 'cc-mode) +(require 'cc-langs) +(require 'custom) +(require 'etags) +(eval-when-compile + (require 'regexp-opt)) + +;; Local variables +(defgroup php nil + "Major mode `php-mode' for editing PHP code." + :prefix "php-" + :group 'languages) + +(defcustom php-default-face 'default + "Default face in `php-mode' buffers." + :type 'face + :group 'php) + +(defcustom php-speedbar-config t + "When set to true automatically configures Speedbar to observe PHP files. +Ignores php-file patterns option; fixed to expression \"\\.\\(inc\\|php[s34]?\\)\"" + :type 'boolean + :set (lambda (sym val) + (set-default sym val) + (if (and val (boundp 'speedbar)) + (speedbar-add-supported-extension + "\\.\\(inc\\|php[s34]?\\|phtml\\)"))) + :group 'php) + +(defcustom php-mode-speedbar-open nil + "Normally `php-mode' starts with the speedbar closed. +Turning this on will open it whenever `php-mode' is loaded." + :type 'boolean + :set (lambda (sym val) + (set-default sym val) + (when val + (speedbar 1))) + :group 'php) + +(defvar php-imenu-generic-expression + '( + ("Private Methods" + "^\\s-*\\(?:\\(?:abstract\\|final\\)\\s-+\\)?private\\s-+\\(?:static\\s-+\\)?function\\s-+\\(\\(?:\\sw\\|\\s_\\)+\\)\\s-*(" 1) + ("Protected Methods" + "^\\s-*\\(?:\\(?:abstract\\|final\\)\\s-+\\)?protected\\s-+\\(?:static\\s-+\\)?function\\s-+\\(\\(?:\\sw\\|\\s_\\)+\\)\\s-*(" 1) + ("Public Methods" + "^\\s-*\\(?:\\(?:abstract\\|final\\)\\s-+\\)?public\\s-+\\(?:static\\s-+\\)?function\\s-+\\(\\(?:\\sw\\|\\s_\\)+\\)\\s-*(" 1) + ("Classes" + "^\\s-*class\\s-+\\(\\(?:\\sw\\|\\s_\\)+\\)\\s-*" 1) + ("All Functions" + "^\\s-*\\(?:\\(?:abstract\\|final\\|private\\|protected\\|public\\|static\\)\\s-+\\)*function\\s-+\\(\\(?:\\sw\\|\\s_\\)+\\)\\s-*(" 1) + ) + "Imenu generic expression for PHP Mode. See `imenu-generic-expression'." + ) + +(defcustom php-manual-url "http://www.php.net/manual/en/" + "URL at which to find PHP manual. +You can replace \"en\" with your ISO language code." + :type 'string + :group 'php) + +(defcustom php-search-url "http://www.php.net/" + "URL at which to search for documentation on a word." + :type 'string + :group 'php) + +(defcustom php-completion-file "" + "Path to the file which contains the function names known to PHP." + :type 'string + :group 'php) + +(defcustom php-manual-path "" + "Path to the directory which contains the PHP manual." + :type 'string + :group 'php) + +;;;###autoload +(defcustom php-file-patterns '("\\.php[s34]?\\'" "\\.phtml\\'" "\\.inc\\'") + "List of file patterns for which to automatically invoke `php-mode'." + :type '(repeat (regexp :tag "Pattern")) + :set (lambda (sym val) + (set-default sym val) + (let ((php-file-patterns-temp val)) + (while php-file-patterns-temp + (add-to-list 'auto-mode-alist + (cons (car php-file-patterns-temp) 'php-mode)) + (setq php-file-patterns-temp (cdr php-file-patterns-temp))))) + :group 'php) + +(defcustom php-mode-hook nil + "List of functions to be executed on entry to `php-mode'." + :type 'hook + :group 'php) + +(defcustom php-mode-pear-hook nil + "Hook called when a PHP PEAR file is opened with `php-mode'." + :type 'hook + :group 'php) + +(defcustom php-mode-force-pear nil + "Normally PEAR coding rules are enforced only when the filename contains \"PEAR.\" +Turning this on will force PEAR rules on all PHP files." + :type 'boolean + :group 'php) + +(defconst php-mode-modified "2008-11-04" + "PHP Mode build date.") + +(defun php-mode-version () + "Display string describing the version of PHP mode." + (interactive) + (message "PHP mode %s of %s" + php-mode-version-number php-mode-modified)) + +(defconst php-beginning-of-defun-regexp + "^\\s-*\\(?:\\(?:abstract\\|final\\|private\\|protected\\|public\\|static\\)\\s-+\\)*function\\s-+&?\\(\\(?:\\sw\\|\\s_\\)+\\)\\s-*(" + "Regular expression for a PHP function.") + +(defun php-beginning-of-defun (&optional arg) + "Move to the beginning of the ARGth PHP function from point. +Implements PHP version of `beginning-of-defun-function'." + (interactive "p") + (let ((arg (or arg 1))) + (while (> arg 0) + (re-search-backward php-beginning-of-defun-regexp + nil 'noerror) + (setq arg (1- arg))) + (while (< arg 0) + (end-of-line 1) + (let ((opoint (point))) + (beginning-of-defun 1) + (forward-list 2) + (forward-line 1) + (if (eq opoint (point)) + (re-search-forward php-beginning-of-defun-regexp + nil 'noerror)) + (setq arg (1+ arg)))))) + +(defun php-end-of-defun (&optional arg) + "Move the end of the ARGth PHP function from point. +Implements PHP befsion of `end-of-defun-function' + +See `php-beginning-of-defun'." + (interactive "p") + (php-beginning-of-defun (- (or arg 1)))) + + +(defvar php-warned-bad-indent nil) +(make-variable-buffer-local 'php-warned-bad-indent) + +;; Do it but tell it is not good if html tags in buffer. +(defun php-check-html-for-indentation () + (let ((html-tag-re "^\\s-*</?\\sw+.*?>") + (here (point))) + (if (not (or (re-search-forward html-tag-re (line-end-position) t) + (re-search-backward html-tag-re (line-beginning-position) t))) + t + (goto-char here) + (setq php-warned-bad-indent t) + (lwarn 'php-indent :warning + "\n\t%s\n\t%s\n\t%s\n" + "Indentation fails badly with mixed HTML and PHP." + "Look for an Emacs Lisp library that supports \"multiple" + "major modes\" like mumamo, mmm-mode or multi-mode.") + nil))) + +(defun php-cautious-indent-region (start end &optional quiet) + (if (or php-warned-bad-indent + (php-check-html-for-indentation)) + (funcall 'c-indent-region start end quiet))) + +(defun php-cautious-indent-line () + (if (or php-warned-bad-indent + (php-check-html-for-indentation)) + (funcall 'c-indent-line))) + +(defconst php-tags '("<?php" "?>" "<?" "<?=")) +(defconst php-tags-key (regexp-opt php-tags)) + +(defconst php-block-stmt-1-kwds '("do" "else" "finally" "try")) +(defconst php-block-stmt-2-kwds + '("for" "if" "while" "switch" "foreach" "elseif" "catch all")) + +(defconst php-block-stmt-1-key + (regexp-opt php-block-stmt-1-kwds)) +(defconst php-block-stmt-2-key + (regexp-opt php-block-stmt-2-kwds)) + +(defconst php-class-decl-kwds '("class" "interface")) + +(defconst php-class-key + (concat + "\\(" (regexp-opt php-class-decl-kwds) "\\)\\s-+" + (c-lang-const c-symbol-key c) ;; Class name. + "\\(\\s-+extends\\s-+" (c-lang-const c-symbol-key c) "\\)?" ;; Name of superclass. + "\\(\\s-+implements\\s-+[^{]+{\\)?")) ;; List of any adopted protocols. + +;;;###autoload +(define-derived-mode php-mode c-mode "PHP" + "Major mode for editing PHP code.\n\n\\{php-mode-map}" + (c-add-language 'php-mode 'c-mode) + +;; PHP doesn't have C-style macros. +;; HACK: Overwrite this syntax with rules to match <?php and others. +;; (c-lang-defconst c-opt-cpp-start php php-tags-key) +;; (c-lang-defvar c-opt-cpp-start (c-lang-const c-opt-cpp-start)) + (set (make-local-variable 'c-opt-cpp-start) php-tags-key) +;; (c-lang-defconst c-opt-cpp-start php php-tags-key) +;; (c-lang-defvar c-opt-cpp-start (c-lang-const c-opt-cpp-start)) + (set (make-local-variable 'c-opt-cpp-prefix) php-tags-key) + + (c-set-offset 'cpp-macro 0) + +;; (c-lang-defconst c-block-stmt-1-kwds php php-block-stmt-1-kwds) +;; (c-lang-defvar c-block-stmt-1-kwds (c-lang-const c-block-stmt-1-kwds)) + (set (make-local-variable 'c-block-stmt-1-key) php-block-stmt-1-key) + +;; (c-lang-defconst c-block-stmt-2-kwds php php-block-stmt-2-kwds) +;; (c-lang-defvar c-block-stmt-2-kwds (c-lang-const c-block-stmt-2-kwds)) + (set (make-local-variable 'c-block-stmt-2-key) php-block-stmt-2-key) + + ;; Specify that cc-mode recognize Javadoc comment style + (set (make-local-variable 'c-doc-comment-style) + '((php-mode . javadoc))) + +;; (c-lang-defconst c-class-decl-kwds +;; php php-class-decl-kwds) + (set (make-local-variable 'c-class-key) php-class-key) + + (make-local-variable 'font-lock-defaults) + (setq font-lock-defaults + '((php-font-lock-keywords-1 + php-font-lock-keywords-2 + ;; Comment-out the next line if the font-coloring is too + ;; extreme/ugly for you. + php-font-lock-keywords-3) + nil ; KEYWORDS-ONLY + t ; CASE-FOLD + (("_" . "w")) ; SYNTAX-ALIST + nil)) ; SYNTAX-BEGIN + + ;; Electric behaviour must be turned off, they do not work since + ;; they can not find the correct syntax in embedded PHP. + ;; + ;; Seems to work with narrowing so let it be on if the user prefers it. + ;;(setq c-electric-flag nil) + + (setq font-lock-maximum-decoration t + case-fold-search t ; PHP vars are case-sensitive + imenu-generic-expression php-imenu-generic-expression) + + ;; Do not force newline at end of file. Such newlines can cause + ;; trouble if the PHP file is included in another file before calls + ;; to header() or cookie(). + (set (make-local-variable 'require-final-newline) nil) + (set (make-local-variable 'next-line-add-newlines) nil) + + ;; PEAR coding standards + (add-hook 'php-mode-pear-hook + (lambda () + (set (make-local-variable 'tab-width) 4) + (set (make-local-variable 'c-basic-offset) 4) + (set (make-local-variable 'indent-tabs-mode) nil) + (c-set-offset 'block-open' - ) + (c-set-offset 'block-close' 0 )) nil t) + + (if (or php-mode-force-pear + (and (stringp buffer-file-name) + (string-match "PEAR\\|pear" + (buffer-file-name)) + (string-match "\\.php$" (buffer-file-name)))) + (run-hooks 'php-mode-pear-hook)) + + (setq indent-line-function 'php-cautious-indent-line) + (setq indent-region-function 'php-cautious-indent-region) + (setq c-special-indent-hook nil) + + (set (make-local-variable 'beginning-of-defun-function) + 'php-beginning-of-defun) + (set (make-local-variable 'end-of-defun-function) + 'php-end-of-defun) + (set (make-local-variable 'open-paren-in-column-0-is-defun-start) + nil) + (set (make-local-variable 'defun-prompt-regexp) + "^\\s-*function\\s-+&?\\s-*\\(\\(\\sw\\|\\s_\\)+\\)\\s-*") + (set (make-local-variable 'add-log-current-defun-header-regexp) + php-beginning-of-defun-regexp) + + (run-hooks 'php-mode-hook)) + +;; Make a menu keymap (with a prompt string) +;; and make it the menu bar item's definition. +(define-key php-mode-map [menu-bar] (make-sparse-keymap)) +(define-key php-mode-map [menu-bar php] + (cons "PHP" (make-sparse-keymap "PHP"))) + +;; Define specific subcommands in this menu. +(define-key php-mode-map [menu-bar php complete-function] + '("Complete function name" . php-complete-function)) +(define-key php-mode-map + [menu-bar php browse-manual] + '("Browse manual" . php-browse-manual)) +(define-key php-mode-map + [menu-bar php search-documentation] + '("Search documentation" . php-search-documentation)) + +;; Define function name completion function +(defvar php-completion-table nil + "Obarray of tag names defined in current tags table and functions known to PHP.") + +(defun php-complete-function () + "Perform function completion on the text around point. +Completes to the set of names listed in the current tags table +and the standard php functions. +The string to complete is chosen in the same way as the default +for \\[find-tag] (which see)." + (interactive) + (let ((pattern (php-get-pattern)) + beg + completion + (php-functions (php-completion-table))) + (if (not pattern) (message "Nothing to complete") + (search-backward pattern) + (setq beg (point)) + (forward-char (length pattern)) + (setq completion (try-completion pattern php-functions nil)) + (cond ((eq completion t)) + ((null completion) + (message "Can't find completion for \"%s\"" pattern) + (ding)) + ((not (string= pattern completion)) + (delete-region beg (point)) + (insert completion)) + (t + (message "Making completion list...") + (with-output-to-temp-buffer "*Completions*" + (display-completion-list + (all-completions pattern php-functions))) + (message "Making completion list...%s" "done")))))) + +(defun php-completion-table () + "Build variable `php-completion-table' on demand. +The table includes the PHP functions and the tags from the +current `tags-file-name'." + (or (and tags-file-name + (save-excursion (tags-verify-table tags-file-name)) + php-completion-table) + (let ((tags-table + (if (and tags-file-name + (functionp 'etags-tags-completion-table)) + (with-current-buffer (get-file-buffer tags-file-name) + (etags-tags-completion-table)) + nil)) + (php-table + (cond ((and (not (string= "" php-completion-file)) + (file-readable-p php-completion-file)) + (php-build-table-from-file php-completion-file)) + (php-manual-path + (php-build-table-from-path php-manual-path)) + (t nil)))) + (unless (or php-table tags-table) + (error + (concat "No TAGS file active nor are " + "`php-completion-file' or `php-manual-path' set"))) + (when tags-table + ;; Combine the tables. + (mapatoms (lambda (sym) (intern (symbol-name sym) php-table)) + tags-table)) + (setq php-completion-table php-table)))) + +(defun php-build-table-from-file (filename) + (let ((table (make-vector 1022 0)) + (buf (find-file-noselect filename))) + (save-excursion + (set-buffer buf) + (goto-char (point-min)) + (while (re-search-forward + "^\\([-a-zA-Z0-9_.]+\\)\n" + nil t) + (intern (buffer-substring (match-beginning 1) (match-end 1)) + table))) + (kill-buffer buf) + table)) + +(defun php-build-table-from-path (path) + (let ((table (make-vector 1022 0)) + (files (directory-files + path + nil + "^function\\..+\\.html$"))) + (mapc (lambda (file) + (string-match "\\.\\([-a-zA-Z_0-9]+\\)\\.html$" file) + (intern + (replace-regexp-in-string + "-" "_" (substring file (match-beginning 1) (match-end 1)) t) + table)) + files) + table)) + +;; Find the pattern we want to complete +;; find-tag-default from GNU Emacs etags.el +(defun php-get-pattern () + (save-excursion + (while (looking-at "\\sw\\|\\s_") + (forward-char 1)) + (if (or (re-search-backward "\\sw\\|\\s_" + (save-excursion (beginning-of-line) (point)) + t) + (re-search-forward "\\(\\sw\\|\\s_\\)+" + (save-excursion (end-of-line) (point)) + t)) + (progn (goto-char (match-end 0)) + (buffer-substring-no-properties + (point) + (progn (forward-sexp -1) + (while (looking-at "\\s'") + (forward-char 1)) + (point)))) + nil))) + +(defun php-show-arglist () + (interactive) + (let* ((tagname (php-get-pattern)) + (buf (find-tag-noselect tagname nil nil)) + arglist) + (save-excursion + (set-buffer buf) + (goto-char (point-min)) + (when (re-search-forward + (format "function\\s-+%s\\s-*(\\([^{]*\\))" tagname) + nil t) + (setq arglist (buffer-substring-no-properties + (match-beginning 1) (match-end 1))))) + (if arglist + (message "Arglist for %s: %s" tagname arglist) + (message "Unknown function: %s" tagname)))) + +;; Define function documentation function +(defun php-search-documentation () + "Search PHP documentation for the word at point." + (interactive) + (browse-url (concat php-search-url (current-word t)))) + +;; Define function for browsing manual +(defun php-browse-manual () + "Bring up manual for PHP." + (interactive) + (browse-url php-manual-url)) + +;; Define shortcut +(define-key php-mode-map + "\C-c\C-f" + 'php-search-documentation) + +;; Define shortcut +(define-key php-mode-map + [(meta tab)] + 'php-complete-function) + +;; Define shortcut +(define-key php-mode-map + "\C-c\C-m" + 'php-browse-manual) + +;; Define shortcut +(define-key php-mode-map + '[(control .)] + 'php-show-arglist) + +(defconst php-constants + (eval-when-compile + (regexp-opt + '(;; core constants + "__LINE__" "__FILE__" + "__FUNCTION__" "__CLASS__" "__METHOD__" + "PHP_OS" "PHP_VERSION" + "TRUE" "FALSE" "NULL" + "E_ERROR" "E_NOTICE" "E_PARSE" "E_WARNING" "E_ALL" "E_STRICT" + "E_USER_ERROR" "E_USER_WARNING" "E_USER_NOTICE" + "DEFAULT_INCLUDE_PATH" "PEAR_INSTALL_DIR" "PEAR_EXTENSION_DIR" + "PHP_BINDIR" "PHP_LIBDIR" "PHP_DATADIR" "PHP_SYSCONFDIR" + "PHP_LOCALSTATEDIR" "PHP_CONFIG_FILE_PATH" + "PHP_EOL" + + ;; date and time constants + "DATE_ATOM" "DATE_COOKIE" "DATE_ISO8601" + "DATE_RFC822" "DATE_RFC850" "DATE_RFC1036" "DATE_RFC1123" + "DATE_RFC2822" "DATE_RFC3339" + "DATE_RSS" "DATE_W3C" + + ;; from ext/standard: + "EXTR_OVERWRITE" "EXTR_SKIP" "EXTR_PREFIX_SAME" + "EXTR_PREFIX_ALL" "EXTR_PREFIX_INVALID" "SORT_ASC" "SORT_DESC" + "SORT_REGULAR" "SORT_NUMERIC" "SORT_STRING" "ASSERT_ACTIVE" + "ASSERT_CALLBACK" "ASSERT_BAIL" "ASSERT_WARNING" + "ASSERT_QUIET_EVAL" "CONNECTION_ABORTED" "CONNECTION_NORMAL" + "CONNECTION_TIMEOUT" "M_E" "M_LOG2E" "M_LOG10E" "M_LN2" + "M_LN10" "M_PI" "M_PI_2" "M_PI_4" "M_1_PI" "M_2_PI" + "M_2_SQRTPI" "M_SQRT2" "M_SQRT1_2" "CRYPT_SALT_LENGTH" + "CRYPT_STD_DES" "CRYPT_EXT_DES" "CRYPT_MD5" "CRYPT_BLOWFISH" + "DIRECTORY_SEPARATOR" "SEEK_SET" "SEEK_CUR" "SEEK_END" + "LOCK_SH" "LOCK_EX" "LOCK_UN" "LOCK_NB" "HTML_SPECIALCHARS" + "HTML_ENTITIES" "ENT_COMPAT" "ENT_QUOTES" "ENT_NOQUOTES" + "INFO_GENERAL" "INFO_CREDITS" "INFO_CONFIGURATION" + "INFO_ENVIRONMENT" "INFO_VARIABLES" "INFO_LICENSE" "INFO_ALL" + "CREDITS_GROUP" "CREDITS_GENERAL" "CREDITS_SAPI" + "CREDITS_MODULES" "CREDITS_DOCS" "CREDITS_FULLPAGE" + "CREDITS_QA" "CREDITS_ALL" "PHP_OUTPUT_HANDLER_START" + "PHP_OUTPUT_HANDLER_CONT" "PHP_OUTPUT_HANDLER_END" + "STR_PAD_LEFT" "STR_PAD_RIGHT" "STR_PAD_BOTH" + "PATHINFO_DIRNAME" "PATHINFO_BASENAME" "PATHINFO_EXTENSION" + "CHAR_MAX" "LC_CTYPE" "LC_NUMERIC" "LC_TIME" "LC_COLLATE" + "LC_MONETARY" "LC_ALL" "LC_MESSAGES" "LOG_EMERG" "LOG_ALERT" + "LOG_CRIT" "LOG_ERR" "LOG_WARNING" "LOG_NOTICE" "LOG_INFO" + "LOG_DEBUG" "LOG_KERN" "LOG_USER" "LOG_MAIL" "LOG_DAEMON" + "LOG_AUTH" "LOG_SYSLOG" "LOG_LPR" "LOG_NEWS" "LOG_UUCP" + "LOG_CRON" "LOG_AUTHPRIV" "LOG_LOCAL0" "LOG_LOCAL1" + "LOG_LOCAL2" "LOG_LOCAL3" "LOG_LOCAL4" "LOG_LOCAL5" + "LOG_LOCAL6" "LOG_LOCAL7" "LOG_PID" "LOG_CONS" "LOG_ODELAY" + "LOG_NDELAY" "LOG_NOWAIT" "LOG_PERROR" + + ;; Disabled by default because they slow buffer loading + ;; If you have use for them, uncomment the strings + ;; that you want colored. + ;; To compile, you may have to increase 'max-specpdl-size' + + ;; from other bundled extensions: +; "CAL_EASTER_TO_xxx" "VT_NULL" "VT_EMPTY" "VT_UI1" "VT_I2" +; "VT_I4" "VT_R4" "VT_R8" "VT_BOOL" "VT_ERROR" "VT_CY" "VT_DATE" +; "VT_BSTR" "VT_DECIMAL" "VT_UNKNOWN" "VT_DISPATCH" "VT_VARIANT" +; "VT_I1" "VT_UI2" "VT_UI4" "VT_INT" "VT_UINT" "VT_ARRAY" +; "VT_BYREF" "CP_ACP" "CP_MACCP" "CP_OEMCP" "CP_SYMBOL" +; "CP_THREAD_ACP" "CP_UTF7" "CP_UTF8" "CPDF_PM_NONE" +; "CPDF_PM_OUTLINES" "CPDF_PM_THUMBS" "CPDF_PM_FULLSCREEN" +; "CPDF_PL_SINGLE" "CPDF_PL_1COLUMN" "CPDF_PL_2LCOLUMN" +; "CPDF_PL_2RCOLUMN" "CURLOPT_PORT" "CURLOPT_FILE" +; "CURLOPT_INFILE" "CURLOPT_INFILESIZE" "CURLOPT_URL" +; "CURLOPT_PROXY" "CURLOPT_VERBOSE" "CURLOPT_HEADER" +; "CURLOPT_HTTPHEADER" "CURLOPT_NOPROGRESS" "CURLOPT_NOBODY" +; "CURLOPT_FAILONERROR" "CURLOPT_UPLOAD" "CURLOPT_POST" +; "CURLOPT_FTPLISTONLY" "CURLOPT_FTPAPPEND" "CURLOPT_NETRC" +; "CURLOPT_FOLLOWLOCATION" "CURLOPT_FTPASCII" "CURLOPT_PUT" +; "CURLOPT_MUTE" "CURLOPT_USERPWD" "CURLOPT_PROXYUSERPWD" +; "CURLOPT_RANGE" "CURLOPT_TIMEOUT" "CURLOPT_POSTFIELDS" +; "CURLOPT_REFERER" "CURLOPT_USERAGENT" "CURLOPT_FTPPORT" +; "CURLOPT_LOW_SPEED_LIMIT" "CURLOPT_LOW_SPEED_TIME" +; "CURLOPT_RESUME_FROM" "CURLOPT_COOKIE" "CURLOPT_SSLCERT" +; "CURLOPT_SSLCERTPASSWD" "CURLOPT_WRITEHEADER" +; "CURLOPT_COOKIEFILE" "CURLOPT_SSLVERSION" +; "CURLOPT_TIMECONDITION" "CURLOPT_TIMEVALUE" +; "CURLOPT_CUSTOMREQUEST" "CURLOPT_STDERR" "CURLOPT_TRANSFERTEXT" +; "CURLOPT_RETURNTRANSFER" "CURLOPT_QUOTE" "CURLOPT_POSTQUOTE" +; "CURLOPT_INTERFACE" "CURLOPT_KRB4LEVEL" +; "CURLOPT_HTTPPROXYTUNNEL" "CURLOPT_FILETIME" +; "CURLOPT_WRITEFUNCTION" "CURLOPT_READFUNCTION" +; "CURLOPT_PASSWDFUNCTION" "CURLOPT_HEADERFUNCTION" +; "CURLOPT_MAXREDIRS" "CURLOPT_MAXCONNECTS" "CURLOPT_CLOSEPOLICY" +; "CURLOPT_FRESH_CONNECT" "CURLOPT_FORBID_REUSE" +; "CURLOPT_RANDOM_FILE" "CURLOPT_EGDSOCKET" +; "CURLOPT_CONNECTTIMEOUT" "CURLOPT_SSL_VERIFYPEER" +; "CURLOPT_CAINFO" "CURLOPT_BINARYTRANSER" +; "CURLCLOSEPOLICY_LEAST_RECENTLY_USED" "CURLCLOSEPOLICY_OLDEST" +; "CURLINFO_EFFECTIVE_URL" "CURLINFO_HTTP_CODE" +; "CURLINFO_HEADER_SIZE" "CURLINFO_REQUEST_SIZE" +; "CURLINFO_TOTAL_TIME" "CURLINFO_NAMELOOKUP_TIME" +; "CURLINFO_CONNECT_TIME" "CURLINFO_PRETRANSFER_TIME" +; "CURLINFO_SIZE_UPLOAD" "CURLINFO_SIZE_DOWNLOAD" +; "CURLINFO_SPEED_DOWNLOAD" "CURLINFO_SPEED_UPLOAD" +; "CURLINFO_FILETIME" "CURLE_OK" "CURLE_UNSUPPORTED_PROTOCOL" +; "CURLE_FAILED_INIT" "CURLE_URL_MALFORMAT" +; "CURLE_URL_MALFORMAT_USER" "CURLE_COULDNT_RESOLVE_PROXY" +; "CURLE_COULDNT_RESOLVE_HOST" "CURLE_COULDNT_CONNECT" +; "CURLE_FTP_WEIRD_SERVER_REPLY" "CURLE_FTP_ACCESS_DENIED" +; "CURLE_FTP_USER_PASSWORD_INCORRECT" +; "CURLE_FTP_WEIRD_PASS_REPLY" "CURLE_FTP_WEIRD_USER_REPLY" +; "CURLE_FTP_WEIRD_PASV_REPLY" "CURLE_FTP_WEIRD_227_FORMAT" +; "CURLE_FTP_CANT_GET_HOST" "CURLE_FTP_CANT_RECONNECT" +; "CURLE_FTP_COULDNT_SET_BINARY" "CURLE_PARTIAL_FILE" +; "CURLE_FTP_COULDNT_RETR_FILE" "CURLE_FTP_WRITE_ERROR" +; "CURLE_FTP_QUOTE_ERROR" "CURLE_HTTP_NOT_FOUND" +; "CURLE_WRITE_ERROR" "CURLE_MALFORMAT_USER" +; "CURLE_FTP_COULDNT_STOR_FILE" "CURLE_READ_ERROR" +; "CURLE_OUT_OF_MEMORY" "CURLE_OPERATION_TIMEOUTED" +; "CURLE_FTP_COULDNT_SET_ASCII" "CURLE_FTP_PORT_FAILED" +; "CURLE_FTP_COULDNT_USE_REST" "CURLE_FTP_COULDNT_GET_SIZE" +; "CURLE_HTTP_RANGE_ERROR" "CURLE_HTTP_POST_ERROR" +; "CURLE_SSL_CONNECT_ERROR" "CURLE_FTP_BAD_DOWNLOAD_RESUME" +; "CURLE_FILE_COULDNT_READ_FILE" "CURLE_LDAP_CANNOT_BIND" +; "CURLE_LDAP_SEARCH_FAILED" "CURLE_LIBRARY_NOT_FOUND" +; "CURLE_FUNCTION_NOT_FOUND" "CURLE_ABORTED_BY_CALLBACK" +; "CURLE_BAD_FUNCTION_ARGUMENT" "CURLE_BAD_CALLING_ORDER" +; "CURLE_HTTP_PORT_FAILED" "CURLE_BAD_PASSWORD_ENTERED" +; "CURLE_TOO_MANY_REDIRECTS" "CURLE_UNKOWN_TELNET_OPTION" +; "CURLE_TELNET_OPTION_SYNTAX" "CURLE_ALREADY_COMPLETE" +; "DBX_MYSQL" "DBX_ODBC" "DBX_PGSQL" "DBX_MSSQL" "DBX_PERSISTENT" +; "DBX_RESULT_INFO" "DBX_RESULT_INDEX" "DBX_RESULT_ASSOC" +; "DBX_CMP_TEXT" "DBX_CMP_NUMBER" "XML_ELEMENT_NODE" +; "XML_ATTRIBUTE_NODE" "XML_TEXT_NODE" "XML_CDATA_SECTION_NODE" +; "XML_ENTITY_REF_NODE" "XML_ENTITY_NODE" "XML_PI_NODE" +; "XML_COMMENT_NODE" "XML_DOCUMENT_NODE" "XML_DOCUMENT_TYPE_NODE" +; "XML_DOCUMENT_FRAG_NODE" "XML_NOTATION_NODE" +; "XML_HTML_DOCUMENT_NODE" "XML_DTD_NODE" "XML_ELEMENT_DECL_NODE" +; "XML_ATTRIBUTE_DECL_NODE" "XML_ENTITY_DECL_NODE" +; "XML_NAMESPACE_DECL_NODE" "XML_GLOBAL_NAMESPACE" +; "XML_LOCAL_NAMESPACE" "XML_ATTRIBUTE_CDATA" "XML_ATTRIBUTE_ID" +; "XML_ATTRIBUTE_IDREF" "XML_ATTRIBUTE_IDREFS" +; "XML_ATTRIBUTE_ENTITY" "XML_ATTRIBUTE_NMTOKEN" +; "XML_ATTRIBUTE_NMTOKENS" "XML_ATTRIBUTE_ENUMERATION" +; "XML_ATTRIBUTE_NOTATION" "XPATH_UNDEFINED" "XPATH_NODESET" +; "XPATH_BOOLEAN" "XPATH_NUMBER" "XPATH_STRING" "XPATH_POINT" +; "XPATH_RANGE" "XPATH_LOCATIONSET" "XPATH_USERS" "FBSQL_ASSOC" +; "FBSQL_NUM" "FBSQL_BOTH" "FDFValue" "FDFStatus" "FDFFile" +; "FDFID" "FDFFf" "FDFSetFf" "FDFClearFf" "FDFFlags" "FDFSetF" +; "FDFClrF" "FDFAP" "FDFAS" "FDFAction" "FDFAA" "FDFAPRef" +; "FDFIF" "FDFEnter" "FDFExit" "FDFDown" "FDFUp" "FDFFormat" +; "FDFValidate" "FDFKeystroke" "FDFCalculate" +; "FRIBIDI_CHARSET_UTF8" "FRIBIDI_CHARSET_8859_6" +; "FRIBIDI_CHARSET_8859_8" "FRIBIDI_CHARSET_CP1255" +; "FRIBIDI_CHARSET_CP1256" "FRIBIDI_CHARSET_ISIRI_3342" +; "FTP_ASCII" "FTP_BINARY" "FTP_IMAGE" "FTP_TEXT" "IMG_GIF" +; "IMG_JPG" "IMG_JPEG" "IMG_PNG" "IMG_WBMP" "IMG_COLOR_TILED" +; "IMG_COLOR_STYLED" "IMG_COLOR_BRUSHED" +; "IMG_COLOR_STYLEDBRUSHED" "IMG_COLOR_TRANSPARENT" +; "IMG_ARC_ROUNDED" "IMG_ARC_PIE" "IMG_ARC_CHORD" +; "IMG_ARC_NOFILL" "IMG_ARC_EDGED" "GMP_ROUND_ZERO" +; "GMP_ROUND_PLUSINF" "GMP_ROUND_MINUSINF" "HW_ATTR_LANG" +; "HW_ATTR_NR" "HW_ATTR_NONE" "IIS_READ" "IIS_WRITE" +; "IIS_EXECUTE" "IIS_SCRIPT" "IIS_ANONYMOUS" "IIS_BASIC" +; "IIS_NTLM" "NIL" "OP_DEBUG" "OP_READONLY" "OP_ANONYMOUS" +; "OP_SHORTCACHE" "OP_SILENT" "OP_PROTOTYPE" "OP_HALFOPEN" +; "OP_EXPUNGE" "OP_SECURE" "CL_EXPUNGE" "FT_UID" "FT_PEEK" +; "FT_NOT" "FT_INTERNAL" "FT_PREFETCHTEXT" "ST_UID" "ST_SILENT" +; "ST_SET" "CP_UID" "CP_MOVE" "SE_UID" "SE_FREE" "SE_NOPREFETCH" +; "SO_FREE" "SO_NOSERVER" "SA_MESSAGES" "SA_RECENT" "SA_UNSEEN" +; "SA_UIDNEXT" "SA_UIDVALIDITY" "SA_ALL" "LATT_NOINFERIORS" +; "LATT_NOSELECT" "LATT_MARKED" "LATT_UNMARKED" "SORTDATE" +; "SORTARRIVAL" "SORTFROM" "SORTSUBJECT" "SORTTO" "SORTCC" +; "SORTSIZE" "TYPETEXT" "TYPEMULTIPART" "TYPEMESSAGE" +; "TYPEAPPLICATION" "TYPEAUDIO" "TYPEIMAGE" "TYPEVIDEO" +; "TYPEOTHER" "ENC7BIT" "ENC8BIT" "ENCBINARY" "ENCBASE64" +; "ENCQUOTEDPRINTABLE" "ENCOTHER" "INGRES_ASSOC" "INGRES_NUM" +; "INGRES_BOTH" "IBASE_DEFAULT" "IBASE_TEXT" "IBASE_UNIXTIME" +; "IBASE_READ" "IBASE_COMMITTED" "IBASE_CONSISTENCY" +; "IBASE_NOWAIT" "IBASE_TIMESTAMP" "IBASE_DATE" "IBASE_TIME" +; "LDAP_DEREF_NEVER" "LDAP_DEREF_SEARCHING" "LDAP_DEREF_FINDING" +; "LDAP_DEREF_ALWAYS" "LDAP_OPT_DEREF" "LDAP_OPT_SIZELIMIT" +; "LDAP_OPT_TIMELIMIT" "LDAP_OPT_PROTOCOL_VERSION" +; "LDAP_OPT_ERROR_NUMBER" "LDAP_OPT_REFERRALS" "LDAP_OPT_RESTART" +; "LDAP_OPT_HOST_NAME" "LDAP_OPT_ERROR_STRING" +; "LDAP_OPT_MATCHED_DN" "LDAP_OPT_SERVER_CONTROLS" +; "LDAP_OPT_CLIENT_CONTROLS" "GSLC_SSL_NO_AUTH" +; "GSLC_SSL_ONEWAY_AUTH" "GSLC_SSL_TWOWAY_AUTH" "MCAL_SUNDAY" +; "MCAL_MONDAY" "MCAL_TUESDAY" "MCAL_WEDNESDAY" "MCAL_THURSDAY" +; "MCAL_FRIDAY" "MCAL_SATURDAY" "MCAL_JANUARY" "MCAL_FEBRUARY" +; "MCAL_MARCH" "MCAL_APRIL" "MCAL_MAY" "MCAL_JUNE" "MCAL_JULY" +; "MCAL_AUGUST" "MCAL_SEPTEMBER" "MCAL_OCTOBER" "MCAL_NOVEMBER" +; "MCAL_RECUR_NONE" "MCAL_RECUR_DAILY" "MCAL_RECUR_WEEKLY" +; "MCAL_RECUR_MONTHLY_MDAY" "MCAL_RECUR_MONTHLY_WDAY" +; "MCAL_RECUR_YEARLY" "MCAL_M_SUNDAY" "MCAL_M_MONDAY" +; "MCAL_M_TUESDAY" "MCAL_M_WEDNESDAY" "MCAL_M_THURSDAY" +; "MCAL_M_FRIDAY" "MCAL_M_SATURDAY" "MCAL_M_WEEKDAYS" +; "MCAL_M_WEEKEND" "MCAL_M_ALLDAYS" "MCRYPT_" "MCRYPT_" +; "MCRYPT_ENCRYPT" "MCRYPT_DECRYPT" "MCRYPT_DEV_RANDOM" +; "MCRYPT_DEV_URANDOM" "MCRYPT_RAND" "SWFBUTTON_HIT" +; "SUNFUNCS_RET_STRING" "SUNFUNCS_RET_DOUBLE" +; "SWFBUTTON_DOWN" "SWFBUTTON_OVER" "SWFBUTTON_UP" +; "SWFBUTTON_MOUSEUPOUTSIDE" "SWFBUTTON_DRAGOVER" +; "SWFBUTTON_DRAGOUT" "SWFBUTTON_MOUSEUP" "SWFBUTTON_MOUSEDOWN" +; "SWFBUTTON_MOUSEOUT" "SWFBUTTON_MOUSEOVER" +; "SWFFILL_RADIAL_GRADIENT" "SWFFILL_LINEAR_GRADIENT" +; "SWFFILL_TILED_BITMAP" "SWFFILL_CLIPPED_BITMAP" +; "SWFTEXTFIELD_HASLENGTH" "SWFTEXTFIELD_NOEDIT" +; "SWFTEXTFIELD_PASSWORD" "SWFTEXTFIELD_MULTILINE" +; "SWFTEXTFIELD_WORDWRAP" "SWFTEXTFIELD_DRAWBOX" +; "SWFTEXTFIELD_NOSELECT" "SWFTEXTFIELD_HTML" +; "SWFTEXTFIELD_ALIGN_LEFT" "SWFTEXTFIELD_ALIGN_RIGHT" +; "SWFTEXTFIELD_ALIGN_CENTER" "SWFTEXTFIELD_ALIGN_JUSTIFY" +; "UDM_FIELD_URLID" "UDM_FIELD_URL" "UDM_FIELD_CONTENT" +; "UDM_FIELD_TITLE" "UDM_FIELD_KEYWORDS" "UDM_FIELD_DESC" +; "UDM_FIELD_DESCRIPTION" "UDM_FIELD_TEXT" "UDM_FIELD_SIZE" +; "UDM_FIELD_RATING" "UDM_FIELD_SCORE" "UDM_FIELD_MODIFIED" +; "UDM_FIELD_ORDER" "UDM_FIELD_CRC" "UDM_FIELD_CATEGORY" +; "UDM_PARAM_PAGE_SIZE" "UDM_PARAM_PAGE_NUM" +; "UDM_PARAM_SEARCH_MODE" "UDM_PARAM_CACHE_MODE" +; "UDM_PARAM_TRACK_MODE" "UDM_PARAM_PHRASE_MODE" +; "UDM_PARAM_CHARSET" "UDM_PARAM_STOPTABLE" +; "UDM_PARAM_STOP_TABLE" "UDM_PARAM_STOPFILE" +; "UDM_PARAM_STOP_FILE" "UDM_PARAM_WEIGHT_FACTOR" +; "UDM_PARAM_WORD_MATCH" "UDM_PARAM_MAX_WORD_LEN" +; "UDM_PARAM_MAX_WORDLEN" "UDM_PARAM_MIN_WORD_LEN" +; "UDM_PARAM_MIN_WORDLEN" "UDM_PARAM_ISPELL_PREFIXES" +; "UDM_PARAM_ISPELL_PREFIX" "UDM_PARAM_PREFIXES" +; "UDM_PARAM_PREFIX" "UDM_PARAM_CROSS_WORDS" +; "UDM_PARAM_CROSSWORDS" "UDM_LIMIT_CAT" "UDM_LIMIT_URL" +; "UDM_LIMIT_TAG" "UDM_LIMIT_LANG" "UDM_LIMIT_DATE" +; "UDM_PARAM_FOUND" "UDM_PARAM_NUM_ROWS" "UDM_PARAM_WORDINFO" +; "UDM_PARAM_WORD_INFO" "UDM_PARAM_SEARCHTIME" +; "UDM_PARAM_SEARCH_TIME" "UDM_PARAM_FIRST_DOC" +; "UDM_PARAM_LAST_DOC" "UDM_MODE_ALL" "UDM_MODE_ANY" +; "UDM_MODE_BOOL" "UDM_MODE_PHRASE" "UDM_CACHE_ENABLED" +; "UDM_CACHE_DISABLED" "UDM_TRACK_ENABLED" "UDM_TRACK_DISABLED" +; "UDM_PHRASE_ENABLED" "UDM_PHRASE_DISABLED" +; "UDM_CROSS_WORDS_ENABLED" "UDM_CROSSWORDS_ENABLED" +; "UDM_CROSS_WORDS_DISABLED" "UDM_CROSSWORDS_DISABLED" +; "UDM_PREFIXES_ENABLED" "UDM_PREFIX_ENABLED" +; "UDM_ISPELL_PREFIXES_ENABLED" "UDM_ISPELL_PREFIX_ENABLED" +; "UDM_PREFIXES_DISABLED" "UDM_PREFIX_DISABLED" +; "UDM_ISPELL_PREFIXES_DISABLED" "UDM_ISPELL_PREFIX_DISABLED" +; "UDM_ISPELL_TYPE_AFFIX" "UDM_ISPELL_TYPE_SPELL" +; "UDM_ISPELL_TYPE_DB" "UDM_ISPELL_TYPE_SERVER" "UDM_MATCH_WORD" +; "UDM_MATCH_BEGIN" "UDM_MATCH_SUBSTR" "UDM_MATCH_END" +; "MSQL_ASSOC" "MSQL_NUM" "MSQL_BOTH" "MYSQL_ASSOC" "MYSQL_NUM" +; "MYSQL_BOTH" "MYSQL_USE_RESULT" "MYSQL_STORE_RESULT" +; "OCI_DEFAULT" "OCI_DESCRIBE_ONLY" "OCI_COMMIT_ON_SUCCESS" +; "OCI_EXACT_FETCH" "SQLT_BFILEE" "SQLT_CFILEE" "SQLT_CLOB" +; "SQLT_BLOB" "SQLT_RDD" "OCI_B_SQLT_NTY" "OCI_SYSDATE" +; "OCI_B_BFILE" "OCI_B_CFILEE" "OCI_B_CLOB" "OCI_B_BLOB" +; "OCI_B_ROWID" "OCI_B_CURSOR" "OCI_B_BIN" "OCI_ASSOC" "OCI_NUM" +; "OCI_BOTH" "OCI_RETURN_NULLS" "OCI_RETURN_LOBS" +; "OCI_DTYPE_FILE" "OCI_DTYPE_LOB" "OCI_DTYPE_ROWID" "OCI_D_FILE" +; "OCI_D_LOB" "OCI_D_ROWID" "ODBC_TYPE" "ODBC_BINMODE_PASSTHRU" +; "ODBC_BINMODE_RETURN" "ODBC_BINMODE_CONVERT" "SQL_ODBC_CURSORS" +; "SQL_CUR_USE_DRIVER" "SQL_CUR_USE_IF_NEEDED" "SQL_CUR_USE_ODBC" +; "SQL_CONCURRENCY" "SQL_CONCUR_READ_ONLY" "SQL_CONCUR_LOCK" +; "SQL_CONCUR_ROWVER" "SQL_CONCUR_VALUES" "SQL_CURSOR_TYPE" +; "SQL_CURSOR_FORWARD_ONLY" "SQL_CURSOR_KEYSET_DRIVEN" +; "SQL_CURSOR_DYNAMIC" "SQL_CURSOR_STATIC" "SQL_KEYSET_SIZE" +; "SQL_CHAR" "SQL_VARCHAR" "SQL_LONGVARCHAR" "SQL_DECIMAL" +; "SQL_NUMERIC" "SQL_BIT" "SQL_TINYINT" "SQL_SMALLINT" +; "SQL_INTEGER" "SQL_BIGINT" "SQL_REAL" "SQL_FLOAT" "SQL_DOUBLE" +; "SQL_BINARY" "SQL_VARBINARY" "SQL_LONGVARBINARY" "SQL_DATE" +; "SQL_TIME" "SQL_TIMESTAMP" "SQL_TYPE_DATE" "SQL_TYPE_TIME" +; "SQL_TYPE_TIMESTAMP" "SQL_BEST_ROWID" "SQL_ROWVER" +; "SQL_SCOPE_CURROW" "SQL_SCOPE_TRANSACTION" "SQL_SCOPE_SESSION" +; "SQL_NO_NULLS" "SQL_NULLABLE" "SQL_INDEX_UNIQUE" +; "SQL_INDEX_ALL" "SQL_ENSURE" "SQL_QUICK" +; "X509_PURPOSE_SSL_CLIENT" "X509_PURPOSE_SSL_SERVER" +; "X509_PURPOSE_NS_SSL_SERVER" "X509_PURPOSE_SMIME_SIGN" +; "X509_PURPOSE_SMIME_ENCRYPT" "X509_PURPOSE_CRL_SIGN" +; "X509_PURPOSE_ANY" "PKCS7_DETACHED" "PKCS7_TEXT" +; "PKCS7_NOINTERN" "PKCS7_NOVERIFY" "PKCS7_NOCHAIN" +; "PKCS7_NOCERTS" "PKCS7_NOATTR" "PKCS7_BINARY" "PKCS7_NOSIGS" +; "OPENSSL_PKCS1_PADDING" "OPENSSL_SSLV23_PADDING" +; "OPENSSL_NO_PADDING" "OPENSSL_PKCS1_OAEP_PADDING" +; "ORA_BIND_INOUT" "ORA_BIND_IN" "ORA_BIND_OUT" +; "ORA_FETCHINTO_ASSOC" "ORA_FETCHINTO_NULLS" +; "PREG_PATTERN_ORDER" "PREG_SET_ORDER" "PREG_SPLIT_NO_EMPTY" +; "PREG_SPLIT_DELIM_CAPTURE" +; "PGSQL_ASSOC" "PGSQL_NUM" "PGSQL_BOTH" +; "PRINTER_COPIES" "PRINTER_MODE" "PRINTER_TITLE" +; "PRINTER_DEVICENAME" "PRINTER_DRIVERVERSION" +; "PRINTER_RESOLUTION_Y" "PRINTER_RESOLUTION_X" "PRINTER_SCALE" +; "PRINTER_BACKGROUND_COLOR" "PRINTER_PAPER_LENGTH" +; "PRINTER_PAPER_WIDTH" "PRINTER_PAPER_FORMAT" +; "PRINTER_FORMAT_CUSTOM" "PRINTER_FORMAT_LETTER" +; "PRINTER_FORMAT_LEGAL" "PRINTER_FORMAT_A3" "PRINTER_FORMAT_A4" +; "PRINTER_FORMAT_A5" "PRINTER_FORMAT_B4" "PRINTER_FORMAT_B5" +; "PRINTER_FORMAT_FOLIO" "PRINTER_ORIENTATION" +; "PRINTER_ORIENTATION_PORTRAIT" "PRINTER_ORIENTATION_LANDSCAPE" +; "PRINTER_TEXT_COLOR" "PRINTER_TEXT_ALIGN" "PRINTER_TA_BASELINE" +; "PRINTER_TA_BOTTOM" "PRINTER_TA_TOP" "PRINTER_TA_CENTER" +; "PRINTER_TA_LEFT" "PRINTER_TA_RIGHT" "PRINTER_PEN_SOLID" +; "PRINTER_PEN_DASH" "PRINTER_PEN_DOT" "PRINTER_PEN_DASHDOT" +; "PRINTER_PEN_DASHDOTDOT" "PRINTER_PEN_INVISIBLE" +; "PRINTER_BRUSH_SOLID" "PRINTER_BRUSH_CUSTOM" +; "PRINTER_BRUSH_DIAGONAL" "PRINTER_BRUSH_CROSS" +; "PRINTER_BRUSH_DIAGCROSS" "PRINTER_BRUSH_FDIAGONAL" +; "PRINTER_BRUSH_HORIZONTAL" "PRINTER_BRUSH_VERTICAL" +; "PRINTER_FW_THIN" "PRINTER_FW_ULTRALIGHT" "PRINTER_FW_LIGHT" +; "PRINTER_FW_NORMAL" "PRINTER_FW_MEDIUM" "PRINTER_FW_BOLD" +; "PRINTER_FW_ULTRABOLD" "PRINTER_FW_HEAVY" "PRINTER_ENUM_LOCAL" +; "PRINTER_ENUM_NAME" "PRINTER_ENUM_SHARED" +; "PRINTER_ENUM_DEFAULT" "PRINTER_ENUM_CONNECTIONS" +; "PRINTER_ENUM_NETWORK" "PRINTER_ENUM_REMOTE" "PSPELL_FAST" +; "PSPELL_NORMAL" "PSPELL_BAD_SPELLERS" "PSPELL_RUN_TOGETHER" +; "SID" "SID" "AF_UNIX" "AF_INET" "SOCK_STREAM" "SOCK_DGRAM" +; "SOCK_RAW" "SOCK_SEQPACKET" "SOCK_RDM" "MSG_OOB" "MSG_WAITALL" +; "MSG_PEEK" "MSG_DONTROUTE" "SO_DEBUG" "SO_REUSEADDR" +; "SO_KEEPALIVE" "SO_DONTROUTE" "SO_LINGER" "SO_BROADCAST" +; "SO_OOBINLINE" "SO_SNDBUF" "SO_RCVBUF" "SO_SNDLOWAT" +; "SO_RCVLOWAT" "SO_SNDTIMEO" "SO_RCVTIMEO" "SO_TYPE" "SO_ERROR" +; "SOL_SOCKET" "PHP_NORMAL_READ" "PHP_BINARY_READ" +; "PHP_SYSTEM_READ" "SOL_TCP" "SOL_UDP" "MOD_COLOR" "MOD_MATRIX" +; "TYPE_PUSHBUTTON" "TYPE_MENUBUTTON" "BSHitTest" "BSDown" +; "BSOver" "BSUp" "OverDowntoIdle" "IdletoOverDown" +; "OutDowntoIdle" "OutDowntoOverDown" "OverDowntoOutDown" +; "OverUptoOverDown" "OverUptoIdle" "IdletoOverUp" "ButtonEnter" +; "ButtonExit" "MenuEnter" "MenuExit" "XML_ERROR_NONE" +; "XML_ERROR_NO_MEMORY" "XML_ERROR_SYNTAX" +; "XML_ERROR_NO_ELEMENTS" "XML_ERROR_INVALID_TOKEN" +; "XML_ERROR_UNCLOSED_TOKEN" "XML_ERROR_PARTIAL_CHAR" +; "XML_ERROR_TAG_MISMATCH" "XML_ERROR_DUPLICATE_ATTRIBUTE" +; "XML_ERROR_JUNK_AFTER_DOC_ELEMENT" "XML_ERROR_PARAM_ENTITY_REF" +; "XML_ERROR_UNDEFINED_ENTITY" "XML_ERROR_RECURSIVE_ENTITY_REF" +; "XML_ERROR_ASYNC_ENTITY" "XML_ERROR_BAD_CHAR_REF" +; "XML_ERROR_BINARY_ENTITY_REF" +; "XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF" +; "XML_ERROR_MISPLACED_XML_PI" "XML_ERROR_UNKNOWN_ENCODING" +; "XML_ERROR_INCORRECT_ENCODING" +; "XML_ERROR_UNCLOSED_CDATA_SECTION" +; "XML_ERROR_EXTERNAL_ENTITY_HANDLING" "XML_OPTION_CASE_FOLDING" +; "XML_OPTION_TARGET_ENCODING" "XML_OPTION_SKIP_TAGSTART" +; "XML_OPTION_SKIP_WHITE" "YPERR_BADARGS" "YPERR_BADDB" +; "YPERR_BUSY" "YPERR_DOMAIN" "YPERR_KEY" "YPERR_MAP" +; "YPERR_NODOM" "YPERR_NOMORE" "YPERR_PMAP" "YPERR_RESRC" +; "YPERR_RPC" "YPERR_YPBIND" "YPERR_YPERR" "YPERR_YPSERV" +; "YPERR_VERS" "FORCE_GZIP" "FORCE_DEFLATE" + + ;; PEAR constants +; "PEAR_ERROR_RETURN" "PEAR_ERROR_PRINT" "PEAR_ERROR_TRIGGER" +; "PEAR_ERROR_DIE" "PEAR_ERROR_CALLBACK" "OS_WINDOWS" "OS_UNIX" +; "PEAR_OS" "DB_OK" "DB_ERROR" "DB_ERROR_SYNTAX" +; "DB_ERROR_CONSTRAINT" "DB_ERROR_NOT_FOUND" +; "DB_ERROR_ALREADY_EXISTS" "DB_ERROR_UNSUPPORTED" +; "DB_ERROR_MISMATCH" "DB_ERROR_INVALID" "DB_ERROR_NOT_CAPABLE" +; "DB_ERROR_TRUNCATED" "DB_ERROR_INVALID_NUMBER" +; "DB_ERROR_INVALID_DATE" "DB_ERROR_DIVZERO" +; "DB_ERROR_NODBSELECTED" "DB_ERROR_CANNOT_CREATE" +; "DB_ERROR_CANNOT_DELETE" "DB_ERROR_CANNOT_DROP" +; "DB_ERROR_NOSUCHTABLE" "DB_ERROR_NOSUCHFIELD" +; "DB_ERROR_NEED_MORE_DATA" "DB_ERROR_NOT_LOCKED" +; "DB_ERROR_VALUE_COUNT_ON_ROW" "DB_ERROR_INVALID_DSN" +; "DB_ERROR_CONNECT_FAILED" "DB_WARNING" "DB_WARNING_READ_ONLY" +; "DB_PARAM_SCALAR" "DB_PARAM_OPAQUE" "DB_BINMODE_PASSTHRU" +; "DB_BINMODE_RETURN" "DB_BINMODE_CONVERT" "DB_FETCHMODE_DEFAULT" +; "DB_FETCHMODE_ORDERED" "DB_FETCHMODE_ASSOC" +; "DB_FETCHMODE_FLIPPED" "DB_GETMODE_ORDERED" "DB_GETMODE_ASSOC" +; "DB_GETMODE_FLIPPED" "DB_TABLEINFO_ORDER" +; "DB_TABLEINFO_ORDERTABLE" "DB_TABLEINFO_FULL" + + ))) + "PHP constants.") + +(defconst php-keywords + (eval-when-compile + (regexp-opt + ;; "class", "new" and "extends" get special treatment + ;; "case" and "default" get special treatment elsewhere + '("and" "as" "break" "continue" "declare" "do" "echo" "else" "elseif" + "endfor" "endforeach" "endif" "endswitch" "endwhile" "exit" + "extends" "for" "foreach" "global" "if" "include" "include_once" + "next" "or" "require" "require_once" "return" "static" "switch" + "then" "var" "while" "xor" "throw" "catch" "try" + "instanceof" "catch all" "finally"))) + "PHP keywords.") + +(defconst php-identifier + (eval-when-compile + '"[a-zA-Z\_\x7f-\xff][a-zA-Z0-9\_\x7f-\xff]*") + "Characters in a PHP identifier.") + +(defconst php-types + (eval-when-compile + (regexp-opt '("array" "bool" "boolean" "char" "const" "double" "float" + "int" "integer" "long" "mixed" "object" "real" + "string"))) + "PHP types.") + +(defconst php-superglobals + (eval-when-compile + (regexp-opt '("_GET" "_POST" "_COOKIE" "_SESSION" "_ENV" "GLOBALS" + "_SERVER" "_FILES" "_REQUEST"))) + "PHP superglobal variables.") + +;; Set up font locking +(defconst php-font-lock-keywords-1 + (list + ;; Fontify constants + (cons + (concat "[^_$]?\\<\\(" php-constants "\\)\\>[^_]?") + '(1 font-lock-constant-face)) + + ;; Fontify keywords + (cons + (concat "[^_$]?\\<\\(" php-keywords "\\)\\>[^_]?") + '(1 font-lock-keyword-face)) + + ;; Fontify keywords and targets, and case default tags. + (list "\\<\\(break\\|case\\|continue\\)\\>\\s-+\\(-?\\sw+\\)?" + '(1 font-lock-keyword-face) '(2 font-lock-constant-face t t)) + ;; This must come after the one for keywords and targets. + '(":" ("^\\s-+\\(\\sw+\\)\\s-+\\s-+$" + (beginning-of-line) (end-of-line) + (1 font-lock-constant-face))) + + ;; treat 'print' as keyword only when not used like a function name + '("\\<print\\s-*(" . php-default-face) + '("\\<print\\>" . font-lock-keyword-face) + + ;; Fontify PHP tag + (cons php-tags-key font-lock-preprocessor-face) + + ;; Fontify ASP-style tag + '("<\\%\\(=\\)?" . font-lock-preprocessor-face) + '("\\%>" . font-lock-preprocessor-face) + + ) + "Subdued level highlighting for PHP mode.") + +(defconst php-font-lock-keywords-2 + (append + php-font-lock-keywords-1 + (list + + ;; class declaration + '("\\<\\(class\\|interface\\)\\s-+\\(\\sw+\\)?" + (1 font-lock-keyword-face) (2 font-lock-type-face nil t)) + ;; handle several words specially, to include following word, + ;; thereby excluding it from unknown-symbol checks later + ;; FIX to handle implementing multiple + ;; currently breaks on "class Foo implements Bar, Baz" + '("\\<\\(new\\|extends\\|implements\\)\\s-+\\$?\\(\\sw+\\)" + (1 font-lock-keyword-face) (2 font-lock-type-face)) + + ;; function declaration + '("\\<\\(function\\)\\s-+&?\\(\\sw+\\)\\s-*(" + (1 font-lock-keyword-face) + (2 font-lock-function-name-face nil t)) + + ;; class hierarchy + '("\\<\\(self\\|parent\\)\\>" (1 font-lock-constant-face nil nil)) + + ;; method and variable features + '("\\<\\(private\\|protected\\|public\\)\\s-+\\$?\\sw+" + (1 font-lock-keyword-face)) + + ;; method features + '("^\\s-*\\(abstract\\|static\\|final\\)\\s-+\\$?\\sw+" + (1 font-lock-keyword-face)) + + ;; variable features + '("^\\s-*\\(static\\|const\\)\\s-+\\$?\\sw+" + (1 font-lock-keyword-face)) + )) + "Medium level highlighting for PHP mode.") + +(defconst php-font-lock-keywords-3 + (append + php-font-lock-keywords-2 + (list + + ;; <word> or </word> for HTML + ;;'("</?\\sw+[^> ]*>" . font-lock-constant-face) + ;;'("</?\\sw+[^>]*" . font-lock-constant-face) + ;;'("<!DOCTYPE" . font-lock-constant-face) + '("</?[a-z!:]+" . font-lock-constant-face) + + ;; HTML > + '("<[^>]*\\(>\\)" (1 font-lock-constant-face)) + + ;; HTML tags + '("\\(<[a-z]+\\)[[:space:]]+\\([a-z:]+=\\)[^>]*?" (1 font-lock-constant-face) (2 font-lock-constant-face) ) + '("\"[[:space:]]+\\([a-z:]+=\\)" (1 font-lock-constant-face)) + + ;; HTML entities + ;;'("&\\w+;" . font-lock-variable-name-face) + + ;; warn about '$' immediately after -> + '("\\$\\sw+->\\s-*\\(\\$\\)\\(\\sw+\\)" + (1 font-lock-warning-face) (2 php-default-face)) + + ;; warn about $word.word -- it could be a valid concatenation, + ;; but without any spaces we'll assume $word->word was meant. + '("\\$\\sw+\\(\\.\\)\\sw" + 1 font-lock-warning-face) + + ;; Warn about ==> instead of => + '("==+>" . font-lock-warning-face) + + ;; exclude casts from bare-word treatment (may contain spaces) + `(,(concat "(\\s-*\\(" php-types "\\)\\s-*)") + 1 font-lock-type-face) + + ;; PHP5: function declarations may contain classes as parameters type + `(,(concat "[(,]\\s-*\\(\\sw+\\)\\s-+&?\\$\\sw+\\>") + 1 font-lock-type-face) + + ;; Fontify variables and function calls + '("\\$\\(this\\|that\\)\\W" (1 font-lock-constant-face nil nil)) + `(,(concat "\\$\\(" php-superglobals "\\)\\W") + (1 font-lock-constant-face nil nil)) ;; $_GET & co + '("\\$\\(\\sw+\\)" (1 font-lock-variable-name-face)) ;; $variable + '("->\\(\\sw+\\)" (1 font-lock-variable-name-face t t)) ;; ->variable + '("->\\(\\sw+\\)\\s-*(" . (1 php-default-face t t)) ;; ->function_call + '("\\(\\sw+\\)::\\sw+\\s-*(?" . (1 font-lock-type-face)) ;; class::member + '("::\\(\\sw+\\>[^(]\\)" . (1 php-default-face)) ;; class::constant + '("\\<\\sw+\\s-*[[(]" . php-default-face) ;; word( or word[ + '("\\<[0-9]+" . php-default-face) ;; number (also matches word) + + ;; Warn on any words not already fontified + '("\\<\\sw+\\>" . font-lock-warning-face) + + )) + "Gauchy level highlighting for PHP mode.") + +(provide 'php-mode) + +;;; php-mode.el ends here+ \ No newline at end of file diff --git a/i3/.i3status.conf b/i3/.i3status.conf @@ -0,0 +1,70 @@ +general { + colors = true + color_good = '#88b090' + color_degraded = '#ccdc90' + color_bad = '#e89393' + interval = 1 +} + +order += "volume master" +#order += "ipv6" +order += "disk /" +#order += "run_watch DHCP" +#order += "run_watch VPN" +#order += "wireless wlan0" +#order += "ethernet eth0" +#order += "battery 0" +#order += "cpu_temperature 0" +order += "load" +order += "cpu_usage 0" +order += "time" + +wireless wlan0 { + format_up = "W: (%quality at %essid) %ip" + format_down = "W: down" +} + +ethernet eth0 { + # if you use %speed, i3status requires root privileges + format_up = "%ip" + format_down = "E: down" +} + +battery 0 { + format = "%status %percentage %remaining" +} + +run_watch DHCP { + pidfile = "/var/run/dhclient*.pid" +} + +run_watch VPN { + pidfile = "/var/run/vpnc/pid" +} + +time { + format = " %a, %m %e %l:%M %p" +} + +load { + format = " %1min " +} + +cpu_usage { + format = " %usage " +} + +cpu_temperature 0 { + format = " %degrees °C" +} + +disk "/" { + format = " %free " +} + +volume master { + format = " %volume " + device = "default" + mixer = "Master" + mixer_idx = 0 +} diff --git a/i3/config b/i3/config @@ -0,0 +1,190 @@ +# This file has been auto-generated by i3-config-wizard(1). +# It will not be overwritten, so edit it as you like. +# +# Should you change your keyboard layout somewhen, delete +# this file and re-run i3-config-wizard(1). +# + +# i3 config file (v4) +# +# Please see http://i3wm.org/docs/userguide.html for a complete reference! + +set $mod Mod4 + +exec gnome-settings-daemon + +exec ~/.dropbox-dist/dropboxd + +exec compton --backend glx --vsync opengl-swc --paint-on-overlay + +exec feh --bg-tile ~/pictures/dimension.png + +# hide dem borders +hide_edge_borders both + +# hide dem titles +for_window [class="^.*"] border pixel 0 +for_window [title="^float$"] floating enable +for_window [title="^float$"] border pixel 3 + +# class border backgr. text indicator +client.focused #303031 #303031 #B7B7B7 #31392F +client.focused_inactive #303031 #303031 #B7B7B7 #676767 +client.unfocused #303031 #303031 #404041 #515151 +client.urgent #471A19 #521414 #ffffff #900000 + +# font for window titles. ISO 10646 = Unicode +#apt-get install xfonts-terminus +font xft:Terminus 8 + +# Use Mouse+$mod to drag floating windows to their wanted position +floating_modifier $mod + +# start a terminal +bindsym $mod+Return exec i3-sensible-terminal +bindsym $mod+t exec i3-sensible-terminal -T float + +# kill focused window +bindsym $mod+shift+Q kill + +# start dmenu (a program launcher) +bindsym $mod+d exec dmenu_run + +bindsym $mod+shift+d exec i3-dmenu-desktop + +# change focus +bindsym $mod+b focus left +bindsym $mod+n focus down +bindsym $mod+p focus up +bindsym $mod+f focus right + +# alternatively, you can use the cursor keys: +bindsym $mod+Left focus left +bindsym $mod+Down focus down +bindsym $mod+Up focus up +bindsym $mod+Right focus right + +# move focused window +bindsym $mod+Shift+b move left +bindsym $mod+Shift+n move down +bindsym $mod+Shift+p move up +bindsym $mod+Shift+f move right + +# alternatively, you can use the cursor keys: +bindsym $mod+Shift+Left move left +bindsym $mod+Shift+Down move down +bindsym $mod+Shift+Up move up +bindsym $mod+Shift+Right move right + +# split in horizontal orientation +bindsym $mod+h split h + +# split in vertical orientation +bindsym $mod+v split v + +# enter fullscreen mode for the focused container +bindsym $mod+Shfit+f fullscreen + +# change container layout (stacked, tabbed, default) +bindsym $mod+s layout stacking +bindsym $mod+w layout tabbed +bindsym $mod+e layout default + +# toggle tiling / floating +bindsym $mod+Shift+space floating toggle + +# change focus between tiling / floating windows +bindsym $mod+space focus mode_toggle + +# focus the parent container +bindsym $mod+a focus parent + +# focus the child container +#bindcode $mod+d focus child + +# switch to workspace +bindsym $mod+1 workspace 1 +bindsym $mod+2 workspace 2 +bindsym $mod+3 workspace 3 +bindsym $mod+4 workspace 4 +bindsym $mod+5 workspace 5 +bindsym $mod+6 workspace 6 +bindsym $mod+7 workspace 7 +bindsym $mod+8 workspace 8 +bindsym $mod+9 workspace 9 +bindsym $mod+0 workspace 10 + +# move focused container to workspace +bindsym $mod+Shift+exclam move workspace 1 +bindsym $mod+Shift+at move workspace 2 +bindsym $mod+Shift+numbersign move workspace 3 +bindsym $mod+Shift+dollar move workspace 4 +bindsym $mod+Shift+percent move workspace 5 +bindsym $mod+Shift+asciicircum move workspace 6 +bindsym $mod+Shift+ampersand move workspace 7 +bindsym $mod+Shift+asterisk move workspace 8 +bindsym $mod+Shift+parenleft move workspace 9 +bindsym $mod+Shift+parenright move workspace 10 + +# reload the configuration file +bindsym $mod+Shift+C reload +# restart i3 inplace (preserves your layout/session, can be used to upgrade i3) +bindsym $mod+Shift+R restart +# exit i3 (logs you out of your X session) +bindsym $mod+Shift+E exit + +# resize window (you can also use the mouse for that) +mode "resize" { + # These bindings trigger as soon as you enter the resize mode + + # They resize the border in the direction you pressed, e.g. + # when pressing left, the window is resized so that it has + # more space on its left + +bindsym j resize shrink left 10 px or 10 ppt +bindsym Shift+J resize grow left 10 px or 10 ppt + +bindsym k resize shrink down 10 px or 10 ppt +bindsym Shift+K resize grow down 10 px or 10 ppt + +bindsym l resize shrink up 10 px or 10 ppt +bindsym Shift+L resize grow up 10 px or 10 ppt + +bindsym semicolon resize shrink right 10 px or 10 ppt +bindsym Shift+colon resize grow right 10 px or 10 ppt + + # same bindings, but for the arrow keys +bindsym Left resize shrink left 10 px or 10 ppt +bindsym Shift+Left resize grow left 10 px or 10 ppt + +bindsym Down resize shrink down 10 px or 10 ppt +bindsym Shift+Down resize grow down 10 px or 10 ppt + +bindsym Up resize shrink up 10 px or 10 ppt +bindsym Shift+Up resize grow up 10 px or 10 ppt + +bindsym Right resize shrink right 10 px or 10 ppt +bindsym Shift+Right resize grow right 10 px or 10 ppt + + # back to normal: Enter or Escape +bindsym Return mode "default" +bindsym Escape mode "default" +} + +bindsym $mod+r mode "resize" + +# Start i3bar to display a workspace bar (plus the system information i3status +# finds out, if available) +bar { + output DFP2 + status_command i3status + colors { + background #131313 + statusline #B7B7B7 + + focused_workspace #303031 #303031 #D78A0C + active_workspace #303031 #303031 #9A9A9A + inactive_workspace #303031 #303031 #9A9A9A + urgent_workspace #303031 #303031 #FF0000 + } +}