Squashed 'lib/smartrep/' content from commit f0ff5a6

git-subtree-dir: lib/smartrep
git-subtree-split: f0ff5a6d7b8603603598ae3045c98b011e58d86e
This commit is contained in:
John Miller 2016-09-09 09:45:44 -05:00
commit a23fd6fc2e
7 changed files with 450 additions and 0 deletions

1
.ert-runner Normal file
View file

@ -0,0 +1 @@
-L .

26
.travis.yml Normal file
View file

@ -0,0 +1,26 @@
language: emacs-lisp
notifications:
email: false
env:
matrix:
# - EMACS=emacs23
- EMACS=emacs24
# - EMACS=emacs-snapshot
before_install:
# PPA for stable Emacs packages
- sudo add-apt-repository -y ppa:cassou/emacs
# PPA for Emacs nightlies
- sudo add-apt-repository -y ppa:ubuntu-elisp/ppa
# Update and install the Emacs for our environment
- sudo apt-get update -qq
- sudo apt-get install -qq -yy ${EMACS}-nox ${EMACS}-el
# Install Cask
- curl -fsSkL --max-time 10 --retry 10 --retry-delay 10
https://raw.github.com/cask/cask/master/go | python
- export PATH="$HOME/.cask/bin:$PATH"
- cask
script:
- emacs --version
- emacs -Q -batch -eval '(message (system-name))'
- make

9
Cask Normal file
View file

@ -0,0 +1,9 @@
(source gnu)
(source melpa)
(package-file "smartrep.el")
(development
(depends-on "ert-runner")
(depends-on "undercover")
(depends-on "cl-lib"))

20
Makefile Normal file
View file

@ -0,0 +1,20 @@
EMACS ?= emacs
CASK ?= cask
all:
${MAKE} clean
${MAKE} test
${MAKE} clean
compile:
${CASK} exec ${EMACS} -Q -batch -L . -eval \
"(progn \
(when (version<= \"24.3\" emacs-version) \
(setq byte-compile-error-on-warn t)) \
(batch-byte-compile))" smartrep.el
test:
${CASK} exec ert-runner
clean:
rm -f smartrep.elc
.PHONY: all compile test clean

142
README.org Normal file
View file

