Taylor Bockman
9 years ago
37 changed files with 0 additions and 20905 deletions
@ -1 +0,0 @@ |
|||||||
(define-package "ag" "20150814.1655" "A front-end for ag ('the silver searcher'), the C ack replacement." '((dash "2.8.0") (s "1.9.0") (cl-lib "0.5"))) |
|
@ -1,617 +0,0 @@ |
|||||||
;;; ag.el --- A front-end for ag ('the silver searcher'), the C ack replacement. |
|
||||||
|
|
||||||
;; Copyright (C) 2013-2014 Wilfred Hughes <me@wilfred.me.uk> |
|
||||||
;; |
|
||||||
;; Author: Wilfred Hughes <me@wilfred.me.uk> |
|
||||||
;; Created: 11 January 2013 |
|
||||||
;; Version: 0.47 |
|
||||||
;; Package-Version: 20150814.1655 |
|
||||||
;; Package-Requires: ((dash "2.8.0") (s "1.9.0") (cl-lib "0.5")) |
|
||||||
;;; Commentary: |
|
||||||
|
|
||||||
;; Please see README.md for documentation, or read it online at |
|
||||||
;; https://github.com/Wilfred/ag.el/#agel |
|
||||||
|
|
||||||
;;; License: |
|
||||||
|
|
||||||
;; This file is not part of GNU Emacs. |
|
||||||
;; However, it is distributed under the same license. |
|
||||||
|
|
||||||
;; GNU Emacs 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. |
|
||||||
|
|
||||||
;; GNU Emacs 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 02110-1301, USA. |
|
||||||
|
|
||||||
;;; Code: |
|
||||||
(eval-when-compile (require 'cl)) ;; dolist, defun*, flet |
|
||||||
(require 'cl-lib) ;; cl-letf |
|
||||||
(require 'dired) ;; dired-sort-inhibit |
|
||||||
(require 'dash) |
|
||||||
(require 's) |
|
||||||
(require 'find-dired) ;; find-dired-filter |
|
||||||
|
|
||||||
(defcustom ag-executable |
|
||||||
"ag" |
|
||||||
"Name of the ag executable to use." |
|
||||||
:type 'string |
|
||||||
:group 'ag) |
|
||||||
|
|
||||||
(defcustom ag-arguments |
|
||||||
(list "--line-number" "--smart-case" "--nogroup" "--column" "--stats" "--") |
|
||||||
"Default arguments passed to ag. |
|
||||||
|
|
||||||
Ag.el requires --nogroup and --column, so we recommend you add any |
|
||||||
additional arguments to the start of this list. |
|
||||||
|
|
||||||
--line-number is required on Window, as otherwise ag will not |
|
||||||
print line numbers when the input is a stream." |
|
||||||
:type '(repeat (string)) |
|
||||||
:group 'ag) |
|
||||||
|
|
||||||
(defcustom ag-highlight-search nil |
|
||||||
"Non-nil means we highlight the current search term in results. |
|
||||||
|
|
||||||
This requires the ag command to support --color-match, which is only in v0.14+" |
|
||||||
:type 'boolean |
|
||||||
:group 'ag) |
|
||||||
|
|
||||||
(defcustom ag-reuse-buffers nil |
|
||||||
"Non-nil means we reuse the existing search results buffer or |
|
||||||
dired results buffer, rather than creating one buffer per unique |
|
||||||
search." |
|
||||||
:type 'boolean |
|
||||||
:group 'ag) |
|
||||||
|
|
||||||
(defcustom ag-reuse-window nil |
|
||||||
"Non-nil means we open search results in the same window, |
|
||||||
hiding the results buffer." |
|
||||||
:type 'boolean |
|
||||||
:group 'ag) |
|
||||||
|
|
||||||
(defcustom ag-project-root-function nil |
|
||||||
"A function to determine the project root for `ag-project'. |
|
||||||
|
|
||||||
If set to a function, call this function with the name of the |
|
||||||
file or directory for which to determine the project root |
|
||||||
directory. |
|
||||||
|
|
||||||
If set to nil, fall back to finding VCS root directories." |
|
||||||
:type '(choice (const :tag "Default (VCS root)" nil) |
|
||||||
(function :tag "Function")) |
|
||||||
:group 'ag) |
|
||||||
|
|
||||||
(defcustom ag-ignore-list nil |
|
||||||
"A list of patterns to ignore when searching." |
|
||||||
:type '(repeat (string)) |
|
||||||
:group 'ag) |
|
||||||
|
|
||||||
(require 'compile) |
|
||||||
|
|
||||||
;; Although ag results aren't exactly errors, we treat them as errors |
|
||||||
;; so `next-error' and `previous-error' work. However, we ensure our |
|
||||||
;; face inherits from `compilation-info-face' so the results are |
|
||||||
;; styled appropriately. |
|
||||||
(defface ag-hit-face '((t :inherit compilation-info)) |
|
||||||
"Face name to use for ag matches." |
|
||||||
:group 'ag) |
|
||||||
|
|
||||||
(defface ag-match-face '((t :inherit match)) |
|
||||||
"Face name to use for ag matches." |
|
||||||
:group 'ag) |
|
||||||
|
|
||||||
(defvar ag-search-finished-hook nil |
|
||||||
"Hook run when ag completes a search in a buffer.") |
|
||||||
|
|
||||||
(defun ag/run-finished-hook (buffer how-finished) |
|
||||||
"Run the ag hook to signal that the search has completed." |
|
||||||
(with-current-buffer buffer |
|
||||||
(run-hooks 'ag-search-finished-hook))) |
|
||||||
|
|
||||||
(defmacro ag/with-patch-function (fun-name fun-args fun-body &rest body) |
|
||||||
"Temporarily override the definition of FUN-NAME whilst BODY is executed. |
|
||||||
|
|
||||||
Assumes FUNCTION is already defined (see http://emacs.stackexchange.com/a/3452/304)." |
|
||||||
`(cl-letf (((symbol-function ,fun-name) |
|
||||||
(lambda ,fun-args ,fun-body))) |
|
||||||
,@body)) |
|
||||||
|
|
||||||
(defun ag/next-error-function (n &optional reset) |
|
||||||
"Open the search result at point in the current window or a |
|
||||||
different window, according to `ag-reuse-window'." |
|
||||||
(if ag-reuse-window |
|
||||||
;; prevent changing the window |
|
||||||
(ag/with-patch-function |
|
||||||
'pop-to-buffer (buffer &rest args) (switch-to-buffer buffer) |
|
||||||
(compilation-next-error-function n reset)) |
|
||||||
|
|
||||||
;; just navigate to the results as normal |
|
||||||
(compilation-next-error-function n reset))) |
|
||||||
|
|
||||||
;; Note that we want to use as tight a regexp as we can to try and |
|
||||||
;; handle weird file names (with colons in them) as well as possible. |
|
||||||
;; E.g. we use [1-9][0-9]* rather than [0-9]+ so as to accept ":034:" |
|
||||||
;; in file names. |
|
||||||
(defvar ag/file-column-pattern |
|
||||||
"^\\(.+?\\):\\([1-9][0-9]*\\):\\([1-9][0-9]*\\):" |
|
||||||
"A regexp pattern that groups output into filename, line number and column number.") |
|
||||||
|
|
||||||
(define-compilation-mode ag-mode "Ag" |
|
||||||
"Ag results compilation mode" |
|
||||||
(set (make-local-variable 'compilation-error-regexp-alist) |
|
||||||
(list 'compilation-ag-nogroup)) |
|
||||||
(set (make-local-variable 'compilation-error-regexp-alist-alist) |
|
||||||
(list (cons 'compilation-ag-nogroup (list ag/file-column-pattern 1 2 3)))) |
|
||||||
(set (make-local-variable 'compilation-error-face) 'ag-hit-face) |
|
||||||
(set (make-local-variable 'next-error-function) #'ag/next-error-function) |
|
||||||
(set (make-local-variable 'compilation-finish-functions) |
|
||||||
#'ag/run-finished-hook) |
|
||||||
(add-hook 'compilation-filter-hook 'ag-filter nil t)) |
|
||||||
|
|
||||||
(define-key ag-mode-map (kbd "p") #'compilation-previous-error) |
|
||||||
(define-key ag-mode-map (kbd "n") #'compilation-next-error) |
|
||||||
(define-key ag-mode-map (kbd "k") '(lambda () (interactive) |
|
||||||
(let (kill-buffer-query-functions) (kill-buffer)))) |
|
||||||
|
|
||||||
(defun ag/buffer-name (search-string directory regexp) |
|
||||||
"Return a buffer name formatted according to ag.el conventions." |
|
||||||
(cond |
|
||||||
(ag-reuse-buffers "*ag search*") |
|
||||||
(regexp (format "*ag search regexp:%s dir:%s*" search-string directory)) |
|
||||||
(:else (format "*ag search text:%s dir:%s*" search-string directory)))) |
|
||||||
|
|
||||||
(defun ag/format-ignore (ignores) |
|
||||||
"Prepend '--ignore' to every item in IGNORES." |
|
||||||
(apply #'append |
|
||||||
(mapcar (lambda (item) (list "--ignore" item)) ignores))) |
|
||||||
|
|
||||||
(defun* ag/search (string directory |
|
||||||
&key (regexp nil) (file-regex nil) (file-type nil)) |
|
||||||
"Run ag searching for the STRING given in DIRECTORY. |
|
||||||
If REGEXP is non-nil, treat STRING as a regular expression." |
|
||||||
(let ((default-directory (file-name-as-directory directory)) |
|
||||||
(arguments ag-arguments) |
|
||||||
(shell-command-switch "-c")) |
|
||||||
(unless regexp |
|
||||||
(setq arguments (cons "--literal" arguments))) |
|
||||||
(if ag-highlight-search |
|
||||||
(setq arguments (append '("--color" "--color-match" "30;43") arguments)) |
|
||||||
(setq arguments (append '("--nocolor") arguments))) |
|
||||||
(when (char-or-string-p file-regex) |
|
||||||
(setq arguments (append `("--file-search-regex" ,file-regex) arguments))) |
|
||||||
(when file-type |
|
||||||
(setq arguments (cons (format "--%s" file-type) arguments))) |
|
||||||
(when ag-ignore-list |
|
||||||
(setq arguments (append (ag/format-ignore ag-ignore-list) arguments))) |
|
||||||
(unless (file-exists-p default-directory) |
|
||||||
(error "No such directory %s" default-directory)) |
|
||||||
(let ((command-string |
|
||||||
(mapconcat #'shell-quote-argument |
|
||||||
(append (list ag-executable) arguments (list string ".")) |
|
||||||
" "))) |
|
||||||
;; If we're called with a prefix, let the user modify the command before |
|
||||||
;; running it. Typically this means they want to pass additional arguments. |
|
||||||
(when current-prefix-arg |
|
||||||
;; Make a space in the command-string for the user to enter more arguments. |
|
||||||
(setq command-string (ag/replace-first command-string " -- " " -- ")) |
|
||||||
;; Prompt for the command. |
|
||||||
(let ((adjusted-point (- (length command-string) (length string) 5))) |
|
||||||
(setq command-string |
|
||||||
(read-from-minibuffer "ag command: " |
|
||||||
(cons command-string adjusted-point))))) |
|
||||||
;; Call ag. |
|
||||||
(compilation-start |
|
||||||
command-string |
|
||||||
#'ag-mode |
|
||||||
`(lambda (mode-name) ,(ag/buffer-name string directory regexp)))))) |
|
||||||
|
|
||||||
(defun ag/dwim-at-point () |
|
||||||
"If there's an active selection, return that. |
|
||||||
Otherwise, get the symbol at point, as a string." |
|
||||||
(cond ((use-region-p) |
|
||||||
(buffer-substring-no-properties (region-beginning) (region-end))) |
|
||||||
((symbol-at-point) |
|
||||||
(substring-no-properties |
|
||||||
(symbol-name (symbol-at-point)))))) |
|
||||||
|
|
||||||
(defun ag/buffer-extension-regex () |
|
||||||
"If the current buffer has an extension, return |
|
||||||
a PCRE pattern that matches files with that extension. |
|
||||||
Returns an empty string otherwise." |
|
||||||
(let ((file-name (buffer-file-name))) |
|
||||||
(if (stringp file-name) |
|
||||||
(format "\\.%s$" (ag/escape-pcre (file-name-extension file-name))) |
|
||||||
""))) |
|
||||||
|
|
||||||
(defun ag/longest-string (&rest strings) |
|
||||||
"Given a list of strings and nils, return the longest string." |
|
||||||
(let ((longest-string nil)) |
|
||||||
(dolist (string strings) |
|
||||||
(cond ((null longest-string) |
|
||||||
(setq longest-string string)) |
|
||||||
((stringp string) |
|
||||||
(when (< (length longest-string) |
|
||||||
(length string)) |
|
||||||
(setq longest-string string))))) |
|
||||||
longest-string)) |
|
||||||
|
|
||||||
(defun ag/replace-first (string before after) |
|
||||||
"Replace the first occurrence of BEFORE in STRING with AFTER." |
|
||||||
(replace-regexp-in-string |
|
||||||
(concat "\\(" (regexp-quote before) "\\)" ".*\\'") |
|
||||||
after string |
|
||||||
nil nil 1)) |
|
||||||
|
|
||||||
(autoload 'vc-git-root "vc-git") |
|
||||||
|
|
||||||
(require 'vc-svn) |
|
||||||
;; Emacs 23.4 doesn't provide vc-svn-root. |
|
||||||
(unless (functionp 'vc-svn-root) |
|
||||||
(defun vc-svn-root (file) |
|
||||||
(vc-find-root file vc-svn-admin-directory))) |
|
||||||
|
|
||||||
(autoload 'vc-hg-root "vc-hg") |
|
||||||
|
|
||||||
(defun ag/project-root (file-path) |
|
||||||
"Guess the project root of the given FILE-PATH. |
|
||||||
|
|
||||||
Use `ag-project-root-function' if set, or fall back to VCS |
|
||||||
roots." |
|
||||||
(if ag-project-root-function |
|
||||||
(funcall ag-project-root-function file-path) |
|
||||||
(or (ag/longest-string |
|
||||||
(vc-git-root file-path) |
|
||||||
(vc-svn-root file-path) |
|
||||||
(vc-hg-root file-path)) |
|
||||||
file-path))) |
|
||||||
|
|
||||||
(defun ag/dired-align-size-column () |
|
||||||
(beginning-of-line) |
|
||||||
(when (looking-at "^ ") |
|
||||||
(forward-char 2) |
|
||||||
(search-forward " " nil t 4) |
|
||||||
(let* ((size-start (point)) |
|
||||||
(size-end (search-forward " " nil t)) |
|
||||||
(width (and size-end (- size-end size-start)))) |
|
||||||
(when (and size-end |
|
||||||
(< width 12) |
|
||||||
(> width 1)) |
|
||||||
(goto-char size-start) |
|
||||||
(insert (make-string (- 12 width) ? )))))) |
|
||||||
|
|
||||||
(defun ag/dired-filter (proc string) |
|
||||||
"Filter the output of ag to make it suitable for `dired-mode'." |
|
||||||
(let ((buf (process-buffer proc)) |
|
||||||
(inhibit-read-only t)) |
|
||||||
(if (buffer-name buf) |
|
||||||
(with-current-buffer buf |
|
||||||
(save-excursion |
|
||||||
(save-restriction |
|
||||||
(widen) |
|
||||||
(let ((beg (point-max))) |
|
||||||
(goto-char beg) |
|
||||||
(insert string) |
|
||||||
(goto-char beg) |
|
||||||
(or (looking-at "^") |
|
||||||
(progn |
|
||||||
(ag/dired-align-size-column) |
|
||||||
(forward-line 1))) |
|
||||||
(while (looking-at "^") |
|
||||||
(insert " ") |
|
||||||
(ag/dired-align-size-column) |
|
||||||
(forward-line 1)) |
|
||||||
(goto-char beg) |
|
||||||
(beginning-of-line) |
|
||||||
|
|
||||||
;; Remove occurrences of default-directory. |
|
||||||
(while (search-forward (concat " " default-directory) nil t) |
|
||||||
(replace-match " " nil t)) |
|
||||||
|
|
||||||
(goto-char (point-max)) |
|
||||||
(if (search-backward "\n" (process-mark proc) t) |
|
||||||
(progn |
|
||||||
(dired-insert-set-properties (process-mark proc) |
|
||||||
(1+ (point))) |
|
||||||
(move-marker (process-mark proc) (1+ (point))))))))) |
|
||||||
(delete-process proc)))) |
|
||||||
|
|
||||||
(defun ag/dired-sentinel (proc state) |
|
||||||
"Update the status/modeline after the process finishes." |
|
||||||
(let ((buf (process-buffer proc)) |
|
||||||
(inhibit-read-only t)) |
|
||||||
(if (buffer-name buf) |
|
||||||
(with-current-buffer buf |
|
||||||
(let ((buffer-read-only nil)) |
|
||||||
(save-excursion |
|
||||||
(goto-char (point-max)) |
|
||||||
(insert "\n ag " state) |
|
||||||
(forward-char -1) ;Back up before \n at end of STATE. |
|
||||||
(insert " at " (substring (current-time-string) 0 19)) |
|
||||||
(forward-char 1) |
|
||||||
(setq mode-line-process |
|
||||||
(concat ":" (symbol-name (process-status proc)))) |
|
||||||
;; Since the buffer and mode line will show that the |
|
||||||
;; process is dead, we can delete it now. Otherwise it |
|
||||||
;; will stay around until M-x list-processes. |
|
||||||
(delete-process proc) |
|
||||||
(force-mode-line-update))) |
|
||||||
(run-hooks 'dired-after-readin-hook) |
|
||||||
(message "%s finished." (current-buffer)))))) |
|
||||||
|
|
||||||
(defun ag/kill-process () |
|
||||||
"Kill the `ag' process running in the current buffer." |
|
||||||
(interactive) |
|
||||||
(let ((ag (get-buffer-process (current-buffer)))) |
|
||||||
(and ag (eq (process-status ag) 'run) |
|
||||||
(eq (process-filter ag) (function find-dired-filter)) |
|
||||||
(condition-case nil |
|
||||||
(delete-process ag) |
|
||||||
(error nil))))) |
|
||||||
|
|
||||||
(defun ag/escape-pcre (regexp) |
|
||||||
"Escape the PCRE-special characters in REGEXP so that it is |
|
||||||
matched literally." |
|
||||||
(let ((alphanum "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")) |
|
||||||
(apply #'concat |
|
||||||
(mapcar |
|
||||||
(lambda (c) |
|
||||||
(cond |
|
||||||
((not (string-match-p (regexp-quote c) alphanum)) |
|
||||||
(concat "\\" c)) |
|
||||||
(t c))) |
|
||||||
(mapcar #'char-to-string (string-to-list regexp)))))) |
|
||||||
|
|
||||||
;;;###autoload |
|
||||||
(defun ag (string directory) |
|
||||||
"Search using ag in a given DIRECTORY for a given search STRING, |
|
||||||
with STRING defaulting to the symbol under point. |
|
||||||
|
|
||||||
If called with a prefix, prompts for flags to pass to ag." |
|
||||||
(interactive (list (ag/read-from-minibuffer "Search string") |
|
||||||
(read-directory-name "Directory: "))) |
|
||||||
(ag/search string directory)) |
|
||||||
|
|
||||||
;;;###autoload |
|
||||||
(defun ag-files (string file-type directory) |
|
||||||
"Search using ag in a given DIRECTORY for a given search STRING, |
|
||||||
limited to files that match FILE-TYPE. STRING defaults to |
|
||||||
the symbol under point. |
|
||||||
|
|
||||||
If called with a prefix, prompts for flags to pass to ag." |
|
||||||
(interactive (list (ag/read-from-minibuffer "Search string") |
|
||||||
(ag/read-file-type) |
|
||||||
(read-directory-name "Directory: "))) |
|
||||||
(apply #'ag/search string directory file-type)) |
|
||||||
|
|
||||||
;;;###autoload |
|
||||||
(defun ag-regexp (string directory) |
|
||||||
"Search using ag in a given directory for a given regexp. |
|
||||||
The regexp should be in PCRE syntax, not Emacs regexp syntax. |
|
||||||
|
|
||||||
If called with a prefix, prompts for flags to pass to ag." |
|
||||||
(interactive "sSearch regexp: \nDDirectory: ") |
|
||||||
(ag/search string directory :regexp t)) |
|
||||||
|
|
||||||
;;;###autoload |
|
||||||
(defun ag-project (string) |
|
||||||
"Guess the root of the current project and search it with ag |
|
||||||
for the given string. |
|
||||||
|
|
||||||
If called with a prefix, prompts for flags to pass to ag." |
|
||||||
(interactive (list (ag/read-from-minibuffer "Search string"))) |
|
||||||
(ag/search string (ag/project-root default-directory))) |
|
||||||
|
|
||||||
;;;###autoload |
|
||||||
(defun ag-project-files (string file-type) |
|
||||||
"Search using ag for a given search STRING, |
|
||||||
limited to files that match FILE-TYPE. STRING defaults to the |
|
||||||
symbol under point. |
|
||||||
|
|
||||||
If called with a prefix, prompts for flags to pass to ag." |
|
||||||
(interactive (list (ag/read-from-minibuffer "Search string") |
|
||||||
(ag/read-file-type))) |
|
||||||
(apply 'ag/search string (ag/project-root default-directory) file-type)) |
|
||||||
|
|
||||||
(defun ag/read-from-minibuffer (prompt) |
|
||||||
"Read a value from the minibuffer with PROMPT. |
|
||||||
If there's a string at point, offer that as a default." |
|
||||||
(let* ((suggested (ag/dwim-at-point)) |
|
||||||
(final-prompt |
|
||||||
(if suggested |
|
||||||
(format "%s (default %s): " prompt suggested) |
|
||||||
(format "%s: " prompt))) |
|
||||||
;; Ask the user for input, but add `suggested' to the history |
|
||||||
;; so they can use M-n if they want to modify it. |
|
||||||
(user-input (read-from-minibuffer |
|
||||||
final-prompt |
|
||||||
nil nil nil nil suggested))) |
|
||||||
;; Return the input provided by the user, or use `suggested' if |
|
||||||
;; the input was empty. |
|
||||||
(if (> (length user-input) 0) |
|
||||||
user-input |
|
||||||
suggested))) |
|
||||||
|
|
||||||
;;;###autoload |
|
||||||
(defun ag-project-regexp (regexp) |
|
||||||
"Guess the root of the current project and search it with ag |
|
||||||
for the given regexp. The regexp should be in PCRE syntax, not |
|
||||||
Emacs regexp syntax. |
|
||||||
|
|
||||||
If called with a prefix, prompts for flags to pass to ag." |
|
||||||
(interactive (list (ag/read-from-minibuffer "Search regexp"))) |
|
||||||
(ag/search regexp (ag/project-root default-directory) :regexp t)) |
|
||||||
|
|
||||||
(autoload 'symbol-at-point "thingatpt") |
|
||||||
|
|
||||||
;;;###autoload |
|
||||||
(defalias 'ag-project-at-point 'ag-project) |
|
||||||
(make-obsolete 'ag-project-at-point 'ag-project "0.19") |
|
||||||
|
|
||||||
;;;###autoload |
|
||||||
(defalias 'ag-regexp-project-at-point 'ag-project-regexp) |
|
||||||
(make-obsolete 'ag-regexp-project-at-point 'ag-project-regexp "0.46") |
|
||||||
|
|
||||||
;;;###autoload |
|
||||||
(defun ag-dired (dir pattern) |
|
||||||
"Recursively find files in DIR matching PATTERN. |
|
||||||
|
|
||||||
The PATTERN is matched against the full path to the file, not |
|
||||||
only against the file name. |
|
||||||
|
|
||||||
The results are presented as a `dired-mode' buffer with |
|
||||||
`default-directory' being DIR. |
|
||||||
|
|
||||||
See also `ag-dired-regexp'." |
|
||||||
(interactive "DDirectory: \nsFile pattern: ") |
|
||||||
(ag-dired-regexp dir (ag/escape-pcre pattern))) |
|
||||||
|
|
||||||
;;;###autoload |
|
||||||
(defun ag-dired-regexp (dir regexp) |
|
||||||
"Recursively find files in DIR matching REGEXP. |
|
||||||
REGEXP should be in PCRE syntax, not Emacs regexp syntax. |
|
||||||
|
|
||||||
The REGEXP is matched against the full path to the file, not |
|
||||||
only against the file name. |
|
||||||
|
|
||||||
Results are presented as a `dired-mode' buffer with |
|
||||||
`default-directory' being DIR. |
|
||||||
|
|
||||||
See also `find-dired'." |
|
||||||
(interactive "DDirectory: \nsFile regexp: ") |
|
||||||
(let* ((dired-buffers dired-buffers) ;; do not mess with regular dired buffers |
|
||||||
(orig-dir dir) |
|
||||||
(dir (file-name-as-directory (expand-file-name dir))) |
|
||||||
(buffer-name (if ag-reuse-buffers |
|
||||||
"*ag dired*" |
|
||||||
(format "*ag dired pattern:%s dir:%s*" regexp dir))) |
|
||||||
(cmd (concat ag-executable " --nocolor -g '" regexp "' " |
|
||||||
(shell-quote-argument dir) |
|
||||||
" | grep -v '^$' | sed s/\\'/\\\\\\\\\\'/ | xargs -I '{}' ls " |
|
||||||
dired-listing-switches " '{}' &"))) |
|
||||||
(with-current-buffer (get-buffer-create buffer-name) |
|
||||||
(switch-to-buffer (current-buffer)) |
|
||||||
(widen) |
|
||||||
(kill-all-local-variables) |
|
||||||
(if (fboundp 'read-only-mode) |
|
||||||
(read-only-mode -1) |
|
||||||
(setq buffer-read-only nil)) |
|
||||||
(let ((inhibit-read-only t)) (erase-buffer)) |
|
||||||
(setq default-directory dir) |
|
||||||
(run-hooks 'dired-before-readin-hook) |
|
||||||
(shell-command cmd (current-buffer)) |
|
||||||
(insert " " dir ":\n") |
|
||||||
(insert " " cmd "\n") |
|
||||||
(dired-mode dir) |
|
||||||
(let ((map (make-sparse-keymap))) |
|
||||||
(set-keymap-parent map (current-local-map)) |
|
||||||
(define-key map "\C-c\C-k" 'ag/kill-process) |
|
||||||
(use-local-map map)) |
|
||||||
(set (make-local-variable 'dired-sort-inhibit) t) |
|
||||||
(set (make-local-variable 'revert-buffer-function) |
|
||||||
`(lambda (ignore-auto noconfirm) |
|
||||||
(ag-dired-regexp ,orig-dir ,regexp))) |
|
||||||
(if (fboundp 'dired-simple-subdir-alist) |
|
||||||
(dired-simple-subdir-alist) |
|
||||||
(set (make-local-variable 'dired-subdir-alist) |
|
||||||
(list (cons default-directory (point-min-marker))))) |
|
||||||
(let ((proc (get-buffer-process (current-buffer)))) |
|
||||||
(set-process-filter proc #'ag/dired-filter) |
|
||||||
(set-process-sentinel proc #'ag/dired-sentinel) |
|
||||||
;; Initialize the process marker; it is used by the filter. |
|
||||||
(move-marker (process-mark proc) 1 (current-buffer))) |
|
||||||
(setq mode-line-process '(":%s"))))) |
|
||||||
|
|
||||||
;;;###autoload |
|
||||||
(defun ag-project-dired (pattern) |
|
||||||
"Recursively find files in current project matching PATTERN. |
|
||||||
|
|
||||||
See also `ag-dired'." |
|
||||||
(interactive "sFile pattern: ") |
|
||||||
(ag-dired-regexp (ag/project-root default-directory) (ag/escape-pcre pattern))) |
|
||||||
|
|
||||||
;;;###autoload |
|
||||||
(defun ag-project-dired-regexp (regexp) |
|
||||||
"Recursively find files in current project matching REGEXP. |
|
||||||
|
|
||||||
See also `ag-dired-regexp'." |
|
||||||
(interactive "sFile regexp: ") |
|
||||||
(ag-dired-regexp (ag/project-root default-directory) regexp)) |
|
||||||
|
|
||||||
;;;###autoload |
|
||||||
(defun ag-kill-buffers () |
|
||||||
"Kill all `ag-mode' buffers." |
|
||||||
(interactive) |
|
||||||
(dolist (buffer (buffer-list)) |
|
||||||
(when (eq (buffer-local-value 'major-mode buffer) 'ag-mode) |
|
||||||
(kill-buffer buffer)))) |
|
||||||
|
|
||||||
;;;###autoload |
|
||||||
(defun ag-kill-other-buffers () |
|
||||||
"Kill all `ag-mode' buffers other than the current buffer." |
|
||||||
(interactive) |
|
||||||
(let ((current-buffer (current-buffer))) |
|
||||||
(dolist (buffer (buffer-list)) |
|
||||||
(when (and |
|
||||||
(eq (buffer-local-value 'major-mode buffer) 'ag-mode) |
|
||||||
(not (eq buffer current-buffer))) |
|
||||||
(kill-buffer buffer))))) |
|
||||||
|
|
||||||
;; Taken from grep-filter, just changed the color regex. |
|
||||||
(defun ag-filter () |
|
||||||
"Handle match highlighting escape sequences inserted by the ag process. |
|
||||||
This function is called from `compilation-filter-hook'." |
|
||||||
(when ag-highlight-search |
|
||||||
(save-excursion |
|
||||||
(forward-line 0) |
|
||||||
(let ((end (point)) beg) |
|
||||||
(goto-char compilation-filter-start) |
|
||||||
(forward-line 0) |
|
||||||
(setq beg (point)) |
|
||||||
;; Only operate on whole lines so we don't get caught with part of an |
|
||||||
;; escape sequence in one chunk and the rest in another. |
|
||||||
(when (< (point) end) |
|
||||||
(setq end (copy-marker end)) |
|
||||||
;; Highlight ag matches and delete marking sequences. |
|
||||||
(while (re-search-forward "\033\\[30;43m\\(.*?\\)\033\\[[0-9]*m" end 1) |
|
||||||
(replace-match (propertize (match-string 1) |
|
||||||
'face nil 'font-lock-face 'ag-match-face) |
|
||||||
t t)) |
|
||||||
;; Delete all remaining escape sequences |
|
||||||
(goto-char beg) |
|
||||||
(while (re-search-forward "\033\\[[0-9;]*[mK]" end 1) |
|
||||||
(replace-match "" t t))))))) |
|
||||||
|
|
||||||
(defun ag/get-supported-types () |
|
||||||
"Query the ag executable for which file types it recognises." |
|
||||||
(let* ((ag-output (shell-command-to-string (format "%s --list-file-types" ag-executable))) |
|
||||||
(lines (-map #'s-trim (s-lines ag-output))) |
|
||||||
(types (--keep (when (s-starts-with? "--" it) (s-chop-prefix "--" it )) lines)) |
|
||||||
(extensions (--map (s-split " " it) (--filter (s-starts-with? "." it) lines)))) |
|
||||||
(-zip types extensions))) |
|
||||||
|
|
||||||
(defun ag/read-file-type () |
|
||||||
"Prompt the user for a known file type, or let them specify a PCRE regex." |
|
||||||
(let* ((all-types-with-extensions (ag/get-supported-types)) |
|
||||||
(all-types (mapcar 'car all-types-with-extensions)) |
|
||||||
(file-type |
|
||||||
(completing-read "Select file type: " |
|
||||||
(append '("custom (provide a PCRE regex)") all-types))) |
|
||||||
(file-type-extensions |
|
||||||
(cdr (assoc file-type all-types-with-extensions)))) |
|
||||||
(if file-type-extensions |
|
||||||
(list :file-type file-type) |
|
||||||
(list :file-regex |
|
||||||
(read-from-minibuffer "Filenames which match PCRE: " |
|
||||||
(ag/buffer-extension-regex)))))) |
|
||||||
|
|
||||||
(provide 'ag) |
|
||||||
;;; ag.el ends here |
|
@ -1,777 +0,0 @@ |
|||||||
(1 |
|
||||||
(ace-window . |
|
||||||
[(0 9 0) |
|
||||||
((avy |
|
||||||
(0 2 0))) |
|
||||||
"Quickly switch windows." single |
|
||||||
((:url . "https://github.com/abo-abo/ace-window") |
|
||||||
(:keywords "window" "location"))]) |
|
||||||
(ack . |
|
||||||
[(1 5) |
|
||||||
nil "interface to ack-like tools" tar |
|
||||||
((:keywords "tools" "processes" "convenience") |
|
||||||
(:url . "https://github.com/leoliu/ack-el"))]) |
|
||||||
(ada-mode . |
|
||||||
[(5 1 8) |
|
||||||
((wisi |
|
||||||
(1 1 1)) |
|
||||||
(cl-lib |
|
||||||
(0 4)) |
|
||||||
(emacs |
|
||||||
(24 2))) |
|
||||||
"major-mode for editing Ada sources" tar |
|
||||||
((:keywords "languages" "ada") |
|
||||||
(:url . "http://stephe-leake.org/emacs/ada-mode/emacs-ada-mode.html"))]) |
|
||||||
(ada-ref-man . |
|
||||||
[(2012 0) |
|
||||||
nil "Ada Reference Manual 2012" tar |
|
||||||
((:keywords "languages" "ada") |
|
||||||
(:url . "http://stephe-leake.org/ada/arm.html"))]) |
|
||||||
(adaptive-wrap . |
|
||||||
[(0 5) |
|
||||||
nil "Smart line-wrapping with wrap-prefix" single |
|
||||||
((:url . "http://elpa.gnu.org/packages/adaptive-wrap.html") |
|
||||||
(:keywords))]) |
|
||||||
(adjust-parens . |
|
||||||
[(3 0) |
|
||||||
nil "Indent and dedent Lisp code, automatically adjust close parens" tar |
|
||||||
((:url . "http://elpa.gnu.org/packages/adjust-parens.html"))]) |
|
||||||
(aggressive-indent . |
|
||||||
[(1 4) |
|
||||||
((emacs |
|
||||||
(24 1)) |
|
||||||
(cl-lib |
|
||||||
(0 5))) |
|
||||||
"Minor mode to aggressively keep your code always indented" single |
|
||||||
((:url . "http://github.com/Malabarba/aggressive-indent-mode") |
|
||||||
(:keywords "indent" "lisp" "maint" "tools"))]) |
|
||||||
(ahungry-theme . |
|
||||||
[(1 0 12) |
|
||||||
((emacs |
|
||||||
(24))) |
|
||||||
"Ahungry color theme for Emacs. Make sure to (load-theme 'ahungry)." tar |
|
||||||
((:keywords "ahungry" "palette" "color" "theme" "emacs" "color-theme" "deftheme") |
|
||||||
(:url . "https://github.com/ahungry/color-theme-ahungry"))]) |
|
||||||
(all . |
|
||||||
[(1 0) |
|
||||||
nil "Edit all lines matching a given regexp" single |
|
||||||
((:url . "http://elpa.gnu.org/packages/all.html") |
|
||||||
(:keywords "matching"))]) |
|
||||||
(ascii-art-to-unicode . |
|
||||||
[(1 9) |
|
||||||
nil "a small artist adjunct" single |
|
||||||
((:url . "http://www.gnuvola.org/software/aa2u/") |
|
||||||
(:keywords "ascii" "unicode" "box-drawing"))]) |
|
||||||
(auctex . |
|
||||||
[(11 88 9) |
|
||||||
nil "Integrated environment for *TeX*" tar |
|
||||||
((:url . "http://www.gnu.org/software/auctex/"))]) |
|
||||||
(aumix-mode . |
|
||||||
[(7) |
|
||||||
nil "run the aumix program in a buffer" single |
|
||||||
((:url . "http://user42.tuxfamily.org/aumix-mode/index.html") |
|
||||||
(:keywords "multimedia" "mixer" "aumix"))]) |
|
||||||
(auto-overlays . |
|
||||||
[(0 10 9) |
|
||||||
nil "Automatic regexp-delimited overlays" tar |
|
||||||
((:keywords "extensions") |
|
||||||
(:url . "http://www.dr-qubit.org/emacs.php"))]) |
|
||||||
(avy . |
|
||||||
[(0 3 0) |
|
||||||
((emacs |
|
||||||
(24 1)) |
|
||||||
(cl-lib |
|
||||||
(0 5))) |
|
||||||
"set-based completion" tar |
|
||||||
((:keywords "point" "location") |
|
||||||
(:url . "https://github.com/abo-abo/avy"))]) |
|
||||||
(beacon . |
|
||||||
[(0 2 1) |
|
||||||
((seq |
|
||||||
(1 9))) |
|
||||||
"Highlight the cursor whenever the window scrolls" single |
|
||||||
((:url . "https://github.com/Malabarba/beacon") |
|
||||||
(:keywords "convenience"))]) |
|
||||||
(bug-hunter . |
|
||||||
[(1 0) |
|
||||||
((seq |
|
||||||
(1 3)) |
|
||||||
(cl-lib |
|
||||||
(0 5))) |
|
||||||
"Hunt down errors in elisp files" single |
|
||||||
((:url . "http://github.com/Malabarba/elisp-bug-hunter") |
|
||||||
(:keywords "lisp"))]) |
|
||||||
(caps-lock . |
|
||||||
[(1 0) |
|
||||||
nil "Caps-lock as a minor mode" single |
|
||||||
((:url . "http://elpa.gnu.org/packages/caps-lock.html") |
|
||||||
(:keywords))]) |
|
||||||
(chess . |
|
||||||
[(2 0 4) |
|
||||||
((cl-lib |
|
||||||
(0 5))) |
|
||||||
"Play chess in GNU Emacs" tar |
|
||||||
((:keywords "games") |
|
||||||
(:url . "http://elpa.gnu.org/packages/chess.html"))]) |
|
||||||
(cl-generic . |
|
||||||
[(0 2) |
|
||||||
nil "Forward cl-generic compatibility for Emacs<25" single |
|
||||||
((:url . "http://elpa.gnu.org/packages/cl-generic.html") |
|
||||||
(:keywords))]) |
|
||||||
(cl-lib . |
|
||||||
[(0 5) |
|
||||||
nil "Properly prefixed CL functions and macros" single |
|
||||||
((:url . "http://elpa.gnu.org/packages/cl-lib.html") |
|
||||||
(:keywords))]) |
|
||||||
(coffee-mode . |
|
||||||
[(0 4 1 1) |
|
||||||
nil "Major mode for CoffeeScript files" single |
|
||||||
((:url . "http://github.com/defunkt/coffee-mode") |
|
||||||
(:keywords "coffeescript" "major" "mode"))]) |
|
||||||
(company . |
|
||||||
[(0 8 12) |
|
||||||
((emacs |
|
||||||
(24 1)) |
|
||||||
(cl-lib |
|
||||||
(0 5))) |
|
||||||
"Modular text completion framework" tar |
|
||||||
((:keywords "abbrev" "convenience" "matching") |
|
||||||
(:url . "http://company-mode.github.io/"))]) |
|
||||||
(company-math . |
|
||||||
[(1 0 1) |
|
||||||
((company |
|
||||||
(0 8 0)) |
|
||||||
(math-symbol-lists |
|
||||||
(1 0))) |
|
||||||
"Completion backends for unicode math symbols and latex tags" single |
|
||||||
((:url . "https://github.com/vspinu/company-math") |
|
||||||
(:keywords "unicode" "symbols" "completion"))]) |
|
||||||
(company-statistics . |
|
||||||
[(0 2 1) |
|
||||||
((emacs |
|
||||||
(24 3)) |
|
||||||
(company |
|
||||||
(0 8 5))) |
|
||||||
"Sort candidates using completion history" tar |
|
||||||
((:keywords "abbrev" "convenience" "matching") |
|
||||||
(:url . "https://github.com/company-mode/company-statistics"))]) |
|
||||||
(context-coloring . |
|
||||||
[(7 1 0) |
|
||||||
((emacs |
|
||||||
(24 3)) |
|
||||||
(js2-mode |
|
||||||
(20150713))) |
|
||||||
"Highlight by scope" single |
|
||||||
((:url . "https://github.com/jacksonrayhamilton/context-coloring") |
|
||||||
(:keywords "convenience" "faces" "tools"))]) |
|
||||||
(crisp . |
|
||||||
[(1 3 4) |
|
||||||
nil "CRiSP/Brief Emacs emulator" single |
|
||||||
((:url . "http://elpa.gnu.org/packages/crisp.html") |
|
||||||
(:keywords "emulations" "brief" "crisp"))]) |
|
||||||
(csv-mode . |
|
||||||
[(1 5) |
|
||||||
nil "Major mode for editing comma/char separated values" single |
|
||||||
((:url . "http://centaur.maths.qmul.ac.uk/Emacs/") |
|
||||||
(:keywords "convenience"))]) |
|
||||||
(darkroom . |
|
||||||
[(0 1) |
|
||||||
((cl-lib |
|
||||||
(0 5))) |
|
||||||
"Remove visual distractions and focus on writing" single |
|
||||||
((:url . "http://elpa.gnu.org/packages/darkroom.html") |
|
||||||
(:keywords "convenience" "emulations"))]) |
|
||||||
(dash . |
|
||||||
[(2 12 0) |
|
||||||
nil "A modern list library for Emacs" tar |
|
||||||
((:keywords "lists") |
|
||||||
(:url . "http://elpa.gnu.org/packages/dash.html"))]) |
|
||||||
(dbus-codegen . |
|
||||||
[(0 1) |
|
||||||
((cl-lib |
|
||||||
(0 5))) |
|
||||||
"Lisp code generation for D-Bus." single |
|
||||||
((:url . "http://elpa.gnu.org/packages/dbus-codegen.html") |
|
||||||
(:keywords "comm" "dbus" "convenience"))]) |
|
||||||
(debbugs . |
|
||||||
[(0 7) |
|
||||||
nil "SOAP library to access debbugs servers" tar |
|
||||||
((:keywords "comm" "hypermedia") |
|
||||||
(:url . "http://elpa.gnu.org/packages/debbugs.html"))]) |
|
||||||
(dict-tree . |
|
||||||
[(0 12 8) |
|
||||||
((trie |
|
||||||
(0 2 5)) |
|
||||||
(tNFA |
|
||||||
(0 1 1)) |
|
||||||
(heap |
|
||||||
(0 3))) |
|
||||||
"Dictionary data structure" single |
|
||||||
((:url . "http://www.dr-qubit.org/emacs.php") |
|
||||||
(:keywords "extensions" "matching" "data structures trie" "tree" "dictionary" "completion" "regexp"))]) |
|
||||||
(diff-hl . |
|
||||||
[(1 8 0) |
|
||||||
((cl-lib |
|
||||||
(0 2))) |
|
||||||
"Highlight uncommitted changes" tar |
|
||||||
((:keywords "vc" "diff") |
|
||||||
(:url . "https://github.com/dgutov/diff-hl"))]) |
|
||||||
(dismal . |
|
||||||
[(1 5) |
|
||||||
((cl-lib |
|
||||||
(0))) |
|
||||||
"Dis Mode Ain't Lotus: Spreadsheet program Emacs" tar |
|
||||||
((:url . "http://elpa.gnu.org/packages/dismal.html"))]) |
|
||||||
(djvu . |
|
||||||
[(0 5) |
|
||||||
nil "Edit and view Djvu files via djvused" single |
|
||||||
((:url . "http://elpa.gnu.org/packages/djvu.html") |
|
||||||
(:keywords "files" "wp"))]) |
|
||||||
(docbook . |
|
||||||
[(0 1) |
|
||||||
nil "Info-like viewer for DocBook" single |
|
||||||
((:url . "http://elpa.gnu.org/packages/docbook.html") |
|
||||||
(:keywords "docs" "help"))]) |
|
||||||
(dts-mode . |
|
||||||
[(0 1 0) |
|
||||||
nil "Major mode for Device Tree source files" single |
|
||||||
((:url . "http://elpa.gnu.org/packages/dts-mode.html") |
|
||||||
(:keywords "languages"))]) |
|
||||||
(easy-kill . |
|
||||||
[(0 9 3) |
|
||||||
((emacs |
|
||||||
(24)) |
|
||||||
(cl-lib |
|
||||||
(0 5))) |
|
||||||
"kill & mark things easily" tar |
|
||||||
((:keywords "killing" "convenience") |
|
||||||
(:url . "https://github.com/leoliu/easy-kill"))]) |
|
||||||
(ediprolog . |
|
||||||
[(1 1) |
|
||||||
nil "Emacs Does Interactive Prolog" single |
|
||||||
((:url . "http://elpa.gnu.org/packages/ediprolog.html") |
|
||||||
(:keywords "languages" "processes"))]) |
|
||||||
(el-search . |
|
||||||
[(0 0 3) |
|
||||||
((emacs |
|
||||||
(25))) |
|
||||||
"Expression based incremental search for emacs-lisp-mode" single |
|
||||||
((:url . "http://elpa.gnu.org/packages/el-search.html") |
|
||||||
(:keywords "lisp"))]) |
|
||||||
(eldoc-eval . |
|
||||||
[(0 1) |
|
||||||
nil "Enable eldoc support when minibuffer is in use." single |
|
||||||
((:url . "http://elpa.gnu.org/packages/eldoc-eval.html") |
|
||||||
(:keywords))]) |
|
||||||
(electric-spacing . |
|
||||||
[(5 0) |
|
||||||
nil "Insert operators with surrounding spaces smartly" single |
|
||||||
((:url . "http://elpa.gnu.org/packages/electric-spacing.html") |
|
||||||
(:keywords))]) |
|
||||||
(enwc . |
|
||||||
[(1 0) |
|
||||||
nil "The Emacs Network Client" tar |
|
||||||
((:keywords "enwc" "network" "wicd" "manager" "nm") |
|
||||||
(:url . "http://elpa.gnu.org/packages/enwc.html"))]) |
|
||||||
(epoch-view . |
|
||||||
[(0 0 1) |
|
||||||
nil "Minor mode to visualize epoch timestamps" single |
|
||||||
((:url . "http://elpa.gnu.org/packages/epoch-view.html") |
|
||||||
(:keywords "data" "timestamp" "epoch" "unix"))]) |
|
||||||
(ergoemacs-mode . |
|
||||||
[(5 14 7 3) |
|
||||||
((emacs |
|
||||||
(24 1)) |
|
||||||
(undo-tree |
|
||||||
(0 6 5))) |
|
||||||
"Emacs mode based on common modern interface and ergonomics." tar |
|
||||||
((:keywords "convenience") |
|
||||||
(:url . "https://github.com/ergoemacs/ergoemacs-mode"))]) |
|
||||||
(f90-interface-browser . |
|
||||||
[(1 1) |
|
||||||
nil "Parse and browse f90 interfaces" single |
|
||||||
((:url . "http://github.com/wence-/f90-iface/") |
|
||||||
(:keywords))]) |
|
||||||
(flylisp . |
|
||||||
[(0 2) |
|
||||||
((emacs |
|
||||||
(24 1)) |
|
||||||
(cl-lib |
|
||||||
(0 4))) |
|
||||||
"Color unbalanced parentheses and parentheses inconsistent with indentation" single |
|
||||||
((:url . "http://elpa.gnu.org/packages/flylisp.html") |
|
||||||
(:keywords))]) |
|
||||||
(fsm . |
|
||||||
[(0 2) |
|
||||||
((emacs |
|
||||||
(24 1)) |
|
||||||
(cl-lib |
|
||||||
(0 5))) |
|
||||||
"state machine library" single |
|
||||||
((:url . "http://elpa.gnu.org/packages/fsm.html") |
|
||||||
(:keywords "extensions"))]) |
|
||||||
(ggtags . |
|
||||||
[(0 8 10) |
|
||||||
((emacs |
|
||||||
(24)) |
|
||||||
(cl-lib |
|
||||||
(0 5))) |
|
||||||
"emacs frontend to GNU Global source code tagging system" single |
|
||||||
((:url . "https://github.com/leoliu/ggtags") |
|
||||||
(:keywords "tools" "convenience"))]) |
|
||||||
(gnorb . |
|
||||||
[(1 1 1) |
|
||||||
((cl-lib |
|
||||||
(0 5))) |
|
||||||
"Glue code between Gnus, Org, and BBDB" tar |
|
||||||
((:keywords "mail" "org" "gnus" "bbdb" "todo" "task") |
|
||||||
(:url . "https://github.com/girzel/gnorb"))]) |
|
||||||
(gnugo . |
|
||||||
[(3 0 0) |
|
||||||
((ascii-art-to-unicode |
|
||||||
(1 5)) |
|
||||||
(xpm |
|
||||||
(1 0 1)) |
|
||||||
(cl-lib |
|
||||||
(0 5))) |
|
||||||
"play GNU Go in a buffer" tar |
|
||||||
((:keywords "games" "processes") |
|
||||||
(:url . "http://www.gnuvola.org/software/gnugo/"))]) |
|
||||||
(heap . |
|
||||||
[(0 3) |
|
||||||
nil "Heap (a.k.a. priority queue) data structure" single |
|
||||||
((:url . "http://www.dr-qubit.org/emacs.php") |
|
||||||
(:keywords "extensions" "data structures" "heap" "priority queue"))]) |
|
||||||
(hydra . |
|
||||||
[(0 13 3) |
|
||||||
((cl-lib |
|
||||||
(0 5))) |
|
||||||
"Make bindings that stick around." tar |
|
||||||
((:keywords "bindings") |
|
||||||
(:url . "https://github.com/abo-abo/hydra"))]) |
|
||||||
(ioccur . |
|
||||||
[(2 4) |
|
||||||
nil "Incremental occur" single |
|
||||||
((:url . "http://elpa.gnu.org/packages/ioccur.html") |
|
||||||
(:keywords))]) |
|
||||||
(iterators . |
|
||||||
[(0 1) |
|
||||||
((emacs |
|
||||||
(25))) |
|
||||||
"Functions for working with iterators" single |
|
||||||
((:url . "http://elpa.gnu.org/packages/iterators.html") |
|
||||||
(:keywords "extensions" "elisp"))]) |
|
||||||
(javaimp . |
|
||||||
[(0 5) |
|
||||||
nil "Add and reorder Java import statements in Maven projects" single |
|
||||||
((:url . "http://elpa.gnu.org/packages/javaimp.html") |
|
||||||
(:keywords "java" "maven" "programming"))]) |
|
||||||
(jgraph-mode . |
|
||||||
[(1 1) |
|
||||||
((cl-lib |
|
||||||
(0 5))) |
|
||||||
"Major mode for Jgraph files" single |
|
||||||
((:url . "http://elpa.gnu.org/packages/jgraph-mode.html") |
|
||||||
(:keywords "tex" "wp"))]) |
|
||||||
(js2-mode . |
|
||||||
[(20150909) |
|
||||||
((emacs |
|
||||||
(24 1)) |
|
||||||
(cl-lib |
|
||||||
(0 5))) |
|
||||||
"Improved JavaScript editing mode" tar |
|
||||||
((:keywords "languages" "javascript") |
|
||||||
(:url . "https://github.com/mooz/js2-mode/"))]) |
|
||||||
(jumpc . |
|
||||||
[(3 0) |
|
||||||
nil "jump to previous insertion points" single |
|
||||||
((:url . "http://elpa.gnu.org/packages/jumpc.html") |
|
||||||
(:keywords))]) |
|
||||||
(landmark . |
|
||||||
[(1 0) |
|
||||||
nil "Neural-network robot that learns landmarks" single |
|
||||||
((:url . "http://elpa.gnu.org/packages/landmark.html") |
|
||||||
(:keywords "games" "neural network" "adaptive search" "chemotaxis"))]) |
|
||||||
(let-alist . |
|
||||||
[(1 0 4) |
|
||||||
nil "Easily let-bind values of an assoc-list by their names" single |
|
||||||
((:url . "http://elpa.gnu.org/packages/let-alist.html") |
|
||||||
(:keywords "extensions" "lisp"))]) |
|
||||||
(lex . |
|
||||||
[(1 1) |
|
||||||
nil "Lexical analyser construction" tar |
|
||||||
((:url . "http://elpa.gnu.org/packages/lex.html"))]) |
|
||||||
(lmc . |
|
||||||
[(1 3) |
|
||||||
nil "Little Man Computer in Elisp" single |
|
||||||
((:url . "http://elpa.gnu.org/packages/lmc.html") |
|
||||||
(:keywords))]) |
|
||||||
(load-dir . |
|
||||||
[(0 0 3) |
|
||||||
nil "Load all Emacs Lisp files in a given directory" single |
|
||||||
((:url . "http://elpa.gnu.org/packages/load-dir.html") |
|
||||||
(:keywords "lisp" "files" "convenience"))]) |
|
||||||
(load-relative . |
|
||||||
[(1 2) |
|
||||||
nil "relative file load (within a multi-file Emacs package)" single |
|
||||||
((:url . "http://github.com/rocky/emacs-load-relative") |
|
||||||
(:keywords "internal"))]) |
|
||||||
(loc-changes . |
|
||||||
[(1 2) |
|
||||||
nil "keep track of positions even after buffer changes" single |
|
||||||
((:url . "http://github.com/rocky/emacs-loc-changes") |
|
||||||
(:keywords))]) |
|
||||||
(markchars . |
|
||||||
[(0 2 0) |
|
||||||
nil "Mark chars fitting certain characteristics" single |
|
||||||
((:url . "http://elpa.gnu.org/packages/markchars.html") |
|
||||||
(:keywords))]) |
|
||||||
(math-symbol-lists . |
|
||||||
[(1 0) |
|
||||||
nil "Lists of Unicode math symbols and latex commands" single |
|
||||||
((:url . "https://github.com/vspinu/math-symbol-lists") |
|
||||||
(:keywords "unicode" "symbols" "mathematics"))]) |
|
||||||
(memory-usage . |
|
||||||
[(0 2) |
|
||||||
nil "Analyze the memory usage of Emacs in various ways" single |
|
||||||
((:url . "http://elpa.gnu.org/packages/memory-usage.html") |
|
||||||
(:keywords "maint"))]) |
|
||||||
(metar . |
|
||||||
[(0 1) |
|
||||||
((cl-lib |
|
||||||
(0 5))) |
|
||||||
"Retrieve and decode METAR weather information" single |
|
||||||
((:url . "http://elpa.gnu.org/packages/metar.html") |
|
||||||
(:keywords "comm"))]) |
|
||||||
(midi-kbd . |
|
||||||
[(0 2) |
|
||||||
((emacs |
|
||||||
(25))) |
|
||||||
"Create keyboard events from Midi input" single |
|
||||||
((:url . "http://elpa.gnu.org/packages/midi-kbd.html") |
|
||||||
(:keywords "convenience" "hardware" "multimedia"))]) |
|
||||||
(minibuffer-line . |
|
||||||
[(0 1) |
|
||||||
nil "Display status info in the minibuffer window" single |
|
||||||
((:url . "http://elpa.gnu.org/packages/minibuffer-line.html") |
|
||||||
(:keywords))]) |
|
||||||
(minimap . |
|
||||||
[(1 2) |
|
||||||
nil "Sidebar showing a \"mini-map\" of a buffer" single |
|
||||||
((:url . "http://elpa.gnu.org/packages/minimap.html") |
|
||||||
(:keywords))]) |
|
||||||
(muse . |
|
||||||
[(3 20) |
|
||||||
nil "Authoring and publishing tool for Emacs" tar |
|
||||||
((:keywords "hypermedia") |
|
||||||
(:url . "http://mwolson.org/projects/EmacsMuse.html"))]) |
|
||||||
(nameless . |
|
||||||
[(0 5 1) |
|
||||||
((emacs |
|
||||||
(24 4))) |
|
||||||
"Hide package namespace in your emacs-lisp code" single |
|
||||||
((:url . "https://github.com/Malabarba/nameless") |
|
||||||
(:keywords "convenience" "lisp"))]) |
|
||||||
(names . |
|
||||||
[(20150723 0) |
|
||||||
((emacs |
|
||||||
(24 1)) |
|
||||||
(cl-lib |
|
||||||
(0 5))) |
|
||||||
"Namespaces for emacs-lisp. Avoid name clobbering without hiding symbols." tar |
|
||||||
((:keywords "extensions" "lisp") |
|
||||||
(:url . "https://github.com/Bruce-Connor/names"))]) |
|
||||||
(nhexl-mode . |
|
||||||
[(0 1) |
|
||||||
nil "Minor mode to edit files via hex-dump format" single |
|
||||||
((:url . "http://elpa.gnu.org/packages/nhexl-mode.html") |
|
||||||
(:keywords "data"))]) |
|
||||||
(nlinum . |
|
||||||
[(1 6) |
|
||||||
nil "Show line numbers in the margin" single |
|
||||||
((:url . "http://elpa.gnu.org/packages/nlinum.html") |
|
||||||
(:keywords "convenience"))]) |
|
||||||
(notes-mode . |
|
||||||
[(1 30) |
|
||||||
nil "Indexing system for on-line note-taking" tar |
|
||||||
((:url . "http://elpa.gnu.org/packages/notes-mode.html"))]) |
|
||||||
(num3-mode . |
|
||||||
[(1 2) |
|
||||||
nil "highlight groups of digits in long numbers" single |
|
||||||
((:url . "http://elpa.gnu.org/packages/num3-mode.html") |
|
||||||
(:keywords "faces" "minor-mode"))]) |
|
||||||
(oauth2 . |
|
||||||
[(0 10) |
|
||||||
nil "OAuth 2.0 Authorization Protocol" single |
|
||||||
((:url . "http://elpa.gnu.org/packages/oauth2.html") |
|
||||||
(:keywords "comm"))]) |
|
||||||
(omn-mode . |
|
||||||
[(1 2) |
|
||||||
nil "Support for OWL Manchester Notation" single |
|
||||||
((:url . "http://elpa.gnu.org/packages/omn-mode.html") |
|
||||||
(:keywords))]) |
|
||||||
(org . |
|
||||||
[(20151005) |
|
||||||
nil "Outline-based notes management and organizer" tar nil]) |
|
||||||
(osc . |
|
||||||
[(0 1) |
|
||||||
nil "Open Sound Control protocol library" single |
|
||||||
((:url . "http://elpa.gnu.org/packages/osc.html") |
|
||||||
(:keywords "comm" "processes" "multimedia"))]) |
|
||||||
(other-frame-window . |
|
||||||
[(1 0 1) |
|
||||||
((emacs |
|
||||||
(24 4))) |
|
||||||
"Minor mode to enable global prefix keys for other frame/window buffer placement" single |
|
||||||
((:url . "http://elpa.gnu.org/packages/other-frame-window.html") |
|
||||||
(:keywords "frame" "window"))]) |
|
||||||
(pabbrev . |
|
||||||
[(4 2 1) |
|
||||||
nil "Predictive abbreviation expansion" single |
|
||||||
((:url . "http://elpa.gnu.org/packages/pabbrev.html") |
|
||||||
(:keywords))]) |
|
||||||
(pinentry . |
|
||||||
[(0 1) |
|
||||||
nil "GnuPG Pinentry server implementation" single |
|
||||||
((:url . "http://elpa.gnu.org/packages/pinentry.html") |
|
||||||
(:keywords "gnupg"))]) |
|
||||||
(poker . |
|
||||||
[(0 1) |
|
||||||
nil "Texas hold'em poker" single |
|
||||||
((:url . "http://elpa.gnu.org/packages/poker.html") |
|
||||||
(:keywords "games"))]) |
|
||||||
(quarter-plane . |
|
||||||
[(0 1) |
|
||||||
nil "Minor mode for quarter-plane style editing" single |
|
||||||
((:url . "http://elpa.gnu.org/packages/quarter-plane.html") |
|
||||||
(:keywords "convenience" "wp"))]) |
|
||||||
(queue . |
|
||||||
[(0 1 1) |
|
||||||
nil "Queue data structure" single |
|
||||||
((:url . "http://www.dr-qubit.org/emacs.php") |
|
||||||
(:keywords "extensions" "data structures" "queue"))]) |
|
||||||
(rainbow-mode . |
|
||||||
[(0 12) |
|
||||||
nil "Colorize color names in buffers" single |
|
||||||
((:url . "http://elpa.gnu.org/packages/rainbow-mode.html") |
|
||||||
(:keywords "faces"))]) |
|
||||||
(register-list . |
|
||||||
[(0 1) |
|
||||||
nil "Interactively list/edit registers" single |
|
||||||
((:url . "http://elpa.gnu.org/packages/register-list.html") |
|
||||||
(:keywords "register"))]) |
|
||||||
(rich-minority . |
|
||||||
[(1 0) |
|
||||||
((cl-lib |
|
||||||
(0 5))) |
|
||||||
"Clean-up and Beautify the list of minor-modes." single |
|
||||||
((:url . "https://github.com/Malabarba/rich-minority") |
|
||||||
(:keywords "mode-line" "faces"))]) |
|
||||||
(rudel . |
|
||||||
[(0 3) |
|
||||||
nil "A collaborative editing framework for Emacs" tar |
|
||||||
((:keywords "rudel" "collaboration") |
|
||||||
(:url . "http://rudel.sourceforge.net/"))]) |
|
||||||
(scroll-restore . |
|
||||||
[(1 0) |
|
||||||
nil "restore original position after scrolling" single |
|
||||||
((:url . "http://elpa.gnu.org/packages/scroll-restore.html") |
|
||||||
(:keywords "scrolling"))]) |
|
||||||
(seq . |
|
||||||
[(1 11) |
|
||||||
nil "Sequence manipulation functions" single |
|
||||||
((:url . "http://elpa.gnu.org/packages/seq.html") |
|
||||||
(:keywords "sequences"))]) |
|
||||||
(shen-mode . |
|
||||||
[(0 1) |
|
||||||
nil "A major mode for editing shen source code" tar |
|
||||||
((:keywords "languages" "shen") |
|
||||||
(:url . "http://elpa.gnu.org/packages/shen-mode.html"))]) |
|
||||||
(sisu-mode . |
|
||||||
[(3 0 3) |
|
||||||
nil "Major mode for SiSU markup text" single |
|
||||||
((:url . "http://elpa.gnu.org/packages/sisu-mode.html") |
|
||||||
(:keywords "text" "processes" "tools"))]) |
|
||||||
(sml-mode . |
|
||||||
[(6 7) |
|
||||||
nil "Major mode for editing (Standard) ML" single |
|
||||||
((:url . "http://elpa.gnu.org/packages/sml-mode.html") |
|
||||||
(:keywords "sml"))]) |
|
||||||
(sokoban . |
|
||||||
[(1 4) |
|
||||||
nil "Implementation of Sokoban for Emacs." tar |
|
||||||
((:keywords "games") |
|
||||||
(:url . "http://elpa.gnu.org/packages/sokoban.html"))]) |
|
||||||
(sotlisp . |
|
||||||
[(1 4 1) |
|
||||||
((emacs |
|
||||||
(24 1))) |
|
||||||
"Write lisp at the speed of thought." single |
|
||||||
((:url . "https://github.com/Malabarba/speed-of-thought-lisp") |
|
||||||
(:keywords "convenience" "lisp"))]) |
|
||||||
(spinner . |
|
||||||
[(1 4) |
|
||||||
nil "Add spinners and progress-bars to the mode-line for ongoing operations" single |
|
||||||
((:url . "https://github.com/Malabarba/spinner.el") |
|
||||||
(:keywords "processes" "mode-line"))]) |
|
||||||
(stream . |
|
||||||
[(1 0) |
|
||||||
((emacs |
|
||||||
(25))) |
|
||||||
"Implementation of streams" single |
|
||||||
((:url . "http://elpa.gnu.org/packages/stream.html") |
|
||||||
(:keywords "stream" "laziness" "sequences"))]) |
|
||||||
(svg . |
|
||||||
[(0 1) |
|
||||||
((emacs |
|
||||||
(25))) |
|
||||||
"svg image creation functions" single |
|
||||||
((:url . "http://elpa.gnu.org/packages/svg.html") |
|
||||||
(:keywords "image"))]) |
|
||||||
(svg-clock . |
|
||||||
[(0 5) |
|
||||||
((svg |
|
||||||
(0 1)) |
|
||||||
(emacs |
|
||||||
(25 0))) |
|
||||||
"Analog clock using Scalable Vector Graphics" single |
|
||||||
((:url . "http://elpa.gnu.org/packages/svg-clock.html") |
|
||||||
(:keywords "demo" "svg" "clock"))]) |
|
||||||
(swiper . |
|
||||||
[(0 5 1) |
|
||||||
((emacs |
|
||||||
(24 1))) |
|
||||||
"Isearch with an overview. Oh, man!" tar |
|
||||||
((:keywords "matching") |
|
||||||
(:url . "https://github.com/abo-abo/swiper"))]) |
|
||||||
(tNFA . |
|
||||||
[(0 1 1) |
|
||||||
((queue |
|
||||||
(0 1))) |
|
||||||
"Tagged non-deterministic finite-state automata" single |
|
||||||
((:url . "http://www.dr-qubit.org/emacs.php") |
|
||||||
(:keywords "extensions" "matching" "data structures tnfa" "nfa" "dfa" "finite state automata" "automata" "regexp"))]) |
|
||||||
(temp-buffer-browse . |
|
||||||
[(1 4) |
|
||||||
nil "temp buffer browse mode" single |
|
||||||
((:url . "http://elpa.gnu.org/packages/temp-buffer-browse.html") |
|
||||||
(:keywords "convenience"))]) |
|
||||||
(test-simple . |
|
||||||
[(1 1) |
|
||||||
((cl-lib |
|
||||||
(0))) |
|
||||||
"Simple Unit Test Framework for Emacs Lisp" single |
|
||||||
((:url . "http://github.com/rocky/emacs-test-simple") |
|
||||||
(:keywords "unit-test"))]) |
|
||||||
(timerfunctions . |
|
||||||
[(1 4 2) |
|
||||||
((cl-lib |
|
||||||
(0 5))) |
|
||||||
"Enhanced versions of some timer.el functions" single |
|
||||||
((:url . "http://elpa.gnu.org/packages/timerfunctions.html") |
|
||||||
(:keywords))]) |
|
||||||
(tiny . |
|
||||||
[(0 1) |
|
||||||
nil "Quickly generate linear ranges in Emacs" tar |
|
||||||
((:keywords "convenience") |
|
||||||
(:url . "https://github.com/abo-abo/tiny"))]) |
|
||||||
(trie . |
|
||||||
[(0 2 6) |
|
||||||
((tNFA |
|
||||||
(0 1 1)) |
|
||||||
(heap |
|
||||||
(0 3))) |
|
||||||
"Trie data structure" single |
|
||||||
((:url . "http://www.dr-qubit.org/emacs.php") |
|
||||||
(:keywords "extensions" "matching" "data structures trie" "ternary search tree" "tree" "completion" "regexp"))]) |
|
||||||
(undo-tree . |
|
||||||
[(0 6 5) |
|
||||||
nil "Treat undo history as a tree" single |
|
||||||
((:url . "http://www.dr-qubit.org/emacs.php") |
|
||||||
(:keywords "convenience" "files" "undo" "redo" "history" "tree"))]) |
|
||||||
(uni-confusables . |
|
||||||
[(0 1) |
|
||||||
nil "Unicode confusables table" tar |
|
||||||
((:url . "http://elpa.gnu.org/packages/uni-confusables.html"))]) |
|
||||||
(vlf . |
|
||||||
[(1 7) |
|
||||||
nil "View Large Files" tar |
|
||||||
((:keywords "large files" "utilities") |
|
||||||
(:url . "https://github.com/m00natic/vlfi"))]) |
|
||||||
(w3 . |
|
||||||
[(4 0 49) |
|
||||||
nil "Fully customizable, largely undocumented web browser for Emacs" tar |
|
||||||
((:keywords "faces" "help" "comm" "news" "mail" "processes" "mouse" "hypermedia") |
|
||||||
(:url . "http://elpa.gnu.org/packages/w3.html"))]) |
|
||||||
(wcheck-mode . |
|
||||||
[(2014 6 21) |
|
||||||
nil "General interface for text checkers" single |
|
||||||
((:url . "https://github.com/tlikonen/wcheck-mode") |
|
||||||
(:keywords "text" "spell" "check" "languages" "ispell"))]) |
|
||||||
(wconf . |
|
||||||
[(0 2 0) |
|
||||||
((emacs |
|
||||||
(24 4))) |
|
||||||
"Minimal window layout manager" single |
|
||||||
((:url . "https://github.com/ilohmar/wconf") |
|
||||||
(:keywords "windows" "frames" "layout"))]) |
|
||||||
(web-server . |
|
||||||
[(0 1 1) |
|
||||||
((emacs |
|
||||||
(24 3))) |
|
||||||
"Emacs Web Server" tar |
|
||||||
((:keywords "http" "server" "network") |
|
||||||
(:url . "https://github.com/eschulte/emacs-web-server"))]) |
|
||||||
(websocket . |
|
||||||
[(1 5) |
|
||||||
nil "Emacs WebSocket client and server" tar |
|
||||||
((:keywords "communication" "websocket" "server") |
|
||||||
(:url . "http://elpa.gnu.org/packages/websocket.html"))]) |
|
||||||
(windresize . |
|
||||||
[(0 1) |
|
||||||
nil "Resize windows interactively" single |
|
||||||
((:url . "http://elpa.gnu.org/packages/windresize.html") |
|
||||||
(:keywords "window"))]) |
|
||||||
(wisi . |
|
||||||
[(1 1 1) |
|
||||||
((cl-lib |
|
||||||
(0 4)) |
|
||||||
(emacs |
|
||||||
(24 2))) |
|
||||||
"Utilities for implementing an indentation/navigation engine using a generalized LALR parser" tar |
|
||||||
((:keywords "parser" "indentation" "navigation") |
|
||||||
(:url . "http://stephe-leake.org/emacs/ada-mode/emacs-ada-mode.html"))]) |
|
||||||
(wpuzzle . |
|
||||||
[(1 1) |
|
||||||
nil "find as many word in a given time" single |
|
||||||
((:url . "http://elpa.gnu.org/packages/wpuzzle.html") |
|
||||||
(:keywords))]) |
|
||||||
(xclip . |
|
||||||
[(1 3) |
|
||||||
nil "use xclip to copy&paste" single |
|
||||||
((:url . "http://elpa.gnu.org/packages/xclip.html") |
|
||||||
(:keywords "convenience" "tools"))]) |
|
||||||
(xelb . |
|
||||||
[(0 2) |
|
||||||
((emacs |
|
||||||
(24 4)) |
|
||||||
(cl-generic |
|
||||||
(0 2))) |
|
||||||
"X protocol Emacs Lisp Binding" tar |
|
||||||
((:keywords "unix") |
|
||||||
(:url . "https://github.com/ch11ng/xelb"))]) |
|
||||||
(xpm . |
|
||||||
[(1 0 3) |
|
||||||
nil "edit XPM images" tar |
|
||||||
((:keywords "multimedia" "xpm") |
|
||||||
(:url . "http://www.gnuvola.org/software/xpm/"))]) |
|
||||||
(yasnippet . |
|
||||||
[(0 8 0) |
|
||||||
nil "Yet another snippet extension for Emacs." tar |
|
||||||
((:keywords "convenience" "emulation") |
|
||||||
(:url . "http://github.com/capitaomorte/yasnippet"))]) |
|
||||||
(ztree . |
|
||||||
[(1 0 2) |
|
||||||
nil "Text mode directory tree" tar |
|
||||||
((:keywords "files" "tools") |
|
||||||
(:url . "https://github.com/fourier/ztree"))])) |
|
@ -1 +0,0 @@ |
|||||||
Good signature from 474F05837FBDEF9B GNU ELPA Signing Agent <elpasign@elpa.gnu.org> (trust undefined) created at 2015-10-24T02:05:02-0700 using DSA |
|
File diff suppressed because one or more lines are too long
@ -1 +0,0 @@ |
|||||||
(define-package "clojure-mode" "20151022.27" "Major mode for Clojure code" '((emacs "24.3")) :url "http://github.com/clojure-emacs/clojure-mode" :keywords '("languages" "clojure" "clojurescript" "lisp")) |
|
File diff suppressed because it is too large
Load Diff
@ -1 +0,0 @@ |
|||||||
(define-package "coffee-mode" "20151019.2009" "Major mode to edit CoffeeScript files in Emacs" '((emacs "24.1") (cl-lib "0.5")) :url "http://github.com/defunkt/coffee-mode" :keywords '("coffeescript" "major" "mode")) |
|
File diff suppressed because it is too large
Load Diff
@ -1 +0,0 @@ |
|||||||
(define-package "dash" "20151021.113" "A modern list library for Emacs" 'nil :keywords '("lists")) |
|
File diff suppressed because it is too large
Load Diff
@ -1 +0,0 @@ |
|||||||
(define-package "epl" "20150517.433" "Emacs Package Library" '((cl-lib "0.3")) :url "http://github.com/cask/epl" :keywords '("convenience")) |
|
@ -1,11 +0,0 @@ |
|||||||
(define-package "flycheck" "20151022.1349" "On-the-fly syntax checking" |
|
||||||
'((dash "2.4.0") |
|
||||||
(pkg-info "0.4") |
|
||||||
(let-alist "1.0.1") |
|
||||||
(cl-lib "0.3") |
|
||||||
(emacs "24.3")) |
|
||||||
:url "https://www.flycheck.org" :keywords |
|
||||||
'("convenience" "languages" "tools")) |
|
||||||
;; Local Variables: |
|
||||||
;; no-byte-compile: t |
|
||||||
;; End: |
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
@ -1 +0,0 @@ |
|||||||
Good signature from 474F05837FBDEF9B GNU ELPA Signing Agent <elpasign@elpa.gnu.org> (trust undefined) created at 2015-06-12T02:05:02-0700 using DSA |
|
@ -1 +0,0 @@ |
|||||||
(define-package "let-alist" "1.0.4" "Easily let-bind values of an assoc-list by their names" 'nil :url "http://elpa.gnu.org/packages/let-alist.html" :keywords '("extensions" "lisp")) |
|
@ -1 +0,0 @@ |
|||||||
(define-package "pkg-info" "20150517.443" "Information about packages" '((epl "0.8")) :url "https://github.com/lunaryorn/pkg-info.el" :keywords '("convenience")) |
|
@ -1 +0,0 @@ |
|||||||
(define-package "s" "20150924.406" "The long lost Emacs string manipulation library." 'nil :keywords '("strings")) |
|
@ -1,605 +0,0 @@ |
|||||||
;;; s.el --- The long lost Emacs string manipulation library. |
|
||||||
|
|
||||||
;; Copyright (C) 2012-2015 Magnar Sveen |
|
||||||
|
|
||||||
;; Author: Magnar Sveen <magnars@gmail.com> |
|
||||||
;; Version: 1.10.0 |
|
||||||
;; Package-Version: 20150924.406 |
|
||||||
;; Keywords: strings |
|
||||||
|
|
||||||
;; This program is free software; you can redistribute it and/or modify |
|
||||||
;; it under the terms of the GNU General Public License as published by |
|
||||||
;; the Free Software Foundation, either version 3 of the License, or |
|
||||||
;; (at your option) any later version. |
|
||||||
|
|
||||||
;; This program is distributed in the hope that it will be useful, |
|
||||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
;; GNU General Public License for more details. |
|
||||||
|
|
||||||
;; You should have received a copy of the GNU General Public License |
|
||||||
;; along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
||||||
|
|
||||||
;;; Commentary: |
|
||||||
|
|
||||||
;; The long lost Emacs string manipulation library. |
|
||||||
;; |
|
||||||
;; See documentation on https://github.com/magnars/s.el#functions |
|
||||||
|
|
||||||
;;; Code: |
|
||||||
|
|
||||||
(require 'ucs-normalize) |
|
||||||
|
|
||||||
(defun s-trim-left (s) |
|
||||||
"Remove whitespace at the beginning of S." |
|
||||||
(if (string-match "\\`[ \t\n\r]+" s) |
|
||||||
(replace-match "" t t s) |
|
||||||
s)) |
|
||||||
|
|
||||||
(defun s-trim-right (s) |
|
||||||
"Remove whitespace at the end of S." |
|
||||||
(if (string-match "[ \t\n\r]+\\'" s) |
|
||||||
(replace-match "" t t s) |
|
||||||
s)) |
|
||||||
|
|
||||||
(defun s-trim (s) |
|
||||||
"Remove whitespace at the beginning and end of S." |
|
||||||
(s-trim-left (s-trim-right s))) |
|
||||||
|
|
||||||
(defun s-collapse-whitespace (s) |
|
||||||
"Convert all adjacent whitespace characters to a single space." |
|
||||||
(replace-regexp-in-string "[ \t\n\r]+" " " s)) |
|
||||||
|
|
||||||
(defun s-split (separator s &optional omit-nulls) |
|
||||||
"Split S into substrings bounded by matches for regexp SEPARATOR. |
|
||||||
If OMIT-NULLS is non-nil, zero-length substrings are omitted. |
|
||||||
|
|
||||||
This is a simple wrapper around the built-in `split-string'." |
|
||||||
(split-string s separator omit-nulls)) |
|
||||||
|
|
||||||
(defun s-split-up-to (separator s n &optional omit-nulls) |
|
||||||
"Split S up to N times into substrings bounded by matches for regexp SEPARATOR. |
|
||||||
|
|
||||||
If OMIT-NULLS is non-nil, zero-length substrings are omitted. |
|
||||||
|
|
||||||
See also `s-split'." |
|
||||||
(save-match-data |
|
||||||
(let ((op 0) |
|
||||||
(r nil)) |
|
||||||
(with-temp-buffer |
|
||||||
(insert s) |
|
||||||
(setq op (goto-char (point-min))) |
|
||||||
(while (and (re-search-forward separator nil t) |
|
||||||
(< 0 n)) |
|
||||||
(let ((sub (buffer-substring-no-properties op (match-beginning 0)))) |
|
||||||
(unless (and omit-nulls |
|
||||||
(equal sub "")) |
|
||||||
(push sub r))) |
|
||||||
(setq op (goto-char (match-end 0))) |
|
||||||
(setq n (1- n))) |
|
||||||
(let ((sub (buffer-substring-no-properties op (point-max)))) |
|
||||||
(unless (and omit-nulls |
|
||||||
(equal sub "")) |
|
||||||
(push sub r)))) |
|
||||||
(nreverse r)))) |
|
||||||
|
|
||||||
(defun s-lines (s) |
|
||||||
"Splits S into a list of strings on newline characters." |
|
||||||
(s-split "\\(\r\n\\|[\n\r]\\)" s)) |
|
||||||
|
|
||||||
(defun s-join (separator strings) |
|
||||||
"Join all the strings in STRINGS with SEPARATOR in between." |
|
||||||
(mapconcat 'identity strings separator)) |
|
||||||
|
|
||||||
(defun s-concat (&rest strings) |
|
||||||
"Join all the string arguments into one string." |
|
||||||
(apply 'concat strings)) |
|
||||||
|
|
||||||
(defun s-prepend (prefix s) |
|
||||||
"Concatenate PREFIX and S." |
|
||||||
(concat prefix s)) |
|
||||||
|
|
||||||
(defun s-append (suffix s) |
|
||||||
"Concatenate S and SUFFIX." |
|
||||||
(concat s suffix)) |
|
||||||
|
|
||||||
(defun s-repeat (num s) |
|
||||||
"Make a string of S repeated NUM times." |
|
||||||
(let (ss) |
|
||||||
(while (> num 0) |
|
||||||
(setq ss (cons s ss)) |
|
||||||
(setq num (1- num))) |
|
||||||
(apply 'concat ss))) |
|
||||||
|
|
||||||
(defun s-chop-suffix (suffix s) |
|
||||||
"Remove SUFFIX if it is at end of S." |
|
||||||
(let ((pos (- (length suffix)))) |
|
||||||
(if (and (>= (length s) (length suffix)) |
|
||||||
(string= suffix (substring s pos))) |
|
||||||
(substring s 0 pos) |
|
||||||
s))) |
|
||||||
|
|
||||||
(defun s-chop-suffixes (suffixes s) |
|
||||||
"Remove SUFFIXES one by one in order, if they are at the end of S." |
|
||||||
(while suffixes |
|
||||||
(setq s (s-chop-suffix (car suffixes) s)) |
|
||||||
(setq suffixes (cdr suffixes))) |
|
||||||
s) |
|
||||||
|
|
||||||
(defun s-chop-prefix (prefix s) |
|
||||||
"Remove PREFIX if it is at the start of S." |
|
||||||
(let ((pos (length prefix))) |
|
||||||
(if (and (>= (length s) (length prefix)) |
|
||||||
(string= prefix (substring s 0 pos))) |
|
||||||
(substring s pos) |
|
||||||
s))) |
|
||||||
|
|
||||||
(defun s-chop-prefixes (prefixes s) |
|
||||||
"Remove PREFIXES one by one in order, if they are at the start of S." |
|
||||||
(while prefixes |
|
||||||
(setq s (s-chop-prefix (car prefixes) s)) |
|
||||||
(setq prefixes (cdr prefixes))) |
|
||||||
s) |
|
||||||
|
|
||||||
(defun s-shared-start (s1 s2) |
|
||||||
"Returns the longest prefix S1 and S2 have in common." |
|
||||||
(let ((search-length (min (length s1) (length s2))) |
|
||||||
(i 0)) |
|
||||||
(while (and (< i search-length) |
|
||||||
(= (aref s1 i) (aref s2 i))) |
|
||||||
(setq i (1+ i))) |
|
||||||
(substring s1 0 i))) |
|
||||||
|
|
||||||
(defun s-shared-end (s1 s2) |
|
||||||
"Returns the longest suffix S1 and S2 have in common." |
|
||||||
(let* ((l1 (length s1)) |
|
||||||
(l2 (length s2)) |
|
||||||
(search-length (min l1 l2)) |
|
||||||
(i 0)) |
|
||||||
(while (and (< i search-length) |
|
||||||
(= (aref s1 (- l1 i 1)) (aref s2 (- l2 i 1)))) |
|
||||||
(setq i (1+ i))) |
|
||||||
;; If I is 0, then it means that there's no common suffix between |
|
||||||
;; S1 and S2. |
|
||||||
;; |
|
||||||
;; However, since (substring s (- 0)) will return the whole |
|
||||||
;; string, `s-shared-end' should simply return the empty string |
|
||||||
;; when I is 0. |
|
||||||
(if (zerop i) |
|
||||||
"" |
|
||||||
(substring s1 (- i))))) |
|
||||||
|
|
||||||
(defun s-chomp (s) |
|
||||||
"Remove one trailing `\\n`, `\\r` or `\\r\\n` from S." |
|
||||||
(s-chop-suffixes '("\n" "\r") s)) |
|
||||||
|
|
||||||
(defun s-truncate (len s) |
|
||||||
"If S is longer than LEN, cut it down to LEN - 3 and add ... at the end." |
|
||||||
(if (> (length s) len) |
|
||||||
(format "%s..." (substring s 0 (- len 3))) |
|
||||||
s)) |
|
||||||
|
|
||||||
(defun s-word-wrap (len s) |
|
||||||
"If S is longer than LEN, wrap the words with newlines." |
|
||||||
(with-temp-buffer |
|
||||||
(insert s) |
|
||||||
(let ((fill-column len)) |
|
||||||
(fill-region (point-min) (point-max))) |
|
||||||
(buffer-substring-no-properties (point-min) (point-max)))) |
|
||||||
|
|
||||||
(defun s-center (len s) |
|
||||||
"If S is shorter than LEN, pad it with spaces so it is centered." |
|
||||||
(let ((extra (max 0 (- len (length s))))) |
|
||||||
(concat |
|
||||||
(make-string (ceiling extra 2) ? ) |
|
||||||
s |
|
||||||
(make-string (floor extra 2) ? )))) |
|
||||||
|
|
||||||
(defun s-pad-left (len padding s) |
|
||||||
"If S is shorter than LEN, pad it with PADDING on the left." |
|
||||||
(let ((extra (max 0 (- len (length s))))) |
|
||||||
(concat (make-string extra (string-to-char padding)) |
|
||||||
s))) |
|
||||||
|
|
||||||
(defun s-pad-right (len padding s) |
|
||||||
"If S is shorter than LEN, pad it with PADDING on the right." |
|
||||||
(let ((extra (max 0 (- len (length s))))) |
|
||||||
(concat s |
|
||||||
(make-string extra (string-to-char padding))))) |
|
||||||
|
|
||||||
(defun s-left (len s) |
|
||||||
"Returns up to the LEN first chars of S." |
|
||||||
(if (> (length s) len) |
|
||||||
(substring s 0 len) |
|
||||||
s)) |
|
||||||
|
|
||||||
(defun s-right (len s) |
|
||||||
"Returns up to the LEN last chars of S." |
|
||||||
(let ((l (length s))) |
|
||||||
(if (> l len) |
|
||||||
(substring s (- l len) l) |
|
||||||
s))) |
|
||||||
|
|
||||||
(defun s-ends-with? (suffix s &optional ignore-case) |
|
||||||
"Does S end with SUFFIX? |
|
||||||
|
|
||||||
If IGNORE-CASE is non-nil, the comparison is done without paying |
|
||||||
attention to case differences. |
|
||||||
|
|
||||||
Alias: `s-suffix?'" |
|
||||||
(let ((start-pos (- (length s) (length suffix)))) |
|
||||||
(and (>= start-pos 0) |
|
||||||
(eq t (compare-strings suffix nil nil |
|
||||||
s start-pos nil ignore-case))))) |
|
||||||
|
|
||||||
(defalias 's-ends-with-p 's-ends-with?) |
|
||||||
|
|
||||||
(defun s-starts-with? (prefix s &optional ignore-case) |
|
||||||
"Does S start with PREFIX? |
|
||||||
|
|
||||||
If IGNORE-CASE is non-nil, the comparison is done without paying |
|
||||||
attention to case differences. |
|
||||||
|
|
||||||
Alias: `s-prefix?'. This is a simple wrapper around the built-in |
|
||||||
`string-prefix-p'." |
|
||||||
(string-prefix-p prefix s ignore-case)) |
|
||||||
|
|
||||||
(defalias 's-starts-with-p 's-starts-with?) |
|
||||||
|
|
||||||
(defalias 's-suffix? 's-ends-with?) |
|
||||||
(defalias 's-prefix? 's-starts-with?) |
|
||||||
(defalias 's-suffix-p 's-ends-with?) |
|
||||||
(defalias 's-prefix-p 's-starts-with?) |
|
||||||
|
|
||||||
(defun s--truthy? (val) |
|
||||||
(not (null val))) |
|
||||||
|
|
||||||
(defun s-contains? (needle s &optional ignore-case) |
|
||||||
"Does S contain NEEDLE? |
|
||||||
|
|
||||||
If IGNORE-CASE is non-nil, the comparison is done without paying |
|
||||||
attention to case differences." |
|
||||||
(let ((case-fold-search ignore-case)) |
|
||||||
(s--truthy? (string-match-p (regexp-quote needle) s)))) |
|
||||||
|
|
||||||
(defalias 's-contains-p 's-contains?) |
|
||||||
|
|
||||||
(defun s-equals? (s1 s2) |
|
||||||
"Is S1 equal to S2? |
|
||||||
|
|
||||||
This is a simple wrapper around the built-in `string-equal'." |
|
||||||
(string-equal s1 s2)) |
|
||||||
|
|
||||||
(defalias 's-equals-p 's-equals?) |
|
||||||
|
|
||||||
(defun s-less? (s1 s2) |
|
||||||
"Is S1 less than S2? |
|
||||||
|
|
||||||
This is a simple wrapper around the built-in `string-lessp'." |
|
||||||
(string-lessp s1 s2)) |
|
||||||
|
|
||||||
(defalias 's-less-p 's-less?) |
|
||||||
|
|
||||||
(defun s-matches? (regexp s &optional start) |
|
||||||
"Does REGEXP match S? |
|
||||||
If START is non-nil the search starts at that index. |
|
||||||
|
|
||||||
This is a simple wrapper around the built-in `string-match-p'." |
|
||||||
(s--truthy? (string-match-p regexp s start))) |
|
||||||
|
|
||||||
(defalias 's-matches-p 's-matches?) |
|
||||||
|
|
||||||
(defun s-blank? (s) |
|
||||||
"Is S nil or the empty string?" |
|
||||||
(or (null s) (string= "" s))) |
|
||||||
|
|
||||||
(defun s-present? (s) |
|
||||||
"Is S anything but nil or the empty string?" |
|
||||||
(not (s-blank? s))) |
|
||||||
|
|
||||||
(defun s-presence (s) |
|
||||||
"Return S if it's `s-present?', otherwise return nil." |
|
||||||
(and (s-present? s) s)) |
|
||||||
|
|
||||||
(defun s-lowercase? (s) |
|
||||||
"Are all the letters in S in lower case?" |
|
||||||
(let ((case-fold-search nil)) |
|
||||||
(not (string-match-p "[[:upper:]]" s)))) |
|
||||||
|
|
||||||
(defun s-uppercase? (s) |
|
||||||
"Are all the letters in S in upper case?" |
|
||||||
(let ((case-fold-search nil)) |
|
||||||
(not (string-match-p "[[:lower:]]" s)))) |
|
||||||
|
|
||||||
(defun s-mixedcase? (s) |
|
||||||
"Are there both lower case and upper case letters in S?" |
|
||||||
(let ((case-fold-search nil)) |
|
||||||
(s--truthy? |
|
||||||
(and (string-match-p "[[:lower:]]" s) |
|
||||||
(string-match-p "[[:upper:]]" s))))) |
|
||||||
|
|
||||||
(defun s-capitalized? (s) |
|
||||||
"In S, is the first letter upper case, and all other letters lower case?" |
|
||||||
(let ((case-fold-search nil)) |
|
||||||
(s--truthy? |
|
||||||
(string-match-p "^[[:upper:]][^[:upper:]]*$" s)))) |
|
||||||
|
|
||||||
(defun s-numeric? (s) |
|
||||||
"Is S a number?" |
|
||||||
(s--truthy? |
|
||||||
(string-match-p "^[0-9]+$" s))) |
|
||||||
|
|
||||||
(defun s-replace (old new s) |
|
||||||
"Replaces OLD with NEW in S." |
|
||||||
(replace-regexp-in-string (regexp-quote old) new s t t)) |
|
||||||
|
|
||||||
(defun s--aget (alist key) |
|
||||||
(cdr (assoc key alist))) |
|
||||||
|
|
||||||
(defun s-replace-all (replacements s) |
|
||||||
"REPLACEMENTS is a list of cons-cells. Each `car` is replaced with `cdr` in S." |
|
||||||
(replace-regexp-in-string (regexp-opt (mapcar 'car replacements)) |
|
||||||
(lambda (it) (s--aget replacements it)) |
|
||||||
s)) |
|
||||||
|
|
||||||
(defun s-downcase (s) |
|
||||||
"Convert S to lower case. |
|
||||||
|
|
||||||
This is a simple wrapper around the built-in `downcase'." |
|
||||||
(downcase s)) |
|
||||||
|
|
||||||
(defun s-upcase (s) |
|
||||||
"Convert S to upper case. |
|
||||||
|
|
||||||
This is a simple wrapper around the built-in `upcase'." |
|
||||||
(upcase s)) |
|
||||||
|
|
||||||
(defun s-capitalize (s) |
|
||||||
"Convert the first word's first character to upper case and the rest to lower case in S." |
|
||||||
(concat (upcase (substring s 0 1)) (downcase (substring s 1)))) |
|
||||||
|
|
||||||
(defun s-titleize (s) |
|
||||||
"Convert each word's first character to upper case and the rest to lower case in S. |
|
||||||
|
|
||||||
This is a simple wrapper around the built-in `capitalize'." |
|
||||||
(capitalize s)) |
|
||||||
|
|
||||||
(defmacro s-with (s form &rest more) |
|
||||||
"Threads S through the forms. Inserts S as the last item |
|
||||||
in the first form, making a list of it if it is not a list |
|
||||||
already. If there are more forms, inserts the first form as the |
|
||||||
last item in second form, etc." |
|
||||||
(declare (debug (form &rest [&or (function &rest form) fboundp]))) |
|
||||||
(if (null more) |
|
||||||
(if (listp form) |
|
||||||
`(,(car form) ,@(cdr form) ,s) |
|
||||||
(list form s)) |
|
||||||
`(s-with (s-with ,s ,form) ,@more))) |
|
||||||
|
|
||||||
(put 's-with 'lisp-indent-function 1) |
|
||||||
|
|
||||||
(defun s-index-of (needle s &optional ignore-case) |
|
||||||
"Returns first index of NEEDLE in S, or nil. |
|
||||||
|
|
||||||
If IGNORE-CASE is non-nil, the comparison is done without paying |
|
||||||
attention to case differences." |
|
||||||
(let ((case-fold-search ignore-case)) |
|
||||||
(string-match-p (regexp-quote needle) s))) |
|
||||||
|
|
||||||
(defun s-reverse (s) |
|
||||||
"Return the reverse of S." |
|
||||||
(if (multibyte-string-p s) |
|
||||||
(let ((input (string-to-list s)) |
|
||||||
(output ())) |
|
||||||
(while input |
|
||||||
;; Handle entire grapheme cluster as a single unit |
|
||||||
(let ((grapheme (list (pop input)))) |
|
||||||
(while (memql (car input) ucs-normalize-combining-chars) |
|
||||||
(push (pop input) grapheme)) |
|
||||||
(setq output (nconc (nreverse grapheme) output)))) |
|
||||||
(concat output)) |
|
||||||
(concat (nreverse (string-to-list s))))) |
|
||||||
|
|
||||||
(defun s-match-strings-all (regex string) |
|
||||||
"Return a list of matches for REGEX in STRING. |
|
||||||
|
|
||||||
Each element itself is a list of matches, as per |
|
||||||
`match-string'. Multiple matches at the same position will be |
|
||||||
ignored after the first." |
|
||||||
(let ((all-strings ()) |
|
||||||
(i 0)) |
|
||||||
(while (and (< i (length string)) |
|
||||||
(string-match regex string i)) |
|
||||||
(setq i (1+ (match-beginning 0))) |
|
||||||
(let (strings |
|
||||||
(num-matches (/ (length (match-data)) 2)) |
|
||||||
(match 0)) |
|
||||||
(while (/= match num-matches) |
|
||||||
(push (match-string match string) strings) |
|
||||||
(setq match (1+ match))) |
|
||||||
(push (nreverse strings) all-strings))) |
|
||||||
(nreverse all-strings))) |
|
||||||
|
|
||||||
(defun s-match (regexp s &optional start) |
|
||||||
"When the given expression matches the string, this function returns a list |
|
||||||
of the whole matching string and a string for each matched subexpressions. |
|
||||||
If it did not match the returned value is an empty list (nil). |
|
||||||
|
|
||||||
When START is non-nil the search will start at that index." |
|
||||||
(save-match-data |
|
||||||
(if (string-match regexp s start) |
|
||||||
(let ((match-data-list (match-data)) |
|
||||||
result) |
|
||||||
(while match-data-list |
|
||||||
(let* ((beg (car match-data-list)) |
|
||||||
(end (cadr match-data-list)) |
|
||||||
(subs (if (and beg end) (substring s beg end) nil))) |
|
||||||
(setq result (cons subs result)) |
|
||||||
(setq match-data-list |
|
||||||
(cddr match-data-list)))) |
|
||||||
(nreverse result))))) |
|
||||||
|
|
||||||
(defun s-slice-at (regexp s) |
|
||||||
"Slices S up at every index matching REGEXP." |
|
||||||
(save-match-data |
|
||||||
(let (i) |
|
||||||
(setq i (string-match regexp s 1)) |
|
||||||
(if i |
|
||||||
(cons (substring s 0 i) |
|
||||||
(s-slice-at regexp (substring s i))) |
|
||||||
(list s))))) |
|
||||||
|
|
||||||
(defun s-split-words (s) |
|
||||||
"Split S into list of words." |
|
||||||
(s-split |
|
||||||
"[^[:word:]0-9]+" |
|
||||||
(let ((case-fold-search nil)) |
|
||||||
(replace-regexp-in-string |
|
||||||
"\\([[:lower:]]\\)\\([[:upper:]]\\)" "\\1 \\2" |
|
||||||
(replace-regexp-in-string "\\([[:upper:]]\\)\\([[:upper:]][0-9[:lower:]]\\)" "\\1 \\2" s))) |
|
||||||
t)) |
|
||||||
|
|
||||||
(defun s--mapcar-head (fn-head fn-rest list) |
|
||||||
"Like MAPCAR, but applies a different function to the first element." |
|
||||||
(if list |
|
||||||
(cons (funcall fn-head (car list)) (mapcar fn-rest (cdr list))))) |
|
||||||
|
|
||||||
(defun s-lower-camel-case (s) |
|
||||||
"Convert S to lowerCamelCase." |
|
||||||
(s-join "" (s--mapcar-head 'downcase 'capitalize (s-split-words s)))) |
|
||||||
|
|
||||||
(defun s-upper-camel-case (s) |
|
||||||
"Convert S to UpperCamelCase." |
|
||||||
(s-join "" (mapcar 'capitalize (s-split-words s)))) |
|
||||||
|
|
||||||
(defun s-snake-case (s) |
|
||||||
"Convert S to snake_case." |
|
||||||
(s-join "_" (mapcar 'downcase (s-split-words s)))) |
|
||||||
|
|
||||||
(defun s-dashed-words (s) |
|
||||||
"Convert S to dashed-words." |
|
||||||
(s-join "-" (mapcar 'downcase (s-split-words s)))) |
|
||||||
|
|
||||||
(defun s-capitalized-words (s) |
|
||||||
"Convert S to Capitalized words." |
|
||||||
(let ((words (s-split-words s))) |
|
||||||
(s-join " " (cons (capitalize (car words)) (mapcar 'downcase (cdr words)))))) |
|
||||||
|
|
||||||
(defun s-titleized-words (s) |
|
||||||
"Convert S to Titleized Words." |
|
||||||
(s-join " " (mapcar 's-titleize (s-split-words s)))) |
|
||||||
|
|
||||||
(defun s-word-initials (s) |
|
||||||
"Convert S to its initials." |
|
||||||
(s-join "" (mapcar (lambda (ss) (substring ss 0 1)) |
|
||||||
(s-split-words s)))) |
|
||||||
|
|
||||||
;; Errors for s-format |
|
||||||
(progn |
|
||||||
(put 's-format-resolve |
|
||||||
'error-conditions |
|
||||||
'(error s-format s-format-resolve)) |
|
||||||
(put 's-format-resolve |
|
||||||
'error-message |
|
||||||
"Cannot resolve a template to values")) |
|
||||||
|
|
||||||
(defun s-format (template replacer &optional extra) |
|
||||||
"Format TEMPLATE with the function REPLACER. |
|
||||||
|
|
||||||
REPLACER takes an argument of the format variable and optionally |
|
||||||
an extra argument which is the EXTRA value from the call to |
|
||||||
`s-format'. |
|
||||||
|
|
||||||
Several standard `s-format' helper functions are recognized and |
|
||||||
adapted for this: |
|
||||||
|
|
||||||
(s-format \"${name}\" 'gethash hash-table) |
|
||||||
(s-format \"${name}\" 'aget alist) |
|
||||||
(s-format \"$0\" 'elt sequence) |
|
||||||
|
|
||||||
The REPLACER function may be used to do any other kind of |
|
||||||
transformation." |
|
||||||
(let ((saved-match-data (match-data))) |
|
||||||
(unwind-protect |
|
||||||
(replace-regexp-in-string |
|
||||||
"\\$\\({\\([^}]+\\)}\\|[0-9]+\\)" |
|
||||||
(lambda (md) |
|
||||||
(let ((var |
|
||||||
(let ((m (match-string 2 md))) |
|
||||||
(if m m |
|
||||||
(string-to-number (match-string 1 md))))) |
|
||||||
(replacer-match-data (match-data))) |
|
||||||
(unwind-protect |
|
||||||
(let ((v |
|
||||||
(cond |
|
||||||
((eq replacer 'gethash) |
|
||||||
(funcall replacer var extra)) |
|
||||||
((eq replacer 'aget) |
|
||||||
(funcall 's--aget extra var)) |
|
||||||
((eq replacer 'elt) |
|
||||||
(funcall replacer extra var)) |
|
||||||
(t |
|
||||||
(set-match-data saved-match-data) |
|
||||||
(if extra |
|
||||||
(funcall replacer var extra) |
|
||||||
(funcall replacer var)))))) |
|
||||||
(if v v (signal 's-format-resolve md))) |
|
||||||
(set-match-data replacer-match-data)))) template |
|
||||||
;; Need literal to make sure it works |
|
||||||
t t) |
|
||||||
(set-match-data saved-match-data)))) |
|
||||||
|
|
||||||
(defvar s-lex-value-as-lisp nil |
|
||||||
"If `t' interpolate lisp values as lisp. |
|
||||||
|
|
||||||
`s-lex-format' inserts values with (format \"%S\").") |
|
||||||
|
|
||||||
(defun s-lex-fmt|expand (fmt) |
|
||||||
"Expand FMT into lisp." |
|
||||||
(list 's-format fmt (quote 'aget) |
|
||||||
(append '(list) |
|
||||||
(mapcar |
|
||||||
(lambda (matches) |
|
||||||
(list |
|
||||||
'cons |
|
||||||
(cadr matches) |
|
||||||
`(format |
|
||||||
(if s-lex-value-as-lisp "%S" "%s") |
|
||||||
,(intern (cadr matches))))) |
|
||||||
(s-match-strings-all "${\\([^}]+\\)}" fmt))))) |
|
||||||
|
|
||||||
(defmacro s-lex-format (format-str) |
|
||||||
"`s-format` with the current environment. |
|
||||||
|
|
||||||
FORMAT-STR may use the `s-format' variable reference to refer to |
|
||||||
any variable: |
|
||||||
|
|
||||||
(let ((x 1)) |
|
||||||
(s-lex-format \"x is: ${x}\")) |
|
||||||
|
|
||||||
The values of the variables are interpolated with \"%s\" unless |
|
||||||
the variable `s-lex-value-as-lisp' is `t' and then they are |
|
||||||
interpolated with \"%S\"." |
|
||||||
(declare (debug (form))) |
|
||||||
(s-lex-fmt|expand format-str)) |
|
||||||
|
|
||||||
(defun s-count-matches (regexp s &optional start end) |
|
||||||
"Count occurrences of `regexp' in `s'. |
|
||||||
|
|
||||||
`start', inclusive, and `end', exclusive, delimit the part of `s' |
|
||||||
to match. " |
|
||||||
(with-temp-buffer |
|
||||||
(insert s) |
|
||||||
(goto-char (point-min)) |
|
||||||
(count-matches regexp (or start 1) (or end (point-max))))) |
|
||||||
|
|
||||||
(defun s-wrap (s prefix &optional suffix) |
|
||||||
"Wrap string S with PREFIX and optionally SUFFIX. |
|
||||||
|
|
||||||
Return string S with PREFIX prepended. If SUFFIX is present, it |
|
||||||
is appended, otherwise PREFIX is used as both prefix and |
|
||||||
suffix." |
|
||||||
(concat prefix s (or suffix prefix))) |
|
||||||
|
|
||||||
(provide 's) |
|
||||||
;;; s.el ends here |
|
Loading…
Reference in new issue