@ -0,0 +1,142 @@
* Smartrep [[http://melpa.org/#/smartrep][file:http://melpa.org/packages/smartrep-badge.svg]] [[http://stable.melpa.org/#/smartrep][file:http://stable.melpa.org/packages/smartrep-badge.svg]] [[https://travis-ci.org/myuhe/smartrep.el][https://travis-ci.org/myuhe/smartrep.el.svg?branch=master]] [[https://coveralls.io/r/myuhe/smartrep.el?branch=master][https://coveralls.io/repos/myuhe/smartrep.el/badge.svg?branch=master]]
=smartrep= is a sequential command interface library. It enables the omittance of typing prefix keys. (e.g., C-c C-n C-n C-n ... instead of C-c C-n C-c C-n C-c C-n ...)
* Contents
- [[https://github.com/myuhe/smartrep.el#usage][Usage]]
- [[https://github.com/myuhe/smartrep.el#example][Examples]]
- [[https://github.com/myuhe/smartrep.el#smartrep-works-in-many-applications][Smartrep works in many applications]]
- [[https://github.com/myuhe/smartrep.el#similar-application][Similar application]]
* Usage
=smartrep= offers only one function =smartrep-define-key=.
The key is bound with =smartrep-define-key= like:
#+begin_src elisp
(smartrep-define-key
global-map "M-g"
'(("n" . next-line)
("p" . previous-line)))
#+end_src
Then after typing =M-g=, =n= exetutes =next-line= and =p= executes =previous-line=.
If any other key is typed, the special key binding is canceled. That is, if =n= is typed, "n" is inserted as a character.
* Examples
** Control Two Buffers
Scroll another buffer. The current buffer is not changed.
If you want to scroll by two lines in the other buffer, just type =C-q n n=.
#+begin_src elisp
(smartrep-define-key
global-map "C-q" '(("n" . (scroll-other-window 1))
("p" . (scroll-other-window -1))
("N" . 'scroll-other-window)
("P" . (scroll-other-window '-))
("a" . (beginning-of-buffer-other-window 0))
("e" . (end-of-buffer-other-window 0))))
#+end_src
** Change Window Size
Changing Window size tends to execute the same command continuously. It is boring work.
So eval this example and type =C-x { { {=.
#+begin_src elisp
(smartrep-define-key
global-map "C-x"
'(("{" . shrink-window-horizontally)
("}" . enlarge-window-horizontally)))
#+end_src
** Move header on Org-mode
Org-mode has complicated prefix keys. It is so frustrating.
This idea simplifies it. If you want to move from heading to heading, then type =C-c= and then =C-n= or =C-p=.
#+begin_src elisp
(smartrep-define-key
org-mode-map "C-c" '(("C-n" . (outline-next-visible-heading 1))
("C-p" . (outline-previous-visible-heading 1))))
#+end_src
** Remotely Control Firefox
You may control Firefox via Emacs.
This example enables the manipulation of Firefox to scroll up, down and more.
It requires [[https://github.com/bard/mozrepl/blob/master/chrome/content/moz.el][moz.el]]
#+begin_src elisp
(autoload 'moz-minor-mode "moz" "Mozilla Minor and Inferior Mozilla Modes" t)
(moz-minor-mode t)
(defun moz-send-message (moz-command)
(comint-send-string
(inferior-moz-process)
(concat moz-repl-name ".pushenv('printPrompt', 'inputMode'); "
moz-repl-name ".setenv('inputMode', 'line'); "
moz-repl-name ".setenv('printPrompt', false); undefined; "))
(comint-send-string
(inferior-moz-process)
(concat moz-command
moz-repl-name ".popenv('inputMode', 'printPrompt'); undefined;\n")))
(defun moz-scrolldown-1 ()
(interactive)
(moz-send-message "goDoCommand('cmd_scrollLineDown');\n"))
(defun moz-scrolldown ()
(interactive)
(moz-send-message "goDoCommand('cmd_scrollPageDown');"))
(defun moz-scrollup-1 ()
(interactive)
(moz-send-message "goDoCommand('cmd_scrollLineUp');\n"))
(defun moz-scrollup ()
(interactive)
(moz-send-message "goDoCommand('cmd_scrollPageUp');"))
(defun moz-top ()
(interactive)
(moz-send-message "goDoCommand('cmd_scrollTop');\n"))
(defun moz-bottom ()
(interactive)
(moz-send-message "goDoCommand('cmd_scrollBottom');\n"))
(require 'smartrep)
(smartrep-define-key
global-map "M-g" '(("n" . moz-scrolldown-1)
("N" . moz-scrolldown)
("p" . moz-scrollup-1)
("P" . moz-scrollup)
("a" . moz-top)
("e" . moz-bottom)))
#+end_src
* Smartrep Works In Many Applications
Many applications use =smartrep=. Thanks!!
- [[https://github.com/rolandwalker/back-button][rolandwalker/back-button]]
- [[https://github.com/rolandwalker/fixmee][rolandwalker/fixmee]]
- [[https://github.com/millejoh/emacs-ipython-notebook][millejoh/emacs-ipython-notebook]]
- [[https://github.com/aki2o/owdriver][aki2o/owdriver]]
* Related article
- [[http://oremacs.com/2015/01/14/repeatable-commands/][Zoom in / out with style · (or emacs]]
- [[http://sheephead.homelinux.org/2011/12/19/6930/][連続操作を素敵にするsmartrep.el作った - sheephead]] (In Japanese)
- [[http://sheephead.homelinux.org/2012/01/30/6934/][smartrep.el 0.0.3をリリースしました - sheephead]] (In Japanese)
- [[http://tam5917.hatenablog.com/entry/20121208/1354931551][multiple-cursors.elのキーバインドを少しだけ改善 - 備忘録]] (In Japanese)
- [[http://d.hatena.ne.jp/rubikitch/20140613/smartrep][Emacs - smartrep.elでrepeatを活性化せよ - http://rubikitch.com/に移転しました]] (In Japanese)
* Similar Applications
[[https://github.com/abo-abo/hydra][abo-abo/hydra]]

194
smartrep.el Normal file
View file

@ -0,0 +1,194 @@
;;; smartrep.el --- Support sequential operation which omitted prefix keys.
;; Filename: smartrep.el
;; Description: Support sequential operation which omitted prefix keys.
;; Author: myuhe <yuhei.maeda_at_gmail.com>
;; Maintainer: myuhe
;; Copyright (C) :2011,2012 myuhe all rights reserved.
;; Created: :2011-12-19
;; Version: 1.0.0
;; Keywords: convenience
;; URL: https://github.com/myuhe/smartrep.el
;; 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, 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 GNU Emacs; see the file COPYING. If not, write to
;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
;; Boston, MA 0:110-1301, USA.
;;; Commentary:
;; Installation:
;; Put the smartrep.el to your load-path.
;; And add to .emacs: (require 'smartrep)
;;; Changelog:
;; 2012-01-06 Remove unnecessary cord.
;; 2012-01-06 read-key is replaced read-event for compatibility. thanks @tomy_kaira !!
;; 2012-01-11 Support function calling form. (buzztaiki)
;; Call interactively when command. (buzztaiki)
;; Support unquoted function. (buzztaiki)
;; 2012-01-11 new command `smartrep-restore-original-position' `smartrep-quit' (rubikitch)
;; add mode line notification (rubikitch)
;; 2012-01-12 add mode-line-color notification
;;
;;; Code:
(eval-when-compile
(require 'cl))
(defgroup smartrep nil
"Support sequential operation which omitted prefix keys"
:group 'keyboard)
(defcustom smartrep-mode-line-string-activated "========== SMARTREP =========="
"Lighter when smartrep-mode is activated"
:type 'string
:group 'smartrep)
(defcustom smartrep-mode-line-active-bg (face-background 'highlight)
"Background color when smartrep-mode is activated"
:type 'string
:group 'smartrep)
(defvar smartrep-key-string nil)
(defvar smartrep-read-event
(if (fboundp 'read-event) 'read-event 'read-key)
"Function to be used for reading keyboard events.")
(defvar smartrep-mode-line-string nil
"Mode line indicator for smartrep.")
(defvar smartrep-global-alist-hash (make-hash-table :test 'equal))
(defvar smartrep-original-position nil
"A cons holding the point and window-start when smartrep is invoked.")
(let ((cell (or (memq 'mode-line-position mode-line-format)
(memq 'mode-line-buffer-identification mode-line-format)))
(newcdr 'smartrep-mode-line-string))
(when cell
(unless (member newcdr mode-line-format)
(setcdr cell (cons newcdr (cdr cell))))))
(defun smartrep-define-key (keymap prefix alist)
(when (eq keymap global-map)
(puthash prefix alist smartrep-global-alist-hash))
(setq alist
(if (eq keymap global-map)
alist
(append alist (gethash prefix smartrep-global-alist-hash))))
(let ((oa (make-vector 13 nil)))
(mapc (lambda(x)
(let ((obj (intern (prin1-to-string
(smartrep-unquote (cdr x)))
oa)))
(fset obj (smartrep-map alist))
(define-key keymap
(read-kbd-macro
(concat prefix " " (car x))) obj)))
alist)))
(put 'smartrep-define-key 'lisp-indent-function 2)
(defun smartrep-map (alist)
(lexical-let ((lst alist))
(lambda () (interactive) (smartrep-map-internal lst))))
(defun smartrep-restore-original-position ()
(interactive)
(destructuring-bind (pt . wstart) smartrep-original-position
(goto-char pt)
(set-window-start (selected-window) wstart)))
(defun smartrep-quit ()
(interactive)
(setq smartrep-mode-line-string "")
(smartrep-restore-original-position)
(keyboard-quit))
(defun smartrep-map-internal (lst)
(interactive)
(setq smartrep-mode-line-string smartrep-mode-line-string-activated)
(let ((ml-original-bg (face-background 'mode-line)))
(when smartrep-mode-line-active-bg
(set-face-background 'mode-line smartrep-mode-line-active-bg)
(force-mode-line-update))
(setq smartrep-original-position (cons (point) (window-start)))
(unwind-protect
(let ((repeat-repeat-char last-command-event))
(smartrep-do-fun repeat-repeat-char lst)
(when repeat-repeat-char
(smartrep-read-event-loop lst)))
(setq smartrep-mode-line-string "")
(when smartrep-mode-line-active-bg
(set-face-background 'mode-line ml-original-bg)
(force-mode-line-update)))))
(defun smartrep-read-event-loop (lst)
(lexical-let ((undo-inhibit-record-point t))
(unwind-protect
(while
(lexical-let ((evt (funcall smartrep-read-event)))
;; (eq (or (car-safe evt) evt)
;; (or (car-safe repeat-repeat-char)
;; repeat-repeat-char))
(setq smartrep-key-string evt)
(smartrep-extract-char evt lst))
(smartrep-do-fun smartrep-key-string lst)))
(setq unread-command-events (list last-input-event))))
(defun smartrep-extract-char (char alist)
(car (smartrep-filter char alist)))
(defun smartrep-extract-fun (char alist)
(let* ((rawform (cdr (smartrep-filter char alist)))
(form (smartrep-unquote rawform)))
(cond
((commandp form)
(setq this-command form)
(unwind-protect
(call-interactively form)
(setq last-command form)))
((functionp form) (funcall form))
((and (listp form) (symbolp (car form))) (eval form))
(t (error "Unsupported form %c %s" char rawform)))))
(defun smartrep-do-fun (char alist)
(condition-case err
(progn
(run-hooks 'pre-command-hook)
(smartrep-extract-fun char alist)
(run-hooks 'post-command-hook))
(error
(ding)
(message "%s" (cdr err)))))
(defun smartrep-unquote (form)
(if (and (listp form) (memq (car form) '(quote function)))
(eval form)
form))
(defun smartrep-filter (char alist)
(loop for (key . form) in alist
for rkm = (read-kbd-macro key)
for number = (if (vectorp rkm)
(aref rkm 0)
(string-to-char rkm))
if (eq char number)
return (cons number form)))
(provide 'smartrep)
;;; smartrep.el ends here

58
test/smartrep-test.el Normal file
View file

@ -0,0 +1,58 @@
;;; smartrep-test.el --- Test smartrep.el
;; Copyright (C) 2014 by myuhe all rights reserved.
;; Author: myuhe <yuhei.maeda_at_gmail.com>
;; URL: https://github.com/myuhe/smartrep.el
;; 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, 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.
(require 'ert)
(require 'undercover)
(undercover "smartrep.el")
(require 'smartrep)
(defun smartrep-test-func (&optional arg)
(or arg 1))
(defun smartrep-test-command ()
(interactive)
;; NOTE: In noninteractive(batch) mode,
;; (called-interactively-p 'interactive) never return `t'
(if (called-interactively-p 'interactive) 2 1))
(ert-deftest smartrep-unquote ()
"Tests for `smartrep-unquote'"
(should (eq (smartrep-unquote '(quote hoge)) 'hoge))
(should (eq (smartrep-unquote '(function hoge)) 'hoge))
(should (eq (smartrep-unquote 'hoge) 'hoge)))
(ert-deftest smartrep-extract-fun ()
"Tests for `smartrep-extract-fun'"
(should (= (smartrep-extract-fun ?a '(("a" . smartrep-test-func))) 1))
(should (= (smartrep-extract-fun ?a '(("a" . (lambda () (smartrep-test-func))))) 1))
(should (= (smartrep-extract-fun ?a '(("a" . (smartrep-test-func)))) 1))
(should (= (smartrep-extract-fun ?a '(("a" . (smartrep-test-func 2)))) 2))
(unless noninteractive
(should (= (smartrep-extract-fun ?a '(("a" . smartrep-test-command))) 2))))
(ert-deftest smartrep-extract-fun-with-quote ()
"Test for `smartrep-extract-fun' with quote"
(should (= (smartrep-extract-fun ?a '(("a" . 'smartrep-test-func))) 1))
(should (= (smartrep-extract-fun ?a '(("a" . '(lambda () (smartrep-test-func))))) 1))
(should (= (smartrep-extract-fun ?a '(("a" . #'(lambda () (smartrep-test-func))))) 1))
(should (= (smartrep-extract-fun ?a '(("a" . '(smartrep-test-func)))) 1))
(should (= (smartrep-extract-fun ?a '(("a" . '(smartrep-test-func 2)))) 2))
(unless noninteractive
(should (= (smartrep-extract-fun ?a '(("a" . 'smartrep-test-command))) 2))))
;;; smartrep-test.el end here