Merge branch 'master' of gitlab.com:marcuskammer/emacs.d
This commit is contained in:
commit
8025d663a7
59 changed files with 20436 additions and 2 deletions
|
@ -84,8 +84,8 @@
|
|||
'(package-enable-at-startup t)
|
||||
'(package-selected-packages
|
||||
(quote
|
||||
(elm-mode dashboard pickle poet-theme flymake-eslint json-mode elpy darkroom dockerfile-mode ein spacemacs-theme flucui-themes leuven-theme htmlize scss-mode berrys-theme web-mode python-docstring sphinx-doc sphinx-frontend sphinx-mode ox-nikola racket-mode slime gherkin-mode powershell typescript-mode ob-http ob-ipython ob-restclient nord-theme restclient request restclient-test yaml-mode magit)))
|
||||
'(python-shell-interpreter "python3" t)
|
||||
(ag xref-js2 js2-refactor js2-mode elm-mode dashboard pickle poet-theme flymake-eslint json-mode elpy darkroom dockerfile-mode ein spacemacs-theme flucui-themes leuven-theme htmlize scss-mode berrys-theme web-mode python-docstring sphinx-doc sphinx-frontend sphinx-mode ox-nikola racket-mode slime gherkin-mode powershell typescript-mode ob-http ob-ipython ob-restclient nord-theme restclient request restclient-test yaml-mode magit)))
|
||||
'(python-shell-interpreter "python3")
|
||||
'(register-preview-delay 2)
|
||||
'(register-separator 43)
|
||||
'(request-log-level (quote debug))
|
||||
|
|
128
elpa/ag-20190726.9/ag-autoloads.el
Normal file
128
elpa/ag-20190726.9/ag-autoloads.el
Normal file
|
@ -0,0 +1,128 @@
|
|||
;;; ag-autoloads.el --- automatically extracted autoloads
|
||||
;;
|
||||
;;; Code:
|
||||
|
||||
(add-to-list 'load-path (directory-file-name
|
||||
(or (file-name-directory #$) (car load-path))))
|
||||
|
||||
|
||||
;;;### (autoloads nil "ag" "ag.el" (0 0 0 0))
|
||||
;;; Generated autoloads from ag.el
|
||||
|
||||
(autoload 'ag "ag" "\
|
||||
Search using ag in a given DIRECTORY for a given literal search STRING,
|
||||
with STRING defaulting to the symbol under point.
|
||||
|
||||
If called with a prefix, prompts for flags to pass to ag.
|
||||
|
||||
\(fn STRING DIRECTORY)" t nil)
|
||||
|
||||
(autoload 'ag-files "ag" "\
|
||||
Search using ag in a given DIRECTORY for a given literal 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.
|
||||
|
||||
\(fn STRING FILE-TYPE DIRECTORY)" t nil)
|
||||
|
||||
(autoload 'ag-regexp "ag" "\
|
||||
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.
|
||||
|
||||
\(fn STRING DIRECTORY)" t nil)
|
||||
|
||||
(autoload 'ag-project "ag" "\
|
||||
Guess the root of the current project and search it with ag
|
||||
for the given literal search STRING.
|
||||
|
||||
If called with a prefix, prompts for flags to pass to ag.
|
||||
|
||||
\(fn STRING)" t nil)
|
||||
|
||||
(autoload 'ag-project-files "ag" "\
|
||||
Search using ag for a given literal 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.
|
||||
|
||||
\(fn STRING FILE-TYPE)" t nil)
|
||||
|
||||
(autoload 'ag-project-regexp "ag" "\
|
||||
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.
|
||||
|
||||
\(fn REGEXP)" t nil)
|
||||
|
||||
(defalias 'ag-project-at-point 'ag-project)
|
||||
|
||||
(defalias 'ag-regexp-project-at-point 'ag-project-regexp)
|
||||
|
||||
(autoload 'ag-dired "ag" "\
|
||||
Recursively find files in DIR matching literal search STRING.
|
||||
|
||||
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'.
|
||||
|
||||
\(fn DIR STRING)" t nil)
|
||||
|
||||
(autoload 'ag-dired-regexp "ag" "\
|
||||
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'.
|
||||
|
||||
\(fn DIR REGEXP)" t nil)
|
||||
|
||||
(autoload 'ag-project-dired "ag" "\
|
||||
Recursively find files in current project matching PATTERN.
|
||||
|
||||
See also `ag-dired'.
|
||||
|
||||
\(fn PATTERN)" t nil)
|
||||
|
||||
(autoload 'ag-project-dired-regexp "ag" "\
|
||||
Recursively find files in current project matching REGEXP.
|
||||
|
||||
See also `ag-dired-regexp'.
|
||||
|
||||
\(fn REGEXP)" t nil)
|
||||
|
||||
(autoload 'ag-kill-buffers "ag" "\
|
||||
Kill all `ag-mode' buffers.
|
||||
|
||||
\(fn)" t nil)
|
||||
|
||||
(autoload 'ag-kill-other-buffers "ag" "\
|
||||
Kill all `ag-mode' buffers other than the current buffer.
|
||||
|
||||
\(fn)" t nil)
|
||||
|
||||
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ag" '("ag-" "ag/")))
|
||||
|
||||
;;;***
|
||||
|
||||
;; Local Variables:
|
||||
;; version-control: never
|
||||
;; no-byte-compile: t
|
||||
;; no-update-autoloads: t
|
||||
;; coding: utf-8
|
||||
;; End:
|
||||
;;; ag-autoloads.el ends here
|
2
elpa/ag-20190726.9/ag-pkg.el
Normal file
2
elpa/ag-20190726.9/ag-pkg.el
Normal file
|
@ -0,0 +1,2 @@
|
|||
;;; -*- no-byte-compile: t -*-
|
||||
(define-package "ag" "20190726.9" "A front-end for ag ('the silver searcher'), the C ack replacement." '((dash "2.8.0") (s "1.9.0") (cl-lib "0.5")) :commit "bd81d68466e44301505629454dfc689b6c17d94b" :authors '(("Wilfred Hughes" . "me@wilfred.me.uk")) :maintainer '("Wilfred Hughes" . "me@wilfred.me.uk"))
|
689
elpa/ag-20190726.9/ag.el
Normal file
689
elpa/ag-20190726.9/ag.el
Normal file
|
@ -0,0 +1,689 @@
|
|||
;;; 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.48
|
||||
;; Package-Version: 20190726.9
|
||||
;; 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:
|
||||
(require 'cl-lib) ;; cl-letf, cl-defun
|
||||
(require 'dired) ;; dired-sort-inhibit
|
||||
(require 'dash)
|
||||
(require 's)
|
||||
(require 'find-dired) ;; find-dired-filter
|
||||
|
||||
(defgroup ag nil
|
||||
"A front-end for ag - The Silver Searcher."
|
||||
:group 'tools
|
||||
:group 'matching)
|
||||
|
||||
(defcustom ag-executable
|
||||
"ag"
|
||||
"Name of the ag executable to use."
|
||||
:type 'string
|
||||
:group 'ag)
|
||||
|
||||
(defcustom ag-arguments
|
||||
(list "--smart-case" "--stats")
|
||||
"Additional arguments passed to ag.
|
||||
|
||||
Ag.el internally uses --column, --line-number and --color
|
||||
options (with specific colors) to match groups, so options
|
||||
specified here should not conflict.
|
||||
|
||||
--line-number is required on Windows, as otherwise ag will not
|
||||
print line numbers when the input is a stream."
|
||||
:type '(repeat (string))
|
||||
:group 'ag)
|
||||
|
||||
(defcustom ag-dired-arguments
|
||||
(list "--nocolor" "-S")
|
||||
"Additional arguments passed to ag-dired."
|
||||
:type '(repeat (string))
|
||||
:group 'ag)
|
||||
|
||||
(defcustom ag-context-lines nil
|
||||
"Number of context lines to include before and after a matching line."
|
||||
:type 'integer
|
||||
:group 'ag)
|
||||
|
||||
(defcustom ag-group-matches t
|
||||
"Group matches in the same file together.
|
||||
|
||||
If nil, the file name is repeated at the beginning of every match line."
|
||||
:type 'boolean
|
||||
: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 for files/directories to ignore when searching."
|
||||
:type '(repeat (string))
|
||||
:group 'ag)
|
||||
(make-variable-buffer-local 'ag-ignore-list)
|
||||
(put 'ag-ignore-list 'safe-local-variable #'listp)
|
||||
|
||||
(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-nogroup
|
||||
"^\\(.+?\\):\\([1-9][0-9]*\\):\\([1-9][0-9]*\\):"
|
||||
"A regexp pattern that groups output into filename, line number and column number.")
|
||||
|
||||
(defvar ag/file-column-pattern-group
|
||||
"^\\([[:digit:]]+\\):\\([[:digit:]]+\\):"
|
||||
"A regexp pattern to match line number and column number with grouped output.")
|
||||
|
||||
(defun ag/compilation-match-grouped-filename ()
|
||||
"Match filename backwards when a line/column match is found in grouped output mode."
|
||||
(save-match-data
|
||||
(save-excursion
|
||||
(when (re-search-backward "^File: \\(.*\\)$" (point-min) t)
|
||||
(list (match-string 1))))))
|
||||
|
||||
(define-compilation-mode ag-mode "Ag"
|
||||
"Ag results compilation mode"
|
||||
(set (make-local-variable 'compilation-error-regexp-alist)
|
||||
'(compilation-ag-nogroup compilation-ag-group))
|
||||
(set (make-local-variable 'compilation-error-regexp-alist-alist)
|
||||
(list (cons 'compilation-ag-nogroup (list ag/file-column-pattern-nogroup 1 2 3))
|
||||
(cons 'compilation-ag-group (list ag/file-column-pattern-group
|
||||
'ag/compilation-match-grouped-filename 1 2))))
|
||||
(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)))
|
||||
|
||||
(cl-defun ag/search (string directory
|
||||
&key (regexp nil) (file-regex nil) (file-type nil) (files '(".")))
|
||||
"Run ag searching for the STRING given in DIRECTORY.
|
||||
If `files` is passed, tell ag to look only on those files.
|
||||
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"))
|
||||
;; Add double dashes at the end of command line if not specified in
|
||||
;; ag-arguments.
|
||||
(unless (equal (car (last arguments)) "--")
|
||||
(setq arguments (append arguments '("--"))))
|
||||
(setq arguments
|
||||
(append '("--line-number" "--column" "--color" "--color-match" "30;43"
|
||||
"--color-path" "1;32")
|
||||
arguments))
|
||||
(if ag-group-matches
|
||||
(setq arguments (cons "--group" arguments))
|
||||
(setq arguments (cons "--nogroup" arguments)))
|
||||
(unless regexp
|
||||
(setq arguments (cons "--literal" arguments)))
|
||||
(when (or (eq system-type 'windows-nt) (eq system-type 'cygwin))
|
||||
;; Use --vimgrep to work around issue #97 on Windows.
|
||||
(setq arguments (cons "--vimgrep" 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)))
|
||||
(if (integerp current-prefix-arg)
|
||||
(setq arguments (cons (format "--context=%d" (abs current-prefix-arg)) arguments))
|
||||
(when ag-context-lines
|
||||
(setq arguments (cons (format "--context=%d" ag-context-lines) 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 (append `(,string) files))
|
||||
" ")))
|
||||
;; 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.
|
||||
;; The numeric value is used for context lines: positive is just context
|
||||
;; number (no modification), negative allows further modification.
|
||||
(when (and current-prefix-arg (not (and (integerp current-prefix-arg) (> current-prefix-arg 0))))
|
||||
;; 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 (-non-nil strings))
|
||||
(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")
|
||||
|
||||
(autoload 'vc-bzr-root "vc-bzr")
|
||||
|
||||
(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)
|
||||
(vc-bzr-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 literal 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 literal 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 literal search 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 literal 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 string)
|
||||
"Recursively find files in DIR matching literal search STRING.
|
||||
|
||||
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 string)))
|
||||
|
||||
;;;###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 (if (string= system-type "windows-nt")
|
||||
(concat ag-executable " " (combine-and-quote-strings ag-dired-arguments " ") " -g \"" regexp "\" "
|
||||
(shell-quote-argument dir)
|
||||
" | grep -v \"^$\" | sed \"s/'/\\\\\\\\'/g\" | xargs -I '{}' "
|
||||
insert-directory-program " "
|
||||
dired-listing-switches " '{}' &")
|
||||
(concat ag-executable " " (combine-and-quote-strings ag-dired-arguments " ") " -g '" regexp "' "
|
||||
(shell-quote-argument dir)
|
||||
" | grep -v '^$' | sed s/\\'/\\\\\\\\\\'/g | xargs -I '{}' "
|
||||
insert-directory-program " "
|
||||
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)))))
|
||||
|
||||
;; Based on grep-filter.
|
||||
(defun ag-filter ()
|
||||
"Handle escape sequences inserted by the ag process.
|
||||
This function is called from `compilation-filter-hook'."
|
||||
(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))
|
||||
(when ag-highlight-search
|
||||
;; Highlight ag matches and delete marking sequences.
|
||||
(while (re-search-forward "\033\\[30;43m\\(.*?\\)\033\\[0m\033\\[K" end 1)
|
||||
(replace-match (propertize (match-string 1)
|
||||
'face nil 'font-lock-face 'ag-match-face)
|
||||
t t)))
|
||||
;; Add marker at start of line for files. This is used by the match
|
||||
;; in `compilation-error-regexp-alist' to extract the file name.
|
||||
(when ag-group-matches
|
||||
(goto-char beg)
|
||||
(while (re-search-forward "\033\\[1;32m\\(.*\\)\033\\[0m\033\\[K" end 1)
|
||||
(replace-match
|
||||
(concat "File: " (propertize (match-string 1) 'face nil 'font-lock-face
|
||||
'compilation-info))
|
||||
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
|
BIN
elpa/ag-20190726.9/ag.elc
Normal file
BIN
elpa/ag-20190726.9/ag.elc
Normal file
Binary file not shown.
349
elpa/js2-mode-20190815.1327/js2-imenu-extras.el
Normal file
349
elpa/js2-mode-20190815.1327/js2-imenu-extras.el
Normal file
|
@ -0,0 +1,349 @@
|
|||
;;; js2-imenu-extras.el --- Imenu support for additional constructs
|
||||
|
||||
;; Copyright (C) 2012-2014 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Dmitry Gutov <dgutov@yandex.ru>
|
||||
;; Keywords: languages, javascript, imenu
|
||||
|
||||
;; This file is part of GNU Emacs.
|
||||
|
||||
;; 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 of the License, 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. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; This package adds Imenu support for additional framework constructs and
|
||||
;; structural patterns to `js2-mode'.
|
||||
|
||||
;; Usage:
|
||||
|
||||
;; (add-hook 'js2-mode-hook 'js2-imenu-extras-mode)
|
||||
|
||||
;; To customize how it works:
|
||||
;; M-x customize-group RET js2-imenu RET
|
||||
|
||||
(eval-when-compile
|
||||
(require 'cl))
|
||||
|
||||
(require 'js2-mode)
|
||||
|
||||
(defvar js2-imenu-extension-styles
|
||||
`((:framework jquery
|
||||
:call-re "\\_<\\(?:jQuery\\|\\$\\|_\\)\\.extend\\s-*("
|
||||
:recorder js2-imenu-record-jquery-extend)
|
||||
|
||||
(:framework jquery-ui
|
||||
:call-re "^\\s-*\\(?:jQuery\\|\\$\\)\\.widget\\s-*("
|
||||
:recorder js2-imenu-record-string-declare)
|
||||
|
||||
(:framework dojo
|
||||
:call-re "^\\s-*dojo.declare\\s-*("
|
||||
:recorder js2-imenu-record-string-declare)
|
||||
|
||||
(:framework backbone
|
||||
:call-re ,(concat "\\_<" js2-mode-identifier-re "\\.extend\\s-*(")
|
||||
:recorder js2-imenu-record-backbone-extend)
|
||||
|
||||
(:framework enyo
|
||||
:call-re "\\_<enyo\\.kind\\s-*("
|
||||
:recorder js2-imenu-record-enyo-kind)
|
||||
|
||||
(:framework react
|
||||
:call-re "\\_<React\\.createClass\\s-*("
|
||||
:recorder js2-imenu-record-react-class)
|
||||
|
||||
(:framework sencha
|
||||
:call-re "^\\s-*Ext\\.define\\s-*("
|
||||
:recorder js2-imenu-record-sencha-class))
|
||||
"List of JavaScript class definition or extension styles.
|
||||
|
||||
:framework is a valid value in `js2-imenu-enabled-frameworks'.
|
||||
|
||||
:call-re is a regular expression that has no capturing groups.
|
||||
|
||||
:recorder is a function name that will be called when the regular
|
||||
expression matches some text in the buffer. When it's called, point will be
|
||||
at the end of the match. The function must keep the point position.")
|
||||
|
||||
(defconst js2-imenu-available-frameworks
|
||||
(mapcar (lambda (style) (plist-get style :framework)) js2-imenu-extension-styles)
|
||||
"List of available JavaScript framework symbols.")
|
||||
|
||||
(defcustom js2-imenu-enabled-frameworks js2-imenu-available-frameworks
|
||||
"Frameworks to be recognized by `js2-mode'."
|
||||
:type (cons 'set (mapcar (lambda (x) (list 'const x))
|
||||
js2-imenu-available-frameworks))
|
||||
:group 'js2-imenu)
|
||||
|
||||
(defcustom js2-imenu-show-other-functions t
|
||||
"Non-nil to show functions not recognized by other mechanisms,
|
||||
in a shared namespace."
|
||||
:type 'boolean
|
||||
:group 'js2-imenu)
|
||||
|
||||
(defcustom js2-imenu-other-functions-ns "?"
|
||||
"Namespace name to use for other functions."
|
||||
:type 'string
|
||||
:group 'js2-imenu)
|
||||
|
||||
(defcustom js2-imenu-show-module-pattern t
|
||||
"Non-nil to recognize the module pattern:
|
||||
|
||||
var foobs = (function(a) {
|
||||
return {fib: function() {}, fub: function() {}};
|
||||
})(b);
|
||||
|
||||
We record the returned hash as belonging to the named module, and
|
||||
prefix any functions defined inside the IIFE with the module name."
|
||||
:type 'boolean
|
||||
:group 'js2-imenu)
|
||||
|
||||
(defcustom js2-imenu-split-string-identifiers t
|
||||
"When non-nil, split string identifiers on dots.
|
||||
Currently used for jQuery widgets, Dojo and Enyo declarations."
|
||||
:type 'boolean
|
||||
:group 'js2-imenu)
|
||||
|
||||
;;;###autoload
|
||||
(defun js2-imenu-extras-setup ()
|
||||
(when js2-imenu-enabled-frameworks
|
||||
(add-hook 'js2-build-imenu-callbacks 'js2-imenu-record-declarations t t))
|
||||
(when (or js2-imenu-show-other-functions js2-imenu-show-module-pattern)
|
||||
(add-hook 'js2-build-imenu-callbacks 'js2-imenu-walk-ast t t)))
|
||||
|
||||
(defun js2-imenu-extras-remove ()
|
||||
(remove-hook 'js2-build-imenu-callbacks 'js2-imenu-record-declarations t)
|
||||
(remove-hook 'js2-build-imenu-callbacks 'js2-imenu-walk-ast t))
|
||||
|
||||
(defun js2-imenu-record-declarations ()
|
||||
(let* ((styles (loop for style in js2-imenu-extension-styles
|
||||
when (memq (plist-get style :framework)
|
||||
js2-imenu-enabled-frameworks)
|
||||
collect style))
|
||||
(re (mapconcat (lambda (style)
|
||||
(concat "\\(" (plist-get style :call-re) "\\)"))
|
||||
styles "\\|")))
|
||||
(goto-char (point-min))
|
||||
(while (js2-re-search-forward re nil t)
|
||||
(loop for i from 0 to (1- (length styles))
|
||||
when (match-beginning (1+ i))
|
||||
return (funcall (plist-get (nth i styles) :recorder))))))
|
||||
|
||||
(defun js2-imenu-record-jquery-extend ()
|
||||
(let ((pred (lambda (subject)
|
||||
(and
|
||||
(js2-prop-get-node-p subject)
|
||||
(string= (js2-name-node-name (js2-prop-get-node-right subject))
|
||||
"prototype")))))
|
||||
(js2-imenu-record-extend-first-arg (1- (point)) pred
|
||||
'js2-compute-nested-prop-get)))
|
||||
|
||||
(defun js2-imenu-record-string-declare ()
|
||||
(js2-imenu-record-extend-first-arg
|
||||
(1- (point)) 'js2-string-node-p
|
||||
(lambda (node)
|
||||
(if js2-imenu-split-string-identifiers
|
||||
(split-string (js2-string-node-value node) "\\." t)
|
||||
(list (js2-string-node-value node))))))
|
||||
|
||||
(defun js2-imenu-record-extend-first-arg (point pred qname-fn)
|
||||
(let* ((node (js2-node-at-point point))
|
||||
(args (js2-call-node-args node))
|
||||
(subject (first args)))
|
||||
(when (funcall pred subject)
|
||||
(loop for arg in (cdr args)
|
||||
when (js2-object-node-p arg)
|
||||
do (js2-record-object-literal
|
||||
arg (funcall qname-fn subject) (js2-node-abs-pos arg))))))
|
||||
|
||||
(defun js2-imenu-record-backbone-or-react ()
|
||||
(let* ((node (js2-node-at-point (1- (point))))
|
||||
(args (js2-call-node-args node))
|
||||
(methods (first args))
|
||||
(parent (js2-node-parent node)))
|
||||
(when (js2-object-node-p methods)
|
||||
(let ((subject (cond ((js2-var-init-node-p parent)
|
||||
(js2-var-init-node-target parent))
|
||||
((js2-assign-node-p parent)
|
||||
(js2-assign-node-left parent)))))
|
||||
(when subject
|
||||
(js2-record-object-literal methods
|
||||
(js2-compute-nested-prop-get subject)
|
||||
(js2-node-abs-pos methods)))))))
|
||||
|
||||
(defalias 'js2-imenu-record-backbone-extend 'js2-imenu-record-backbone-or-react)
|
||||
|
||||
(defalias 'js2-imenu-record-react-class 'js2-imenu-record-backbone-or-react)
|
||||
|
||||
(defun js2-imenu-record-enyo-kind ()
|
||||
(let* ((node (js2-node-at-point (1- (point))))
|
||||
(args (js2-call-node-args node))
|
||||
(options (first args)))
|
||||
(when (js2-object-node-p options)
|
||||
(let ((name-value
|
||||
(loop for elem in (js2-object-node-elems options)
|
||||
thereis
|
||||
(let ((key (js2-object-prop-node-left elem))
|
||||
(value (js2-object-prop-node-right elem)))
|
||||
(when (and (equal
|
||||
(cond ((js2-name-node-p key)
|
||||
(js2-name-node-name key))
|
||||
((js2-string-node-p key)
|
||||
(js2-string-node-value key)))
|
||||
"name")
|
||||
(js2-string-node-p value))
|
||||
(js2-string-node-value value))))))
|
||||
(when name-value
|
||||
(js2-record-object-literal options
|
||||
(if js2-imenu-split-string-identifiers
|
||||
(split-string name-value "\\.")
|
||||
(list name-value))
|
||||
(js2-node-abs-pos options)))))))
|
||||
|
||||
(defun js2-imenu-record-sencha-class ()
|
||||
(let* ((node (js2-node-at-point (1- (point))))
|
||||
(args (js2-call-node-args node))
|
||||
(name (first args))
|
||||
(methods (second args)))
|
||||
(when (and (js2-string-node-p name) (js2-object-node-p methods))
|
||||
(let ((name-value (js2-string-node-value name)))
|
||||
(js2-record-object-literal methods
|
||||
(if js2-imenu-split-string-identifiers
|
||||
(split-string name-value "\\." t)
|
||||
(list name-value))
|
||||
(js2-node-abs-pos methods))))))
|
||||
|
||||
(defun js2-imenu-walk-ast ()
|
||||
(js2-visit-ast
|
||||
js2-mode-ast
|
||||
(lambda (node end-p)
|
||||
(unless end-p
|
||||
(cond
|
||||
((and js2-imenu-show-other-functions
|
||||
(js2-object-prop-node-p node))
|
||||
(js2-imenu-record-orphan-prop-node-function node))
|
||||
((js2-assign-node-p node)
|
||||
(cond
|
||||
((and js2-imenu-show-other-functions
|
||||
(js2-function-node-p
|
||||
(js2-assign-node-right node)))
|
||||
(js2-imenu-record-orphan-assign-node-function
|
||||
(js2-assign-node-left node)
|
||||
(js2-assign-node-right node)))
|
||||
((and js2-imenu-show-module-pattern
|
||||
(js2-call-node-p
|
||||
(js2-assign-node-right node)))
|
||||
(js2-imenu-record-module-pattern
|
||||
(js2-assign-node-left node)
|
||||
(js2-assign-node-right node)))))
|
||||
((js2-var-init-node-p node)
|
||||
(cond
|
||||
((and js2-imenu-show-other-functions
|
||||
(js2-function-node-p
|
||||
(js2-var-init-node-initializer node)))
|
||||
(js2-imenu-record-orphan-assign-node-function
|
||||
(js2-var-init-node-target node)
|
||||
(js2-var-init-node-initializer node)))
|
||||
((and js2-imenu-show-module-pattern
|
||||
(js2-call-node-p
|
||||
(js2-var-init-node-initializer node)))
|
||||
(js2-imenu-record-module-pattern
|
||||
(js2-var-init-node-target node)
|
||||
(js2-var-init-node-initializer node))))))
|
||||
t))))
|
||||
|
||||
(defun js2-imenu-parent-key-names (node)
|
||||
"Get the list of parent key names of NODE.
|
||||
|
||||
For example, for code
|
||||
|
||||
{rules: {password: {required: function() {}}}}
|
||||
|
||||
when NODE is the inner `js2-object-prop-mode',
|
||||
it returns `(\"rules\" \"password\")'."
|
||||
(let (rlt (n node))
|
||||
(while (setq n (js2-imenu-parent-prop-node n))
|
||||
(push (js2-prop-node-name (js2-object-prop-node-left n)) rlt))
|
||||
rlt))
|
||||
|
||||
(defun js2-imenu-parent-prop-node (node)
|
||||
"When the parent of NODE is `js2-object-node',
|
||||
and the grandparent is `js2-object-prop-node',
|
||||
return the grandparent."
|
||||
;; Suppose the code is:
|
||||
;; {parent-key: {required: function() {}}}
|
||||
;; NODE is `required: function() {}'.
|
||||
(let (p2 p3)
|
||||
;; Parent is `{required: function() {}}'.
|
||||
(setq p2 (js2-node-parent node))
|
||||
;; GP is `parent-key: {required: function() {}}'.
|
||||
(when (and p2 (js2-object-node-p p2))
|
||||
(setq p3 (js2-node-parent p2))
|
||||
(if (and p3 (js2-object-prop-node-p p3)) p3))))
|
||||
|
||||
(defun js2-imenu-record-orphan-prop-node-function (node)
|
||||
"Record orphan function when it's the value of NODE.
|
||||
NODE must be `js2-object-prop-node'."
|
||||
(when (js2-function-node-p (js2-object-prop-node-right node))
|
||||
(let ((fn-node (js2-object-prop-node-right node)))
|
||||
(unless (and js2-imenu-function-map
|
||||
(gethash fn-node js2-imenu-function-map))
|
||||
(let ((key-node (js2-object-prop-node-left node))
|
||||
(parent-prop-node (js2-imenu-parent-prop-node node))
|
||||
chain)
|
||||
(setq chain (nconc (js2-imenu-parent-key-names node)
|
||||
(list (js2-prop-node-name key-node))))
|
||||
(push js2-imenu-other-functions-ns chain)
|
||||
(js2-record-imenu-entry fn-node chain
|
||||
(js2-node-abs-pos key-node)))))))
|
||||
|
||||
(defun js2-imenu-record-orphan-assign-node-function (target-node fn-node)
|
||||
"Record orphan function FN-NODE assigned to node TARGET."
|
||||
(when (or (not js2-imenu-function-map)
|
||||
(eq 'skip
|
||||
(gethash fn-node js2-imenu-function-map 'skip)))
|
||||
(let ((chain (js2-compute-nested-prop-get target-node)))
|
||||
(when chain
|
||||
(push js2-imenu-other-functions-ns chain)
|
||||
(js2-record-imenu-entry fn-node chain (js2-node-abs-pos fn-node))))))
|
||||
|
||||
(defun js2-imenu-record-module-pattern (target init)
|
||||
"Recognize and record module pattern use instance.
|
||||
INIT must be `js2-call-node'."
|
||||
(let ((callt (js2-call-node-target init)))
|
||||
;; Just basic call form: (function() {...})();
|
||||
;; TODO: Handle variations without duplicating `js2-wrapper-function-p'?
|
||||
(when (and (js2-paren-node-p callt)
|
||||
(js2-function-node-p (js2-paren-node-expr callt)))
|
||||
(let* ((fn (js2-paren-node-expr callt))
|
||||
(blk (js2-function-node-body fn))
|
||||
(ret (car (last (js2-block-node-kids blk)))))
|
||||
(when (and (js2-return-node-p ret)
|
||||
(js2-object-node-p (js2-return-node-retval ret)))
|
||||
;; TODO: Map function names when revealing module pattern is used.
|
||||
(let ((retval (js2-return-node-retval ret))
|
||||
(target-qname (js2-compute-nested-prop-get target)))
|
||||
(js2-record-object-literal retval target-qname
|
||||
(js2-node-abs-pos retval))
|
||||
(js2-record-imenu-entry fn target-qname
|
||||
(js2-node-abs-pos target))))))))
|
||||
|
||||
;;;###autoload
|
||||
(define-minor-mode js2-imenu-extras-mode
|
||||
"Toggle Imenu support for frameworks and structural patterns."
|
||||
:lighter ""
|
||||
(if js2-imenu-extras-mode
|
||||
(js2-imenu-extras-setup)
|
||||
(js2-imenu-extras-remove)))
|
||||
|
||||
(provide 'js2-imenu-extras)
|
BIN
elpa/js2-mode-20190815.1327/js2-imenu-extras.elc
Normal file
BIN
elpa/js2-mode-20190815.1327/js2-imenu-extras.elc
Normal file
Binary file not shown.
85
elpa/js2-mode-20190815.1327/js2-mode-autoloads.el
Normal file
85
elpa/js2-mode-20190815.1327/js2-mode-autoloads.el
Normal file
|
@ -0,0 +1,85 @@
|
|||
;;; js2-mode-autoloads.el --- automatically extracted autoloads
|
||||
;;
|
||||
;;; Code:
|
||||
|
||||
(add-to-list 'load-path (directory-file-name
|
||||
(or (file-name-directory #$) (car load-path))))
|
||||
|
||||
|
||||
;;;### (autoloads nil "js2-imenu-extras" "js2-imenu-extras.el" (0
|
||||
;;;;;; 0 0 0))
|
||||
;;; Generated autoloads from js2-imenu-extras.el
|
||||
|
||||
(autoload 'js2-imenu-extras-setup "js2-imenu-extras" "\
|
||||
|
||||
|
||||
\(fn)" nil nil)
|
||||
|
||||
(autoload 'js2-imenu-extras-mode "js2-imenu-extras" "\
|
||||
Toggle Imenu support for frameworks and structural patterns.
|
||||
|
||||
\(fn &optional ARG)" t nil)
|
||||
|
||||
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "js2-imenu-extras" '("js2-imenu-")))
|
||||
|
||||
;;;***
|
||||
|
||||
;;;### (autoloads nil "js2-mode" "js2-mode.el" (0 0 0 0))
|
||||
;;; Generated autoloads from js2-mode.el
|
||||
|
||||
(autoload 'js2-highlight-unused-variables-mode "js2-mode" "\
|
||||
Toggle highlight of unused variables.
|
||||
|
||||
\(fn &optional ARG)" t nil)
|
||||
|
||||
(autoload 'js2-minor-mode "js2-mode" "\
|
||||
Minor mode for running js2 as a background linter.
|
||||
This allows you to use a different major mode for JavaScript editing,
|
||||
such as `js-mode', while retaining the asynchronous error/warning
|
||||
highlighting features of `js2-mode'.
|
||||
|
||||
\(fn &optional ARG)" t nil)
|
||||
|
||||
(autoload 'js2-mode "js2-mode" "\
|
||||
Major mode for editing JavaScript code.
|
||||
|
||||
\(fn)" t nil)
|
||||
|
||||
(autoload 'js2-jsx-mode "js2-mode" "\
|
||||
Major mode for editing JSX code in Emacs 26 and earlier.
|
||||
|
||||
To edit JSX code in Emacs 27, use `js-mode' as your major mode
|
||||
with `js2-minor-mode' enabled.
|
||||
|
||||
To customize the indentation for this mode, set the SGML offset
|
||||
variables (`sgml-basic-offset' et al) locally, like so:
|
||||
|
||||
(defun set-jsx-indentation ()
|
||||
(setq-local sgml-basic-offset js2-basic-offset))
|
||||
(add-hook \\='js2-jsx-mode-hook #\\='set-jsx-indentation)
|
||||
|
||||
\(fn)" t nil)
|
||||
|
||||
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "js2-mode" '("js2-")))
|
||||
|
||||
;;;***
|
||||
|
||||
;;;### (autoloads nil "js2-old-indent" "js2-old-indent.el" (0 0 0
|
||||
;;;;;; 0))
|
||||
;;; Generated autoloads from js2-old-indent.el
|
||||
|
||||
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "js2-old-indent" '("js2-")))
|
||||
|
||||
;;;***
|
||||
|
||||
;;;### (autoloads nil nil ("js2-mode-pkg.el") (0 0 0 0))
|
||||
|
||||
;;;***
|
||||
|
||||
;; Local Variables:
|
||||
;; version-control: never
|
||||
;; no-byte-compile: t
|
||||
;; no-update-autoloads: t
|
||||
;; coding: utf-8
|
||||
;; End:
|
||||
;;; js2-mode-autoloads.el ends here
|
15
elpa/js2-mode-20190815.1327/js2-mode-pkg.el
Normal file
15
elpa/js2-mode-20190815.1327/js2-mode-pkg.el
Normal file
|
@ -0,0 +1,15 @@
|
|||
(define-package "js2-mode" "20190815.1327" "Improved JavaScript editing mode"
|
||||
'((emacs "24.1")
|
||||
(cl-lib "0.5"))
|
||||
:keywords
|
||||
'("languages" "javascript")
|
||||
:authors
|
||||
'(("Steve Yegge" . "steve.yegge@gmail.com")
|
||||
("mooz" . "stillpedant@gmail.com")
|
||||
("Dmitry Gutov" . "dgutov@yandex.ru"))
|
||||
:maintainer
|
||||
'("Steve Yegge" . "steve.yegge@gmail.com")
|
||||
:url "https://github.com/mooz/js2-mode/")
|
||||
;; Local Variables:
|
||||
;; no-byte-compile: t
|
||||
;; End:
|
12940
elpa/js2-mode-20190815.1327/js2-mode.el
Normal file
12940
elpa/js2-mode-20190815.1327/js2-mode.el
Normal file
File diff suppressed because it is too large
Load diff
BIN
elpa/js2-mode-20190815.1327/js2-mode.elc
Normal file
BIN
elpa/js2-mode-20190815.1327/js2-mode.elc
Normal file
Binary file not shown.
712
elpa/js2-mode-20190815.1327/js2-old-indent.el
Normal file
712
elpa/js2-mode-20190815.1327/js2-old-indent.el
Normal file
|
@ -0,0 +1,712 @@
|
|||
;;; js2-old-indent.el --- Indentation code kept for compatibility
|
||||
|
||||
;; Copyright (C) 2015 Free Software Foundation, Inc.
|
||||
|
||||
;; This file is part of GNU Emacs.
|
||||
|
||||
;; 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 of the License, 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. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; All features of this indentation code have been ported to Emacs's
|
||||
;; built-in `js-mode' by now, so we derive from it. An older
|
||||
;; commentary follows.
|
||||
|
||||
;; This code is kept for Emacs 24.5 and ealier.
|
||||
|
||||
;; This indenter is based on Karl Landström's "javascript.el" indenter.
|
||||
;; Karl cleverly deduces that the desired indentation level is often a
|
||||
;; function of paren/bracket/brace nesting depth, which can be determined
|
||||
;; quickly via the built-in `parse-partial-sexp' function. His indenter
|
||||
;; then does some equally clever checks to see if we're in the context of a
|
||||
;; substatement of a possibly braceless statement keyword such as if, while,
|
||||
;; or finally. This approach yields pretty good results.
|
||||
|
||||
;; The indenter is often "wrong", however, and needs to be overridden.
|
||||
;; The right long-term solution is probably to emulate (or integrate
|
||||
;; with) cc-engine, but it's a nontrivial amount of coding. Even when a
|
||||
;; parse tree from `js2-parse' is present, which is not true at the
|
||||
;; moment the user is typing, computing indentation is still thousands
|
||||
;; of lines of code to handle every possible syntactic edge case.
|
||||
|
||||
;; In the meantime, the compromise solution is that we offer a "bounce
|
||||
;; indenter", configured with `js2-bounce-indent-p', which cycles the
|
||||
;; current line indent among various likely guess points. This approach
|
||||
;; is far from perfect, but should at least make it slightly easier to
|
||||
;; move the line towards its desired indentation when manually
|
||||
;; overriding Karl's heuristic nesting guesser.
|
||||
|
||||
;; I've made miscellaneous tweaks to Karl's code to handle some Ecma
|
||||
;; extensions such as `let' and Array comprehensions. Major kudos to
|
||||
;; Karl for coming up with the initial approach, which packs a lot of
|
||||
;; punch for so little code. -- Steve
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'sgml-mode)
|
||||
|
||||
(defvar js2-language-version)
|
||||
|
||||
(declare-function js2-backward-sws "js2-mode")
|
||||
(declare-function js2-forward-sws "js2-mode")
|
||||
(declare-function js2-same-line "js2-mode")
|
||||
|
||||
(defcustom js2-basic-offset (if (and (boundp 'c-basic-offset)
|
||||
(numberp c-basic-offset))
|
||||
c-basic-offset
|
||||
4)
|
||||
"Number of spaces to indent nested statements.
|
||||
Similar to `c-basic-offset'."
|
||||
:group 'js2-mode
|
||||
:safe 'integerp
|
||||
:type 'integer)
|
||||
|
||||
(defcustom js2-pretty-multiline-declarations t
|
||||
"Non-nil to line up multiline declarations vertically:
|
||||
|
||||
var a = 10,
|
||||
b = 20,
|
||||
c = 30;
|
||||
|
||||
If the value is t, and the first assigned value in the
|
||||
declaration is a function/array/object literal spanning several
|
||||
lines, it won't be indented additionally:
|
||||
|
||||
var o = { var bar = 2,
|
||||
foo: 3 vs. o = {
|
||||
}, foo: 3
|
||||
bar = 2; };
|
||||
|
||||
If the value is `all', it will always be indented additionally:
|
||||
|
||||
var o = {
|
||||
foo: 3
|
||||
};
|
||||
|
||||
var o = {
|
||||
foo: 3
|
||||
},
|
||||
bar = 2;
|
||||
|
||||
If the value is `dynamic', it will be indented additionally only
|
||||
if the declaration contains more than one variable:
|
||||
|
||||
var o = {
|
||||
foo: 3
|
||||
};
|
||||
|
||||
var o = {
|
||||
foo: 3
|
||||
},
|
||||
bar = 2;"
|
||||
:group 'js2-mode
|
||||
:safe 'symbolp
|
||||
:type 'symbol)
|
||||
|
||||
(defcustom js2-indent-switch-body nil
|
||||
"When nil, case labels are indented on the same level as the
|
||||
containing switch statement. Otherwise, all lines inside
|
||||
switch statement body are indented one additional level."
|
||||
:type 'boolean
|
||||
:safe 'booleanp
|
||||
:group 'js2-mode)
|
||||
|
||||
(defconst js2-possibly-braceless-keywords-re
|
||||
(concat "else[ \t]+if\\|for[ \t]+each\\|"
|
||||
(regexp-opt '("catch" "do" "else" "finally" "for" "if"
|
||||
"try" "while" "with" "let")))
|
||||
"Regular expression matching keywords that are optionally
|
||||
followed by an opening brace.")
|
||||
|
||||
(defconst js2-indent-operator-re
|
||||
(concat "[-+*/%<>&^|?:.]\\([^-+*/.]\\|$\\)\\|!?=\\|"
|
||||
(regexp-opt '("in" "instanceof") 'symbols))
|
||||
"Regular expression matching operators that affect indentation
|
||||
of continued expressions.")
|
||||
|
||||
(defconst js2-declaration-keyword-re
|
||||
(regexp-opt '("var" "let" "const") 'symbols)
|
||||
"Regular expression matching variable declaration keywords.")
|
||||
|
||||
(defun js2-re-search-forward-inner (regexp &optional bound count)
|
||||
"Auxiliary function for `js2-re-search-forward'."
|
||||
(let (parse saved-point)
|
||||
(while (> count 0)
|
||||
(re-search-forward regexp bound)
|
||||
(setq parse (if saved-point
|
||||
(parse-partial-sexp saved-point (point))
|
||||
(syntax-ppss (point))))
|
||||
(cond ((nth 3 parse)
|
||||
(re-search-forward
|
||||
(concat "\\(\\=\\|[^\\]\\|^\\)" (string (nth 3 parse)))
|
||||
(save-excursion (end-of-line) (point)) t))
|
||||
((nth 7 parse)
|
||||
(forward-line))
|
||||
((or (nth 4 parse)
|
||||
(and (eq (char-before) ?\/) (eq (char-after) ?\*)))
|
||||
(re-search-forward "\\*/"))
|
||||
(t
|
||||
(setq count (1- count))))
|
||||
(setq saved-point (point))))
|
||||
(point))
|
||||
|
||||
(defun js2-re-search-forward (regexp &optional bound noerror count)
|
||||
"Search forward but ignore strings and comments.
|
||||
Invokes `re-search-forward' but treats the buffer as if strings
|
||||
and comments have been removed."
|
||||
(let ((saved-point (point)))
|
||||
(condition-case err
|
||||
(cond ((null count)
|
||||
(js2-re-search-forward-inner regexp bound 1))
|
||||
((< count 0)
|
||||
(js2-re-search-backward-inner regexp bound (- count)))
|
||||
((> count 0)
|
||||
(js2-re-search-forward-inner regexp bound count)))
|
||||
(search-failed
|
||||
(goto-char saved-point)
|
||||
(unless noerror
|
||||
(error (error-message-string err)))))))
|
||||
|
||||
(defun js2-re-search-backward-inner (regexp &optional bound count)
|
||||
"Auxiliary function for `js2-re-search-backward'."
|
||||
(let (parse)
|
||||
(while (> count 0)
|
||||
(re-search-backward regexp bound)
|
||||
(setq parse (syntax-ppss (point)))
|
||||
(cond ((nth 3 parse)
|
||||
(re-search-backward
|
||||
(concat "\\([^\\]\\|^\\)" (string (nth 3 parse)))
|
||||
(line-beginning-position) t))
|
||||
((nth 7 parse)
|
||||
(goto-char (nth 8 parse)))
|
||||
((or (nth 4 parse)
|
||||
(and (eq (char-before) ?/) (eq (char-after) ?*)))
|
||||
(re-search-backward "/\\*"))
|
||||
(t
|
||||
(setq count (1- count))))))
|
||||
(point))
|
||||
|
||||
(defun js2-re-search-backward (regexp &optional bound noerror count)
|
||||
"Search backward but ignore strings and comments.
|
||||
Invokes `re-search-backward' but treats the buffer as if strings
|
||||
and comments have been removed."
|
||||
(let ((saved-point (point)))
|
||||
(condition-case err
|
||||
(cond ((null count)
|
||||
(js2-re-search-backward-inner regexp bound 1))
|
||||
((< count 0)
|
||||
(js2-re-search-forward-inner regexp bound (- count)))
|
||||
((> count 0)
|
||||
(js2-re-search-backward-inner regexp bound count)))
|
||||
(search-failed
|
||||
(goto-char saved-point)
|
||||
(unless noerror
|
||||
(error (error-message-string err)))))))
|
||||
|
||||
(defun js2-looking-at-operator-p ()
|
||||
"Return non-nil if text after point is a non-comma operator."
|
||||
(defvar js2-mode-identifier-re)
|
||||
(and (looking-at js2-indent-operator-re)
|
||||
(or (not (eq (char-after) ?:))
|
||||
(save-excursion
|
||||
(and (js2-re-search-backward "[?:{]\\|\\_<case\\_>" nil t)
|
||||
(eq (char-after) ??))))
|
||||
(not (and
|
||||
(eq (char-after) ?/)
|
||||
(save-excursion
|
||||
(eq (nth 3 (syntax-ppss)) ?/))))
|
||||
(not (and
|
||||
(eq (char-after) ?*)
|
||||
;; Generator method (possibly using computed property).
|
||||
(looking-at (concat "\\* *\\(?:\\[\\|"
|
||||
js2-mode-identifier-re
|
||||
" *(\\)"))
|
||||
(save-excursion
|
||||
(js2-backward-sws)
|
||||
;; We might misindent some expressions that would
|
||||
;; return NaN anyway. Shouldn't be a problem.
|
||||
(memq (char-before) '(?, ?} ?{)))))))
|
||||
|
||||
(defun js2-continued-expression-p ()
|
||||
"Return non-nil if the current line continues an expression."
|
||||
(save-excursion
|
||||
(back-to-indentation)
|
||||
(if (js2-looking-at-operator-p)
|
||||
(or (not (memq (char-after) '(?- ?+)))
|
||||
(progn
|
||||
(forward-comment (- (point)))
|
||||
(not (memq (char-before) '(?, ?\[ ?\()))))
|
||||
(forward-comment (- (point)))
|
||||
(or (bobp) (backward-char))
|
||||
(when (js2-looking-at-operator-p)
|
||||
(backward-char)
|
||||
(not (looking-at "\\*\\|\\+\\+\\|--\\|/[/*]"))))))
|
||||
|
||||
(defun js2-end-of-do-while-loop-p ()
|
||||
"Return non-nil if word after point is `while' of a do-while
|
||||
statement, else returns nil. A braceless do-while statement
|
||||
spanning several lines requires that the start of the loop is
|
||||
indented to the same column as the current line."
|
||||
(interactive)
|
||||
(save-excursion
|
||||
(when (looking-at "\\s-*\\_<while\\_>")
|
||||
(if (save-excursion
|
||||
(skip-chars-backward "[ \t\n]*}")
|
||||
(looking-at "[ \t\n]*}"))
|
||||
(save-excursion
|
||||
(backward-list) (backward-word 1) (looking-at "\\_<do\\_>"))
|
||||
(js2-re-search-backward "\\_<do\\_>" (point-at-bol) t)
|
||||
(or (looking-at "\\_<do\\_>")
|
||||
(let ((saved-indent (current-indentation)))
|
||||
(while (and (js2-re-search-backward "^[ \t]*\\_<" nil t)
|
||||
(/= (current-indentation) saved-indent)))
|
||||
(and (looking-at "[ \t]*\\_<do\\_>")
|
||||
(not (js2-re-search-forward
|
||||
"\\_<while\\_>" (point-at-eol) t))
|
||||
(= (current-indentation) saved-indent))))))))
|
||||
|
||||
(defun js2-multiline-decl-indentation ()
|
||||
"Return the declaration indentation column if the current line belongs
|
||||
to a multiline declaration statement. See `js2-pretty-multiline-declarations'."
|
||||
(let (forward-sexp-function ; use Lisp version
|
||||
at-opening-bracket)
|
||||
(save-excursion
|
||||
(back-to-indentation)
|
||||
(when (not (looking-at js2-declaration-keyword-re))
|
||||
(when (looking-at js2-indent-operator-re)
|
||||
(goto-char (match-end 0))) ; continued expressions are ok
|
||||
(while (and (not at-opening-bracket)
|
||||
(not (bobp))
|
||||
(let ((pos (point)))
|
||||
(save-excursion
|
||||
(js2-backward-sws)
|
||||
(or (eq (char-before) ?,)
|
||||
(and (not (eq (char-before) ?\;))
|
||||
(prog2 (skip-syntax-backward ".")
|
||||
(looking-at js2-indent-operator-re)
|
||||
(js2-backward-sws))
|
||||
(not (eq (char-before) ?\;)))
|
||||
(js2-same-line pos)))))
|
||||
(condition-case _
|
||||
(backward-sexp)
|
||||
(scan-error (setq at-opening-bracket t))))
|
||||
(when (looking-at js2-declaration-keyword-re)
|
||||
(goto-char (match-end 0))
|
||||
(1+ (current-column)))))))
|
||||
|
||||
(defun js2-ctrl-statement-indentation ()
|
||||
"Return the proper indentation of current line if it is a control statement.
|
||||
Returns an indentation if this line starts the body of a control
|
||||
statement without braces, else returns nil."
|
||||
(let (forward-sexp-function)
|
||||
(save-excursion
|
||||
(back-to-indentation)
|
||||
(when (and (not (js2-same-line (point-min)))
|
||||
(not (looking-at "{"))
|
||||
(js2-re-search-backward "[[:graph:]]" nil t)
|
||||
(not (looking-at "[{([]"))
|
||||
(progn
|
||||
(forward-char)
|
||||
(when (= (char-before) ?\))
|
||||
;; scan-sexps sometimes throws an error
|
||||
(ignore-errors (backward-sexp))
|
||||
(skip-chars-backward " \t" (point-at-bol)))
|
||||
(let ((pt (point)))
|
||||
(back-to-indentation)
|
||||
(when (looking-at "}[ \t]*")
|
||||
(goto-char (match-end 0)))
|
||||
(and (looking-at js2-possibly-braceless-keywords-re)
|
||||
(= (match-end 0) pt)
|
||||
(not (js2-end-of-do-while-loop-p))))))
|
||||
(+ (current-indentation) js2-basic-offset)))))
|
||||
|
||||
(defun js2-indent-in-array-comp (parse-status)
|
||||
"Return non-nil if we think we're in an array comprehension.
|
||||
In particular, return the buffer position of the first `for' kwd."
|
||||
(let ((bracket (nth 1 parse-status))
|
||||
(end (point)))
|
||||
(when bracket
|
||||
(save-excursion
|
||||
(goto-char bracket)
|
||||
(when (looking-at "\\[")
|
||||
(forward-char 1)
|
||||
(js2-forward-sws)
|
||||
(if (looking-at "[[{]")
|
||||
(let (forward-sexp-function) ; use Lisp version
|
||||
(forward-sexp) ; skip destructuring form
|
||||
(js2-forward-sws)
|
||||
(if (and (/= (char-after) ?,) ; regular array
|
||||
(looking-at "for"))
|
||||
(match-beginning 0)))
|
||||
;; to skip arbitrary expressions we need the parser,
|
||||
;; so we'll just guess at it.
|
||||
(if (and (> end (point)) ; not empty literal
|
||||
(re-search-forward "[^,]]* \\(for\\) " end t)
|
||||
;; not inside comment or string literal
|
||||
(let ((state (parse-partial-sexp bracket (point))))
|
||||
(and (= 1 (car state))
|
||||
(not (nth 8 state)))))
|
||||
(match-beginning 1))))))))
|
||||
|
||||
(defun js2-array-comp-indentation (parse-status for-kwd)
|
||||
(if (js2-same-line for-kwd)
|
||||
;; first continuation line
|
||||
(save-excursion
|
||||
(goto-char (nth 1 parse-status))
|
||||
(forward-char 1)
|
||||
(skip-chars-forward " \t")
|
||||
(current-column))
|
||||
(save-excursion
|
||||
(goto-char for-kwd)
|
||||
(current-column))))
|
||||
|
||||
(defun js2-maybe-goto-declaration-keyword-end (bracket)
|
||||
"Helper function for `js2-proper-indentation'.
|
||||
Depending on the value of `js2-pretty-multiline-declarations',
|
||||
move point to the end of a variable declaration keyword so that
|
||||
indentation is aligned to that column."
|
||||
(cond
|
||||
((eq js2-pretty-multiline-declarations 'all)
|
||||
(when (looking-at js2-declaration-keyword-re)
|
||||
(goto-char (1+ (match-end 0)))))
|
||||
((eq js2-pretty-multiline-declarations 'dynamic)
|
||||
(let (declaration-keyword-end
|
||||
at-closing-bracket-p
|
||||
comma-p)
|
||||
(when (looking-at js2-declaration-keyword-re)
|
||||
;; Preserve the match data lest it somehow be overridden.
|
||||
(setq declaration-keyword-end (match-end 0))
|
||||
(save-excursion
|
||||
(goto-char bracket)
|
||||
(setq at-closing-bracket-p
|
||||
;; Handle scan errors gracefully.
|
||||
(condition-case nil
|
||||
(progn
|
||||
;; Use the regular `forward-sexp-function' because the
|
||||
;; normal one for this mode uses the AST.
|
||||
(let (forward-sexp-function)
|
||||
(forward-sexp))
|
||||
t)
|
||||
(error nil)))
|
||||
(when at-closing-bracket-p
|
||||
(js2-forward-sws)
|
||||
(setq comma-p (looking-at-p ","))))
|
||||
(when comma-p
|
||||
(goto-char (1+ declaration-keyword-end))))))))
|
||||
|
||||
(cl-defun js2-proper-indentation (parse-status)
|
||||
"Return the proper indentation for the current line."
|
||||
(save-excursion
|
||||
(back-to-indentation)
|
||||
(when (nth 4 parse-status)
|
||||
(cl-return-from js2-proper-indentation (js2--comment-indent parse-status)))
|
||||
(let* ((at-closing-bracket (looking-at "[]})]"))
|
||||
(same-indent-p (or at-closing-bracket
|
||||
(looking-at "\\_<case\\_>[^:]")
|
||||
(and (looking-at "\\_<default:")
|
||||
(save-excursion
|
||||
(js2-backward-sws)
|
||||
(not (memq (char-before) '(?, ?{)))))))
|
||||
(continued-expr-p (js2-continued-expression-p))
|
||||
(declaration-indent (and js2-pretty-multiline-declarations
|
||||
(js2-multiline-decl-indentation)))
|
||||
(bracket (nth 1 parse-status))
|
||||
beg indent)
|
||||
(cond
|
||||
;; indent array comprehension continuation lines specially
|
||||
((and bracket
|
||||
(>= js2-language-version 170)
|
||||
(not (js2-same-line bracket))
|
||||
(setq beg (js2-indent-in-array-comp parse-status))
|
||||
(>= (point) (save-excursion
|
||||
(goto-char beg)
|
||||
(point-at-bol)))) ; at or after first loop?
|
||||
(js2-array-comp-indentation parse-status beg))
|
||||
|
||||
((js2-ctrl-statement-indentation))
|
||||
|
||||
((and declaration-indent continued-expr-p)
|
||||
(+ declaration-indent js2-basic-offset))
|
||||
|
||||
(declaration-indent)
|
||||
|
||||
(bracket
|
||||
(goto-char bracket)
|
||||
(cond
|
||||
((looking-at "[({[][ \t]*\\(/[/*]\\|$\\)")
|
||||
(when (save-excursion (skip-chars-backward " \t\n)")
|
||||
(looking-at ")"))
|
||||
(backward-list))
|
||||
(back-to-indentation)
|
||||
(js2-maybe-goto-declaration-keyword-end bracket)
|
||||
(setq indent
|
||||
(cond (same-indent-p
|
||||
(current-column))
|
||||
(continued-expr-p
|
||||
(+ (current-column) (* 2 js2-basic-offset)))
|
||||
(t
|
||||
(+ (current-column) js2-basic-offset))))
|
||||
(if (and js2-indent-switch-body
|
||||
(not at-closing-bracket)
|
||||
(looking-at "\\_<switch\\_>"))
|
||||
(+ indent js2-basic-offset)
|
||||
indent))
|
||||
(t
|
||||
(unless same-indent-p
|
||||
(forward-char)
|
||||
(skip-chars-forward " \t"))
|
||||
(current-column))))
|
||||
|
||||
(continued-expr-p js2-basic-offset)
|
||||
|
||||
(t 0)))))
|
||||
|
||||
(defun js2--comment-indent (parse-status)
|
||||
"Indentation inside a multi-line block comment continuation line."
|
||||
(save-excursion
|
||||
(goto-char (nth 8 parse-status))
|
||||
(if (looking-at "/\\*")
|
||||
(+ 1 (current-column))
|
||||
0)))
|
||||
|
||||
(defun js2-indent-line (&optional bounce-backwards)
|
||||
"Indent the current line as JavaScript source text."
|
||||
(interactive)
|
||||
(let (parse-status offset
|
||||
;; Don't whine about errors/warnings when we're indenting.
|
||||
;; This has to be set before calling parse-partial-sexp below.
|
||||
(inhibit-point-motion-hooks t))
|
||||
(setq parse-status (save-excursion
|
||||
(syntax-ppss (point-at-bol)))
|
||||
offset (- (point) (save-excursion
|
||||
(back-to-indentation)
|
||||
(point))))
|
||||
;; Don't touch multiline strings.
|
||||
(unless (nth 3 parse-status)
|
||||
(indent-line-to (js2-proper-indentation parse-status))
|
||||
(when (cl-plusp offset)
|
||||
(forward-char offset)))))
|
||||
|
||||
;;; JSX Indentation
|
||||
|
||||
;; The following JSX indentation code is copied basically verbatim from js.el at
|
||||
;; 958da7f, except that the prefixes on the functions/variables are changed.
|
||||
|
||||
(defsubst js2--jsx-find-before-tag ()
|
||||
"Find where JSX starts.
|
||||
|
||||
Assume JSX appears in the following instances:
|
||||
- Inside parentheses, when returned or as the first argument
|
||||
to a function, and after a newline
|
||||
- When assigned to variables or object properties, but only
|
||||
on a single line
|
||||
- As the N+1th argument to a function
|
||||
|
||||
This is an optimized version of (re-search-backward \"[(,]\n\"
|
||||
nil t), except set point to the end of the match. This logic
|
||||
executes up to the number of lines in the file, so it should be
|
||||
really fast to reduce that impact."
|
||||
(let (pos)
|
||||
(while (and (> (point) (point-min))
|
||||
(not (progn
|
||||
(end-of-line 0)
|
||||
(when (or (eq (char-before) 40) ; (
|
||||
(eq (char-before) 44)) ; ,
|
||||
(setq pos (1- (point))))))))
|
||||
pos))
|
||||
|
||||
(defconst js2--jsx-end-tag-re
|
||||
(concat "</" sgml-name-re ">\\|/>")
|
||||
"Find the end of a JSX element.")
|
||||
|
||||
(defconst js2--jsx-after-tag-re "[),]"
|
||||
"Find where JSX ends.
|
||||
This complements the assumption of where JSX appears from
|
||||
`js--jsx-before-tag-re', which see.")
|
||||
|
||||
(defun js2--jsx-indented-element-p ()
|
||||
"Determine if/how the current line should be indented as JSX.
|
||||
|
||||
Return `first' for the first JSXElement on its own line.
|
||||
Return `nth' for subsequent lines of the first JSXElement.
|
||||
Return `expression' for an embedded JS expression.
|
||||
Return `after' for anything after the last JSXElement.
|
||||
Return nil for non-JSX lines.
|
||||
|
||||
Currently, JSX indentation supports the following styles:
|
||||
|
||||
- Single-line elements (indented like normal JS):
|
||||
|
||||
var element = <div></div>;
|
||||
|
||||
- Multi-line elements (enclosed in parentheses):
|
||||
|
||||
function () {
|
||||
return (
|
||||
<div>
|
||||
<div></div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
- Function arguments:
|
||||
|
||||
React.render(
|
||||
<div></div>,
|
||||
document.querySelector('.root')
|
||||
);"
|
||||
(let ((current-pos (point))
|
||||
(current-line (line-number-at-pos))
|
||||
last-pos
|
||||
before-tag-pos before-tag-line
|
||||
tag-start-pos tag-start-line
|
||||
tag-end-pos tag-end-line
|
||||
after-tag-line
|
||||
parens paren type)
|
||||
(save-excursion
|
||||
(and
|
||||
;; Determine if we're inside a jsx element
|
||||
(progn
|
||||
(end-of-line)
|
||||
(while (and (not tag-start-pos)
|
||||
(setq last-pos (js2--jsx-find-before-tag)))
|
||||
(while (forward-comment 1))
|
||||
(when (= (char-after) 60) ; <
|
||||
(setq before-tag-pos last-pos
|
||||
tag-start-pos (point)))
|
||||
(goto-char last-pos))
|
||||
tag-start-pos)
|
||||
(progn
|
||||
(setq before-tag-line (line-number-at-pos before-tag-pos)
|
||||
tag-start-line (line-number-at-pos tag-start-pos))
|
||||
(and
|
||||
;; A "before" line which also starts an element begins with js, so
|
||||
;; indent it like js
|
||||
(> current-line before-tag-line)
|
||||
;; Only indent the jsx lines like jsx
|
||||
(>= current-line tag-start-line)))
|
||||
(cond
|
||||
;; Analyze bounds if there are any
|
||||
((progn
|
||||
(while (and (not tag-end-pos)
|
||||
(setq last-pos (re-search-forward js2--jsx-end-tag-re nil t)))
|
||||
(while (forward-comment 1))
|
||||
(when (looking-at js2--jsx-after-tag-re)
|
||||
(setq tag-end-pos last-pos)))
|
||||
tag-end-pos)
|
||||
(setq tag-end-line (line-number-at-pos tag-end-pos)
|
||||
after-tag-line (line-number-at-pos after-tag-line))
|
||||
(or (and
|
||||
;; Ensure we're actually within the bounds of the jsx
|
||||
(<= current-line tag-end-line)
|
||||
;; An "after" line which does not end an element begins with
|
||||
;; js, so indent it like js
|
||||
(<= current-line after-tag-line))
|
||||
(and
|
||||
;; Handle another case where there could be e.g. comments after
|
||||
;; the element
|
||||
(> current-line tag-end-line)
|
||||
(< current-line after-tag-line)
|
||||
(setq type 'after))))
|
||||
;; They may not be any bounds (yet)
|
||||
(t))
|
||||
;; Check if we're inside an embedded multi-line js expression
|
||||
(cond
|
||||
((not type)
|
||||
(goto-char current-pos)
|
||||
(end-of-line)
|
||||
(setq parens (nth 9 (syntax-ppss)))
|
||||
(while (and parens (not type))
|
||||
(setq paren (car parens))
|
||||
(cond
|
||||
((and (>= paren tag-start-pos)
|
||||
;; Curly bracket indicates the start of an embedded expression
|
||||
(= (char-after paren) 123) ; {
|
||||
;; The first line of the expression is indented like sgml
|
||||
(> current-line (line-number-at-pos paren))
|
||||
;; Check if within a closing curly bracket (if any)
|
||||
;; (exclusive, as the closing bracket is indented like sgml)
|
||||
(cond
|
||||
((progn
|
||||
(goto-char paren)
|
||||
(ignore-errors (let (forward-sexp-function)
|
||||
(forward-sexp))))
|
||||
(< current-line (line-number-at-pos)))
|
||||
(t)))
|
||||
;; Indicate this guy will be indented specially
|
||||
(setq type 'expression))
|
||||
(t (setq parens (cdr parens)))))
|
||||
t)
|
||||
(t))
|
||||
(cond
|
||||
(type)
|
||||
;; Indent the first jsx thing like js so we can indent future jsx things
|
||||
;; like sgml relative to the first thing
|
||||
((= current-line tag-start-line) 'first)
|
||||
('nth))))))
|
||||
|
||||
(defmacro js2--as-sgml (&rest body)
|
||||
"Execute BODY as if in sgml-mode."
|
||||
`(with-syntax-table sgml-mode-syntax-table
|
||||
(let (forward-sexp-function
|
||||
parse-sexp-lookup-properties)
|
||||
,@body)))
|
||||
|
||||
(defun js2--expression-in-sgml-indent-line ()
|
||||
"Indent the current line as JavaScript or SGML (whichever is farther)."
|
||||
(let* (indent-col
|
||||
(savep (point))
|
||||
;; Don't whine about errors/warnings when we're indenting.
|
||||
;; This has to be set before calling parse-partial-sexp below.
|
||||
(inhibit-point-motion-hooks t)
|
||||
(parse-status (save-excursion
|
||||
(syntax-ppss (point-at-bol)))))
|
||||
;; Don't touch multiline strings.
|
||||
(unless (nth 3 parse-status)
|
||||
(setq indent-col (save-excursion
|
||||
(back-to-indentation)
|
||||
(if (>= (point) savep) (setq savep nil))
|
||||
(js2--as-sgml (sgml-calculate-indent))))
|
||||
(if (null indent-col)
|
||||
'noindent
|
||||
;; Use whichever indentation column is greater, such that the sgml
|
||||
;; column is effectively a minimum
|
||||
(setq indent-col (max (js2-proper-indentation parse-status)
|
||||
(+ indent-col js2-basic-offset)))
|
||||
(if savep
|
||||
(save-excursion (indent-line-to indent-col))
|
||||
(indent-line-to indent-col))))))
|
||||
|
||||
(defun js2-jsx-indent-line ()
|
||||
"Indent the current line as JSX (with SGML offsets).
|
||||
i.e., customize JSX element indentation with `sgml-basic-offset'
|
||||
et al."
|
||||
(interactive)
|
||||
(let ((indentation-type (js2--jsx-indented-element-p)))
|
||||
(cond
|
||||
((eq indentation-type 'expression)
|
||||
(js2--expression-in-sgml-indent-line))
|
||||
((or (eq indentation-type 'first)
|
||||
(eq indentation-type 'after))
|
||||
;; Don't treat this first thing as a continued expression (often a "<" or
|
||||
;; ">" causes this misinterpretation)
|
||||
(cl-letf (((symbol-function #'js2-continued-expression-p) 'ignore))
|
||||
(js2-indent-line)))
|
||||
((eq indentation-type 'nth)
|
||||
(js2--as-sgml (sgml-indent-line)))
|
||||
(t (js2-indent-line)))))
|
||||
|
||||
(provide 'js2-old-indent)
|
||||
|
||||
;;; js2-old-indent.el ends here
|
BIN
elpa/js2-mode-20190815.1327/js2-old-indent.elc
Normal file
BIN
elpa/js2-mode-20190815.1327/js2-old-indent.elc
Normal file
Binary file not shown.
123
elpa/js2-refactor-20190630.2108/js2-refactor-autoloads.el
Normal file
123
elpa/js2-refactor-20190630.2108/js2-refactor-autoloads.el
Normal file
|
@ -0,0 +1,123 @@
|
|||
;;; js2-refactor-autoloads.el --- automatically extracted autoloads
|
||||
;;
|
||||
;;; Code:
|
||||
|
||||
(add-to-list 'load-path (directory-file-name
|
||||
(or (file-name-directory #$) (car load-path))))
|
||||
|
||||
|
||||
;;;### (autoloads nil "js2-refactor" "js2-refactor.el" (0 0 0 0))
|
||||
;;; Generated autoloads from js2-refactor.el
|
||||
|
||||
(autoload 'js2-refactor-mode "js2-refactor" "\
|
||||
Minor mode providing JavaScript refactorings.
|
||||
|
||||
\(fn &optional ARG)" t nil)
|
||||
|
||||
(autoload 'js2r-add-keybindings-with-prefix "js2-refactor" "\
|
||||
Add js2r keybindings using the prefix PREFIX.
|
||||
|
||||
\(fn PREFIX)" nil nil)
|
||||
|
||||
(autoload 'js2r-add-keybindings-with-modifier "js2-refactor" "\
|
||||
Add js2r keybindings using the modifier MODIFIER.
|
||||
|
||||
\(fn MODIFIER)" nil nil)
|
||||
|
||||
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "js2-refactor" '("js2")))
|
||||
|
||||
;;;***
|
||||
|
||||
;;;### (autoloads nil "js2r-conditionals" "js2r-conditionals.el"
|
||||
;;;;;; (0 0 0 0))
|
||||
;;; Generated autoloads from js2r-conditionals.el
|
||||
|
||||
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "js2r-conditionals" '("js2r-ternary-to-if")))
|
||||
|
||||
;;;***
|
||||
|
||||
;;;### (autoloads nil "js2r-conveniences" "js2r-conveniences.el"
|
||||
;;;;;; (0 0 0 0))
|
||||
;;; Generated autoloads from js2r-conveniences.el
|
||||
|
||||
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "js2r-conveniences" '("js2r-" "move-line-")))
|
||||
|
||||
;;;***
|
||||
|
||||
;;;### (autoloads nil "js2r-formatting" "js2r-formatting.el" (0 0
|
||||
;;;;;; 0 0))
|
||||
;;; Generated autoloads from js2r-formatting.el
|
||||
|
||||
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "js2r-formatting" '("js2r-")))
|
||||
|
||||
;;;***
|
||||
|
||||
;;;### (autoloads nil "js2r-functions" "js2r-functions.el" (0 0 0
|
||||
;;;;;; 0))
|
||||
;;; Generated autoloads from js2r-functions.el
|
||||
|
||||
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "js2r-functions" '("js2r-")))
|
||||
|
||||
;;;***
|
||||
|
||||
;;;### (autoloads nil "js2r-helpers" "js2r-helpers.el" (0 0 0 0))
|
||||
;;; Generated autoloads from js2r-helpers.el
|
||||
|
||||
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "js2r-helpers" '("js2r--")))
|
||||
|
||||
;;;***
|
||||
|
||||
;;;### (autoloads nil "js2r-iife" "js2r-iife.el" (0 0 0 0))
|
||||
;;; Generated autoloads from js2r-iife.el
|
||||
|
||||
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "js2r-iife" '("js2r-")))
|
||||
|
||||
;;;***
|
||||
|
||||
;;;### (autoloads nil "js2r-paredit" "js2r-paredit.el" (0 0 0 0))
|
||||
;;; Generated autoloads from js2r-paredit.el
|
||||
|
||||
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "js2r-paredit" '("js2r-")))
|
||||
|
||||
;;;***
|
||||
|
||||
;;;### (autoloads nil "js2r-vars" "js2r-vars.el" (0 0 0 0))
|
||||
;;; Generated autoloads from js2r-vars.el
|
||||
|
||||
(autoload 'js2r-extract-var "js2r-vars" "\
|
||||
|
||||
|
||||
\(fn)" t nil)
|
||||
|
||||
(autoload 'js2r-extract-let "js2r-vars" "\
|
||||
|
||||
|
||||
\(fn)" t nil)
|
||||
|
||||
(autoload 'js2r-extract-const "js2r-vars" "\
|
||||
|
||||
|
||||
\(fn)" t nil)
|
||||
|
||||
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "js2r-vars" '("js2r-" "current-line-contents")))
|
||||
|
||||
;;;***
|
||||
|
||||
;;;### (autoloads nil "js2r-wrapping" "js2r-wrapping.el" (0 0 0 0))
|
||||
;;; Generated autoloads from js2r-wrapping.el
|
||||
|
||||
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "js2r-wrapping" '("js2r-")))
|
||||
|
||||
;;;***
|
||||
|
||||
;;;### (autoloads nil nil ("js2-refactor-pkg.el") (0 0 0 0))
|
||||
|
||||
;;;***
|
||||
|
||||
;; Local Variables:
|
||||
;; version-control: never
|
||||
;; no-byte-compile: t
|
||||
;; no-update-autoloads: t
|
||||
;; coding: utf-8
|
||||
;; End:
|
||||
;;; js2-refactor-autoloads.el ends here
|
10
elpa/js2-refactor-20190630.2108/js2-refactor-pkg.el
Normal file
10
elpa/js2-refactor-20190630.2108/js2-refactor-pkg.el
Normal file
|
@ -0,0 +1,10 @@
|
|||
(define-package "js2-refactor" "20190630.2108" "A JavaScript refactoring library for emacs."
|
||||
'((js2-mode "20101228")
|
||||
(s "1.9.0")
|
||||
(multiple-cursors "1.0.0")
|
||||
(dash "1.0.0")
|
||||
(s "1.0.0")
|
||||
(yasnippet "0.9.0.1")))
|
||||
;; Local Variables:
|
||||
;; no-byte-compile: t
|
||||
;; End:
|
238
elpa/js2-refactor-20190630.2108/js2-refactor.el
Normal file
238
elpa/js2-refactor-20190630.2108/js2-refactor.el
Normal file
|
@ -0,0 +1,238 @@
|
|||
;;; js2-refactor.el --- The beginnings of a JavaScript refactoring library in emacs. -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2012-2014 Magnar Sveen
|
||||
;; Copyright (C) 2015-2016 Magnar Sveen and Nicolas Petton
|
||||
|
||||
;; Author: Magnar Sveen <magnars@gmail.com>,
|
||||
;; Nicolas Petton <nicolas@petton.fr>
|
||||
;; Keywords: conveniences
|
||||
|
||||
;; This program is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation, either version 3 of the License, or
|
||||
;; (at your option) any later version.
|
||||
|
||||
;; This program is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; This is a collection of small refactoring functions to further the idea of a
|
||||
;; JavaScript IDE in Emacs that started with js2-mode.
|
||||
|
||||
;; ## Installation
|
||||
|
||||
;; Start by installing the dependencies:
|
||||
|
||||
;; * js2-mode https://github.com/mooz/js2-mode/
|
||||
;; * dash https://github.com/magnars/dash.el
|
||||
;; * multiple-cursors https://github.com/magnars/multiple-cursors.el
|
||||
|
||||
;; It is also recommended to get
|
||||
;; [expand-region](https://github.com/magnars/expand-region.el) to more easily mark
|
||||
;; vars, method calls and functions for refactorings.
|
||||
|
||||
;; Then add this to your Emacs settings:
|
||||
|
||||
;; (require 'js2-refactor)
|
||||
;; (add-hook 'js2-mode-hook #'js2-refactor-mode)
|
||||
;; (js2r-add-keybindings-with-prefix "C-c C-m")
|
||||
|
||||
;; Note: I am working on a smoother installation path through package.el,
|
||||
;; but I haven't had the time to whip this project into that sort of
|
||||
;; structure - yet.
|
||||
|
||||
;; ## Usage
|
||||
|
||||
;; All refactorings start with `C-c C-m` and then a two-letter mnemonic shortcut.
|
||||
|
||||
;; * `ee` is `expand-node-at-point`: Expand bracketed list according to node type at point (array, object, function, call args).
|
||||
;; * `cc` is `contract-node-at-point`: Contract bracketed list according to node type at point (array, object, function, call args).
|
||||
;; * `ef` is `extract-function`: Extracts the marked expressions out into a new named function.
|
||||
;; * `em` is `extract-method`: Extracts the marked expressions out into a new named method in an object literal.
|
||||
;; * `tf` is `toggle-function-expression-and-declaration`: Toggle between function name() {} and var name = function ();
|
||||
;; * `ta` is `toggle-arrow-function-and-expression`: Toggle between function expression to arrow function.
|
||||
;; * `ts` is `toggle-function-async`: Toggle between an async and a regular function.
|
||||
;; * `ip` is `introduce-parameter`: Changes the marked expression to a parameter in a local function.
|
||||
;; * `lp` is `localize-parameter`: Changes a parameter to a local var in a local function.
|
||||
;; * `wi` is `wrap-buffer-in-iife`: Wraps the entire buffer in an immediately invoked function expression
|
||||
;; * `ig` is `inject-global-in-iife`: Creates a shortcut for a marked global by injecting it in the wrapping immediately invoked function expression
|
||||
;; * `ag` is `add-to-globals-annotation`: Creates a `/*global */` annotation if it is missing, and adds the var at point to it.
|
||||
;; * `ev` is `extract-var`: Takes a marked expression and replaces it with a var.
|
||||
;; * `el` is `extract-var`: Takes a marked expression and replaces it with a let.
|
||||
;; * `ec` is `extract-var`: Takes a marked expression and replaces it with a const.
|
||||
;; * `iv` is `inline-var`: Replaces all instances of a variable with its initial value.
|
||||
;; * `rv` is `rename-var`: Renames the variable on point and all occurrences in its lexical scope.
|
||||
;; * `vt` is `var-to-this`: Changes local `var a` to be `this.a` instead.
|
||||
;; * `ao` is `arguments-to-object`: Replaces arguments to a function call with an object literal of named arguments.
|
||||
;; * `3i` is `ternary-to-if`: Converts ternary operator to if-statement.
|
||||
;; * `sv` is `split-var-declaration`: Splits a `var` with multiple vars declared, into several `var` statements.
|
||||
;; * `ss` is `split-string`: Splits a `string`.
|
||||
;; * `st` is `string-to-template`: Converts a `string` into a template string.
|
||||
;; * `uw` is `unwrap`: Replaces the parent statement with the selected region.
|
||||
;; * `lt` is `log-this`: Adds a console.log() statement for what is at point (or region). With a prefix argument, use JSON pretty-printing.
|
||||
;; * `dt` is `debug-this`: Adds a debug() statement for what is at point (or region).
|
||||
;; * `sl` is `forward-slurp`: Moves the next statement into current function, if-statement, for-loop or while-loop.
|
||||
;; * `ba` is `forward-barf`: Moves the last child out of current function, if-statement, for-loop or while-loop.
|
||||
;; * `k` is `kill`: Kills to the end of the line, but does not cross semantic boundaries.
|
||||
|
||||
;; There are also some minor conveniences bundled:
|
||||
|
||||
;; * `C-S-down` and `C-S-up` moves the current line up or down. If the line is an
|
||||
;; element in an object or array literal, it makes sure that the commas are
|
||||
;; still correctly placed.
|
||||
;; * `k` `kill-line`: Like `kill-line` but respecting the AST.
|
||||
|
||||
;; ## Todo
|
||||
|
||||
;; A list of some wanted improvements for the current refactorings.
|
||||
|
||||
;; * expand- and contract-array: should work recursively with nested object literals and nested arrays.
|
||||
;; * expand- and contract-function: should deal better with nested object literals, array declarations, and statements terminated only by EOLs (without semicolons).
|
||||
;; * wrap-buffer-in-iife: should skip comments and namespace initializations at buffer start.
|
||||
;; * extract-variable: could end with a query-replace of the expression in its scope.
|
||||
|
||||
;; ## Contributions
|
||||
|
||||
;; * [Matt Briggs](https://github.com/mbriggs) contributed `js2r-add-to-globals-annotation`
|
||||
;; * [Alex Chamberlain](https://github.com/apchamberlain) contributed contracting and expanding arrays and functions.
|
||||
;; * [Nicolas Petton](https://github.com/NicolasPetton) contributed `js2r-kill`
|
||||
;; Thanks!
|
||||
|
||||
;; ## Contribute
|
||||
|
||||
;; This project is still in its infancy, and everything isn't quite sorted out
|
||||
;; yet. If you're eager to contribute, please add an issue here on github and we
|
||||
;; can discuss your changes a little before diving into the elisp :-).
|
||||
|
||||
;; To fetch the test dependencies:
|
||||
|
||||
;; $ cd /path/to/multiple-cursors
|
||||
;; $ git submodule init
|
||||
;; $ git submodule update
|
||||
|
||||
;; Run the tests with:
|
||||
|
||||
;; $ ./util/ecukes/ecukes features
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'js2-mode)
|
||||
(require 'js2r-helpers)
|
||||
(require 'js2r-formatting)
|
||||
(require 'js2r-iife)
|
||||
(require 'js2r-vars)
|
||||
(require 'js2r-functions)
|
||||
(require 'js2r-wrapping)
|
||||
(require 'js2r-conditionals)
|
||||
(require 'js2r-conveniences)
|
||||
(require 'js2r-paredit)
|
||||
|
||||
(defvar js2-refactor-mode-map
|
||||
(make-sparse-keymap)
|
||||
"Keymap for js2-refactor.")
|
||||
|
||||
(defvar js2-refactor-keybinding-prefix
|
||||
nil
|
||||
"Store keybinding prefix used by js2-refactor.")
|
||||
|
||||
;;;###autoload
|
||||
(define-minor-mode js2-refactor-mode
|
||||
"Minor mode providing JavaScript refactorings."
|
||||
:lighter " js2r"
|
||||
:keymap js2-refactor-mode-map
|
||||
(when js2-refactor-mode
|
||||
(yas-minor-mode-on)))
|
||||
|
||||
;;; Settings ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(defgroup js2-refactor nil
|
||||
"Minor mode providing JavaScript refactorings."
|
||||
:group 'tools
|
||||
:prefix "js2r-"
|
||||
:link '(url-link :tag "Repository" "https://github.com/magnars/js2-refactor.el"))
|
||||
|
||||
(defcustom js2r-use-strict nil
|
||||
"When non-nil, js2r inserts strict declarations in IIFEs."
|
||||
:group 'js2-refactor
|
||||
:type 'boolean)
|
||||
|
||||
(defcustom js2r-prefered-quote-type 1
|
||||
"The prefered quote style for strings."
|
||||
:group 'js2-refactor
|
||||
:type '(choice (const :tag "Double" 1)
|
||||
(const :tag "Single" 2)))
|
||||
|
||||
(defcustom js2r-always-insert-parens-around-arrow-function-params nil
|
||||
"When non-nil, js2r always inserts parenthesis around arrow function params.
|
||||
This only affects arrow functions with one parameter."
|
||||
:group 'js2-refactor
|
||||
:type 'boolean)
|
||||
|
||||
(defcustom js2r-prefer-let-over-var nil
|
||||
"When non-nil, js2r uses let constructs over var when performing refactorings."
|
||||
:group 'js2-refactor
|
||||
:type 'boolean)
|
||||
|
||||
(defcustom js2r-log-before-point nil
|
||||
"When non-nil, js2r inserts logging and debug statements before point.
|
||||
When nil, logging and debug statements are inserted after point,
|
||||
unless point is in a return statement."
|
||||
:group 'js2-refactor
|
||||
:type 'boolean)
|
||||
|
||||
;;; Keybindings ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(defun js2r--add-keybindings (key-fn)
|
||||
"Add js2r refactoring keybindings to `js2-mode-map' using KEY-FN to create each keybinding."
|
||||
(define-key js2-refactor-mode-map (funcall key-fn "ee") #'js2r-expand-node-at-point)
|
||||
(define-key js2-refactor-mode-map (funcall key-fn "cc") #'js2r-contract-node-at-point)
|
||||
(define-key js2-refactor-mode-map (funcall key-fn "wi") #'js2r-wrap-buffer-in-iife)
|
||||
(define-key js2-refactor-mode-map (funcall key-fn "ig") #'js2r-inject-global-in-iife)
|
||||
(define-key js2-refactor-mode-map (funcall key-fn "ev") #'js2r-extract-var)
|
||||
(define-key js2-refactor-mode-map (funcall key-fn "el") #'js2r-extract-let)
|
||||
(define-key js2-refactor-mode-map (funcall key-fn "ec") #'js2r-extract-const)
|
||||
(define-key js2-refactor-mode-map (funcall key-fn "iv") #'js2r-inline-var)
|
||||
(define-key js2-refactor-mode-map (funcall key-fn "rv") #'js2r-rename-var)
|
||||
(define-key js2-refactor-mode-map (funcall key-fn "vt") #'js2r-var-to-this)
|
||||
(define-key js2-refactor-mode-map (funcall key-fn "ag") #'js2r-add-to-globals-annotation)
|
||||
(define-key js2-refactor-mode-map (funcall key-fn "sv") #'js2r-split-var-declaration)
|
||||
(define-key js2-refactor-mode-map (funcall key-fn "ss") #'js2r-split-string)
|
||||
(define-key js2-refactor-mode-map (funcall key-fn "st") #'js2r-string-to-template)
|
||||
(define-key js2-refactor-mode-map (funcall key-fn "ef") #'js2r-extract-function)
|
||||
(define-key js2-refactor-mode-map (funcall key-fn "em") #'js2r-extract-method)
|
||||
(define-key js2-refactor-mode-map (funcall key-fn "ip") #'js2r-introduce-parameter)
|
||||
(define-key js2-refactor-mode-map (funcall key-fn "lp") #'js2r-localize-parameter)
|
||||
(define-key js2-refactor-mode-map (funcall key-fn "tf") #'js2r-toggle-function-expression-and-declaration)
|
||||
(define-key js2-refactor-mode-map (funcall key-fn "ta") #'js2r-toggle-arrow-function-and-expression)
|
||||
(define-key js2-refactor-mode-map (funcall key-fn "ts") #'js2r-toggle-function-async)
|
||||
(define-key js2-refactor-mode-map (funcall key-fn "ao") #'js2r-arguments-to-object)
|
||||
(define-key js2-refactor-mode-map (funcall key-fn "uw") #'js2r-unwrap)
|
||||
(define-key js2-refactor-mode-map (funcall key-fn "wl") #'js2r-wrap-in-for-loop)
|
||||
(define-key js2-refactor-mode-map (funcall key-fn "3i") #'js2r-ternary-to-if)
|
||||
(define-key js2-refactor-mode-map (funcall key-fn "lt") #'js2r-log-this)
|
||||
(define-key js2-refactor-mode-map (funcall key-fn "dt") #'js2r-debug-this)
|
||||
(define-key js2-refactor-mode-map (funcall key-fn "sl") #'js2r-forward-slurp)
|
||||
(define-key js2-refactor-mode-map (funcall key-fn "ba") #'js2r-forward-barf)
|
||||
(define-key js2-refactor-mode-map (funcall key-fn "k") #'js2r-kill)
|
||||
(define-key js2-refactor-mode-map (kbd "<C-S-down>") #'js2r-move-line-down)
|
||||
(define-key js2-refactor-mode-map (kbd "<C-S-up>") #'js2r-move-line-up))
|
||||
|
||||
;;;###autoload
|
||||
(defun js2r-add-keybindings-with-prefix (prefix)
|
||||
"Add js2r keybindings using the prefix PREFIX."
|
||||
(setq js2-refactor-keybinding-prefix (read-kbd-macro prefix))
|
||||
(js2r--add-keybindings (-partial #'js2r--key-pairs-with-prefix prefix)))
|
||||
|
||||
;;;###autoload
|
||||
(defun js2r-add-keybindings-with-modifier (modifier)
|
||||
"Add js2r keybindings using the modifier MODIFIER."
|
||||
(js2r--add-keybindings (-partial #'js2r--key-pairs-with-modifier modifier)))
|
||||
|
||||
(provide 'js2-refactor)
|
||||
;;; js2-refactor.el ends here
|
BIN
elpa/js2-refactor-20190630.2108/js2-refactor.elc
Normal file
BIN
elpa/js2-refactor-20190630.2108/js2-refactor.elc
Normal file
Binary file not shown.
57
elpa/js2-refactor-20190630.2108/js2r-conditionals.el
Normal file
57
elpa/js2-refactor-20190630.2108/js2r-conditionals.el
Normal file
|
@ -0,0 +1,57 @@
|
|||
;;; js2r-conditionals.el --- Conditional refactoring functions for js2-refactor -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2012-2014 Magnar Sveen
|
||||
;; Copyright (C) 2015-2016 Magnar Sveen and Nicolas Petton
|
||||
|
||||
;; Author: Magnar Sveen <magnars@gmail.com>,
|
||||
;; Nicolas Petton <nicolas@petton.fr>
|
||||
;; Keywords: conveniences
|
||||
|
||||
;; This program is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation, either version 3 of the License, or
|
||||
;; (at your option) any later version.
|
||||
|
||||
;; This program is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 's)
|
||||
|
||||
(require 'js2r-helpers)
|
||||
|
||||
(defun js2r-ternary-to-if ()
|
||||
"Convert a ternary operator to an if-statement."
|
||||
(interactive)
|
||||
(js2r--guard)
|
||||
(js2r--wait-for-parse
|
||||
(save-excursion
|
||||
(let* ((ternary (js2r--closest 'js2-cond-node-p))
|
||||
(test-expr (js2-node-string (js2-cond-node-test-expr ternary)))
|
||||
(true-expr (js2-node-string (js2-cond-node-true-expr ternary)))
|
||||
(false-expr (js2-node-string (js2-cond-node-false-expr ternary)))
|
||||
(stmt (js2-node-parent-stmt ternary))
|
||||
(stmt-pre (buffer-substring (js2-node-abs-pos stmt) (js2-node-abs-pos ternary)))
|
||||
(stmt-post (s-trim (buffer-substring (js2-node-abs-end ternary) (js2-node-abs-end stmt))))
|
||||
(beg (js2-node-abs-pos stmt)))
|
||||
(goto-char beg)
|
||||
(delete-char (js2-node-len stmt))
|
||||
(insert "if (" test-expr ") {")
|
||||
(newline)
|
||||
(insert stmt-pre true-expr stmt-post)
|
||||
(newline)
|
||||
(insert "} else {")
|
||||
(newline)
|
||||
(insert stmt-pre false-expr stmt-post)
|
||||
(newline)
|
||||
(insert "}")
|
||||
(indent-region beg (point))))))
|
||||
|
||||
(provide 'js2r-conditionals)
|
||||
;;; js2r-conditionals ends here
|
BIN
elpa/js2-refactor-20190630.2108/js2r-conditionals.elc
Normal file
BIN
elpa/js2-refactor-20190630.2108/js2r-conditionals.elc
Normal file
Binary file not shown.
242
elpa/js2-refactor-20190630.2108/js2r-conveniences.el
Normal file
242
elpa/js2-refactor-20190630.2108/js2r-conveniences.el
Normal file
|
@ -0,0 +1,242 @@
|
|||
;;; js2r-conveniences.el --- Convenience functions for js2-refactor -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2012-2014 Magnar Sveen
|
||||
;; Copyright (C) 2015-2016 Magnar Sveen and Nicolas Petton
|
||||
|
||||
;; Author: Magnar Sveen <magnars@gmail.com>,
|
||||
;; Nicolas Petton <nicolas@petton.fr>
|
||||
;; Keywords: conveniences
|
||||
|
||||
;; 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:
|
||||
|
||||
;; Convenience functions for logging statements by inserting
|
||||
;; `console.log' statements and moving lines respecting object
|
||||
;; literal syntax.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'js2r-helpers)
|
||||
|
||||
(defun js2r-log-this (arg)
|
||||
"Log of the node at point, adding a 'console.log()' statement.
|
||||
With a prefix argument ARG, use JSON pretty-printing for logging."
|
||||
(interactive "P")
|
||||
(js2r--guard)
|
||||
(js2r--wait-for-parse
|
||||
(let* ((log-info (js2r--figure-out-what-to-log-where))
|
||||
(stmt (car log-info))
|
||||
(pos (cdr log-info)))
|
||||
(save-excursion
|
||||
(goto-char pos)
|
||||
(when (looking-at "[;{]")
|
||||
(forward-char 1))
|
||||
(newline-and-indent)
|
||||
(if arg
|
||||
(progn (insert "console.log(\"" stmt " = \");")
|
||||
(newline-and-indent)
|
||||
(insert "console.dir(" stmt ", { depth:null, colors: true });"))
|
||||
(insert "console.log(\"" stmt " = \", " stmt ");"))))))
|
||||
|
||||
(defun js2r-debug-this ()
|
||||
"Debug the node at point, adding a 'debug()' statement."
|
||||
(interactive)
|
||||
(js2r--guard)
|
||||
(js2r--wait-for-parse
|
||||
(let* ((log-info (js2r--figure-out-what-to-log-where))
|
||||
(stmt (car log-info))
|
||||
(pos (cdr log-info)))
|
||||
(save-excursion
|
||||
(goto-char pos)
|
||||
(when (looking-at "[;{]")
|
||||
(forward-char 1))
|
||||
(newline-and-indent)
|
||||
(insert "debug(" (js2r--wrap-text stmt " = %s") ", " stmt ");")))))
|
||||
|
||||
(defun js2r--figure-out-what-to-log-where ()
|
||||
"Return a dotted pair containing the statement to log and the
|
||||
position where the log should be inserted."
|
||||
(let ((parent-stmt (js2-node-parent-stmt (js2-node-at-point))))
|
||||
|
||||
(if (use-region-p)
|
||||
(cons (buffer-substring (region-beginning) (region-end))
|
||||
(js2r--find-suitable-log-position-around parent-stmt))
|
||||
|
||||
(let* ((node (js2r--name-node-at-point))
|
||||
(parent (js2-node-parent node)))
|
||||
|
||||
(cond
|
||||
|
||||
((js2-function-node-p parent)
|
||||
(cons (js2-name-node-name node)
|
||||
(js2-node-abs-pos (js2-function-node-body parent))))
|
||||
|
||||
((js2-prop-get-node-p parent)
|
||||
(cons (buffer-substring (js2-node-abs-pos parent) (js2-node-abs-end parent))
|
||||
(js2r--find-suitable-log-position-around parent-stmt)))
|
||||
|
||||
(:else
|
||||
(cons (js2-name-node-name node)
|
||||
(js2r--find-suitable-log-position-around parent-stmt))))))))
|
||||
|
||||
(defun js2r--find-suitable-log-position-around (parent-stmt)
|
||||
"Return the position close to PARENT-STMT where the log statement should be inserted."
|
||||
(if (or js2r-log-before-point (js2-return-node-p parent-stmt))
|
||||
(save-excursion
|
||||
(goto-char (js2-node-abs-pos parent-stmt))
|
||||
(skip-chars-backward " \t\n\r") ; Can't use skip-syntax-backward since \n is end-comment
|
||||
(point))
|
||||
(js2-node-abs-end parent-stmt)))
|
||||
|
||||
(defun js2r-split-string ()
|
||||
"Split the string node at point. If the string is already split, join it instead."
|
||||
(interactive)
|
||||
(when (js2r--point-inside-string-p)
|
||||
(let ((delimiter (js2r--string-delimiter (js2-node-at-point))))
|
||||
(if (looking-back " \"")
|
||||
(progn
|
||||
(forward-char -2)
|
||||
(insert " +")
|
||||
(forward-char -2))
|
||||
(if (looking-at (regexp-quote (format "%s + %s" delimiter delimiter)))
|
||||
(delete-char 5)
|
||||
(insert (format "%s + %s" delimiter delimiter)))))))
|
||||
|
||||
(defun js2r-string-to-template ()
|
||||
"Convert the string at point into a template string."
|
||||
(interactive)
|
||||
(let ((node (js2-node-at-point)))
|
||||
(when (js2-string-node-p node)
|
||||
(let* ((start (js2-node-abs-pos node))
|
||||
(end (+ start (js2-node-len node))))
|
||||
(when (memq (char-after start) '(?' ?\"))
|
||||
(save-excursion
|
||||
(goto-char end) (delete-char -1) (insert "`")
|
||||
(goto-char start) (delete-char 1) (insert "`")
|
||||
(perform-replace "`" "\\`" nil nil nil nil nil (1+ start) (1- end))))))))
|
||||
|
||||
(defun js2r--string-delimiter (node)
|
||||
"Return the delimiter character of the string node NODE.
|
||||
It can be a single or double quote."
|
||||
(save-excursion
|
||||
(goto-char (js2-node-abs-pos node))
|
||||
(char-to-string (following-char))))
|
||||
|
||||
(defun move-line-down ()
|
||||
"Move the current line down one line."
|
||||
(interactive)
|
||||
(let ((col (current-column)))
|
||||
(save-excursion
|
||||
(forward-line)
|
||||
(transpose-lines 1))
|
||||
(forward-line)
|
||||
(move-to-column col)))
|
||||
|
||||
(defun move-line-up ()
|
||||
"Move the current line up one line."
|
||||
(interactive)
|
||||
(let ((col (current-column)))
|
||||
(transpose-lines 1)
|
||||
(forward-line -2)
|
||||
(move-to-column col)))
|
||||
|
||||
(defun js2r-move-line-down ()
|
||||
"Move the current line down one line.
|
||||
Make sure commas are placed correctly when moving a line up or
|
||||
down in an object or array literal."
|
||||
(interactive)
|
||||
(if (and (js2r--current-line-is-a-list-item)
|
||||
(js2r--next-line-is-a-list-item))
|
||||
(js2r--move-line-down-as-list-item)
|
||||
(move-line-down))
|
||||
(funcall indent-line-function))
|
||||
|
||||
(defun js2r-move-line-up ()
|
||||
"Move the current line up one line.
|
||||
Make sure commas are placed correctly when moving a line up or
|
||||
down in an object or array literal."
|
||||
(interactive)
|
||||
(if (and (js2r--current-line-is-a-list-item)
|
||||
(js2r--previous-line-is-a-list-item))
|
||||
(js2r--move-line-up-as-list-item)
|
||||
(move-line-up))
|
||||
(funcall indent-line-function))
|
||||
|
||||
(defun js2r--current-line-is-prefixed-with-list-item-start ()
|
||||
"Return whether the current line is prefixed with '{' or '['."
|
||||
(save-excursion
|
||||
(back-to-indentation)
|
||||
(looking-back "\\({\\|\\[\\|,\\)\\(\s\\|\n\\|\t\\)*")))
|
||||
|
||||
(defun js2r--current-line-is-postfixed-with-list-item-end ()
|
||||
"Return whether the current line is postfixed with '{' or '['."
|
||||
(save-excursion
|
||||
(end-of-line)
|
||||
(or (looking-back ",\s*") ; line ends in comma
|
||||
(looking-at "\\(\s\\|\n\\|\t\\)*\\(\\]\\|}\\)"))))
|
||||
|
||||
(defun js2r--current-line-is-a-list-item ()
|
||||
"Return whether the current line contain an array or object literal."
|
||||
(and (js2r--current-line-is-prefixed-with-list-item-start)
|
||||
(js2r--current-line-is-postfixed-with-list-item-end)))
|
||||
|
||||
(defun js2r--next-line-is-a-list-item ()
|
||||
"Return whether the current line contain an array or object literal."
|
||||
(save-excursion
|
||||
(forward-line)
|
||||
(js2r--current-line-is-a-list-item)))
|
||||
|
||||
(defun js2r--previous-line-is-a-list-item ()
|
||||
"Return whether the previous line contain an array or object literal, and only that."
|
||||
(save-excursion
|
||||
(forward-line -1)
|
||||
(js2r--current-line-is-a-list-item)))
|
||||
|
||||
(defun js2r--current-line-has-comma ()
|
||||
"Return whether the current line ends with a comma."
|
||||
(save-excursion
|
||||
(end-of-line)
|
||||
(looking-back ",\s*")))
|
||||
|
||||
(defun js2r--previous-line-has-comma ()
|
||||
"Return whether the previous line ends with a comma."
|
||||
(save-excursion
|
||||
(forward-line -1)
|
||||
(js2r--current-line-has-comma)))
|
||||
|
||||
(defun js2r--move-line-down-as-list-item ()
|
||||
"Move the current line containing a list literal down one line, and also move the comma."
|
||||
(move-line-down)
|
||||
(if (not (js2r--previous-line-has-comma))
|
||||
(save-excursion
|
||||
(end-of-line)
|
||||
(delete-char -1)
|
||||
(forward-line -1)
|
||||
(end-of-line)
|
||||
(insert ","))))
|
||||
|
||||
(defun js2r--move-line-up-as-list-item ()
|
||||
"Move the current line containing a list literal up one line, and also move the comma."
|
||||
(move-line-up)
|
||||
(if (not (js2r--current-line-has-comma))
|
||||
(save-excursion
|
||||
(end-of-line)
|
||||
(insert ",")
|
||||
(forward-line)
|
||||
(end-of-line)
|
||||
(delete-char -1))))
|
||||
|
||||
(provide 'js2r-conveniences)
|
||||
;;; js2r-conveniences.el ends here
|
BIN
elpa/js2-refactor-20190630.2108/js2r-conveniences.elc
Normal file
BIN
elpa/js2-refactor-20190630.2108/js2r-conveniences.elc
Normal file
Binary file not shown.
251
elpa/js2-refactor-20190630.2108/js2r-formatting.el
Normal file
251
elpa/js2-refactor-20190630.2108/js2r-formatting.el
Normal file
|
@ -0,0 +1,251 @@
|
|||
;;; js2r-formatting.el --- Private helper functions for formatting -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2012-2014 Magnar Sveen
|
||||
;; Copyright (C) 2015-2016 Magnar Sveen and Nicolas Petton
|
||||
|
||||
;; Author: Magnar Sveen <magnars@gmail.com>,
|
||||
;; Nicolas Petton <nicolas@petton.fr>
|
||||
;; Keywords: conveniences
|
||||
|
||||
;; This program is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation, either version 3 of the License, or
|
||||
;; (at your option) any later version.
|
||||
|
||||
;; This program is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Code:
|
||||
|
||||
|
||||
(defun js2r--ensure-newline ()
|
||||
(if (and (not (looking-at "\s*\n"))
|
||||
(not (looking-back "\n\s*")))
|
||||
(newline-and-indent)))
|
||||
|
||||
(defun js2r--ensure-just-one-space ()
|
||||
(interactive)
|
||||
(while (or (looking-at "\s*\n")
|
||||
(looking-back "\n\s*"))
|
||||
(when (looking-at "\n")
|
||||
(delete-char 1))
|
||||
(when (looking-back "\n\s")
|
||||
(backward-char)
|
||||
(delete-char -1))
|
||||
(just-one-space))
|
||||
(just-one-space))
|
||||
|
||||
(defmacro js2r--create-bracketed-whitespace-traverser
|
||||
(name ws-fix-func looking-at-start-func
|
||||
goto-closest-start-func subexpr-str)
|
||||
"Build a function to expand or contract a given type of
|
||||
bracketed expression, i.e., function body, object literal, or
|
||||
array (any of which may be nested).
|
||||
Parameters:
|
||||
name: name of the function to be built
|
||||
ws-fix-func: function to adjust whitespace at point
|
||||
looking-at-start-func: returns t if point is at
|
||||
the start of the bracketed
|
||||
thing we want to act on
|
||||
goto-closest-start-func: moves point if necessary
|
||||
until looking-at-start-func
|
||||
is true
|
||||
subexpr-str: literal delimiter of parts of the
|
||||
thing to be expanded or contracted"
|
||||
`(defun ,name ()
|
||||
(interactive)
|
||||
(save-excursion
|
||||
(if (not ,looking-at-start-func)
|
||||
,goto-closest-start-func)
|
||||
(let ((end (make-marker)))
|
||||
(set-marker end (save-excursion
|
||||
(forward-list)
|
||||
(point)))
|
||||
(forward-char)
|
||||
,ws-fix-func
|
||||
(while (< (point) end)
|
||||
(while (js2r--point-inside-string-p)
|
||||
(forward-char))
|
||||
(when (looking-at ,subexpr-str)
|
||||
(forward-char)
|
||||
(unless (js2-comment-node-p (js2-node-at-point))
|
||||
,ws-fix-func))
|
||||
(if (looking-at "\\s(")
|
||||
(forward-list)
|
||||
(forward-char)))
|
||||
(backward-char)
|
||||
,ws-fix-func))))
|
||||
|
||||
(defun js2r--looking-at-object-start ()
|
||||
(and (looking-at "{")
|
||||
(not (looking-back ")[\s\n]*"))))
|
||||
|
||||
(defun js2r--goto-closest-object-start ()
|
||||
(while (not (js2r--looking-at-object-start))
|
||||
(if (eq (car (syntax-ppss)) 0)
|
||||
(error "Cursor is not on an object")
|
||||
(goto-char (nth 1 (syntax-ppss))))))
|
||||
|
||||
(js2r--create-bracketed-whitespace-traverser js2r-expand-object
|
||||
(js2r--ensure-newline)
|
||||
(js2r--looking-at-object-start)
|
||||
(js2r--goto-closest-object-start)
|
||||
",")
|
||||
|
||||
(js2r--create-bracketed-whitespace-traverser js2r-contract-object
|
||||
(js2r--ensure-just-one-space)
|
||||
(js2r--looking-at-object-start)
|
||||
(js2r--goto-closest-object-start)
|
||||
",")
|
||||
|
||||
(defun js2r--looking-at-array-start ()
|
||||
(looking-at "\\["))
|
||||
|
||||
(defun js2r--goto-closest-array-start ()
|
||||
(while (not (js2r--looking-at-array-start))
|
||||
(if (eq (car (syntax-ppss)) 0)
|
||||
(error "Cursor is not on an array")
|
||||
(goto-char (nth 1 (syntax-ppss))))))
|
||||
|
||||
(js2r--create-bracketed-whitespace-traverser js2r-expand-array
|
||||
(js2r--ensure-newline)
|
||||
(js2r--looking-at-array-start)
|
||||
(js2r--goto-closest-array-start)
|
||||
",")
|
||||
|
||||
(js2r--create-bracketed-whitespace-traverser js2r-contract-array
|
||||
(js2r--ensure-just-one-space)
|
||||
(js2r--looking-at-array-start)
|
||||
(js2r--goto-closest-array-start)
|
||||
",")
|
||||
|
||||
;; (defun js2r--looking-at-function-start ()
|
||||
;; (or
|
||||
;; (and (looking-at "{")
|
||||
;; (looking-back
|
||||
;; ;; This horrible-looking regexp is actually pretty simple. It
|
||||
;; ;; matches "function <optional_name> (<optional_parameters,...>)"
|
||||
;; ;; allowing for whitespace. TODO: support Unicode in function and
|
||||
;; ;; parameter names.
|
||||
;; (concat "function[\s\n]*"
|
||||
;; "\\\([a-zA-Z_$][a-zA-Z_$0-9]*[\s\n]*\\\)?"
|
||||
;; "\(\\\([a-zA-Z_$][a-zA-Z_$0-9]*"
|
||||
;; "[\s\n]*,[\s\n]*\\\)*[\s\n]*"
|
||||
;; "\\\([a-zA-Z_$][a-zA-Z_$0-9]*[\s\n]*\\\)*"
|
||||
;; "[\s\n]*\)[\s\n]*")))
|
||||
;; ;; arrow functions
|
||||
;; (and (looking-at "{")
|
||||
;; (looking-back "=>[\s\n]*")
|
||||
;; (not (js2r--point-inside-string-p)))))
|
||||
|
||||
(defun js2r--looking-at-function-start ()
|
||||
"Return non-nil if the point is at the start of a function body."
|
||||
(let* ((node (js2-node-at-point))
|
||||
(parent (js2-node-parent node)))
|
||||
(and (looking-at "{")
|
||||
(js2-block-node-p node)
|
||||
(js2-function-node-p parent))))
|
||||
|
||||
(defun js2r--goto-closest-function-start ()
|
||||
(while (not (js2r--looking-at-function-start))
|
||||
(if (eq (car (syntax-ppss)) 0)
|
||||
(error "Cursor is not on a function body")
|
||||
(goto-char (nth 1 (syntax-ppss))))))
|
||||
|
||||
(js2r--create-bracketed-whitespace-traverser js2r-expand-function
|
||||
(js2r--ensure-newline)
|
||||
(js2r--looking-at-function-start)
|
||||
(js2r--goto-closest-function-start)
|
||||
";")
|
||||
|
||||
;; TODO: It'd be great if js2r-contract-function could recognize
|
||||
;; newlines that are implied statement terminators and insert
|
||||
;; semicolons correctly, but that would probably mean not using the
|
||||
;; same macro as the other "contract" function definitions.
|
||||
(js2r--create-bracketed-whitespace-traverser js2r-contract-function
|
||||
(js2r--ensure-just-one-space)
|
||||
(js2r--looking-at-function-start)
|
||||
(js2r--goto-closest-function-start)
|
||||
";")
|
||||
|
||||
(defun js2r--looking-at-call-start ()
|
||||
(looking-at "("))
|
||||
|
||||
(defun js2r--goto-closest-call-start ()
|
||||
(while (not (js2r--looking-at-call-start))
|
||||
(if (eq (car (syntax-ppss)) 0)
|
||||
(error "Cursor is not on a call")
|
||||
(goto-char (nth 1 (syntax-ppss))))))
|
||||
|
||||
(js2r--create-bracketed-whitespace-traverser js2r-expand-call-args
|
||||
(js2r--ensure-newline)
|
||||
(js2r--looking-at-call-start)
|
||||
(js2r--goto-closest-call-start)
|
||||
",")
|
||||
|
||||
(js2r--create-bracketed-whitespace-traverser js2r-contract-call-args
|
||||
(js2r--ensure-just-one-space)
|
||||
(js2r--looking-at-call-start)
|
||||
(js2r--goto-closest-call-start)
|
||||
",")
|
||||
|
||||
(defun js2r--expand-contract-node-at-point (&optional is-contract)
|
||||
"Expand or contract bracketed list according to node type in point.
|
||||
Currently working on array, object, function and call args node types.
|
||||
With argument, contract closest expression, otherwise expand."
|
||||
(let ((pos (point))
|
||||
(array-start (point-max))
|
||||
(object-start (point-max))
|
||||
(function-start (point-max))
|
||||
(call-start (point-max)))
|
||||
(save-excursion
|
||||
(ignore-errors
|
||||
(js2r--goto-closest-array-start)
|
||||
(setq array-start (- pos (point)))))
|
||||
(save-excursion
|
||||
(ignore-errors
|
||||
(js2r--goto-closest-object-start)
|
||||
(setq object-start (- pos (point)))))
|
||||
(save-excursion
|
||||
(ignore-errors
|
||||
(js2r--goto-closest-function-start)
|
||||
(setq function-start (- pos (point)))))
|
||||
(save-excursion
|
||||
(ignore-errors
|
||||
(js2r--goto-closest-call-start)
|
||||
(setq call-start (- pos (point)))))
|
||||
(setq pos (-min (list array-start object-start function-start call-start)))
|
||||
(when (= pos array-start)
|
||||
(if is-contract
|
||||
(js2r-contract-array)
|
||||
(js2r-expand-array)))
|
||||
(when (= pos object-start)
|
||||
(if is-contract
|
||||
(js2r-contract-object)
|
||||
(js2r-expand-object)))
|
||||
(when (= pos function-start)
|
||||
(if is-contract
|
||||
(js2r-contract-function)
|
||||
(js2r-expand-function)))
|
||||
(when (= pos call-start)
|
||||
(if is-contract
|
||||
(js2r-contract-call-args)
|
||||
(js2r-expand-call-args)))))
|
||||
|
||||
(defun js2r-expand-node-at-point ()
|
||||
"Expand bracketed list according to node type at point."
|
||||
(interactive)
|
||||
(js2r--expand-contract-node-at-point))
|
||||
|
||||
(defun js2r-contract-node-at-point ()
|
||||
"Contract bracketed list according to node type at point."
|
||||
(interactive)
|
||||
(js2r--expand-contract-node-at-point t))
|
||||
|
||||
(provide 'js2r-formatting)
|
||||
;;; js2-formatting.el ends here
|
BIN
elpa/js2-refactor-20190630.2108/js2r-formatting.elc
Normal file
BIN
elpa/js2-refactor-20190630.2108/js2r-formatting.elc
Normal file
Binary file not shown.
537
elpa/js2-refactor-20190630.2108/js2r-functions.el
Normal file
537
elpa/js2-refactor-20190630.2108/js2r-functions.el
Normal file
|
@ -0,0 +1,537 @@
|
|||
;;; js2r-functions.el --- Function manipulation functions for js2-refactor -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2012-2014 Magnar Sveen
|
||||
;; Copyright (C) 2015-2016 Magnar Sveen and Nicolas Petton
|
||||
|
||||
;; Author: Magnar Sveen <magnars@gmail.com>,
|
||||
;; Nicolas Petton <nicolas@petton.fr>
|
||||
;; Keywords: conveniences
|
||||
|
||||
;; This program is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation, either version 3 of the License, or
|
||||
;; (at your option) any later version.
|
||||
|
||||
;; This program is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'dash)
|
||||
(require 'yasnippet)
|
||||
|
||||
(require 'js2r-helpers)
|
||||
|
||||
(defun js2r-localize-parameter ()
|
||||
"Turn parameter into local var in local function."
|
||||
(interactive)
|
||||
(js2r--guard)
|
||||
(js2r--wait-for-parse
|
||||
(if (js2-name-node-p (js2-node-at-point))
|
||||
(js2r--localize-parameter-pull)
|
||||
(js2r--localize-parameter-push))))
|
||||
|
||||
(defun js2r--localize-parameter-push ()
|
||||
(let* ((node (js2-node-at-point))
|
||||
(arg-node (or (js2r--closest-node-where 'js2r--parent-is-call-node node)
|
||||
(error "Place cursor on argument to localize")))
|
||||
(call-node (js2-node-parent arg-node))
|
||||
(value (js2-node-string arg-node))
|
||||
(target (js2-call-node-target call-node))
|
||||
(fn (if (js2-name-node-p target)
|
||||
(js2r--local-fn-from-name-node target)
|
||||
(error "Can only localize parameter for local functions")))
|
||||
(usages (js2r--function-usages fn))
|
||||
(index (car (--keep (when (eq arg-node it) it-index)
|
||||
(js2-call-node-args call-node))))
|
||||
(name (js2-name-node-name (nth index (js2-function-node-params fn)))))
|
||||
(js2r--localize-parameter fn usages index name value)))
|
||||
|
||||
(defun js2r--localize-parameter-pull ()
|
||||
(let* ((name-node (js2-node-at-point))
|
||||
(name (if (js2-name-node-p name-node)
|
||||
(js2-name-node-name name-node)
|
||||
(error "Place cursor on parameter to localize")))
|
||||
(fn (or (js2r--closest-node-where #'js2r--is-local-function name-node)
|
||||
(error "Can only localize parameter in local functions")))
|
||||
(index (or (js2r--param-index-for name fn)
|
||||
(error "%S isn't a parameter to this function" name)))
|
||||
(usages (js2r--function-usages fn))
|
||||
(examples (-distinct (--map (js2r--argument index it) usages)))
|
||||
(value (js2r--choose-one "Value: " examples)))
|
||||
(js2r--localize-parameter fn usages index name value)))
|
||||
|
||||
(defun js2r--localize-parameter (fn usages index name value)
|
||||
(save-excursion
|
||||
(js2r--goto-fn-body-beg fn)
|
||||
(save-excursion
|
||||
(--each usages (js2r--remove-argument-at-index index it)))
|
||||
(newline-and-indent)
|
||||
(insert "var " name " = " value ";")
|
||||
(js2r--remove-parameter-at-index index fn)))
|
||||
|
||||
(defun js2r--parent-is-call-node (node)
|
||||
(js2-call-node-p (js2-node-parent node)))
|
||||
|
||||
(defun js2r--local-fn-from-name-node (name-node)
|
||||
(->> name-node
|
||||
(js2r--local-usages-of-name-node)
|
||||
(-map #'js2-node-parent)
|
||||
(-first #'js2-function-node-p)))
|
||||
|
||||
(defun js2r--param-index-for (name fn)
|
||||
(car (--keep (when (equal name (js2-name-node-name it)) it-index)
|
||||
(js2-function-node-params fn))))
|
||||
|
||||
(defun js2r--argument (index call-node)
|
||||
(js2-node-string (nth index (js2-call-node-args call-node))))
|
||||
|
||||
(defun js2r--remove-parameter-at-index (index fn)
|
||||
(js2r--delete-node-in-params (nth index (js2-function-node-params fn))))
|
||||
|
||||
(defun js2r--remove-argument-at-index (index call-node)
|
||||
(js2r--delete-node-in-params (nth index (js2-call-node-args call-node))))
|
||||
|
||||
(defun js2r--delete-node-in-params (node)
|
||||
(goto-char (js2-node-abs-pos node))
|
||||
(delete-char (js2-node-len node))
|
||||
(if (and (looking-back "(")
|
||||
(looking-at ", "))
|
||||
(delete-char 2)
|
||||
(when (looking-back ", ")
|
||||
(delete-char -2))))
|
||||
|
||||
(defun js2r--choose-one (prompt options)
|
||||
(when options
|
||||
(if (cdr options)
|
||||
(completing-read prompt options)
|
||||
(car options))))
|
||||
|
||||
(defun js2r-introduce-parameter ()
|
||||
"Introduce a parameter in a local function."
|
||||
(interactive)
|
||||
(js2r--guard)
|
||||
(js2r--wait-for-parse
|
||||
(if (use-region-p)
|
||||
(js2r--introduce-parameter-between (region-beginning) (region-end))
|
||||
(let ((node (js2r--closest-extractable-node)))
|
||||
(js2r--introduce-parameter-between (js2-node-abs-pos node)
|
||||
(js2-node-abs-end node))))))
|
||||
|
||||
(defun js2r--introduce-parameter-between (beg end)
|
||||
(unless (js2r--single-complete-expression-between-p beg end)
|
||||
(error "Can only introduce single, complete expressions as parameter"))
|
||||
|
||||
(let ((fn (js2r--closest-node-where #'js2r--is-local-function (js2-node-at-point))))
|
||||
(unless fn
|
||||
(error "Can only introduce parameter in local functions"))
|
||||
(save-excursion
|
||||
(let ((name (read-string "Parameter name: "))
|
||||
(val (buffer-substring beg end))
|
||||
(usages (js2r--function-usages fn)))
|
||||
(goto-char beg)
|
||||
(save-excursion
|
||||
(-each usages (-partial #'js2r--add-parameter val)))
|
||||
(delete-char (- end beg))
|
||||
(insert name)
|
||||
(js2r--add-parameter name fn)
|
||||
(query-replace val name nil (js2-node-abs-pos fn) (js2r--fn-body-end fn))))))
|
||||
|
||||
(defun js2r--function-usages (fn)
|
||||
(-map #'js2-node-parent (js2r--function-usages-name-nodes fn)))
|
||||
|
||||
(defun js2r--function-usages-name-nodes (fn)
|
||||
(let ((name-node (or (js2-function-node-name fn)
|
||||
(js2-var-init-node-target (js2-node-parent fn)))))
|
||||
(remove name-node (js2r--local-usages-of-name-node name-node))))
|
||||
|
||||
(defun js2r--add-parameter (name node)
|
||||
(save-excursion
|
||||
(js2r--goto-closing-paren node)
|
||||
(unless (looking-back "(")
|
||||
(insert ", "))
|
||||
(insert name)))
|
||||
|
||||
(defun js2r--goto-closing-paren (node)
|
||||
(goto-char (js2-node-abs-pos node))
|
||||
(search-forward "(")
|
||||
(forward-char -1)
|
||||
(forward-list)
|
||||
(forward-char -1))
|
||||
|
||||
(defun js2r--goto-fn-body-beg (fn)
|
||||
(goto-char (js2-node-abs-pos fn))
|
||||
(search-forward "{"))
|
||||
|
||||
(defun js2r--fn-body-end (fn)
|
||||
(save-excursion
|
||||
(js2r--goto-fn-body-beg fn)
|
||||
(forward-char -1)
|
||||
(forward-list)
|
||||
(point)))
|
||||
|
||||
(defun js2r--is-local-function (node)
|
||||
(or (js2r--is-var-function-expression node)
|
||||
(js2r--is-function-declaration node)))
|
||||
|
||||
(defun js2r--is-method (node)
|
||||
(and (js2-function-node-p node)
|
||||
(js2-object-prop-node-p (js2-node-parent node))))
|
||||
|
||||
(defun js2r--is-var-function-expression (node)
|
||||
(and (js2-function-node-p node)
|
||||
(js2-var-init-node-p (js2-node-parent node))))
|
||||
|
||||
(defun js2r--is-assigned-function-expression (node)
|
||||
(and (js2-function-node-p node)
|
||||
(js2-assign-node-p (js2-node-parent node))))
|
||||
|
||||
(defun js2r--is-function-declaration (node)
|
||||
(let ((parent (js2-node-parent node)))
|
||||
(and (js2-function-node-p node)
|
||||
(not (js2-assign-node-p parent))
|
||||
(not (js2-var-init-node-p parent))
|
||||
(not (js2-object-prop-node-p parent)))))
|
||||
|
||||
(defun js2r-arguments-to-object ()
|
||||
"Change from a list of arguments to a parameter object."
|
||||
(interactive)
|
||||
(js2r--guard)
|
||||
(js2r--wait-for-parse
|
||||
(let ((node (js2-node-at-point)))
|
||||
(unless (and (looking-at "(")
|
||||
(or (js2-function-node-p node)
|
||||
(js2-call-node-p node)
|
||||
(js2-new-node-p node)))
|
||||
(error "Place point right before the opening paren in the call or function"))
|
||||
|
||||
(-when-let* ((target (js2r--node-target node))
|
||||
(fn (and (js2-name-node-p target)
|
||||
(js2r--local-fn-from-name-node target))))
|
||||
(setq node fn))
|
||||
(if (js2-function-node-p node)
|
||||
(js2r--arguments-to-object-for-function node)
|
||||
(js2r--arguments-to-object-for-args-with-unknown-function (js2r--node-args node))))))
|
||||
|
||||
(defun js2r--arguments-to-object-for-function (function-node)
|
||||
(let ((params (js2-function-node-params function-node)))
|
||||
(when (null params)
|
||||
(error "No params to convert"))
|
||||
(save-excursion
|
||||
(js2r--execute-changes
|
||||
(-concat
|
||||
;; change parameter list to just (params)
|
||||
(list
|
||||
(list :beg (+ (js2-node-abs-pos function-node) (js2-function-node-lp function-node))
|
||||
:end (+ (js2-node-abs-pos function-node) (js2-function-node-rp function-node) 1)
|
||||
:contents "(params)"))
|
||||
|
||||
;; add params. in front of function local param usages
|
||||
(let* ((local-param-name-nodes (--mapcat (-> it
|
||||
(js2-node-abs-pos)
|
||||
(js2r--local-name-node-at-point)
|
||||
(js2r--local-usages-of-name-node))
|
||||
params))
|
||||
(local-param-name-usages (--remove (js2-function-node-p (js2-node-parent it))
|
||||
local-param-name-nodes))
|
||||
(local-param-name-positions (-map #'js2-node-abs-pos local-param-name-usages)))
|
||||
(--map
|
||||
(list :beg it :end it :contents "params.")
|
||||
local-param-name-positions))
|
||||
|
||||
;; update usages of function
|
||||
(let ((names (-map #'js2-name-node-name params))
|
||||
(usages (js2r--function-usages function-node)))
|
||||
(--map
|
||||
(js2r--changes/arguments-to-object it names)
|
||||
usages)))))))
|
||||
|
||||
(defun js2r--changes/arguments-to-object (node names)
|
||||
(let ((args (js2r--node-args node)))
|
||||
(list :beg (+ (js2-node-abs-pos node) (js2r--node-lp node))
|
||||
:end (+ (js2-node-abs-pos node) (js2r--node-rp node) 1)
|
||||
:contents (js2r--create-object-with-arguments names args))))
|
||||
|
||||
(defun js2r--arguments-to-object-for-args-with-unknown-function (args)
|
||||
(when (null args)
|
||||
(error "No arguments to convert"))
|
||||
(let ((names (--map-indexed
|
||||
(format "${%d:%s}"
|
||||
(1+ it-index)
|
||||
(if (js2-name-node-p it)
|
||||
(js2-name-node-name it)
|
||||
"key"))
|
||||
args)))
|
||||
(yas-expand-snippet (js2r--create-object-with-arguments names args)
|
||||
(point)
|
||||
(save-excursion (forward-list) (point)))))
|
||||
|
||||
(defun js2r--create-object-with-arguments (names args)
|
||||
(let (arg key result)
|
||||
(--dotimes (length args)
|
||||
(setq arg (nth it args))
|
||||
(setq key (nth it names))
|
||||
(setq result
|
||||
(concat result
|
||||
(format " %s: %s,\n"
|
||||
key
|
||||
(buffer-substring (js2-node-abs-pos arg)
|
||||
(js2-node-abs-end arg))))))
|
||||
(concat "({\n" (substring result 0 -2) "\n})")))
|
||||
|
||||
(defun js2r-extract-function (name)
|
||||
"Extract a function from the closest statement expression from the point."
|
||||
(interactive "sName of new function: ")
|
||||
(js2r--extract-fn
|
||||
name
|
||||
(lambda ()
|
||||
(unless (js2r--looking-at-function-declaration)
|
||||
(goto-char (js2-node-abs-pos (js2r--closest #'js2-expr-stmt-node-p)))))
|
||||
"%s(%s);"
|
||||
"function %s(%s) {\n%s\n}\n\n"))
|
||||
|
||||
(defun js2r-extract-method (name)
|
||||
"Extract a method from the closest statement expression from the point."
|
||||
(interactive "sName of new method: ")
|
||||
(let ((class-node (js2r--closest #'js2-class-node-p)))
|
||||
(js2r--extract-fn
|
||||
name
|
||||
(unless class-node
|
||||
(lambda ()
|
||||
(goto-char (js2-node-abs-pos (js2r--closest #'js2-object-prop-node-p)))))
|
||||
"this.%s(%s);"
|
||||
(if class-node
|
||||
"%s(%s) {\n%s\n}\n\n"
|
||||
"%s: function (%s) {\n%s\n},\n\n"))))
|
||||
|
||||
(defun js2r--extract-fn (name goto-position call-template function-template)
|
||||
(js2r--guard)
|
||||
(js2r--wait-for-parse
|
||||
(unless (use-region-p)
|
||||
(error "Mark the expressions to extract first"))
|
||||
(save-excursion
|
||||
(let* ((parent (js2r--first-common-ancestor-in-region (region-beginning) (region-end)))
|
||||
(block (js2r--closest-node-where #'js2-block-node-p parent))
|
||||
(fn (js2r--closest-node-where #'js2-function-node-p block))
|
||||
(exprs (js2r--marked-expressions-in-block block))
|
||||
(vars (-mapcat #'js2r--name-node-decendants exprs))
|
||||
(local (--filter (js2r--local-to-fn-p fn it) vars))
|
||||
(names (-distinct (-map 'js2-name-node-name local)))
|
||||
(declared-in-exprs (-map #'js2r--var-init-node-target-name (-mapcat #'js2r--var-init-node-decendants exprs)))
|
||||
(outside-exprs (-difference (js2-block-node-kids block) exprs))
|
||||
(outside-var-uses (-map #'js2-name-node-name (-mapcat #'js2r--name-node-decendants outside-exprs)))
|
||||
(declared-in-but-used-outside (-intersection declared-in-exprs outside-var-uses))
|
||||
(export-var (car declared-in-but-used-outside))
|
||||
(params (-difference names declared-in-exprs))
|
||||
(params-string (mapconcat #'identity (reverse params) ", "))
|
||||
(first (car exprs))
|
||||
(last (car (last exprs)))
|
||||
(beg (js2-node-abs-pos (car exprs)))
|
||||
(end (js2-node-abs-end last))
|
||||
(contents (buffer-substring beg end)))
|
||||
(goto-char beg)
|
||||
(delete-region beg end)
|
||||
(when (js2-return-node-p last)
|
||||
(insert "return "))
|
||||
(when export-var
|
||||
(setq contents (concat contents "\nreturn " export-var ";"))
|
||||
(insert "var " export-var " = "))
|
||||
(insert (format call-template name params-string))
|
||||
(goto-char (js2-node-abs-pos fn))
|
||||
(when goto-position (funcall goto-position))
|
||||
(let ((start (point)))
|
||||
(insert (format function-template name params-string contents))
|
||||
(indent-region start (1+ (point))))))))
|
||||
|
||||
(defun js2r--var-init-node-target-name (node)
|
||||
(js2-name-node-name
|
||||
(js2-var-init-node-target node)))
|
||||
|
||||
(defun js2r--function-around-region ()
|
||||
(or
|
||||
(js2r--closest-node-where #'js2-function-node-p
|
||||
(js2r--first-common-ancestor-in-region
|
||||
(region-beginning)
|
||||
(region-end)))
|
||||
(error "This only works when you mark stuff inside a function")))
|
||||
|
||||
(defun js2r--marked-expressions-in-block (fn)
|
||||
(-select #'js2r--node-is-marked (js2-block-node-kids fn)))
|
||||
|
||||
(defun js2r--node-is-marked (node)
|
||||
(and
|
||||
(<= (region-beginning) (js2-node-abs-end node))
|
||||
(>= (region-end) (js2-node-abs-pos node))))
|
||||
|
||||
(defun js2r--name-node-decendants (node)
|
||||
(-select #'js2-name-node-p (js2r--decendants node)))
|
||||
|
||||
(defun js2r--var-init-node-decendants (node)
|
||||
(-select #'js2-var-init-node-p (js2r--decendants node)))
|
||||
|
||||
(defun js2r--decendants (node)
|
||||
(let (vars)
|
||||
(js2-visit-ast node
|
||||
(lambda (node end-p)
|
||||
(unless end-p
|
||||
(setq vars (cons node vars)))))
|
||||
vars))
|
||||
|
||||
(defun js2r--local-to-fn-p (fn name-node)
|
||||
(let* ((name (js2-name-node-name name-node))
|
||||
(scope (js2-node-get-enclosing-scope name-node))
|
||||
(scope (js2-get-defining-scope scope name)))
|
||||
(eq fn scope)))
|
||||
|
||||
|
||||
(defun js2r-toggle-arrow-function-and-expression ()
|
||||
"Toggle between function expression to arrow function."
|
||||
(interactive)
|
||||
(save-excursion
|
||||
(js2r--find-closest-function)
|
||||
(cond ((js2r--arrow-function-p)
|
||||
(js2r--transform-arrow-function-to-expression))
|
||||
((and (js2r--function-start-p) (not (js2r--looking-at-function-declaration)))
|
||||
(js2r--transform-function-expression-to-arrow))
|
||||
(t (error "Can only toggle between function expressions and arrow function")))))
|
||||
|
||||
|
||||
;; Toggle between function name() {} and var name = function ();
|
||||
|
||||
(defun js2r-toggle-function-expression-and-declaration ()
|
||||
(interactive)
|
||||
(save-excursion
|
||||
(js2r--find-closest-function)
|
||||
(cond
|
||||
((js2r--looking-at-var-function-expression)
|
||||
(when (js2r--arrow-function-p) (js2r--transform-arrow-function-to-expression))
|
||||
(js2r--transform-function-expression-to-declaration))
|
||||
((js2r--looking-at-function-declaration)
|
||||
(js2r--transform-function-declaration-to-expression))
|
||||
(t (error "Can only toggle between function declarations and free standing function expressions")))))
|
||||
|
||||
|
||||
(defun js2r--arrow-function-p ()
|
||||
(interactive)
|
||||
(save-excursion
|
||||
(ignore-errors
|
||||
(js2r--find-closest-function)
|
||||
(and (looking-at "(?[,[:space:][:word:]]*)?[[:space:]]*=>")
|
||||
(not (js2r--point-inside-string-p))))))
|
||||
|
||||
(defun js2r--transform-arrow-function-to-expression ()
|
||||
(when (js2r--arrow-function-p)
|
||||
(let (has-parenthesis)
|
||||
(save-excursion
|
||||
(js2r--find-closest-function)
|
||||
(let ((end (make-marker)))
|
||||
(save-excursion
|
||||
(search-forward "=>")
|
||||
(set-marker end (js2-node-abs-end (js2-node-at-point))))
|
||||
(setq has-parenthesis (looking-at "\\s-*("))
|
||||
(insert "function ")
|
||||
(if has-parenthesis
|
||||
(forward-list)
|
||||
(insert "("))
|
||||
(search-forward "=>")
|
||||
(delete-char -2)
|
||||
(js2r--ensure-just-one-space)
|
||||
(unless has-parenthesis
|
||||
(backward-char 1)
|
||||
(insert ")"))
|
||||
(unless (looking-at "\\s-*{")
|
||||
(js2r--ensure-just-one-space)
|
||||
(insert "{ return ")
|
||||
(js2r--ensure-just-one-space)
|
||||
(goto-char (marker-position end))
|
||||
(insert "; }")))))))
|
||||
|
||||
(defun js2r--transform-function-expression-to-arrow ()
|
||||
(when (not (js2r--arrow-function-p))
|
||||
(save-excursion
|
||||
(js2r--find-closest-function)
|
||||
(let ((pos (point))
|
||||
(params
|
||||
(js2-function-node-params (js2-node-at-point)))
|
||||
parenthesis-start
|
||||
parenthesis-end)
|
||||
(when (js2r--looking-at-function-declaration)
|
||||
(error "Can not convert function declarations to arrow function"))
|
||||
(search-forward "(")
|
||||
(backward-char 1)
|
||||
(delete-region pos (point))
|
||||
(setq parenthesis-start (point))
|
||||
(forward-list)
|
||||
(setq parenthesis-end (point))
|
||||
(insert " => ")
|
||||
(js2r--ensure-just-one-space)
|
||||
(when (and (= 1 (length params))
|
||||
(not js2r-always-insert-parens-around-arrow-function-params))
|
||||
(goto-char parenthesis-end)
|
||||
(backward-delete-char 1)
|
||||
(goto-char parenthesis-start)
|
||||
(delete-char 1))))))
|
||||
|
||||
|
||||
(defun js2r--function-start-p()
|
||||
(let* ((fn (js2r--closest #'js2-function-node-p)))
|
||||
(and fn
|
||||
(= (js2-node-abs-pos fn) (point)))))
|
||||
|
||||
(defun js2r--find-closest-function ()
|
||||
(when (not (js2r--function-start-p))
|
||||
(let* ((fn (js2r--closest #'js2-function-node-p)))
|
||||
(goto-char (js2-node-abs-pos fn)))))
|
||||
|
||||
(defun js2r--looking-at-method ()
|
||||
(and (js2r--function-start-p)
|
||||
(looking-back ": ?")))
|
||||
|
||||
(defun js2r--looking-at-function-declaration ()
|
||||
(and (js2r--function-start-p)
|
||||
(looking-back "^ *")))
|
||||
|
||||
(defun js2r--looking-at-var-function-expression ()
|
||||
(and (js2r--function-start-p)
|
||||
(looking-back "^ *var[\s\n]*[a-z_$]+[\s\n]*=[\s\n]*")))
|
||||
|
||||
(defun js2r--transform-function-expression-to-declaration ()
|
||||
(when (js2r--looking-at-var-function-expression)
|
||||
(delete-char 9)
|
||||
(forward-list)
|
||||
(forward-list)
|
||||
(delete-char 1)
|
||||
(backward-list)
|
||||
(backward-list)
|
||||
(delete-backward-char 3)
|
||||
(back-to-indentation)
|
||||
(delete-char 4)
|
||||
(insert "function ")))
|
||||
|
||||
(defun js2r--transform-function-declaration-to-expression ()
|
||||
(when (js2r--looking-at-function-declaration)
|
||||
(delete-char 9)
|
||||
(insert "var ")
|
||||
(search-forward "(")
|
||||
(backward-char 1)
|
||||
(insert " = function ")
|
||||
(forward-list)
|
||||
(forward-list)
|
||||
(insert ";")))
|
||||
|
||||
(defun js2r-toggle-function-async ()
|
||||
"Toggle the innermost function from sync to async."
|
||||
(interactive)
|
||||
(save-excursion
|
||||
(js2r--find-closest-function)
|
||||
(if (looking-back "async[[:space:]\n]+")
|
||||
(delete-region (match-beginning 0) (match-end 0))
|
||||
(insert "async "))))
|
||||
|
||||
(provide 'js2r-functions)
|
||||
;;; js2-functions.el ends here
|
BIN
elpa/js2-refactor-20190630.2108/js2r-functions.elc
Normal file
BIN
elpa/js2-refactor-20190630.2108/js2r-functions.elc
Normal file
Binary file not shown.
220
elpa/js2-refactor-20190630.2108/js2r-helpers.el
Normal file
220
elpa/js2-refactor-20190630.2108/js2r-helpers.el
Normal file
|
@ -0,0 +1,220 @@
|
|||
;;; js2r-helpers.el --- Private helper functions for js2-refactor -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2012-2014 Magnar Sveen
|
||||
;; Copyright (C) 2015-2016 Magnar Sveen and Nicolas Petton
|
||||
|
||||
;; Author: Magnar Sveen <magnars@gmail.com>,
|
||||
;; Nicolas Petton <nicolas@petton.fr>
|
||||
;; Keywords: conveniences
|
||||
|
||||
;; This program is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation, either version 3 of the License, or
|
||||
;; (at your option) any later version.
|
||||
|
||||
;; This program is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'dash)
|
||||
(require 's)
|
||||
(require 'js2-mode)
|
||||
|
||||
(defmacro js2r--wait-for-parse (&rest body)
|
||||
"Evaluate BODY once the current buffer has been parsed."
|
||||
`(js2-mode-wait-for-parse (lambda () ,@body)))
|
||||
|
||||
(defun js2r--wrap-text (&rest text)
|
||||
"Wrap TEXT with the prefered quotes. The prefered quotes is set with `js2r-prefered-quote-type'."
|
||||
(let ((prefered-quotes "\""))
|
||||
(when (= 2 js2r-prefered-quote-type)
|
||||
(setq prefered-quotes "'"))
|
||||
(concat prefered-quotes (apply 'concat text) prefered-quotes)))
|
||||
|
||||
(defun js2r--fix-special-modifier-combinations (key)
|
||||
(case key
|
||||
("C-s-i" "s-TAB")
|
||||
("C-s-m" "s-RET")
|
||||
(otherwise key)))
|
||||
|
||||
(defun js2r--key-pairs-with-modifier (modifier keys)
|
||||
(->> (string-to-list keys)
|
||||
(--map (js2r--fix-special-modifier-combinations
|
||||
(concat modifier (char-to-string it))))
|
||||
(s-join " ")
|
||||
(read-kbd-macro)))
|
||||
|
||||
(defun js2r--key-pairs-with-prefix (prefix keys)
|
||||
(read-kbd-macro (concat prefix " " keys)))
|
||||
|
||||
(defun js2r--guard ()
|
||||
(when js2-parsed-errors
|
||||
(error "Can't refactor while buffer has parse errors")))
|
||||
|
||||
(defun js2r--current-quotes-char ()
|
||||
"The char that is the current quote delimiter"
|
||||
(nth 3 (syntax-ppss)))
|
||||
|
||||
(defalias 'js2r--point-inside-string-p 'js2r--current-quotes-char)
|
||||
|
||||
(defun js2r--closest-node-where (p node)
|
||||
(if (or (null node)
|
||||
(apply p node nil))
|
||||
node
|
||||
(js2r--closest-node-where p (js2-node-parent node))))
|
||||
|
||||
(defun js2r--closest (p)
|
||||
(save-excursion
|
||||
(cond
|
||||
((bolp) (back-to-indentation))
|
||||
((looking-at ";") (forward-char -1))
|
||||
((looking-back ";") (forward-char -2))
|
||||
((looking-back "}") (forward-char -1)))
|
||||
(js2r--closest-node-where p (js2-node-at-point))))
|
||||
|
||||
(defun js2r--goto-and-delete-node (node)
|
||||
(goto-char (js2-node-abs-pos node))
|
||||
(delete-char (js2-node-len node)))
|
||||
|
||||
|
||||
(defun js2r--path-to-root (node)
|
||||
(when node
|
||||
(cons node (js2r--path-to-root (js2-node-parent node)))))
|
||||
|
||||
(defun js2r--first-common-ancestor (node1 node2)
|
||||
(if (eq node1 node2)
|
||||
node1
|
||||
(let ((path1 (reverse (js2r--path-to-root node1)))
|
||||
(path2 (reverse (js2r--path-to-root node2)))
|
||||
(last-common nil))
|
||||
(while (eq (car path1) (car path2))
|
||||
(setq last-common (car path1))
|
||||
(setq path1 (cdr path1))
|
||||
(setq path2 (cdr path2)))
|
||||
last-common)))
|
||||
|
||||
(defun js2r--first-common-ancestor-in-region (beg end)
|
||||
(js2r--first-common-ancestor (js2-node-at-point beg)
|
||||
(js2-node-at-point end)))
|
||||
|
||||
;; abstract away node type on some common property getters
|
||||
(defun js2r--node-target (node)
|
||||
(cond
|
||||
((js2-call-node-p node) (js2-call-node-target node))
|
||||
((js2-new-node-p node) (js2-new-node-target node))
|
||||
(:else nil)))
|
||||
|
||||
(defun js2r--node-args (node)
|
||||
(cond
|
||||
((js2-call-node-p node) (js2-call-node-args node))
|
||||
((js2-new-node-p node) (js2-new-node-args node))
|
||||
(:else nil)))
|
||||
|
||||
(defun js2r--node-lp (node)
|
||||
(cond
|
||||
((js2-call-node-p node) (js2-call-node-lp node))
|
||||
((js2-new-node-p node) (js2-new-node-lp node))
|
||||
(:else nil)))
|
||||
|
||||
(defun js2r--node-rp (node)
|
||||
(cond
|
||||
((js2-call-node-p node) (js2-call-node-rp node))
|
||||
((js2-new-node-p node) (js2-new-node-rp node))
|
||||
(:else nil)))
|
||||
|
||||
(defun js2r--node-kids (node)
|
||||
(cond
|
||||
((js2-function-node-p node) (js2-block-node-kids (js2-function-node-body node)))
|
||||
((js2-if-node-p node) (js2-scope-kids (js2-if-node-then-part node)))
|
||||
((js2-for-node-p node) (js2-block-node-kids (js2-for-node-body node)))
|
||||
((js2-while-node-p node) (js2-block-node-kids (js2-while-node-body node)))))
|
||||
|
||||
;; finding expressions and arguments
|
||||
|
||||
(defun js2r--closest-extractable-node ()
|
||||
"Return the most appropriate node the be extracted into a variable or paramter.
|
||||
Lookup the closest expression node from the point, or the closest literal node instead.
|
||||
If no node is found, signal an error."
|
||||
(or (or (js2r--closest #'js2r--expression-p)
|
||||
(js2r--closest #'js2r--literal-node-p))
|
||||
(error "Cannot perform refactoring: Nothing to extract at point")))
|
||||
|
||||
(defun js2r--closest-stmt-node ()
|
||||
"Return the closest standalone statement node.
|
||||
Special care is taken for if branch nodes: if a statement node is
|
||||
part of an if branch node (like 'else if' nodes), return the
|
||||
parent node."
|
||||
(let* ((node (js2-node-parent-stmt (js2-node-at-point)))
|
||||
(parent (js2-node-parent node)))
|
||||
(if (and (js2-if-node-p node)
|
||||
(js2-if-node-p parent))
|
||||
parent
|
||||
node)))
|
||||
|
||||
(defun js2r--argument-p (node)
|
||||
(let ((parent (js2-node-parent node)))
|
||||
(and (js2-call-node-p parent)
|
||||
(member node (js2-call-node-args parent)))))
|
||||
|
||||
(defun js2r--expression-p (node)
|
||||
(or (js2-call-node-p node)
|
||||
(js2r--argument-p node)
|
||||
(and (js2-prop-get-node-p node)
|
||||
(not (js2-call-node-p (js2-node-parent node))))))
|
||||
|
||||
(defun js2r--literal-node-p (node)
|
||||
(or (js2-object-node-p node)
|
||||
(js2-string-node-p node)
|
||||
(js2-number-node-p node)
|
||||
(js2r--boolean-node-p node)))
|
||||
|
||||
(defun js2r--boolean-node-p (node)
|
||||
(let* ((beg (js2-node-abs-pos node))
|
||||
(end (js2-node-abs-end node))
|
||||
(content (buffer-substring beg end)))
|
||||
(and (js2-keyword-node-p node)
|
||||
(member content '("true" "false")))))
|
||||
|
||||
(defun js2r--single-complete-expression-between-p (beg end)
|
||||
(let ((ancestor (js2r--first-common-ancestor-in-region beg (- end 1))))
|
||||
(and (= beg (js2-node-abs-pos ancestor))
|
||||
(= end (js2-node-abs-end ancestor)))))
|
||||
|
||||
|
||||
;; executing a list of changes
|
||||
;; ensures changes are executed from last to first
|
||||
|
||||
(defun js2r--by-end-descending (change1 change2)
|
||||
(> (plist-get change1 :end)
|
||||
(plist-get change2 :end)))
|
||||
|
||||
(defun js2r--any-overlapping-changes (sorted-changes)
|
||||
(--any?
|
||||
(let ((one (car it))
|
||||
(two (cadr it)))
|
||||
(< (plist-get one :beg)
|
||||
(plist-get two :end)))
|
||||
(-partition-in-steps 2 1 sorted-changes)))
|
||||
|
||||
(defun js2r--execute-changes (changes)
|
||||
(when changes
|
||||
(let ((sorted-changes (sort changes 'js2r--by-end-descending)))
|
||||
(when (js2r--any-overlapping-changes sorted-changes)
|
||||
(error "These changes overlap, cannot execute properly."))
|
||||
(let ((abs-end (set-marker (make-marker) (1+ (plist-get (car sorted-changes) :end))))
|
||||
(abs-beg (plist-get (car (last sorted-changes)) :beg)))
|
||||
(--each sorted-changes
|
||||
(goto-char (plist-get it :beg))
|
||||
(delete-char (- (plist-get it :end) (plist-get it :beg)))
|
||||
(insert (plist-get it :contents)))
|
||||
(indent-region abs-beg abs-end)
|
||||
(set-marker abs-end nil)))))
|
||||
|
||||
(provide 'js2r-helpers)
|
||||
;;; js2-helpers.el ends here
|
BIN
elpa/js2-refactor-20190630.2108/js2r-helpers.elc
Normal file
BIN
elpa/js2-refactor-20190630.2108/js2r-helpers.elc
Normal file
Binary file not shown.
92
elpa/js2-refactor-20190630.2108/js2r-iife.el
Normal file
92
elpa/js2-refactor-20190630.2108/js2r-iife.el
Normal file
|
@ -0,0 +1,92 @@
|
|||
;;; js2r-iife.el --- IIFE wrapping functions for js2-refactor -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2012-2014 Magnar Sveen
|
||||
;; Copyright (C) 2015-2016 Magnar Sveen and Nicolas Petton
|
||||
|
||||
;; Author: Magnar Sveen <magnars@gmail.com>,
|
||||
;; Nicolas Petton <nicolas@petton.fr>
|
||||
;; Keywords: conveniences
|
||||
|
||||
;; This program is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation, either version 3 of the License, or
|
||||
;; (at your option) any later version.
|
||||
|
||||
;; This program is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'js2r-helpers)
|
||||
|
||||
(defvar js2r--iife-regexp "^(function (")
|
||||
|
||||
(defun js2r-wrap-buffer-in-iife ()
|
||||
"Wrap the entire buffer in an immediately invoked function expression"
|
||||
(interactive)
|
||||
(save-excursion
|
||||
(when (ignore-errors (search-backward-regexp js2r--iife-regexp))
|
||||
(error "Buffer already contains an immediately invoked function expression."))
|
||||
(goto-char (point-min))
|
||||
(insert "(function () {\n")
|
||||
(when js2r-use-strict (insert "\"use strict\";\n"))
|
||||
(insert "\n")
|
||||
(goto-char (point-max))
|
||||
(insert "\n")
|
||||
(delete-blank-lines)
|
||||
(insert "\n}());")
|
||||
(indent-region (point-min) (point-max))))
|
||||
|
||||
(defun js2r--selected-name-positions ()
|
||||
"Returns the (beginning . end) of the name at cursor, or active region."
|
||||
(let ((current-node (js2-node-at-point))
|
||||
beg end)
|
||||
(unless (js2-name-node-p current-node)
|
||||
(setq current-node (js2-node-at-point (- (point) 1))))
|
||||
(if (not (and current-node (js2-name-node-p current-node)))
|
||||
(error "Point is not on an identifier."))
|
||||
(if (use-region-p)
|
||||
(cons (region-beginning) (region-end))
|
||||
(progn
|
||||
(setq end (+ (js2-node-abs-pos current-node)
|
||||
(js2-node-len current-node)))
|
||||
(skip-syntax-backward ".w_")
|
||||
(cons (point) end)))))
|
||||
|
||||
(defun js2r-inject-global-in-iife ()
|
||||
"Create shortcut for marked global by injecting it in the wrapping IIFE"
|
||||
(interactive)
|
||||
(js2r--guard)
|
||||
(js2r--wait-for-parse
|
||||
(save-excursion
|
||||
(let* ((name-pos (js2r--selected-name-positions))
|
||||
(name-beg (car name-pos))
|
||||
(name-end (cdr name-pos))
|
||||
(name (buffer-substring-no-properties name-beg name-end))
|
||||
(short (buster--global-shortcut name))
|
||||
beg end)
|
||||
(unless (search-backward-regexp js2r--iife-regexp)
|
||||
(error "No immediately invoked function expression found."))
|
||||
(deactivate-mark)
|
||||
(forward-char 11)
|
||||
(insert short)
|
||||
(unless (looking-at ")")
|
||||
(insert ", "))
|
||||
(search-forward "{")
|
||||
(setq beg (point))
|
||||
(backward-char)
|
||||
(forward-list)
|
||||
(forward-char)
|
||||
(setq end (point))
|
||||
(insert name)
|
||||
(unless (looking-at ")")
|
||||
(insert ", "))
|
||||
(replace-string name short t beg end)))))
|
||||
|
||||
(provide 'js2r-iife)
|
||||
;;; js2-iife.el ends here
|
BIN
elpa/js2-refactor-20190630.2108/js2r-iife.elc
Normal file
BIN
elpa/js2-refactor-20190630.2108/js2r-iife.elc
Normal file
Binary file not shown.
227
elpa/js2-refactor-20190630.2108/js2r-paredit.el
Normal file
227
elpa/js2-refactor-20190630.2108/js2r-paredit.el
Normal file
|
@ -0,0 +1,227 @@
|
|||
;;; js2r-paredit.el --- Paredit-like extensions for js2-refactor -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2012-2014 Magnar Sveen
|
||||
;; Copyright (C) 2015-2016 Magnar Sveen and Nicolas Petton
|
||||
|
||||
;; Author: Magnar Sveen <magnars@gmail.com>,
|
||||
;; Nicolas Petton <nicolas@petton.fr>
|
||||
;; Keywords: conveniences
|
||||
|
||||
;; This program is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation, either version 3 of the License, or
|
||||
;; (at your option) any later version.
|
||||
|
||||
;; This program is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'dash)
|
||||
|
||||
(require 'js2r-helpers)
|
||||
|
||||
(defun js2r--nesting-node-p (node)
|
||||
(or (js2-function-node-p node)
|
||||
(js2-if-node-p node)
|
||||
(js2-for-node-p node)
|
||||
(js2-while-node-p node)))
|
||||
|
||||
(defun js2r--standalone-node-p (node)
|
||||
(or (js2-stmt-node-p node)
|
||||
(and (js2-function-node-p node)
|
||||
(eq 'FUNCTION_STATEMENT (js2-function-node-form node)))))
|
||||
|
||||
(defun js2r-kill ()
|
||||
"Kill a line like `kill-line' but tries to respect node boundaries.
|
||||
Falls back to `kill-line' if the buffer has parse errors.
|
||||
|
||||
if(|foo) {bar();} -> if() {bar();}
|
||||
|
||||
function foo() {|2 + 3} -> function foo() {}
|
||||
|
||||
// some |comment -> // some
|
||||
|
||||
'this is a| string' -> 'this is a'
|
||||
"
|
||||
(interactive)
|
||||
(if js2-parsed-errors
|
||||
(progn
|
||||
(message "Buffer has parse errors. Killing the line")
|
||||
(kill-line))
|
||||
(condition-case error
|
||||
(js2r--kill-line)
|
||||
(progn
|
||||
(message "Error occured while trying to kill AST node. Killing the line.")
|
||||
(kill-line)))))
|
||||
|
||||
(defun js2r--kill-line ()
|
||||
"Kill a line, but respecting node boundaries."
|
||||
(let ((node (js2r--next-node)))
|
||||
(cond
|
||||
((js2-comment-node-p node) (kill-line))
|
||||
((js2-string-node-p node) (js2r--kill-line-in-string))
|
||||
(t (js2r--kill-line-in-sexp)))))
|
||||
|
||||
(defun js2r--next-node ()
|
||||
"Return the node at point, or the node after the point if the
|
||||
point is at the exact end of a node."
|
||||
(save-excursion
|
||||
(when (= (js2-node-abs-end (js2-node-at-point))
|
||||
(point))
|
||||
(forward-char 1))
|
||||
(js2-node-at-point)))
|
||||
|
||||
(defun js2r--kill-line-in-sexp ()
|
||||
"Kill a line, but only kills until the closest outer sexp on
|
||||
the current line, delimited with \")}]\". If no sexp is found
|
||||
on the current line, falls back to
|
||||
`js2r--kill-line-with-inner-sexp'."
|
||||
(condition-case error
|
||||
(let* ((beg (point))
|
||||
(end (save-excursion
|
||||
(up-list)
|
||||
(forward-char -1)
|
||||
(point))))
|
||||
(if (js2-same-line end)
|
||||
(kill-region beg end)
|
||||
(js2r--kill-line-with-inner-sexp)))
|
||||
(scan-error
|
||||
(js2r--kill-line-with-inner-sexp))))
|
||||
|
||||
(defun js2r--kill-line-with-inner-sexp ()
|
||||
"Kill a line, but respecting inner killed sexps, ensuring that
|
||||
we kill up to the end to the next inner sexp if it starts in
|
||||
the current line.
|
||||
|
||||
If the parentheses are unbalanced, fallback to `kill-line' and
|
||||
warn the user."
|
||||
(condition-case error
|
||||
(let* ((beg (point))
|
||||
(end (save-excursion
|
||||
(forward-visible-line 1)
|
||||
(point)))
|
||||
(beg-of-sexp (save-excursion
|
||||
(js2r--goto-last-sexp-on-line)
|
||||
(point)))
|
||||
(end-of-sexp (save-excursion
|
||||
(goto-char beg-of-sexp)
|
||||
(forward-list)
|
||||
;; Kill all remaining semi-colons as well
|
||||
(while (looking-at ";")
|
||||
(forward-char))
|
||||
(point))))
|
||||
(if (js2-same-line beg-of-sexp)
|
||||
(kill-region beg (max end end-of-sexp))
|
||||
(kill-line)))
|
||||
(scan-error
|
||||
(message "Unbalanced parentheses. Killing the line.")
|
||||
(kill-line))))
|
||||
|
||||
(defun js2r--goto-last-sexp-on-line ()
|
||||
"Move the cursor to the opening of the last sexp on the current
|
||||
line, or to the end of the line if no sexp is found."
|
||||
(let ((pos (point)))
|
||||
(down-list)
|
||||
(backward-char 1)
|
||||
(forward-list)
|
||||
(if (js2-same-line pos)
|
||||
(js2r--goto-last-sexp-on-line)
|
||||
(backward-list))))
|
||||
|
||||
(defun js2r--kill-line-in-string ()
|
||||
"Kill a line in a string node, respecting the node boundaries.
|
||||
When at the beginning of the node, kill from outside of it."
|
||||
(let* ((node (js2-node-at-point))
|
||||
(beg (point))
|
||||
(node-start (js2-node-abs-pos node))
|
||||
(node-end (js2-node-abs-end node)))
|
||||
(if (= beg node-start)
|
||||
(js2r--kill-line-in-sexp)
|
||||
(kill-region beg (1- node-end)))))
|
||||
|
||||
(defun js2r-forward-slurp (&optional arg)
|
||||
"Add the expression following the current function into it.
|
||||
|
||||
The addition is performed by moving the closing brace of the
|
||||
function down.
|
||||
|
||||
When called with a prefix argument ARG, slurp ARG expressions
|
||||
following the current function."
|
||||
(interactive "p")
|
||||
(js2r--guard)
|
||||
(js2r--wait-for-parse
|
||||
(let* ((nesting (js2r--closest 'js2r--nesting-node-p))
|
||||
(standalone (if (js2r--standalone-node-p nesting)
|
||||
nesting
|
||||
(js2-node-parent-stmt nesting)))
|
||||
(next-sibling (js2-node-next-sibling standalone))
|
||||
(beg (js2-node-abs-pos next-sibling))
|
||||
(last-sibling (if (wholenump arg)
|
||||
(let ((num arg)
|
||||
(iter-sibling next-sibling))
|
||||
(while (> num 1) ;; Do next-sibling arg nbr of times
|
||||
(setq iter-sibling (js2-node-next-sibling iter-sibling))
|
||||
(setq num (1- num)))
|
||||
iter-sibling)
|
||||
next-sibling)) ;; No optional arg. Just use next-sibling
|
||||
(end (js2-node-abs-end last-sibling))
|
||||
(text (buffer-substring beg end)))
|
||||
(save-excursion
|
||||
(delete-region beg end)
|
||||
;; Delete newline character if the deleted AST node was at the end of the line
|
||||
(goto-char beg)
|
||||
(when (and (eolp)
|
||||
(not (eobp)))
|
||||
(delete-char 1))
|
||||
(goto-char (js2-node-abs-end nesting))
|
||||
(forward-char -1)
|
||||
(when (looking-back "{ *")
|
||||
(newline))
|
||||
(setq beg (point))
|
||||
(insert text)
|
||||
(when (looking-at " *}")
|
||||
(newline))
|
||||
(setq end (point))
|
||||
(indent-region beg end)))))
|
||||
|
||||
(defun js2r-forward-barf (&optional arg)
|
||||
(interactive "p")
|
||||
(js2r--guard)
|
||||
(js2r--wait-for-parse
|
||||
(let* ((nesting (js2r--closest 'js2r--nesting-node-p))
|
||||
(standalone (if (js2r--standalone-node-p nesting)
|
||||
nesting
|
||||
(js2-node-parent-stmt nesting)))
|
||||
(standalone-end (js2-node-abs-end standalone))
|
||||
(last-child (car (last (if (js2-if-node-p nesting)
|
||||
(js2-scope-kids (js2r--closest 'js2-scope-p))
|
||||
(js2r--node-kids nesting)))))
|
||||
(first-barf-child (if (wholenump arg)
|
||||
(let ((num arg)
|
||||
(iter-child last-child))
|
||||
(while (> num 1) ;; Do prev-sibling arg nbr of times
|
||||
(setq iter-child (js2-node-prev-sibling iter-child))
|
||||
(setq num (1- num)))
|
||||
iter-child)
|
||||
last-child)) ; No optional arg. Just use last-child
|
||||
(last-child-beg (save-excursion
|
||||
(goto-char (js2-node-abs-pos first-barf-child))
|
||||
(skip-syntax-backward " ")
|
||||
(while (looking-back "\n") (backward-char))
|
||||
(point)))
|
||||
(last-child-end (js2-node-abs-end last-child))
|
||||
(text (buffer-substring last-child-beg last-child-end)))
|
||||
(save-excursion
|
||||
(js2r--execute-changes
|
||||
(list
|
||||
(list :beg last-child-beg :end last-child-end :contents "")
|
||||
(list :beg standalone-end :end standalone-end :contents text)))))))
|
||||
|
||||
(provide 'js2r-paredit)
|
||||
;;; js2r-paredit.el ends here
|
BIN
elpa/js2-refactor-20190630.2108/js2r-paredit.elc
Normal file
BIN
elpa/js2-refactor-20190630.2108/js2r-paredit.elc
Normal file
Binary file not shown.
375
elpa/js2-refactor-20190630.2108/js2r-vars.el
Normal file
375
elpa/js2-refactor-20190630.2108/js2r-vars.el
Normal file
|
@ -0,0 +1,375 @@
|
|||
;;; js2r-vars.el --- Variable declaration manipulation functions for js2-refactor -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2012-2014 Magnar Sveen
|
||||
;; Copyright (C) 2015-2016 Magnar Sveen and Nicolas Petton
|
||||
|
||||
;; Author: Magnar Sveen <magnars@gmail.com>,
|
||||
;; Nicolas Petton <nicolas@petton.fr>
|
||||
;; Keywords: conveniences
|
||||
|
||||
;; This program is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation, either version 3 of the License, or
|
||||
;; (at your option) any later version.
|
||||
|
||||
;; This program is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'multiple-cursors-core)
|
||||
(require 'dash)
|
||||
|
||||
(require 'js2r-helpers)
|
||||
|
||||
;; Helpers
|
||||
|
||||
(defun js2r--name-node-at-point (&optional pos)
|
||||
(setq pos (or pos (point)))
|
||||
(let ((current-node (js2-node-at-point pos)))
|
||||
(unless (js2-name-node-p current-node)
|
||||
(setq current-node (js2-node-at-point (- (point) 1))))
|
||||
(if (not (and current-node (js2-name-node-p current-node)))
|
||||
(error "Point is not on an identifier.")
|
||||
current-node)))
|
||||
|
||||
(defun js2r--local-name-node-at-point (&optional pos)
|
||||
(setq pos (or pos (point)))
|
||||
(let ((current-node (js2r--name-node-at-point pos)))
|
||||
(unless (js2r--local-name-node-p current-node)
|
||||
(error "Point is not on a local identifier"))
|
||||
current-node))
|
||||
|
||||
(defun js2r--local-name-node-p (node)
|
||||
(let ((parent (js2-node-parent node)))
|
||||
(and parent (js2-name-node-p node)
|
||||
;; is not foo in { foo: 1 }
|
||||
(not (and (js2-object-prop-node-p parent)
|
||||
(eq node (js2-object-prop-node-left parent))
|
||||
;; could be { foo } though, in which case the node
|
||||
;; is parent's both left and right.
|
||||
(not (eq node (js2-object-prop-node-right parent)))))
|
||||
;; is not foo in x.foo
|
||||
(not (and (js2-prop-get-node-p parent)
|
||||
(eq node (js2-prop-get-node-right parent))))
|
||||
;; is not foo in import { foo as bar } from ...
|
||||
;; could be bar, though.
|
||||
(not (and (js2-export-binding-node-p parent)
|
||||
(eq node (js2-export-binding-node-extern-name parent))
|
||||
(not (eq node (js2-export-binding-node-local-name parent))))))))
|
||||
|
||||
(defun js2r--name-node-defining-scope (name-node)
|
||||
(unless (js2r--local-name-node-p name-node)
|
||||
(error "Node is not on a local identifier"))
|
||||
(js2-get-defining-scope
|
||||
(js2-node-get-enclosing-scope name-node)
|
||||
(js2-name-node-name name-node)))
|
||||
|
||||
(defun js2r--local-usages-of-name-node (name-node)
|
||||
(unless (js2r--local-name-node-p name-node)
|
||||
(error "Node is not on a local identifier"))
|
||||
(let* ((name (js2-name-node-name name-node))
|
||||
(scope (js2r--name-node-defining-scope name-node))
|
||||
(result nil))
|
||||
(js2-visit-ast
|
||||
scope
|
||||
(lambda (node end-p)
|
||||
(when (and (not end-p)
|
||||
(js2r--local-name-node-p node)
|
||||
(string= name (js2-name-node-name node))
|
||||
(eq scope (js2r--name-node-defining-scope node)))
|
||||
(add-to-list 'result node))
|
||||
t))
|
||||
result))
|
||||
|
||||
(defun js2r--local-var-positions (name-node)
|
||||
(-map 'js2-node-abs-pos (js2r--local-usages-of-name-node name-node)))
|
||||
|
||||
(defun js2r--var-defining-node (var-node)
|
||||
(unless (js2r--local-name-node-p var-node)
|
||||
(error "Node is not on a local identifier"))
|
||||
(let* ((name (js2-name-node-name var-node))
|
||||
(scope (js2r--name-node-defining-scope var-node)))
|
||||
(js2-symbol-ast-node
|
||||
(js2-scope-get-symbol scope name))))
|
||||
|
||||
|
||||
;; Add to jslint globals annotation
|
||||
|
||||
(defun current-line-contents ()
|
||||
"Find the contents of the current line, minus indentation."
|
||||
(buffer-substring (save-excursion (back-to-indentation) (point))
|
||||
(save-excursion (end-of-line) (point))))
|
||||
|
||||
(require 'thingatpt)
|
||||
|
||||
(defun js2r-add-to-globals-annotation ()
|
||||
(interactive)
|
||||
(let ((var (thing-at-point 'symbol)))
|
||||
(save-excursion
|
||||
(beginning-of-buffer)
|
||||
(when (not (string-match "^/\\* *global " (current-line-contents)))
|
||||
(newline)
|
||||
(forward-line -1)
|
||||
(insert "/* global */")
|
||||
(newline)
|
||||
(forward-line -1))
|
||||
(while (not (string-match "*/" (current-line-contents)))
|
||||
(forward-line))
|
||||
(end-of-line)
|
||||
(delete-char -2)
|
||||
(unless (looking-back "global ")
|
||||
(while (looking-back " ")
|
||||
(delete-char -1))
|
||||
(insert ", "))
|
||||
(insert (concat var " */")))))
|
||||
|
||||
|
||||
;; Rename variable
|
||||
|
||||
(defun js2r-rename-var ()
|
||||
"Renames the variable on point and all occurrences in its lexical scope."
|
||||
(interactive)
|
||||
(js2r--guard)
|
||||
(js2r--wait-for-parse
|
||||
(let* ((current-node (js2r--local-name-node-at-point))
|
||||
(len (js2-node-len current-node))
|
||||
(current-start (js2-node-abs-pos current-node))
|
||||
(current-end (+ current-start len)))
|
||||
(save-excursion
|
||||
(mapc (lambda (beg)
|
||||
(when (not (= beg current-start))
|
||||
(goto-char beg)
|
||||
(set-mark (+ beg len))
|
||||
(mc/create-fake-cursor-at-point)))
|
||||
(js2r--local-var-positions current-node)))
|
||||
(push-mark current-end)
|
||||
(goto-char current-start)
|
||||
(activate-mark))
|
||||
(mc/maybe-multiple-cursors-mode)))
|
||||
|
||||
(add-to-list 'mc--default-cmds-to-run-once 'js2r-rename-var)
|
||||
|
||||
;; Change local variable to use this. instead
|
||||
|
||||
(defun js2r-var-to-this ()
|
||||
"Changes the variable on point to use this.var instead."
|
||||
(interactive)
|
||||
(js2r--guard)
|
||||
(js2r--wait-for-parse
|
||||
(save-excursion
|
||||
(let ((node (js2-node-at-point)))
|
||||
(when (js2-var-decl-node-p node)
|
||||
(let ((kids (js2-var-decl-node-kids node)))
|
||||
(when (cdr kids)
|
||||
(error "Currently does not support converting multivar statements."))
|
||||
(goto-char (js2-node-abs-pos (car kids))))))
|
||||
(--each (js2r--local-var-positions (js2r--local-name-node-at-point))
|
||||
(goto-char it)
|
||||
(cond ((looking-back "var ") (delete-char -4))
|
||||
((looking-back "let ") (delete-char -4))
|
||||
((looking-back "const ") (delete-char -6)))
|
||||
(insert "this.")))))
|
||||
|
||||
;; Inline var
|
||||
|
||||
(defun js2r-inline-var ()
|
||||
(interactive)
|
||||
(js2r--guard)
|
||||
(js2r--wait-for-parse
|
||||
(save-excursion
|
||||
(let* ((current-node (js2r--local-name-node-at-point))
|
||||
(definer (js2r--var-defining-node current-node))
|
||||
(definer-start (js2-node-abs-pos definer))
|
||||
(var-init (js2-node-parent definer))
|
||||
(initializer (js2-var-init-node-initializer
|
||||
var-init)))
|
||||
(unless initializer
|
||||
(error "Var is not initialized when defined."))
|
||||
(let* ((var-len (js2-node-len current-node))
|
||||
(init-beg (js2-node-abs-pos initializer))
|
||||
(init-end (+ init-beg (js2-node-len initializer)))
|
||||
(var-init-beg (copy-marker (js2-node-abs-pos var-init)))
|
||||
(var-init-end (copy-marker (+ var-init-beg (js2-node-len var-init))))
|
||||
(contents (buffer-substring init-beg init-end)))
|
||||
(mapc (lambda (beg)
|
||||
(when (not (= beg definer-start))
|
||||
(goto-char beg)
|
||||
(delete-char var-len)
|
||||
(insert contents)))
|
||||
(js2r--local-var-positions current-node))
|
||||
(js2r--delete-var-init var-init-beg var-init-end))))))
|
||||
|
||||
|
||||
(defun js2r--was-single-var ()
|
||||
(save-excursion
|
||||
(goto-char (point-at-bol))
|
||||
(or (looking-at "^[[:space:]]*\\(var\\|const\\|let\\)[[:space:]]?;?$")
|
||||
(looking-at "^[[:space:]]*,[[:space:]]*$"))))
|
||||
|
||||
(defun js2r--was-starting-var ()
|
||||
(or (looking-back "var ")
|
||||
(looking-back "const ")
|
||||
(looking-back "let ")))
|
||||
|
||||
(defun js2r--was-ending-var ()
|
||||
(looking-at ";"))
|
||||
|
||||
(defun js2r--delete-var-init (beg end)
|
||||
(goto-char beg)
|
||||
(delete-char (- end beg))
|
||||
(cond
|
||||
((js2r--was-single-var)
|
||||
(delete-region (point-at-bol) (point-at-eol))
|
||||
(delete-blank-lines))
|
||||
|
||||
((js2r--was-starting-var)
|
||||
(delete-char 1)
|
||||
(if (looking-at " ")
|
||||
(delete-char 1)
|
||||
(join-line -1)))
|
||||
|
||||
((js2r--was-ending-var)
|
||||
(if (looking-back ", ")
|
||||
(delete-char -1)
|
||||
(join-line)
|
||||
(delete-char 1))
|
||||
(delete-char -1))
|
||||
|
||||
(t (delete-char 2))))
|
||||
|
||||
;; two cases
|
||||
;; - it's the only var -> remove the line
|
||||
;; - there are several vars -> remove the node then clean up commas
|
||||
|
||||
|
||||
;; Extract variable
|
||||
|
||||
(defun js2r--start-of-parent-stmt ()
|
||||
(js2-node-abs-pos (js2r--closest-stmt-node)))
|
||||
|
||||
(defun js2r--object-literal-key-behind (pos)
|
||||
(save-excursion
|
||||
(goto-char pos)
|
||||
(when (looking-back "\\sw: ?")
|
||||
(backward-char 2)
|
||||
(js2-name-node-name (js2r--name-node-at-point)))))
|
||||
|
||||
(defun js2r--line-above-is-blank ()
|
||||
(save-excursion
|
||||
(forward-line -1)
|
||||
(string= "" (current-line-contents))))
|
||||
|
||||
;;;###autoload
|
||||
(defun js2r-extract-var ()
|
||||
(interactive)
|
||||
(js2r--guard)
|
||||
(js2r--wait-for-parse
|
||||
(let ((keyword (if js2r-prefer-let-over-var "let" "var")))
|
||||
(if (use-region-p)
|
||||
(js2r--extract-var-between (region-beginning) (region-end) keyword)
|
||||
(let ((node (js2r--closest-extractable-node)))
|
||||
(js2r--extract-var-between (js2-node-abs-pos node)
|
||||
(js2-node-abs-end node) keyword))))))
|
||||
|
||||
;;;###autoload
|
||||
(defun js2r-extract-let ()
|
||||
(interactive)
|
||||
(js2r--guard)
|
||||
(js2r--wait-for-parse
|
||||
(if (use-region-p)
|
||||
(js2r--extract-var-between (region-beginning) (region-end) "let")
|
||||
(let ((node (js2r--closest-extractable-node)))
|
||||
(js2r--extract-var-between (js2-node-abs-pos node)
|
||||
(js2-node-abs-end node) "let")))))
|
||||
|
||||
;;;###autoload
|
||||
(defun js2r-extract-const ()
|
||||
(interactive)
|
||||
(js2r--guard)
|
||||
(js2r--wait-for-parse
|
||||
(if (use-region-p)
|
||||
(js2r--extract-var-between (region-beginning) (region-end) "const")
|
||||
(let ((node (js2r--closest-extractable-node)))
|
||||
(js2r--extract-var-between (js2-node-abs-pos node)
|
||||
(js2-node-abs-end node) "const")))))
|
||||
|
||||
(add-to-list 'mc--default-cmds-to-run-once 'js2r-extract-var)
|
||||
(add-to-list 'mc--default-cmds-to-run-once 'js2r-extract-let)
|
||||
(add-to-list 'mc--default-cmds-to-run-once 'js2r-extract-const)
|
||||
|
||||
(defun js2r--extract-var-between (beg end keyword)
|
||||
(interactive "r")
|
||||
(unless (js2r--single-complete-expression-between-p beg end)
|
||||
(error "Can only extract single, complete expressions to var"))
|
||||
|
||||
(let ((deactivate-mark nil)
|
||||
(expression (buffer-substring beg end))
|
||||
(orig-var-end (make-marker))
|
||||
(new-var-end (make-marker))
|
||||
(name (or (js2r--object-literal-key-behind beg) "name")))
|
||||
|
||||
(delete-region beg end)
|
||||
(insert name)
|
||||
(set-marker orig-var-end (point))
|
||||
|
||||
(goto-char (js2r--start-of-parent-stmt))
|
||||
(js2r--insert-var name keyword)
|
||||
(set-marker new-var-end (point))
|
||||
(insert " = " expression ";")
|
||||
(when (or (js2r--line-above-is-blank)
|
||||
(string-match-p "^function " expression))
|
||||
(newline))
|
||||
(newline)
|
||||
(indent-region new-var-end orig-var-end)
|
||||
(save-excursion
|
||||
(goto-char new-var-end)
|
||||
(set-mark (- (point) (length name)))
|
||||
(mc/create-fake-cursor-at-point))
|
||||
(goto-char orig-var-end)
|
||||
(set-mark (- (point) (length name)))
|
||||
(set-marker orig-var-end nil)
|
||||
(set-marker new-var-end nil))
|
||||
(mc/maybe-multiple-cursors-mode))
|
||||
|
||||
(defun js2r--insert-var (name keyword)
|
||||
"Insert a var definition for NAME."
|
||||
(insert (format "%s %s" keyword name)))
|
||||
|
||||
(defun js2r-split-var-declaration ()
|
||||
"Split a variable declaration into separate variable
|
||||
declarations for each declared variable."
|
||||
(interactive)
|
||||
(js2r--guard)
|
||||
(js2r--wait-for-parse
|
||||
(save-excursion
|
||||
(let* ((declaration (or (js2r--closest #'js2-var-decl-node-p) (error "No var declaration at point.")))
|
||||
(kids (js2-var-decl-node-kids declaration))
|
||||
(stmt (js2-node-parent-stmt declaration))
|
||||
(tt (js2-var-decl-node-decl-type declaration))
|
||||
(keyword (cond
|
||||
((= tt js2-VAR) "var")
|
||||
((= tt js2-LET) "let")
|
||||
((= tt js2-CONST) "const"))))
|
||||
(goto-char (js2-node-abs-end stmt))
|
||||
(mapc (lambda (kid)
|
||||
(js2r--insert-var (js2-node-string kid) keyword)
|
||||
(insert ";")
|
||||
(newline)
|
||||
(if (save-excursion
|
||||
(goto-char (js2-node-abs-end kid))
|
||||
(looking-at ", *\n *\n"))
|
||||
(newline)))
|
||||
kids)
|
||||
(delete-char -1) ;; delete final newline
|
||||
(let ((end (point)))
|
||||
(js2r--goto-and-delete-node stmt)
|
||||
(indent-region (point) end))))))
|
||||
|
||||
(provide 'js2r-vars)
|
||||
;;; js2-vars.el ends here
|
BIN
elpa/js2-refactor-20190630.2108/js2r-vars.elc
Normal file
BIN
elpa/js2-refactor-20190630.2108/js2r-vars.elc
Normal file
Binary file not shown.
76
elpa/js2-refactor-20190630.2108/js2r-wrapping.el
Normal file
76
elpa/js2-refactor-20190630.2108/js2r-wrapping.el
Normal file
|
@ -0,0 +1,76 @@
|
|||
;;; js2r-wrapping.el --- Helper functions for wrapping/unwrapping -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2017 Nicolas Petton
|
||||
|
||||
;; Author: Nicolas Petton
|
||||
|
||||
;; 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:
|
||||
|
||||
;;
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'yasnippet)
|
||||
|
||||
(require 'js2r-helpers)
|
||||
|
||||
(defvar js2r--space-str " \t\n")
|
||||
|
||||
(defun js2r--skip-region-whitespace ()
|
||||
(let ((p-first (< (point) (mark))))
|
||||
(unless p-first
|
||||
(exchange-point-and-mark))
|
||||
(skip-chars-forward js2r--space-str)
|
||||
(exchange-point-and-mark)
|
||||
(skip-chars-backward js2r--space-str)
|
||||
(when p-first
|
||||
(exchange-point-and-mark))))
|
||||
|
||||
(defun js2r-unwrap ()
|
||||
(interactive)
|
||||
(js2r--guard)
|
||||
(js2r--wait-for-parse
|
||||
(let (beg end)
|
||||
(if (use-region-p)
|
||||
(progn
|
||||
(js2r--skip-region-whitespace)
|
||||
(setq beg (min (point) (mark)))
|
||||
(setq end (max (point) (mark))))
|
||||
(let ((stmt (js2-node-parent-stmt (js2-node-at-point))))
|
||||
(setq beg (js2-node-abs-pos stmt))
|
||||
(setq end (js2-node-abs-end stmt))))
|
||||
(let* ((ancestor (js2-node-parent-stmt
|
||||
(js2r--first-common-ancestor-in-region beg end)))
|
||||
(abeg (js2-node-abs-pos ancestor))
|
||||
(aend (js2-node-abs-end ancestor)))
|
||||
(save-excursion
|
||||
(goto-char end)
|
||||
(delete-char (- aend end))
|
||||
(goto-char abeg)
|
||||
(delete-char (- beg abeg)))
|
||||
(indent-region (point-min) (point-max))))))
|
||||
|
||||
(defun js2r-wrap-in-for-loop (beg end)
|
||||
(interactive "r")
|
||||
(js2r--skip-region-whitespace)
|
||||
(setq beg (min (point) (mark)))
|
||||
(setq end (max (point) (mark)))
|
||||
(let ((yas-wrap-around-region t))
|
||||
(yas-expand-snippet "for (var i = 0, l = ${1:length}; i < l; i++) {\n$0\n}"
|
||||
beg end)))
|
||||
|
||||
(provide 'js2r-wrapping)
|
||||
;;; js2r-wrapping.el ends here
|
BIN
elpa/js2-refactor-20190630.2108/js2r-wrapping.elc
Normal file
BIN
elpa/js2-refactor-20190630.2108/js2r-wrapping.elc
Normal file
Binary file not shown.
119
elpa/multiple-cursors-20191210.1759/mc-cycle-cursors.el
Normal file
119
elpa/multiple-cursors-20191210.1759/mc-cycle-cursors.el
Normal file
|
@ -0,0 +1,119 @@
|
|||
;;; mc-cycle-cursors.el
|
||||
|
||||
;; Copyright (C) 2012-2016 Magnar Sveen
|
||||
|
||||
;; Author: Magnar Sveen <magnars@gmail.com>
|
||||
;; Keywords: editing cursors
|
||||
|
||||
;; This program is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation, either version 3 of the License, or
|
||||
;; (at your option) any later version.
|
||||
|
||||
;; This program is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; This scrolls the buffer to center each cursor in turn.
|
||||
;; Scroll down with C-v, scroll up with M-v
|
||||
;; This is nice when you have cursors that's outside of your view.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'multiple-cursors-core)
|
||||
|
||||
(defun mc/next-fake-cursor-after-point ()
|
||||
(let ((pos (point))
|
||||
(next-pos (1+ (point-max)))
|
||||
next)
|
||||
(mc/for-each-fake-cursor
|
||||
(let ((cursor-pos (overlay-get cursor 'point)))
|
||||
(when (and (< pos cursor-pos)
|
||||
(< cursor-pos next-pos))
|
||||
(setq next-pos cursor-pos)
|
||||
(setq next cursor))))
|
||||
next))
|
||||
|
||||
(defun mc/prev-fake-cursor-before-point ()
|
||||
(let ((pos (point))
|
||||
(prev-pos (1- (point-min)))
|
||||
prev)
|
||||
(mc/for-each-fake-cursor
|
||||
(let ((cursor-pos (overlay-get cursor 'point)))
|
||||
(when (and (> pos cursor-pos)
|
||||
(> cursor-pos prev-pos))
|
||||
(setq prev-pos cursor-pos)
|
||||
(setq prev cursor))))
|
||||
prev))
|
||||
|
||||
(defcustom mc/cycle-looping-behaviour 'continue
|
||||
"What to do if asked to cycle beyond the last cursor or before the first cursor."
|
||||
:type '(radio (const :tag "Loop around to beginning/end of document." continue)
|
||||
(const :tag "Warn and then loop around." warn)
|
||||
(const :tag "Signal an error." error)
|
||||
(const :tag "Don't loop." stop))
|
||||
:group 'multiple-cursors)
|
||||
|
||||
(defun mc/handle-loop-condition (error-message)
|
||||
(cl-ecase mc/cycle-looping-behaviour
|
||||
(error (error error-message))
|
||||
(warn (message error-message))
|
||||
(continue 'continue)
|
||||
(stop 'stop)))
|
||||
|
||||
(defun mc/first-fake-cursor-after (point)
|
||||
"Very similar to mc/furthest-cursor-before-point, but ignores (mark) and (point)."
|
||||
(let* ((cursors (mc/all-fake-cursors))
|
||||
(cursors-after-point (cl-remove-if (lambda (cursor)
|
||||
(< (mc/cursor-beg cursor) point))
|
||||
cursors))
|
||||
(cursors-in-order (cl-sort cursors-after-point '< :key 'mc/cursor-beg)))
|
||||
(car cursors-in-order)))
|
||||
|
||||
(defun mc/last-fake-cursor-before (point)
|
||||
"Very similar to mc/furthest-cursor-before-point, but ignores (mark) and (point)."
|
||||
(let* ((cursors (mc/all-fake-cursors))
|
||||
(cursors-before-point (cl-remove-if (lambda (cursor)
|
||||
(> (mc/cursor-end cursor) point))
|
||||
cursors))
|
||||
(cursors-in-order (cl-sort cursors-before-point '> :key 'mc/cursor-end)))
|
||||
(car cursors-in-order)))
|
||||
|
||||
(cl-defun mc/cycle (next-cursor fallback-cursor loop-message)
|
||||
(when (null next-cursor)
|
||||
(when (eql 'stop (mc/handle-loop-condition loop-message))
|
||||
(return-from mc/cycle nil))
|
||||
(setf next-cursor fallback-cursor))
|
||||
(mc/create-fake-cursor-at-point)
|
||||
(mc/pop-state-from-overlay next-cursor)
|
||||
(recenter))
|
||||
|
||||
(defun mc/cycle-forward ()
|
||||
(interactive)
|
||||
(mc/cycle (mc/next-fake-cursor-after-point)
|
||||
(mc/first-fake-cursor-after (point-min))
|
||||
"We're already at the last cursor."))
|
||||
|
||||
(defun mc/cycle-backward ()
|
||||
(interactive)
|
||||
(mc/cycle (mc/prev-fake-cursor-before-point)
|
||||
(mc/last-fake-cursor-before (point-max))
|
||||
"We're already at the last cursor"))
|
||||
|
||||
(define-key mc/keymap (kbd "C-v") 'mc/cycle-forward)
|
||||
(define-key mc/keymap (kbd "M-v") 'mc/cycle-backward)
|
||||
|
||||
(provide 'mc-cycle-cursors)
|
||||
|
||||
|
||||
;; Local Variables:
|
||||
;; coding: utf-8
|
||||
;; End:
|
||||
|
||||
;;; mc-cycle-cursors.el ends here
|
BIN
elpa/multiple-cursors-20191210.1759/mc-cycle-cursors.elc
Normal file
BIN
elpa/multiple-cursors-20191210.1759/mc-cycle-cursors.elc
Normal file
Binary file not shown.
110
elpa/multiple-cursors-20191210.1759/mc-edit-lines.el
Normal file
110
elpa/multiple-cursors-20191210.1759/mc-edit-lines.el
Normal file
|
@ -0,0 +1,110 @@
|
|||
;;; mc-edit-lines.el
|
||||
|
||||
;; Copyright (C) 2012-2016 Magnar Sveen
|
||||
|
||||
;; Author: Magnar Sveen <magnars@gmail.com>
|
||||
;; Keywords: editing cursors
|
||||
|
||||
;; This program is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation, either version 3 of the License, or
|
||||
;; (at your option) any later version.
|
||||
|
||||
;; This program is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; This file contains functions to add multiple cursors to consecutive lines
|
||||
;; given an active region.
|
||||
|
||||
;; Please see multiple-cursors.el for more commentary.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'multiple-cursors-core)
|
||||
|
||||
(defcustom mc/edit-lines-empty-lines nil
|
||||
"What should be done by `mc/edit-lines' when a line is not long enough."
|
||||
:type '(radio (const :tag "Pad the line with spaces." pad)
|
||||
(const :tag "Ignore the line." ignore)
|
||||
(const :tag "Signal an error." error)
|
||||
(const :tag "Nothing. Cursor is at end of line." nil))
|
||||
:group 'multiple-cursors)
|
||||
|
||||
;;;###autoload
|
||||
(defun mc/edit-lines (&optional arg)
|
||||
"Add one cursor to each line of the active region.
|
||||
Starts from mark and moves in straight down or up towards the
|
||||
line point is on.
|
||||
|
||||
What is done with lines which are not long enough is governed by
|
||||
`mc/edit-lines-empty-lines'. The prefix argument ARG can be used
|
||||
to override this. If ARG is a symbol (when called from Lisp),
|
||||
that symbol is used instead of `mc/edit-lines-empty-lines'.
|
||||
Otherwise, if ARG negative, short lines will be ignored. Any
|
||||
other non-nil value will cause short lines to be padded."
|
||||
(interactive "P")
|
||||
(when (not (and mark-active (/= (point) (mark))))
|
||||
(error "Mark a set of lines first"))
|
||||
(mc/remove-fake-cursors)
|
||||
(let* ((col (current-column))
|
||||
(point-line (mc/line-number-at-pos))
|
||||
(mark-line (progn (exchange-point-and-mark) (mc/line-number-at-pos)))
|
||||
(direction (if (< point-line mark-line) :up :down))
|
||||
(style (cond
|
||||
;; called from lisp
|
||||
((and arg (symbolp arg))
|
||||
arg)
|
||||
;; negative argument
|
||||
((< (prefix-numeric-value arg) 0)
|
||||
'ignore)
|
||||
(arg 'pad)
|
||||
(t mc/edit-lines-empty-lines))))
|
||||
(deactivate-mark)
|
||||
(when (and (eq direction :up) (bolp))
|
||||
(previous-logical-line 1 nil)
|
||||
(move-to-column col))
|
||||
;; Add the cursors
|
||||
(while (not (eq (mc/line-number-at-pos) point-line))
|
||||
;; Pad the line
|
||||
(when (eq style 'pad)
|
||||
(while (< (current-column) col)
|
||||
(insert " ")))
|
||||
;; Error
|
||||
(when (and (eq style 'error)
|
||||
(not (equal col (current-column))))
|
||||
(error "Short line encountered in `mc/edit-lines'"))
|
||||
;; create the cursor
|
||||
(unless (and (eq style 'ignore)
|
||||
(not (equal col (current-column))))
|
||||
(mc/create-fake-cursor-at-point))
|
||||
;; proceed to next
|
||||
(if (eq direction :up)
|
||||
(previous-logical-line 1 nil)
|
||||
(next-logical-line 1 nil))
|
||||
(move-to-column col))
|
||||
(multiple-cursors-mode)))
|
||||
|
||||
;;;###autoload
|
||||
(defun mc/edit-ends-of-lines ()
|
||||
"Add one cursor to the end of each line in the active region."
|
||||
(interactive)
|
||||
(mc/edit-lines)
|
||||
(mc/execute-command-for-all-cursors 'end-of-line))
|
||||
|
||||
;;;###autoload
|
||||
(defun mc/edit-beginnings-of-lines ()
|
||||
"Add one cursor to the beginning of each line in the active region."
|
||||
(interactive)
|
||||
(mc/edit-lines)
|
||||
(mc/execute-command-for-all-cursors 'beginning-of-line))
|
||||
|
||||
(provide 'mc-edit-lines)
|
||||
|
||||
;;; mc-edit-lines.el ends here
|
BIN
elpa/multiple-cursors-20191210.1759/mc-edit-lines.elc
Normal file
BIN
elpa/multiple-cursors-20191210.1759/mc-edit-lines.elc
Normal file
Binary file not shown.
|
@ -0,0 +1,107 @@
|
|||
;;; mc-hide-unmatched-lines.el
|
||||
|
||||
;; Copyright (C) 2014 Aleksey Fedotov
|
||||
|
||||
;; Author: Aleksey Fedotov <lexa@cfotr.com>
|
||||
;; Keywords: editing cursors
|
||||
|
||||
;; This program is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation, either version 3 of the License, or
|
||||
;; (at your option) any later version.
|
||||
|
||||
;; This program is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; This minor mode when enabled hides all lines where no cursors (and
|
||||
;; also hum/lines-to-expand below and above) To make use of this mode
|
||||
;; press "C-'" while multiple-cursor-mode is active. You can still
|
||||
;; edit lines while you are in mc-hide-unmatched-lines mode. To leave
|
||||
;; this mode press "<return>" or "C-g"
|
||||
;;
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'multiple-cursors-core)
|
||||
(require 'mc-mark-more)
|
||||
|
||||
(defvar hum/hide-unmatched-lines-mode-map (make-sparse-keymap)
|
||||
"Keymap for hide unmatched lines is mainly for rebinding C-g")
|
||||
|
||||
(define-key hum/hide-unmatched-lines-mode-map (kbd "C-g") 'hum/keyboard-quit)
|
||||
(define-key hum/hide-unmatched-lines-mode-map (kbd "<return>") 'hum/keyboard-quit)
|
||||
|
||||
(defun hum/keyboard-quit ()
|
||||
"Leave hide-unmatched-lines mode"
|
||||
(interactive)
|
||||
(mc-hide-unmatched-lines-mode 0))
|
||||
|
||||
;; used only in in multiple-cursors-mode-disabled-hook
|
||||
(defun hum/disable-hum-mode ()
|
||||
(mc-hide-unmatched-lines-mode 0))
|
||||
|
||||
;;;###autoload
|
||||
(define-minor-mode mc-hide-unmatched-lines-mode
|
||||
"Minor mode when enabled hides all lines where no cursors (and
|
||||
also hum/lines-to-expand below and above) To make use of this
|
||||
mode press \"C-'\" while multiple-cursor-mode is active. You can
|
||||
still edit lines while you are in mc-hide-unmatched-lines
|
||||
mode. To leave this mode press <return> or \"C-g\""
|
||||
nil " hu"
|
||||
hum/hide-unmatched-lines-mode-map
|
||||
(if mc-hide-unmatched-lines-mode
|
||||
;;just in case if mc mode will be disabled while hide-unmatched-lines is active
|
||||
(progn
|
||||
(hum/hide-unmatched-lines)
|
||||
(add-hook 'multiple-cursors-mode-disabled-hook 'hum/disable-hum-mode t t))
|
||||
(progn
|
||||
(hum/unhide-unmatched-lines)
|
||||
(remove-hook 'multiple-cursors-mode-disabled-hook 'hum/disable-hum-mode))))
|
||||
|
||||
(defconst hum/invisible-overlay-name 'hum/invisible-overlay-name)
|
||||
|
||||
(defcustom hum/lines-to-expand 2
|
||||
"How many lines below and above cursor to show"
|
||||
:type '(integer)
|
||||
:group 'multiple-cursors)
|
||||
|
||||
(defcustom hum/placeholder "..."
|
||||
"Placeholder which will be placed instead of hidden text"
|
||||
:type '(string)
|
||||
:group 'multiple-cursors)
|
||||
|
||||
(defun hum/add-invisible-overlay (begin end)
|
||||
(let ((overlay (make-overlay begin
|
||||
end
|
||||
(current-buffer)
|
||||
t
|
||||
nil
|
||||
)))
|
||||
(overlay-put overlay hum/invisible-overlay-name t)
|
||||
(overlay-put overlay 'invisible t)
|
||||
(overlay-put overlay 'intangible t)
|
||||
(overlay-put overlay 'evaporate t)
|
||||
(overlay-put overlay 'after-string hum/placeholder)))
|
||||
|
||||
(defun hum/hide-unmatched-lines ()
|
||||
(let ((begin (point-min)))
|
||||
(mc/for-each-cursor-ordered
|
||||
(save-excursion
|
||||
(goto-char (mc/cursor-beg cursor))
|
||||
(if (< begin (line-beginning-position (- hum/lines-to-expand)))
|
||||
(hum/add-invisible-overlay begin (line-end-position (- hum/lines-to-expand))))
|
||||
(setq begin (line-beginning-position (+ 2 hum/lines-to-expand)))))
|
||||
(hum/add-invisible-overlay begin (point-max))))
|
||||
|
||||
(defun hum/unhide-unmatched-lines ()
|
||||
(remove-overlays nil nil hum/invisible-overlay-name t))
|
||||
|
||||
(provide 'mc-hide-unmatched-lines-mode)
|
||||
(define-key mc/keymap (kbd "C-'") 'mc-hide-unmatched-lines-mode)
|
Binary file not shown.
709
elpa/multiple-cursors-20191210.1759/mc-mark-more.el
Normal file
709
elpa/multiple-cursors-20191210.1759/mc-mark-more.el
Normal file
|
@ -0,0 +1,709 @@
|
|||
;;; mc-mark-more.el
|
||||
|
||||
;; Copyright (C) 2012-2016 Magnar Sveen
|
||||
|
||||
;; Author: Magnar Sveen <magnars@gmail.com>
|
||||
;; Keywords: editing cursors
|
||||
|
||||
;; This program is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation, either version 3 of the License, or
|
||||
;; (at your option) any later version.
|
||||
|
||||
;; This program is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; This file contains functions to mark more parts of the buffer.
|
||||
;; See ./features/mark-more.feature for examples.
|
||||
|
||||
;; Please see multiple-cursors.el for more commentary.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'multiple-cursors-core)
|
||||
(require 'thingatpt)
|
||||
|
||||
(defun mc/cursor-end (cursor)
|
||||
(if (overlay-get cursor 'mark-active)
|
||||
(max (overlay-get cursor 'point)
|
||||
(overlay-get cursor 'mark))
|
||||
(overlay-get cursor 'point)))
|
||||
|
||||
(defun mc/cursor-beg (cursor)
|
||||
(if (overlay-get cursor 'mark-active)
|
||||
(min (overlay-get cursor 'point)
|
||||
(overlay-get cursor 'mark))
|
||||
(overlay-get cursor 'point)))
|
||||
|
||||
(defun mc/furthest-region-end ()
|
||||
(let ((end (max (mark) (point))))
|
||||
(mc/for-each-fake-cursor
|
||||
(setq end (max end (mc/cursor-end cursor))))
|
||||
end))
|
||||
|
||||
(defun mc/first-region-start ()
|
||||
(let ((beg (min (mark) (point))))
|
||||
(mc/for-each-fake-cursor
|
||||
(setq beg (min beg (mc/cursor-beg cursor))))
|
||||
beg))
|
||||
|
||||
(defun mc/furthest-cursor-before-point ()
|
||||
(let ((beg (if mark-active (min (mark) (point)) (point)))
|
||||
furthest)
|
||||
(mc/for-each-fake-cursor
|
||||
(when (< (mc/cursor-beg cursor) beg)
|
||||
(setq beg (mc/cursor-beg cursor))
|
||||
(setq furthest cursor)))
|
||||
furthest))
|
||||
|
||||
(defun mc/furthest-cursor-after-point ()
|
||||
(let ((end (if mark-active (max (mark) (point)) (point)))
|
||||
furthest)
|
||||
(mc/for-each-fake-cursor
|
||||
(when (> (mc/cursor-end cursor) end)
|
||||
(setq end (mc/cursor-end cursor))
|
||||
(setq furthest cursor)))
|
||||
furthest))
|
||||
|
||||
(defun mc/fake-cursor-at-point (&optional point)
|
||||
"Return the fake cursor with its point right at POINT (defaults
|
||||
to (point)), or nil."
|
||||
(setq point (or point (point)))
|
||||
(let ((cursors (mc/all-fake-cursors))
|
||||
(c nil))
|
||||
(catch 'found
|
||||
(while (setq c (pop cursors))
|
||||
(when (eq (marker-position (overlay-get c 'point))
|
||||
point)
|
||||
(throw 'found c))))))
|
||||
|
||||
(defun mc/region-strings ()
|
||||
(let ((strings (list (buffer-substring-no-properties (point) (mark)))))
|
||||
(mc/for-each-fake-cursor
|
||||
(add-to-list 'strings (buffer-substring-no-properties
|
||||
(mc/cursor-beg cursor)
|
||||
(mc/cursor-end cursor))))
|
||||
strings))
|
||||
|
||||
(defvar mc/enclose-search-term nil
|
||||
"How should mc/mark-more-* search for more matches?
|
||||
|
||||
Match everything: nil
|
||||
Match only whole words: 'words
|
||||
Match only whole symbols: 'symbols
|
||||
|
||||
Use like case-fold-search, don't recommend setting it globally.")
|
||||
|
||||
(defun mc/mark-more-like-this (skip-last direction)
|
||||
(let ((case-fold-search nil)
|
||||
(re (regexp-opt (mc/region-strings) mc/enclose-search-term))
|
||||
(point-out-of-order (cl-ecase direction
|
||||
(forwards (< (point) (mark)))
|
||||
(backwards (not (< (point) (mark))))))
|
||||
(furthest-cursor (cl-ecase direction
|
||||
(forwards (mc/furthest-cursor-after-point))
|
||||
(backwards (mc/furthest-cursor-before-point))))
|
||||
(start-char (cl-ecase direction
|
||||
(forwards (mc/furthest-region-end))
|
||||
(backwards (mc/first-region-start))))
|
||||
(search-function (cl-ecase direction
|
||||
(forwards 'search-forward-regexp)
|
||||
(backwards 'search-backward-regexp)))
|
||||
(match-point-getter (cl-ecase direction
|
||||
(forwards 'match-beginning)
|
||||
(backwards 'match-end))))
|
||||
(if (and skip-last (not furthest-cursor))
|
||||
(error "No cursors to be skipped")
|
||||
(mc/save-excursion
|
||||
(goto-char start-char)
|
||||
(when skip-last
|
||||
(mc/remove-fake-cursor furthest-cursor))
|
||||
(if (funcall search-function re nil t)
|
||||
(progn
|
||||
(push-mark (funcall match-point-getter 0))
|
||||
(when point-out-of-order
|
||||
(exchange-point-and-mark))
|
||||
(mc/create-fake-cursor-at-point))
|
||||
(user-error "no more matches found."))))))
|
||||
|
||||
;;;###autoload
|
||||
(defun mc/mark-next-like-this (arg)
|
||||
"Find and mark the next part of the buffer matching the currently active region
|
||||
If no region is active add a cursor on the next line
|
||||
With negative ARG, delete the last one instead.
|
||||
With zero ARG, skip the last one and mark next."
|
||||
(interactive "p")
|
||||
(if (< arg 0)
|
||||
(let ((cursor (mc/furthest-cursor-after-point)))
|
||||
(if cursor
|
||||
(mc/remove-fake-cursor cursor)
|
||||
(error "No cursors to be unmarked")))
|
||||
(if (region-active-p)
|
||||
(mc/mark-more-like-this (= arg 0) 'forwards)
|
||||
(mc/mark-lines arg 'forwards)))
|
||||
(mc/maybe-multiple-cursors-mode))
|
||||
|
||||
;;;###autoload
|
||||
(defun mc/mark-next-like-this-word (arg)
|
||||
"Find and mark the next part of the buffer matching the currently active region
|
||||
If no region is active, mark the word at the point and find the next match
|
||||
With negative ARG, delete the last one instead.
|
||||
With zero ARG, skip the last one and mark next."
|
||||
(interactive "p")
|
||||
(if (< arg 0)
|
||||
(let ((cursor (mc/furthest-cursor-after-point)))
|
||||
(if cursor
|
||||
(mc/remove-fake-cursor cursor)
|
||||
(error "No cursors to be unmarked")))
|
||||
(if (region-active-p)
|
||||
(mc/mark-more-like-this (= arg 0) 'forwards)
|
||||
(mc--select-thing-at-point 'word)
|
||||
(mc/mark-more-like-this (= arg 0) 'forwards)))
|
||||
(mc/maybe-multiple-cursors-mode))
|
||||
|
||||
(defun mc/mark-next-like-this-symbol (arg)
|
||||
"Find and mark the next part of the buffer matching the currently active region
|
||||
If no region is active, mark the symbol at the point and find the next match
|
||||
With negative ARG, delete the last one instead.
|
||||
With zero ARG, skip the last one and mark next."
|
||||
(interactive "p")
|
||||
(if (< arg 0)
|
||||
(let ((cursor (mc/furthest-cursor-after-point)))
|
||||
(if cursor
|
||||
(mc/remove-fake-cursor cursor)
|
||||
(error "No cursors to be unmarked")))
|
||||
(if (region-active-p)
|
||||
(mc/mark-more-like-this (= arg 0) 'forwards)
|
||||
(mc--select-thing-at-point 'symbol)
|
||||
(mc/mark-more-like-this (= arg 0) 'forwards)))
|
||||
(mc/maybe-multiple-cursors-mode))
|
||||
|
||||
|
||||
;;;###autoload
|
||||
(defun mc/mark-next-word-like-this (arg)
|
||||
"Find and mark the next word of the buffer matching the currently active region
|
||||
The matching region must be a whole word to be a match
|
||||
If no region is active, mark the symbol at the point and find the next match
|
||||
With negative ARG, delete the last one instead.
|
||||
With zero ARG, skip the last one and mark next."
|
||||
(interactive "p")
|
||||
(let ((mc/enclose-search-term 'words))
|
||||
(mc/mark-next-like-this arg)))
|
||||
|
||||
;;;###autoload
|
||||
(defun mc/mark-next-symbol-like-this (arg)
|
||||
"Find and mark the next symbol of the buffer matching the currently active region
|
||||
The matching region must be a whole symbol to be a match
|
||||
If no region is active, mark the symbol at the point and find the next match
|
||||
With negative ARG, delete the last one instead.
|
||||
With zero ARG, skip the last one and mark next."
|
||||
(interactive "p")
|
||||
(let ((mc/enclose-search-term 'symbols))
|
||||
(mc/mark-next-like-this arg)))
|
||||
|
||||
;;;###autoload
|
||||
(defun mc/mark-previous-like-this (arg)
|
||||
"Find and mark the previous part of the buffer matching the currently active region
|
||||
If no region is active add a cursor on the previous line
|
||||
With negative ARG, delete the last one instead.
|
||||
With zero ARG, skip the last one and mark next."
|
||||
(interactive "p")
|
||||
(if (< arg 0)
|
||||
(let ((cursor (mc/furthest-cursor-before-point)))
|
||||
(if cursor
|
||||
(mc/remove-fake-cursor cursor)
|
||||
(error "No cursors to be unmarked")))
|
||||
(if (region-active-p)
|
||||
(mc/mark-more-like-this (= arg 0) 'backwards)
|
||||
(mc/mark-lines arg 'backwards)))
|
||||
(mc/maybe-multiple-cursors-mode))
|
||||
|
||||
;;;###autoload
|
||||
(defun mc/mark-previous-like-this-word (arg)
|
||||
"Find and mark the previous part of the buffer matching the currently active region
|
||||
If no region is active, mark the word at the point and find the previous match
|
||||
With negative ARG, delete the last one instead.
|
||||
With zero ARG, skip the last one and mark previous."
|
||||
(interactive "p")
|
||||
(if (< arg 0)
|
||||
(let ((cursor (mc/furthest-cursor-after-point)))
|
||||
(if cursor
|
||||
(mc/remove-fake-cursor cursor)
|
||||
(error "No cursors to be unmarked")))
|
||||
(if (region-active-p)
|
||||
(mc/mark-more-like-this (= arg 0) 'backwards)
|
||||
(mc--select-thing-at-point 'word)
|
||||
(mc/mark-more-like-this (= arg 0) 'backwards)))
|
||||
(mc/maybe-multiple-cursors-mode))
|
||||
|
||||
(defun mc/mark-previous-like-this-symbol (arg)
|
||||
"Find and mark the previous part of the buffer matching the currently active region
|
||||
If no region is active, mark the symbol at the point and find the previous match
|
||||
With negative ARG, delete the last one instead.
|
||||
With zero ARG, skip the last one and mark previous."
|
||||
(interactive "p")
|
||||
(if (< arg 0)
|
||||
(let ((cursor (mc/furthest-cursor-after-point)))
|
||||
(if cursor
|
||||
(mc/remove-fake-cursor cursor)
|
||||
(error "No cursors to be unmarked")))
|
||||
(if (region-active-p)
|
||||
(mc/mark-more-like-this (= arg 0) 'backwards)
|
||||
(mc--select-thing-at-point 'symbol)
|
||||
(mc/mark-more-like-this (= arg 0) 'backwards)))
|
||||
(mc/maybe-multiple-cursors-mode))
|
||||
|
||||
|
||||
;;;###autoload
|
||||
(defun mc/mark-previous-word-like-this (arg)
|
||||
"Find and mark the previous part of the buffer matching the currently active region
|
||||
The matching region must be a whole word to be a match
|
||||
If no region is active add a cursor on the previous line
|
||||
With negative ARG, delete the last one instead.
|
||||
With zero ARG, skip the last one and mark next."
|
||||
(interactive "p")
|
||||
(let ((mc/enclose-search-term 'words))
|
||||
(mc/mark-previous-like-this arg)))
|
||||
|
||||
;;;###autoload
|
||||
(defun mc/mark-previous-symbol-like-this (arg)
|
||||
"Find and mark the previous part of the buffer matching the currently active region
|
||||
The matching region must be a whole symbol to be a match
|
||||
If no region is active add a cursor on the previous line
|
||||
With negative ARG, delete the last one instead.
|
||||
With zero ARG, skip the last one and mark next."
|
||||
(interactive "p")
|
||||
(let ((mc/enclose-search-term 'symbols))
|
||||
(mc/mark-previous-like-this arg)))
|
||||
|
||||
(defun mc/mark-lines (num-lines direction)
|
||||
(dotimes (i (if (= num-lines 0) 1 num-lines))
|
||||
(mc/save-excursion
|
||||
(let ((furthest-cursor (cl-ecase direction
|
||||
(forwards (mc/furthest-cursor-after-point))
|
||||
(backwards (mc/furthest-cursor-before-point)))))
|
||||
(when (overlayp furthest-cursor)
|
||||
(goto-char (overlay-get furthest-cursor 'point))
|
||||
(when (= num-lines 0)
|
||||
(mc/remove-fake-cursor furthest-cursor))))
|
||||
(cl-ecase direction
|
||||
(forwards (next-logical-line 1 nil))
|
||||
(backwards (previous-logical-line 1 nil)))
|
||||
(mc/create-fake-cursor-at-point))))
|
||||
|
||||
;;;###autoload
|
||||
(defun mc/mark-next-lines (arg)
|
||||
(interactive "p")
|
||||
(mc/mark-lines arg 'forwards)
|
||||
(mc/maybe-multiple-cursors-mode))
|
||||
|
||||
;;;###autoload
|
||||
(defun mc/mark-previous-lines (arg)
|
||||
(interactive "p")
|
||||
(mc/mark-lines arg 'backwards)
|
||||
(mc/maybe-multiple-cursors-mode))
|
||||
|
||||
;;;###autoload
|
||||
(defun mc/unmark-next-like-this ()
|
||||
"Deselect next part of the buffer matching the currently active region."
|
||||
(interactive)
|
||||
(mc/mark-next-like-this -1))
|
||||
|
||||
;;;###autoload
|
||||
(defun mc/unmark-previous-like-this ()
|
||||
"Deselect prev part of the buffer matching the currently active region."
|
||||
(interactive)
|
||||
(mc/mark-previous-like-this -1))
|
||||
|
||||
;;;###autoload
|
||||
(defun mc/skip-to-next-like-this ()
|
||||
"Skip the current one and select the next part of the buffer matching the currently active region."
|
||||
(interactive)
|
||||
(mc/mark-next-like-this 0))
|
||||
|
||||
;;;###autoload
|
||||
(defun mc/skip-to-previous-like-this ()
|
||||
"Skip the current one and select the prev part of the buffer matching the currently active region."
|
||||
(interactive)
|
||||
(mc/mark-previous-like-this 0))
|
||||
|
||||
;;;###autoload
|
||||
(defun mc/mark-all-like-this ()
|
||||
"Find and mark all the parts of the buffer matching the currently active region"
|
||||
(interactive)
|
||||
(unless (region-active-p)
|
||||
(error "Mark a region to match first."))
|
||||
(mc/remove-fake-cursors)
|
||||
(let ((master (point))
|
||||
(case-fold-search nil)
|
||||
(point-first (< (point) (mark)))
|
||||
(re (regexp-opt (mc/region-strings) mc/enclose-search-term)))
|
||||
(mc/save-excursion
|
||||
(goto-char 0)
|
||||
(while (search-forward-regexp re nil t)
|
||||
(push-mark (match-beginning 0))
|
||||
(when point-first (exchange-point-and-mark))
|
||||
(unless (= master (point))
|
||||
(mc/create-fake-cursor-at-point))
|
||||
(when point-first (exchange-point-and-mark)))))
|
||||
(if (> (mc/num-cursors) 1)
|
||||
(multiple-cursors-mode 1)
|
||||
(multiple-cursors-mode 0)))
|
||||
|
||||
(defun mc--select-thing-at-point (thing)
|
||||
(let ((bound (bounds-of-thing-at-point thing)))
|
||||
(when bound
|
||||
(set-mark (car bound))
|
||||
(goto-char (cdr bound))
|
||||
bound)))
|
||||
|
||||
(defun mc--select-thing-at-point-or-bark (thing)
|
||||
(unless (or (region-active-p) (mc--select-thing-at-point thing))
|
||||
(error "Mark a region or set cursor on a %s." thing)))
|
||||
|
||||
;;;###autoload
|
||||
(defun mc/mark-all-words-like-this ()
|
||||
(interactive)
|
||||
(mc--select-thing-at-point-or-bark 'word)
|
||||
(let ((mc/enclose-search-term 'words))
|
||||
(mc/mark-all-like-this)))
|
||||
|
||||
;;;###autoload
|
||||
(defun mc/mark-all-symbols-like-this ()
|
||||
(interactive)
|
||||
(mc--select-thing-at-point-or-bark 'symbol)
|
||||
(let ((mc/enclose-search-term 'symbols))
|
||||
(mc/mark-all-like-this)))
|
||||
|
||||
;;;###autoload
|
||||
(defun mc/mark-all-in-region (beg end &optional search)
|
||||
"Find and mark all the parts in the region matching the given search"
|
||||
(interactive "r")
|
||||
(let ((search (or search (read-from-minibuffer "Mark all in region: ")))
|
||||
(case-fold-search nil))
|
||||
(if (string= search "")
|
||||
(message "Mark aborted")
|
||||
(progn
|
||||
(mc/remove-fake-cursors)
|
||||
(goto-char beg)
|
||||
(while (search-forward search end t)
|
||||
(push-mark (match-beginning 0))
|
||||
(mc/create-fake-cursor-at-point))
|
||||
(let ((first (mc/furthest-cursor-before-point)))
|
||||
(if (not first)
|
||||
(error "Search failed for %S" search)
|
||||
(mc/pop-state-from-overlay first)))
|
||||
(if (> (mc/num-cursors) 1)
|
||||
(multiple-cursors-mode 1)
|
||||
(multiple-cursors-mode 0))))))
|
||||
|
||||
;;;###autoload
|
||||
(defun mc/mark-all-in-region-regexp (beg end)
|
||||
"Find and mark all the parts in the region matching the given regexp."
|
||||
(interactive "r")
|
||||
(let ((search (read-regexp "Mark regexp in region: "))
|
||||
(case-fold-search nil))
|
||||
(if (string= search "")
|
||||
(message "Mark aborted")
|
||||
(progn
|
||||
(mc/remove-fake-cursors)
|
||||
(goto-char beg)
|
||||
(let ((lastmatch))
|
||||
(while (and (< (point) end) ; can happen because of (forward-char)
|
||||
(search-forward-regexp search end t))
|
||||
(push-mark (match-beginning 0))
|
||||
(mc/create-fake-cursor-at-point)
|
||||
(setq lastmatch (point))
|
||||
(when (= (point) (match-beginning 0))
|
||||
(forward-char)))
|
||||
(unless lastmatch
|
||||
(error "Search failed for %S" search)))
|
||||
(goto-char (match-end 0))
|
||||
(if (< (mc/num-cursors) 3)
|
||||
(multiple-cursors-mode 0)
|
||||
(mc/pop-state-from-overlay (mc/furthest-cursor-before-point))
|
||||
(multiple-cursors-mode 1))))))
|
||||
|
||||
(when (not (fboundp 'set-temporary-overlay-map))
|
||||
;; Backport this function from newer emacs versions
|
||||
(defun set-temporary-overlay-map (map &optional keep-pred)
|
||||
"Set a new keymap that will only exist for a short period of time.
|
||||
The new keymap to use must be given in the MAP variable. When to
|
||||
remove the keymap depends on user input and KEEP-PRED:
|
||||
|
||||
- if KEEP-PRED is nil (the default), the keymap disappears as
|
||||
soon as any key is pressed, whether or not the key is in MAP;
|
||||
|
||||
- if KEEP-PRED is t, the keymap disappears as soon as a key *not*
|
||||
in MAP is pressed;
|
||||
|
||||
- otherwise, KEEP-PRED must be a 0-arguments predicate that will
|
||||
decide if the keymap should be removed (if predicate returns
|
||||
nil) or kept (otherwise). The predicate will be called after
|
||||
each key sequence."
|
||||
|
||||
(let* ((clearfunsym (make-symbol "clear-temporary-overlay-map"))
|
||||
(overlaysym (make-symbol "t"))
|
||||
(alist (list (cons overlaysym map)))
|
||||
(clearfun
|
||||
`(lambda ()
|
||||
(unless ,(cond ((null keep-pred) nil)
|
||||
((eq t keep-pred)
|
||||
`(eq this-command
|
||||
(lookup-key ',map
|
||||
(this-command-keys-vector))))
|
||||
(t `(funcall ',keep-pred)))
|
||||
(remove-hook 'pre-command-hook ',clearfunsym)
|
||||
(setq emulation-mode-map-alists
|
||||
(delq ',alist emulation-mode-map-alists))))))
|
||||
(set overlaysym overlaysym)
|
||||
(fset clearfunsym clearfun)
|
||||
(add-hook 'pre-command-hook clearfunsym)
|
||||
|
||||
(push alist emulation-mode-map-alists))))
|
||||
|
||||
;;;###autoload
|
||||
(defun mc/mark-more-like-this-extended ()
|
||||
"Like mark-more-like-this, but then lets you adjust with arrows key.
|
||||
The adjustments work like this:
|
||||
|
||||
<up> Mark previous like this and set direction to 'up
|
||||
<down> Mark next like this and set direction to 'down
|
||||
|
||||
If direction is 'up:
|
||||
|
||||
<left> Skip past the cursor furthest up
|
||||
<right> Remove the cursor furthest up
|
||||
|
||||
If direction is 'down:
|
||||
|
||||
<left> Remove the cursor furthest down
|
||||
<right> Skip past the cursor furthest down
|
||||
|
||||
The bindings for these commands can be changed. See `mc/mark-more-like-this-extended-keymap'."
|
||||
(interactive)
|
||||
(mc/mmlte--down)
|
||||
(set-temporary-overlay-map mc/mark-more-like-this-extended-keymap t))
|
||||
|
||||
(defvar mc/mark-more-like-this-extended-direction nil
|
||||
"When using mc/mark-more-like-this-extended are we working on the next or previous cursors?")
|
||||
|
||||
(make-variable-buffer-local 'mc/mark-more-like-this-extended)
|
||||
|
||||
(defun mc/mmlte--message ()
|
||||
(if (eq mc/mark-more-like-this-extended-direction 'up)
|
||||
(message "<up> to mark previous, <left> to skip, <right> to remove, <down> to mark next")
|
||||
(message "<down> to mark next, <right> to skip, <left> to remove, <up> to mark previous")))
|
||||
|
||||
(defun mc/mmlte--up ()
|
||||
(interactive)
|
||||
(mc/mark-previous-like-this 1)
|
||||
(setq mc/mark-more-like-this-extended-direction 'up)
|
||||
(mc/mmlte--message))
|
||||
|
||||
(defun mc/mmlte--down ()
|
||||
(interactive)
|
||||
(mc/mark-next-like-this 1)
|
||||
(setq mc/mark-more-like-this-extended-direction 'down)
|
||||
(mc/mmlte--message))
|
||||
|
||||
(defun mc/mmlte--left ()
|
||||
(interactive)
|
||||
(if (eq mc/mark-more-like-this-extended-direction 'down)
|
||||
(mc/unmark-next-like-this)
|
||||
(mc/skip-to-previous-like-this))
|
||||
(mc/mmlte--message))
|
||||
|
||||
(defun mc/mmlte--right ()
|
||||
(interactive)
|
||||
(if (eq mc/mark-more-like-this-extended-direction 'up)
|
||||
(mc/unmark-previous-like-this)
|
||||
(mc/skip-to-next-like-this))
|
||||
(mc/mmlte--message))
|
||||
|
||||
(defvar mc/mark-more-like-this-extended-keymap (make-sparse-keymap))
|
||||
|
||||
(define-key mc/mark-more-like-this-extended-keymap (kbd "<up>") 'mc/mmlte--up)
|
||||
(define-key mc/mark-more-like-this-extended-keymap (kbd "<down>") 'mc/mmlte--down)
|
||||
(define-key mc/mark-more-like-this-extended-keymap (kbd "<left>") 'mc/mmlte--left)
|
||||
(define-key mc/mark-more-like-this-extended-keymap (kbd "<right>") 'mc/mmlte--right)
|
||||
|
||||
(defvar mc--restrict-mark-all-to-symbols nil)
|
||||
|
||||
;;;###autoload
|
||||
(defun mc/mark-all-like-this-dwim (arg)
|
||||
"Tries to guess what you want to mark all of.
|
||||
Can be pressed multiple times to increase selection.
|
||||
|
||||
With prefix, it behaves the same as original `mc/mark-all-like-this'"
|
||||
(interactive "P")
|
||||
(if arg
|
||||
(mc/mark-all-like-this)
|
||||
(if (and (not (use-region-p))
|
||||
(derived-mode-p 'sgml-mode)
|
||||
(mc--on-tag-name-p))
|
||||
(mc/mark-sgml-tag-pair)
|
||||
(let ((before (mc/num-cursors)))
|
||||
(unless (eq last-command 'mc/mark-all-like-this-dwim)
|
||||
(setq mc--restrict-mark-all-to-symbols nil))
|
||||
(unless (use-region-p)
|
||||
(mc--mark-symbol-at-point)
|
||||
(setq mc--restrict-mark-all-to-symbols t))
|
||||
(if mc--restrict-mark-all-to-symbols
|
||||
(mc/mark-all-symbols-like-this-in-defun)
|
||||
(mc/mark-all-like-this-in-defun))
|
||||
(when (<= (mc/num-cursors) before)
|
||||
(if mc--restrict-mark-all-to-symbols
|
||||
(mc/mark-all-symbols-like-this)
|
||||
(mc/mark-all-like-this)))
|
||||
(when (<= (mc/num-cursors) before)
|
||||
(mc/mark-all-like-this))))))
|
||||
|
||||
;;;###autoload
|
||||
(defun mc/mark-all-dwim (arg)
|
||||
"Tries even harder to guess what you want to mark all of.
|
||||
|
||||
If the region is active and spans multiple lines, it will behave
|
||||
as if `mc/mark-all-in-region'. With the prefix ARG, it will call
|
||||
`mc/edit-lines' instead.
|
||||
|
||||
If the region is inactive or on a single line, it will behave like
|
||||
`mc/mark-all-like-this-dwim'."
|
||||
(interactive "P")
|
||||
(if (and (use-region-p)
|
||||
(not (> (mc/num-cursors) 1))
|
||||
(not (= (mc/line-number-at-pos (region-beginning))
|
||||
(mc/line-number-at-pos (region-end)))))
|
||||
(if arg
|
||||
(call-interactively 'mc/edit-lines)
|
||||
(call-interactively 'mc/mark-all-in-region))
|
||||
(progn
|
||||
(setq this-command 'mc/mark-all-like-this-dwim)
|
||||
(mc/mark-all-like-this-dwim arg))))
|
||||
|
||||
(defun mc--in-defun ()
|
||||
(bounds-of-thing-at-point 'defun))
|
||||
|
||||
;;;###autoload
|
||||
(defun mc/mark-all-like-this-in-defun ()
|
||||
"Mark all like this in defun."
|
||||
(interactive)
|
||||
(if (mc--in-defun)
|
||||
(save-restriction
|
||||
(widen)
|
||||
(narrow-to-defun)
|
||||
(mc/mark-all-like-this))
|
||||
(mc/mark-all-like-this)))
|
||||
|
||||
;;;###autoload
|
||||
(defun mc/mark-all-words-like-this-in-defun ()
|
||||
"Mark all words like this in defun."
|
||||
(interactive)
|
||||
(mc--select-thing-at-point-or-bark 'word)
|
||||
(if (mc--in-defun)
|
||||
(save-restriction
|
||||
(widen)
|
||||
(narrow-to-defun)
|
||||
(mc/mark-all-words-like-this))
|
||||
(mc/mark-all-words-like-this)))
|
||||
|
||||
;;;###autoload
|
||||
(defun mc/mark-all-symbols-like-this-in-defun ()
|
||||
"Mark all symbols like this in defun."
|
||||
(interactive)
|
||||
(mc--select-thing-at-point-or-bark 'symbol)
|
||||
(if (mc--in-defun)
|
||||
(save-restriction
|
||||
(widen)
|
||||
(narrow-to-defun)
|
||||
(mc/mark-all-symbols-like-this))
|
||||
(mc/mark-all-symbols-like-this)))
|
||||
|
||||
(defun mc--mark-symbol-at-point ()
|
||||
"Select the symbol under cursor"
|
||||
(interactive)
|
||||
(when (not (use-region-p))
|
||||
(let ((b (bounds-of-thing-at-point 'symbol)))
|
||||
(goto-char (car b))
|
||||
(set-mark (cdr b)))))
|
||||
|
||||
(defun mc--get-nice-sgml-context ()
|
||||
(car
|
||||
(last
|
||||
(progn
|
||||
(when (looking-at "<") (forward-char 1))
|
||||
(when (looking-back ">") (forward-char -1))
|
||||
(sgml-get-context)))))
|
||||
|
||||
(defun mc--on-tag-name-p ()
|
||||
(let* ((context (save-excursion (mc--get-nice-sgml-context)))
|
||||
(tag-name-len (length (aref context 4)))
|
||||
(beg (aref context 2))
|
||||
(end (+ beg tag-name-len (if (eq 'open (aref context 1)) 1 3))))
|
||||
(and context
|
||||
(>= (point) beg)
|
||||
(<= (point) end))))
|
||||
|
||||
;;;###autoload
|
||||
(defun mc/toggle-cursor-on-click (event)
|
||||
"Add a cursor where you click, or remove a fake cursor that is
|
||||
already there."
|
||||
(interactive "e")
|
||||
(mouse-minibuffer-check event)
|
||||
;; Use event-end in case called from mouse-drag-region.
|
||||
;; If EVENT is a click, event-end and event-start give same value.
|
||||
(let ((position (event-end event)))
|
||||
(if (not (windowp (posn-window position)))
|
||||
(error "Position not in text area of window"))
|
||||
(select-window (posn-window position))
|
||||
(let ((pt (posn-point position)))
|
||||
(if (numberp pt)
|
||||
;; is there a fake cursor with the actual *point* right where we are?
|
||||
(let ((existing (mc/fake-cursor-at-point pt)))
|
||||
(if existing
|
||||
(mc/remove-fake-cursor existing)
|
||||
(save-excursion
|
||||
(goto-char pt)
|
||||
(mc/create-fake-cursor-at-point))))))
|
||||
(mc/maybe-multiple-cursors-mode)))
|
||||
|
||||
;;;###autoload
|
||||
(defalias 'mc/add-cursor-on-click 'mc/toggle-cursor-on-click)
|
||||
|
||||
;;;###autoload
|
||||
(defun mc/mark-sgml-tag-pair ()
|
||||
"Mark the tag we're in and its pair for renaming."
|
||||
(interactive)
|
||||
(when (not (mc--inside-tag-p))
|
||||
(error "Place point inside tag to rename."))
|
||||
(let ((context (mc--get-nice-sgml-context)))
|
||||
(if (looking-at "</")
|
||||
(setq context (car (last (sgml-get-context)))))
|
||||
(goto-char (aref context 2))
|
||||
(let* ((tag-name (aref context 4))
|
||||
(num-chars (length tag-name))
|
||||
(master-start (1+ (point)))
|
||||
(mirror-end (save-excursion
|
||||
(sgml-skip-tag-forward 1)
|
||||
(1- (point)))))
|
||||
(goto-char (- mirror-end num-chars))
|
||||
(set-mark mirror-end)
|
||||
(mc/create-fake-cursor-at-point)
|
||||
(goto-char master-start)
|
||||
(set-mark (+ (point) num-chars))))
|
||||
(mc/maybe-multiple-cursors-mode))
|
||||
|
||||
(defun mc--inside-tag-p ()
|
||||
(save-excursion
|
||||
(not (null (sgml-get-context)))))
|
||||
|
||||
(provide 'mc-mark-more)
|
||||
|
||||
;;; mc-mark-more.el ends here
|
BIN
elpa/multiple-cursors-20191210.1759/mc-mark-more.elc
Normal file
BIN
elpa/multiple-cursors-20191210.1759/mc-mark-more.elc
Normal file
Binary file not shown.
22
elpa/multiple-cursors-20191210.1759/mc-mark-pop.el
Normal file
22
elpa/multiple-cursors-20191210.1759/mc-mark-pop.el
Normal file
|
@ -0,0 +1,22 @@
|
|||
;;; mc-mark-pop.el --- Pop cursors off of the mark stack
|
||||
|
||||
(require 'multiple-cursors-core)
|
||||
|
||||
;;;###autoload
|
||||
(defun mc/mark-pop ()
|
||||
"Add a cursor at the current point, pop off mark ring and jump
|
||||
to the popped mark."
|
||||
(interactive)
|
||||
;; If the mark happens to be at the current point, just pop that one off.
|
||||
(while (eql (mark) (point))
|
||||
(pop-mark))
|
||||
(mc/create-fake-cursor-at-point)
|
||||
(exchange-point-and-mark)
|
||||
(pop-mark)
|
||||
(mc/maybe-multiple-cursors-mode))
|
||||
|
||||
;; A good key binding for this feature is perhaps "C-S-p" ('p' for pop).
|
||||
|
||||
(provide 'mc-mark-pop)
|
||||
|
||||
;;; mc-mark-pop.el ends here
|
BIN
elpa/multiple-cursors-20191210.1759/mc-mark-pop.elc
Normal file
BIN
elpa/multiple-cursors-20191210.1759/mc-mark-pop.elc
Normal file
Binary file not shown.
150
elpa/multiple-cursors-20191210.1759/mc-separate-operations.el
Normal file
150
elpa/multiple-cursors-20191210.1759/mc-separate-operations.el
Normal file
|
@ -0,0 +1,150 @@
|
|||
;;; mc-separate-operations.el - functions that work differently on each cursor
|
||||
|
||||
;; Copyright (C) 2012-2016 Magnar Sveen
|
||||
|
||||
;; Author: Magnar Sveen <magnars@gmail.com>
|
||||
;; Keywords: editing cursors
|
||||
|
||||
;; This program is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation, either version 3 of the License, or
|
||||
;; (at your option) any later version.
|
||||
|
||||
;; This program is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; This file contains functions that work differently on each cursor,
|
||||
;; instead of treating all of them the same.
|
||||
|
||||
;; Please see multiple-cursors.el for more commentary.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'multiple-cursors-core)
|
||||
|
||||
(defcustom mc/insert-numbers-default 0
|
||||
"The default number at which to start counting for
|
||||
`mc/insert-numbers'"
|
||||
:type 'integer
|
||||
:group 'multiple-cursors)
|
||||
|
||||
(defvar mc--insert-numbers-number 0)
|
||||
|
||||
;;;###autoload
|
||||
(defun mc/insert-numbers (arg)
|
||||
"Insert increasing numbers for each cursor, starting at
|
||||
`mc/insert-numbers-default' or ARG."
|
||||
(interactive "P")
|
||||
(setq mc--insert-numbers-number (or (and arg (prefix-numeric-value arg))
|
||||
mc/insert-numbers-default))
|
||||
(mc/for-each-cursor-ordered
|
||||
(mc/execute-command-for-fake-cursor 'mc--insert-number-and-increase cursor)))
|
||||
|
||||
(defun mc--insert-number-and-increase ()
|
||||
(interactive)
|
||||
(insert (number-to-string mc--insert-numbers-number))
|
||||
(setq mc--insert-numbers-number (1+ mc--insert-numbers-number)))
|
||||
|
||||
(defun mc--ordered-region-strings ()
|
||||
(let (strings)
|
||||
(save-excursion
|
||||
(mc/for-each-cursor-ordered
|
||||
(setq strings (cons (buffer-substring-no-properties
|
||||
(mc/cursor-beg cursor)
|
||||
(mc/cursor-end cursor)) strings))))
|
||||
(nreverse strings)))
|
||||
|
||||
(defvar mc--insert-letters-number 0)
|
||||
|
||||
;;;###autoload
|
||||
(defun mc/insert-letters (arg)
|
||||
"Insert increasing letters for each cursor, starting at 0 or ARG.
|
||||
Where letter[0]=a letter[2]=c letter[26]=aa"
|
||||
(interactive "P")
|
||||
(setq mc--insert-letters-number (or (and arg (prefix-numeric-value arg))
|
||||
0))
|
||||
(mc/for-each-cursor-ordered
|
||||
(mc/execute-command-for-fake-cursor 'mc--insert-letter-and-increase cursor)))
|
||||
|
||||
(defun mc--number-to-letters (number)
|
||||
(let ((letter
|
||||
(char-to-string
|
||||
(+ (mod number 26) ?a)))
|
||||
(number2 (/ number 26)))
|
||||
(if (> number2 0)
|
||||
(concat (mc--number-to-letters (- number2 1)) letter)
|
||||
letter)))
|
||||
|
||||
(defun mc--insert-letter-and-increase ()
|
||||
(interactive)
|
||||
(insert (mc--number-to-letters mc--insert-letters-number))
|
||||
(setq mc--insert-letters-number (1+ mc--insert-letters-number)))
|
||||
|
||||
(defvar mc--strings-to-replace nil)
|
||||
|
||||
(defun mc--replace-region-strings-1 ()
|
||||
(interactive)
|
||||
(delete-region (region-beginning) (region-end))
|
||||
(save-excursion (insert (car mc--strings-to-replace)))
|
||||
(setq mc--strings-to-replace (cdr mc--strings-to-replace)))
|
||||
|
||||
(defun mc--replace-region-strings ()
|
||||
(mc/for-each-cursor-ordered
|
||||
(mc/execute-command-for-fake-cursor 'mc--replace-region-strings-1 cursor)))
|
||||
|
||||
;;;###autoload
|
||||
(defun mc/reverse-regions ()
|
||||
(interactive)
|
||||
(if (not multiple-cursors-mode)
|
||||
(progn
|
||||
(mc/mark-next-lines 1)
|
||||
(mc/reverse-regions)
|
||||
(multiple-cursors-mode 0))
|
||||
(unless (use-region-p)
|
||||
(mc/execute-command-for-all-cursors 'mark-sexp))
|
||||
(setq mc--strings-to-replace (nreverse (mc--ordered-region-strings)))
|
||||
(mc--replace-region-strings)))
|
||||
|
||||
;;;###autoload
|
||||
(defun mc/sort-regions ()
|
||||
(interactive)
|
||||
(unless (use-region-p)
|
||||
(mc/execute-command-for-all-cursors 'mark-sexp))
|
||||
(setq mc--strings-to-replace (sort (mc--ordered-region-strings) 'string<))
|
||||
(mc--replace-region-strings))
|
||||
|
||||
|
||||
;;;###autoload
|
||||
(defun mc/vertical-align (character)
|
||||
"Aligns all cursors vertically with a given CHARACTER to the one with the
|
||||
highest column number (the rightest).
|
||||
Might not behave as intended if more than one cursors are on the same line."
|
||||
(interactive "c")
|
||||
(let ((rightest-column (current-column)))
|
||||
(mc/execute-command-for-all-cursors
|
||||
(lambda () "get the rightest cursor"
|
||||
(interactive)
|
||||
(setq rightest-column (max (current-column) rightest-column))
|
||||
))
|
||||
(mc/execute-command-for-all-cursors
|
||||
(lambda ()
|
||||
(interactive)
|
||||
(let ((missing-spaces (- rightest-column (current-column))))
|
||||
(save-excursion (insert (make-string missing-spaces character)))
|
||||
(forward-char missing-spaces))))))
|
||||
|
||||
;;;###autoload
|
||||
(defun mc/vertical-align-with-space ()
|
||||
"Aligns all cursors with whitespace like `mc/vertical-align' does"
|
||||
(interactive)
|
||||
(mc/vertical-align 32))
|
||||
|
||||
(provide 'mc-separate-operations)
|
||||
;;; mc-separate-operations.el ends here
|
BIN
elpa/multiple-cursors-20191210.1759/mc-separate-operations.elc
Normal file
BIN
elpa/multiple-cursors-20191210.1759/mc-separate-operations.elc
Normal file
Binary file not shown.
|
@ -0,0 +1,362 @@
|
|||
;;; multiple-cursors-autoloads.el --- automatically extracted autoloads
|
||||
;;
|
||||
;;; Code:
|
||||
|
||||
(add-to-list 'load-path (directory-file-name
|
||||
(or (file-name-directory #$) (car load-path))))
|
||||
|
||||
|
||||
;;;### (autoloads nil "mc-cycle-cursors" "mc-cycle-cursors.el" (0
|
||||
;;;;;; 0 0 0))
|
||||
;;; Generated autoloads from mc-cycle-cursors.el
|
||||
|
||||
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mc-cycle-cursors" '("mc/")))
|
||||
|
||||
;;;***
|
||||
|
||||
;;;### (autoloads nil "mc-edit-lines" "mc-edit-lines.el" (0 0 0 0))
|
||||
;;; Generated autoloads from mc-edit-lines.el
|
||||
|
||||
(autoload 'mc/edit-lines "mc-edit-lines" "\
|
||||
Add one cursor to each line of the active region.
|
||||
Starts from mark and moves in straight down or up towards the
|
||||
line point is on.
|
||||
|
||||
What is done with lines which are not long enough is governed by
|
||||
`mc/edit-lines-empty-lines'. The prefix argument ARG can be used
|
||||
to override this. If ARG is a symbol (when called from Lisp),
|
||||
that symbol is used instead of `mc/edit-lines-empty-lines'.
|
||||
Otherwise, if ARG negative, short lines will be ignored. Any
|
||||
other non-nil value will cause short lines to be padded.
|
||||
|
||||
\(fn &optional ARG)" t nil)
|
||||
|
||||
(autoload 'mc/edit-ends-of-lines "mc-edit-lines" "\
|
||||
Add one cursor to the end of each line in the active region.
|
||||
|
||||
\(fn)" t nil)
|
||||
|
||||
(autoload 'mc/edit-beginnings-of-lines "mc-edit-lines" "\
|
||||
Add one cursor to the beginning of each line in the active region.
|
||||
|
||||
\(fn)" t nil)
|
||||
|
||||
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mc-edit-lines" '("mc/edit-lines-empty-lines")))
|
||||
|
||||
;;;***
|
||||
|
||||
;;;### (autoloads nil "mc-hide-unmatched-lines-mode" "mc-hide-unmatched-lines-mode.el"
|
||||
;;;;;; (0 0 0 0))
|
||||
;;; Generated autoloads from mc-hide-unmatched-lines-mode.el
|
||||
|
||||
(autoload 'mc-hide-unmatched-lines-mode "mc-hide-unmatched-lines-mode" "\
|
||||
Minor mode when enabled hides all lines where no cursors (and
|
||||
also hum/lines-to-expand below and above) To make use of this
|
||||
mode press \"C-'\" while multiple-cursor-mode is active. You can
|
||||
still edit lines while you are in mc-hide-unmatched-lines
|
||||
mode. To leave this mode press <return> or \"C-g\"
|
||||
|
||||
\(fn &optional ARG)" t nil)
|
||||
|
||||
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mc-hide-unmatched-lines-mode" '("hum/")))
|
||||
|
||||
;;;***
|
||||
|
||||
;;;### (autoloads nil "mc-mark-more" "mc-mark-more.el" (0 0 0 0))
|
||||
;;; Generated autoloads from mc-mark-more.el
|
||||
|
||||
(autoload 'mc/mark-next-like-this "mc-mark-more" "\
|
||||
Find and mark the next part of the buffer matching the currently active region
|
||||
If no region is active add a cursor on the next line
|
||||
With negative ARG, delete the last one instead.
|
||||
With zero ARG, skip the last one and mark next.
|
||||
|
||||
\(fn ARG)" t nil)
|
||||
|
||||
(autoload 'mc/mark-next-like-this-word "mc-mark-more" "\
|
||||
Find and mark the next part of the buffer matching the currently active region
|
||||
If no region is active, mark the word at the point and find the next match
|
||||
With negative ARG, delete the last one instead.
|
||||
With zero ARG, skip the last one and mark next.
|
||||
|
||||
\(fn ARG)" t nil)
|
||||
|
||||
(autoload 'mc/mark-next-word-like-this "mc-mark-more" "\
|
||||
Find and mark the next word of the buffer matching the currently active region
|
||||
The matching region must be a whole word to be a match
|
||||
If no region is active, mark the symbol at the point and find the next match
|
||||
With negative ARG, delete the last one instead.
|
||||
With zero ARG, skip the last one and mark next.
|
||||
|
||||
\(fn ARG)" t nil)
|
||||
|
||||
(autoload 'mc/mark-next-symbol-like-this "mc-mark-more" "\
|
||||
Find and mark the next symbol of the buffer matching the currently active region
|
||||
The matching region must be a whole symbol to be a match
|
||||
If no region is active, mark the symbol at the point and find the next match
|
||||
With negative ARG, delete the last one instead.
|
||||
With zero ARG, skip the last one and mark next.
|
||||
|
||||
\(fn ARG)" t nil)
|
||||
|
||||
(autoload 'mc/mark-previous-like-this "mc-mark-more" "\
|
||||
Find and mark the previous part of the buffer matching the currently active region
|
||||
If no region is active add a cursor on the previous line
|
||||
With negative ARG, delete the last one instead.
|
||||
With zero ARG, skip the last one and mark next.
|
||||
|
||||
\(fn ARG)" t nil)
|
||||
|
||||
(autoload 'mc/mark-previous-like-this-word "mc-mark-more" "\
|
||||
Find and mark the previous part of the buffer matching the currently active region
|
||||
If no region is active, mark the word at the point and find the previous match
|
||||
With negative ARG, delete the last one instead.
|
||||
With zero ARG, skip the last one and mark previous.
|
||||
|
||||
\(fn ARG)" t nil)
|
||||
|
||||
(autoload 'mc/mark-previous-word-like-this "mc-mark-more" "\
|
||||
Find and mark the previous part of the buffer matching the currently active region
|
||||
The matching region must be a whole word to be a match
|
||||
If no region is active add a cursor on the previous line
|
||||
With negative ARG, delete the last one instead.
|
||||
With zero ARG, skip the last one and mark next.
|
||||
|
||||
\(fn ARG)" t nil)
|
||||
|
||||
(autoload 'mc/mark-previous-symbol-like-this "mc-mark-more" "\
|
||||
Find and mark the previous part of the buffer matching the currently active region
|
||||
The matching region must be a whole symbol to be a match
|
||||
If no region is active add a cursor on the previous line
|
||||
With negative ARG, delete the last one instead.
|
||||
With zero ARG, skip the last one and mark next.
|
||||
|
||||
\(fn ARG)" t nil)
|
||||
|
||||
(autoload 'mc/mark-next-lines "mc-mark-more" "\
|
||||
|
||||
|
||||
\(fn ARG)" t nil)
|
||||
|
||||
(autoload 'mc/mark-previous-lines "mc-mark-more" "\
|
||||
|
||||
|
||||
\(fn ARG)" t nil)
|
||||
|
||||
(autoload 'mc/unmark-next-like-this "mc-mark-more" "\
|
||||
Deselect next part of the buffer matching the currently active region.
|
||||
|
||||
\(fn)" t nil)
|
||||
|
||||
(autoload 'mc/unmark-previous-like-this "mc-mark-more" "\
|
||||
Deselect prev part of the buffer matching the currently active region.
|
||||
|
||||
\(fn)" t nil)
|
||||
|
||||
(autoload 'mc/skip-to-next-like-this "mc-mark-more" "\
|
||||
Skip the current one and select the next part of the buffer matching the currently active region.
|
||||
|
||||
\(fn)" t nil)
|
||||
|
||||
(autoload 'mc/skip-to-previous-like-this "mc-mark-more" "\
|
||||
Skip the current one and select the prev part of the buffer matching the currently active region.
|
||||
|
||||
\(fn)" t nil)
|
||||
|
||||
(autoload 'mc/mark-all-like-this "mc-mark-more" "\
|
||||
Find and mark all the parts of the buffer matching the currently active region
|
||||
|
||||
\(fn)" t nil)
|
||||
|
||||
(autoload 'mc/mark-all-words-like-this "mc-mark-more" "\
|
||||
|
||||
|
||||
\(fn)" t nil)
|
||||
|
||||
(autoload 'mc/mark-all-symbols-like-this "mc-mark-more" "\
|
||||
|
||||
|
||||
\(fn)" t nil)
|
||||
|
||||
(autoload 'mc/mark-all-in-region "mc-mark-more" "\
|
||||
Find and mark all the parts in the region matching the given search
|
||||
|
||||
\(fn BEG END &optional SEARCH)" t nil)
|
||||
|
||||
(autoload 'mc/mark-all-in-region-regexp "mc-mark-more" "\
|
||||
Find and mark all the parts in the region matching the given regexp.
|
||||
|
||||
\(fn BEG END)" t nil)
|
||||
|
||||
(autoload 'mc/mark-more-like-this-extended "mc-mark-more" "\
|
||||
Like mark-more-like-this, but then lets you adjust with arrows key.
|
||||
The adjustments work like this:
|
||||
|
||||
<up> Mark previous like this and set direction to 'up
|
||||
<down> Mark next like this and set direction to 'down
|
||||
|
||||
If direction is 'up:
|
||||
|
||||
<left> Skip past the cursor furthest up
|
||||
<right> Remove the cursor furthest up
|
||||
|
||||
If direction is 'down:
|
||||
|
||||
<left> Remove the cursor furthest down
|
||||
<right> Skip past the cursor furthest down
|
||||
|
||||
The bindings for these commands can be changed. See `mc/mark-more-like-this-extended-keymap'.
|
||||
|
||||
\(fn)" t nil)
|
||||
|
||||
(autoload 'mc/mark-all-like-this-dwim "mc-mark-more" "\
|
||||
Tries to guess what you want to mark all of.
|
||||
Can be pressed multiple times to increase selection.
|
||||
|
||||
With prefix, it behaves the same as original `mc/mark-all-like-this'
|
||||
|
||||
\(fn ARG)" t nil)
|
||||
|
||||
(autoload 'mc/mark-all-dwim "mc-mark-more" "\
|
||||
Tries even harder to guess what you want to mark all of.
|
||||
|
||||
If the region is active and spans multiple lines, it will behave
|
||||
as if `mc/mark-all-in-region'. With the prefix ARG, it will call
|
||||
`mc/edit-lines' instead.
|
||||
|
||||
If the region is inactive or on a single line, it will behave like
|
||||
`mc/mark-all-like-this-dwim'.
|
||||
|
||||
\(fn ARG)" t nil)
|
||||
|
||||
(autoload 'mc/mark-all-like-this-in-defun "mc-mark-more" "\
|
||||
Mark all like this in defun.
|
||||
|
||||
\(fn)" t nil)
|
||||
|
||||
(autoload 'mc/mark-all-words-like-this-in-defun "mc-mark-more" "\
|
||||
Mark all words like this in defun.
|
||||
|
||||
\(fn)" t nil)
|
||||
|
||||
(autoload 'mc/mark-all-symbols-like-this-in-defun "mc-mark-more" "\
|
||||
Mark all symbols like this in defun.
|
||||
|
||||
\(fn)" t nil)
|
||||
|
||||
(autoload 'mc/toggle-cursor-on-click "mc-mark-more" "\
|
||||
Add a cursor where you click, or remove a fake cursor that is
|
||||
already there.
|
||||
|
||||
\(fn EVENT)" t nil)
|
||||
|
||||
(defalias 'mc/add-cursor-on-click 'mc/toggle-cursor-on-click)
|
||||
|
||||
(autoload 'mc/mark-sgml-tag-pair "mc-mark-more" "\
|
||||
Mark the tag we're in and its pair for renaming.
|
||||
|
||||
\(fn)" t nil)
|
||||
|
||||
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mc-mark-more" '("mc/" "mc--")))
|
||||
|
||||
;;;***
|
||||
|
||||
;;;### (autoloads nil "mc-mark-pop" "mc-mark-pop.el" (0 0 0 0))
|
||||
;;; Generated autoloads from mc-mark-pop.el
|
||||
|
||||
(autoload 'mc/mark-pop "mc-mark-pop" "\
|
||||
Add a cursor at the current point, pop off mark ring and jump
|
||||
to the popped mark.
|
||||
|
||||
\(fn)" t nil)
|
||||
|
||||
;;;***
|
||||
|
||||
;;;### (autoloads nil "mc-separate-operations" "mc-separate-operations.el"
|
||||
;;;;;; (0 0 0 0))
|
||||
;;; Generated autoloads from mc-separate-operations.el
|
||||
|
||||
(autoload 'mc/insert-numbers "mc-separate-operations" "\
|
||||
Insert increasing numbers for each cursor, starting at
|
||||
`mc/insert-numbers-default' or ARG.
|
||||
|
||||
\(fn ARG)" t nil)
|
||||
|
||||
(autoload 'mc/insert-letters "mc-separate-operations" "\
|
||||
Insert increasing letters for each cursor, starting at 0 or ARG.
|
||||
Where letter[0]=a letter[2]=c letter[26]=aa
|
||||
|
||||
\(fn ARG)" t nil)
|
||||
|
||||
(autoload 'mc/reverse-regions "mc-separate-operations" "\
|
||||
|
||||
|
||||
\(fn)" t nil)
|
||||
|
||||
(autoload 'mc/sort-regions "mc-separate-operations" "\
|
||||
|
||||
|
||||
\(fn)" t nil)
|
||||
|
||||
(autoload 'mc/vertical-align "mc-separate-operations" "\
|
||||
Aligns all cursors vertically with a given CHARACTER to the one with the
|
||||
highest column number (the rightest).
|
||||
Might not behave as intended if more than one cursors are on the same line.
|
||||
|
||||
\(fn CHARACTER)" t nil)
|
||||
|
||||
(autoload 'mc/vertical-align-with-space "mc-separate-operations" "\
|
||||
Aligns all cursors with whitespace like `mc/vertical-align' does
|
||||
|
||||
\(fn)" t nil)
|
||||
|
||||
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mc-separate-operations" '("mc/insert-numbers-default" "mc--")))
|
||||
|
||||
;;;***
|
||||
|
||||
;;;### (autoloads nil "multiple-cursors-core" "multiple-cursors-core.el"
|
||||
;;;;;; (0 0 0 0))
|
||||
;;; Generated autoloads from multiple-cursors-core.el
|
||||
|
||||
(autoload 'multiple-cursors-mode "multiple-cursors-core" "\
|
||||
Mode while multiple cursors are active.
|
||||
|
||||
\(fn &optional ARG)" t nil)
|
||||
|
||||
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "multiple-cursors-core" '("multiple-cursors-mode" "unsupported-cmd" "deactivate-cursor-after-undo" "activate-cursor-for-undo")))
|
||||
|
||||
;;;***
|
||||
|
||||
;;;### (autoloads nil "rectangular-region-mode" "rectangular-region-mode.el"
|
||||
;;;;;; (0 0 0 0))
|
||||
;;; Generated autoloads from rectangular-region-mode.el
|
||||
|
||||
(autoload 'set-rectangular-region-anchor "rectangular-region-mode" "\
|
||||
Anchors the rectangular region at point.
|
||||
|
||||
Think of this one as `set-mark' except you're marking a rectangular region. It is
|
||||
an exceedingly quick way of adding multiple cursors to multiple lines.
|
||||
|
||||
\(fn)" t nil)
|
||||
|
||||
(autoload 'rectangular-region-mode "rectangular-region-mode" "\
|
||||
A mode for creating a rectangular region to edit
|
||||
|
||||
\(fn &optional ARG)" t nil)
|
||||
|
||||
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "rectangular-region-mode" '("rectangular-region-mode" "rrm/")))
|
||||
|
||||
;;;***
|
||||
|
||||
;;;### (autoloads nil nil ("multiple-cursors-pkg.el" "multiple-cursors.el")
|
||||
;;;;;; (0 0 0 0))
|
||||
|
||||
;;;***
|
||||
|
||||
;; Local Variables:
|
||||
;; version-control: never
|
||||
;; no-byte-compile: t
|
||||
;; no-update-autoloads: t
|
||||
;; coding: utf-8
|
||||
;; End:
|
||||
;;; multiple-cursors-autoloads.el ends here
|
852
elpa/multiple-cursors-20191210.1759/multiple-cursors-core.el
Normal file
852
elpa/multiple-cursors-20191210.1759/multiple-cursors-core.el
Normal file
|
@ -0,0 +1,852 @@
|
|||
;;; multiple-cursors-core.el --- An experiment in multiple cursors for emacs.
|
||||
|
||||
;; Copyright (C) 2012-2016 Magnar Sveen
|
||||
|
||||
;; Author: Magnar Sveen <magnars@gmail.com>
|
||||
;; Keywords: editing cursors
|
||||
|
||||
;; This program is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation, either version 3 of the License, or
|
||||
;; (at your option) any later version.
|
||||
|
||||
;; This program is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; This file contains the core functionality of multiple-cursors.
|
||||
;; Please see multiple-cursors.el for more commentary.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'cl-lib)
|
||||
(require 'rect)
|
||||
|
||||
(defvar mc--read-char)
|
||||
|
||||
(defface mc/cursor-face
|
||||
'((t (:inverse-video t)))
|
||||
"The face used for fake cursors"
|
||||
:group 'multiple-cursors)
|
||||
|
||||
(defface mc/cursor-bar-face
|
||||
`((t (:height 1 :background ,(face-attribute 'cursor :background))))
|
||||
"The face used for fake cursors if the cursor-type is bar"
|
||||
:group 'multiple-cursors)
|
||||
|
||||
(defface mc/region-face
|
||||
'((t :inherit region))
|
||||
"The face used for fake regions"
|
||||
:group 'multiple-cursors)
|
||||
|
||||
(defmacro mc/add-fake-cursor-to-undo-list (&rest forms)
|
||||
"Make sure point is in the right place when undoing"
|
||||
(let ((uc (make-symbol "undo-cleaner")))
|
||||
`(let ((,uc (cons 'apply (cons 'deactivate-cursor-after-undo (list id)))))
|
||||
(setq buffer-undo-list (cons ,uc buffer-undo-list))
|
||||
,@forms
|
||||
(if (eq ,uc (car buffer-undo-list)) ;; if nothing has been added to the undo-list
|
||||
(setq buffer-undo-list (cdr buffer-undo-list)) ;; then pop the cleaner right off again
|
||||
(setq buffer-undo-list ;; otherwise add a function to activate this cursor
|
||||
(cons (cons 'apply (cons 'activate-cursor-for-undo (list id))) buffer-undo-list))))))
|
||||
|
||||
(defun mc/all-fake-cursors (&optional start end)
|
||||
(cl-remove-if-not 'mc/fake-cursor-p
|
||||
(overlays-in (or start (point-min))
|
||||
(or end (point-max)))))
|
||||
|
||||
(defmacro mc/for-each-fake-cursor (&rest forms)
|
||||
"Runs the body for each fake cursor, bound to the name cursor"
|
||||
`(mapc #'(lambda (cursor) ,@forms)
|
||||
(mc/all-fake-cursors)))
|
||||
|
||||
(defmacro mc/save-excursion (&rest forms)
|
||||
"Saves and restores all the state that multiple-cursors cares about."
|
||||
(let ((cs (make-symbol "current-state")))
|
||||
`(let ((,cs (mc/store-current-state-in-overlay
|
||||
(make-overlay (point) (point) nil nil t))))
|
||||
(overlay-put ,cs 'type 'original-cursor)
|
||||
(save-excursion ,@forms)
|
||||
(mc/pop-state-from-overlay ,cs))))
|
||||
|
||||
(defun mc--compare-by-overlay-start (o1 o2)
|
||||
(< (overlay-start o1) (overlay-start o2)))
|
||||
|
||||
(defmacro mc/for-each-cursor-ordered (&rest forms)
|
||||
"Runs the body for each cursor, fake and real, bound to the name cursor"
|
||||
(let ((rci (make-symbol "real-cursor-id")))
|
||||
`(let ((,rci (overlay-get (mc/create-fake-cursor-at-point) 'mc-id)))
|
||||
(mapc #'(lambda (cursor)
|
||||
(when (mc/fake-cursor-p cursor)
|
||||
,@forms))
|
||||
(sort (overlays-in (point-min) (point-max)) 'mc--compare-by-overlay-start))
|
||||
(mc/pop-state-from-overlay (mc/cursor-with-id ,rci)))))
|
||||
|
||||
(defmacro mc/save-window-scroll (&rest forms)
|
||||
"Saves and restores the window scroll position"
|
||||
(let ((p (make-symbol "p"))
|
||||
(s (make-symbol "start"))
|
||||
(h (make-symbol "hscroll")))
|
||||
`(let ((,p (set-marker (make-marker) (point)))
|
||||
(,s (set-marker (make-marker) (window-start)))
|
||||
(,h (window-hscroll)))
|
||||
,@forms
|
||||
(goto-char ,p)
|
||||
(set-window-start nil ,s t)
|
||||
(set-window-hscroll nil ,h)
|
||||
(set-marker ,p nil)
|
||||
(set-marker ,s nil))))
|
||||
|
||||
(defun mc/cursor-is-bar ()
|
||||
"Return non-nil if the cursor is a bar."
|
||||
(or (eq cursor-type 'bar)
|
||||
(and (listp cursor-type)
|
||||
(eq (car cursor-type) 'bar))))
|
||||
|
||||
(defun mc/line-number-at-pos (&optional pos absolute)
|
||||
"Faster implementation of `line-number-at-pos'."
|
||||
(if pos
|
||||
(save-excursion
|
||||
(if absolute
|
||||
(save-restriction
|
||||
(widen)
|
||||
(goto-char pos)
|
||||
(string-to-number (format-mode-line "%l")))
|
||||
(goto-char pos)
|
||||
(string-to-number (format-mode-line "%l"))))
|
||||
(string-to-number (format-mode-line "%l"))))
|
||||
|
||||
(defun mc/make-cursor-overlay-at-eol (pos)
|
||||
"Create overlay to look like cursor at end of line."
|
||||
(let ((overlay (make-overlay pos pos nil nil nil)))
|
||||
(if (mc/cursor-is-bar)
|
||||
(overlay-put overlay 'before-string (propertize "|" 'face 'mc/cursor-bar-face))
|
||||
(overlay-put overlay 'after-string (propertize " " 'face 'mc/cursor-face)))
|
||||
overlay))
|
||||
|
||||
(defun mc/make-cursor-overlay-inline (pos)
|
||||
"Create overlay to look like cursor inside text."
|
||||
(let ((overlay (make-overlay pos (1+ pos) nil nil nil)))
|
||||
(if (mc/cursor-is-bar)
|
||||
(overlay-put overlay 'before-string (propertize "|" 'face 'mc/cursor-bar-face))
|
||||
(overlay-put overlay 'face 'mc/cursor-face))
|
||||
overlay))
|
||||
|
||||
(defun mc/make-cursor-overlay-at-point ()
|
||||
"Create overlay to look like cursor.
|
||||
Special case for end of line, because overlay over a newline
|
||||
highlights the entire width of the window."
|
||||
(if (eolp)
|
||||
(mc/make-cursor-overlay-at-eol (point))
|
||||
(mc/make-cursor-overlay-inline (point))))
|
||||
|
||||
(defun mc/make-region-overlay-between-point-and-mark ()
|
||||
"Create overlay to look like active region."
|
||||
(let ((overlay (make-overlay (mark) (point) nil nil t)))
|
||||
(overlay-put overlay 'face 'mc/region-face)
|
||||
(overlay-put overlay 'type 'additional-region)
|
||||
overlay))
|
||||
|
||||
(defvar mc/cursor-specific-vars '(transient-mark-mode
|
||||
kill-ring
|
||||
kill-ring-yank-pointer
|
||||
mark-ring
|
||||
mark-active
|
||||
yank-undo-function
|
||||
autopair-action
|
||||
autopair-wrap-action
|
||||
temporary-goal-column
|
||||
er/history
|
||||
dabbrev--abbrev-char-regexp
|
||||
dabbrev--check-other-buffers
|
||||
dabbrev--friend-buffer-list
|
||||
dabbrev--last-abbrev-location
|
||||
dabbrev--last-abbreviation
|
||||
dabbrev--last-buffer
|
||||
dabbrev--last-buffer-found
|
||||
dabbrev--last-direction
|
||||
dabbrev--last-expansion
|
||||
dabbrev--last-expansion-location
|
||||
dabbrev--last-table)
|
||||
"A list of vars that need to be tracked on a per-cursor basis.")
|
||||
|
||||
(defun mc/store-current-state-in-overlay (o)
|
||||
"Store relevant info about point and mark in the given overlay."
|
||||
(overlay-put o 'point (set-marker (make-marker) (point)))
|
||||
(overlay-put o 'mark (set-marker (make-marker)
|
||||
(let ((mark-even-if-inactive t))
|
||||
(mark))))
|
||||
(dolist (var mc/cursor-specific-vars)
|
||||
(when (boundp var) (overlay-put o var (symbol-value var))))
|
||||
o)
|
||||
|
||||
(defun mc/restore-state-from-overlay (o)
|
||||
"Restore point and mark from stored info in the given overlay."
|
||||
(goto-char (overlay-get o 'point))
|
||||
(set-marker (mark-marker) (overlay-get o 'mark))
|
||||
(dolist (var mc/cursor-specific-vars)
|
||||
(when (boundp var) (set var (overlay-get o var)))))
|
||||
|
||||
(defun mc/remove-fake-cursor (o)
|
||||
"Delete overlay with state, including dependent overlays and markers."
|
||||
(set-marker (overlay-get o 'point) nil)
|
||||
(set-marker (overlay-get o 'mark) nil)
|
||||
(mc/delete-region-overlay o)
|
||||
(delete-overlay o))
|
||||
|
||||
(defun mc/pop-state-from-overlay (o)
|
||||
"Restore the state stored in given overlay and then remove the overlay."
|
||||
(mc/restore-state-from-overlay o)
|
||||
(mc/remove-fake-cursor o))
|
||||
|
||||
(defun mc/delete-region-overlay (o)
|
||||
"Remove the dependent region overlay for a given cursor overlay."
|
||||
(ignore-errors
|
||||
(delete-overlay (overlay-get o 'region-overlay))))
|
||||
|
||||
(defvar mc--current-cursor-id 0
|
||||
"Var to store increasing id of fake cursors, used to keep track of them for undo.")
|
||||
|
||||
(defun mc/create-cursor-id ()
|
||||
"Returns a unique cursor id"
|
||||
(cl-incf mc--current-cursor-id))
|
||||
|
||||
(defvar mc--max-cursors-original nil
|
||||
"This variable maintains the original maximum number of cursors.
|
||||
When `mc/create-fake-cursor-at-point' is called and
|
||||
`mc/max-cursors' is overridden, this value serves as a backup so
|
||||
that `mc/max-cursors' can take on a new value. When
|
||||
`mc/remove-fake-cursors' is called, the values are reset.")
|
||||
|
||||
(defcustom mc/max-cursors nil
|
||||
"Safety ceiling for the number of active cursors.
|
||||
If your emacs slows down or freezes when using too many cursors,
|
||||
customize this value appropriately.
|
||||
|
||||
Cursors will be added until this value is reached, at which point
|
||||
you can either temporarily override the value or abort the
|
||||
operation entirely.
|
||||
|
||||
If this value is nil, there is no ceiling."
|
||||
:type '(integer)
|
||||
:group 'multiple-cursors)
|
||||
|
||||
(defun mc/create-fake-cursor-at-point (&optional id)
|
||||
"Add a fake cursor and possibly a fake active region overlay based on point and mark.
|
||||
Saves the current state in the overlay to be restored later."
|
||||
(unless mc--max-cursors-original
|
||||
(setq mc--max-cursors-original mc/max-cursors))
|
||||
(when mc/max-cursors
|
||||
(unless (< (mc/num-cursors) mc/max-cursors)
|
||||
(if (yes-or-no-p (format "%d active cursors. Continue? " (mc/num-cursors)))
|
||||
(setq mc/max-cursors (read-number "Enter a new, temporary maximum: "))
|
||||
(mc/remove-fake-cursors)
|
||||
(error "Aborted: too many cursors"))))
|
||||
(let ((overlay (mc/make-cursor-overlay-at-point)))
|
||||
(overlay-put overlay 'mc-id (or id (mc/create-cursor-id)))
|
||||
(overlay-put overlay 'type 'fake-cursor)
|
||||
(overlay-put overlay 'priority 100)
|
||||
(mc/store-current-state-in-overlay overlay)
|
||||
(when (use-region-p)
|
||||
(overlay-put overlay 'region-overlay
|
||||
(mc/make-region-overlay-between-point-and-mark)))
|
||||
overlay))
|
||||
|
||||
(defun mc/execute-command (cmd)
|
||||
"Run command, simulating the parts of the command loop that makes sense for fake cursors."
|
||||
(setq this-command cmd)
|
||||
(run-hooks 'pre-command-hook)
|
||||
(unless (eq this-command 'ignore)
|
||||
(call-interactively cmd))
|
||||
(run-hooks 'post-command-hook)
|
||||
(when deactivate-mark (deactivate-mark)))
|
||||
|
||||
(defvar mc--executing-command-for-fake-cursor nil)
|
||||
|
||||
(defun mc/execute-command-for-fake-cursor (cmd cursor)
|
||||
(let ((mc--executing-command-for-fake-cursor t)
|
||||
(id (overlay-get cursor 'mc-id))
|
||||
(annoying-arrows-mode nil)
|
||||
(smooth-scroll-margin 0))
|
||||
(mc/add-fake-cursor-to-undo-list
|
||||
(mc/pop-state-from-overlay cursor)
|
||||
(ignore-errors
|
||||
(mc/execute-command cmd)
|
||||
(mc/create-fake-cursor-at-point id)))))
|
||||
|
||||
(defun mc/execute-command-for-all-fake-cursors (cmd)
|
||||
"Calls CMD interactively for each cursor.
|
||||
It works by moving point to the fake cursor, setting
|
||||
up the proper environment, and then removing the cursor.
|
||||
After executing the command, it sets up a new fake
|
||||
cursor with updated info."
|
||||
(mc/save-excursion
|
||||
(mc/save-window-scroll
|
||||
(mc/for-each-fake-cursor
|
||||
(save-excursion
|
||||
(mc/execute-command-for-fake-cursor cmd cursor)))))
|
||||
(mc--reset-read-prompts))
|
||||
|
||||
(defun mc/execute-command-for-all-cursors (cmd)
|
||||
"Calls CMD interactively for the real cursor and all fakes."
|
||||
(call-interactively cmd)
|
||||
(mc/execute-command-for-all-fake-cursors cmd))
|
||||
|
||||
;; Intercept some reading commands so you won't have to
|
||||
;; answer them for every single cursor
|
||||
|
||||
(defvar mc--read-char nil)
|
||||
(defvar multiple-cursors-mode nil)
|
||||
(defadvice read-char (around mc-support activate)
|
||||
(if (not multiple-cursors-mode)
|
||||
ad-do-it
|
||||
(unless mc--read-char
|
||||
(setq mc--read-char ad-do-it))
|
||||
(setq ad-return-value mc--read-char)))
|
||||
|
||||
(defvar mc--read-quoted-char nil)
|
||||
(defadvice read-quoted-char (around mc-support activate)
|
||||
(if (not multiple-cursors-mode)
|
||||
ad-do-it
|
||||
(unless mc--read-quoted-char
|
||||
(setq mc--read-quoted-char ad-do-it))
|
||||
(setq ad-return-value mc--read-quoted-char)))
|
||||
|
||||
(defun mc--reset-read-prompts ()
|
||||
(setq mc--read-char nil)
|
||||
(setq mc--read-quoted-char nil))
|
||||
|
||||
(mc--reset-read-prompts)
|
||||
|
||||
(defun mc/fake-cursor-p (o)
|
||||
"Predicate to check if an overlay is a fake cursor"
|
||||
(eq (overlay-get o 'type) 'fake-cursor))
|
||||
|
||||
(defun mc/cursor-with-id (id)
|
||||
"Find the first cursor with the given id, or nil"
|
||||
(cl-find-if #'(lambda (o) (and (mc/fake-cursor-p o)
|
||||
(= id (overlay-get o 'mc-id))))
|
||||
(overlays-in (point-min) (point-max))))
|
||||
|
||||
(defvar mc--stored-state-for-undo nil
|
||||
"Variable to keep the state of the real cursor while undoing a fake one")
|
||||
|
||||
(defun activate-cursor-for-undo (id)
|
||||
"Called when undoing to temporarily activate the fake cursor which action is being undone."
|
||||
(let ((cursor (mc/cursor-with-id id)))
|
||||
(when cursor
|
||||
(setq mc--stored-state-for-undo (mc/store-current-state-in-overlay
|
||||
(make-overlay (point) (point) nil nil t)))
|
||||
(mc/pop-state-from-overlay cursor))))
|
||||
|
||||
(defun deactivate-cursor-after-undo (id)
|
||||
"Called when undoing to reinstate the real cursor after undoing a fake one."
|
||||
(when mc--stored-state-for-undo
|
||||
(mc/create-fake-cursor-at-point id)
|
||||
(mc/pop-state-from-overlay mc--stored-state-for-undo)
|
||||
(setq mc--stored-state-for-undo nil)))
|
||||
|
||||
(defcustom mc/always-run-for-all nil
|
||||
"Disables whitelisting and always executes commands for every fake cursor."
|
||||
:type '(boolean)
|
||||
:group 'multiple-cursors)
|
||||
|
||||
(defcustom mc/always-repeat-command nil
|
||||
"Disables confirmation for `mc/repeat-command' command."
|
||||
:type '(boolean)
|
||||
:group 'multiple-cursors)
|
||||
|
||||
(defun mc/prompt-for-inclusion-in-whitelist (original-command)
|
||||
"Asks the user, then adds the command either to the once-list or the all-list."
|
||||
(let ((all-p (y-or-n-p (format "Do %S for all cursors?" original-command))))
|
||||
(if all-p
|
||||
(add-to-list 'mc/cmds-to-run-for-all original-command)
|
||||
(add-to-list 'mc/cmds-to-run-once original-command))
|
||||
(mc/save-lists)
|
||||
all-p))
|
||||
|
||||
(defun mc/num-cursors ()
|
||||
"The number of cursors (real and fake) in the buffer."
|
||||
(1+ (cl-count-if 'mc/fake-cursor-p
|
||||
(overlays-in (point-min) (point-max)))))
|
||||
|
||||
(defvar mc--this-command nil
|
||||
"Used to store the original command being run.")
|
||||
(make-variable-buffer-local 'mc--this-command)
|
||||
|
||||
(defun mc/make-a-note-of-the-command-being-run ()
|
||||
"Used with pre-command-hook to store the original command being run.
|
||||
Since that cannot be reliably determined in the post-command-hook.
|
||||
|
||||
Specifically, this-original-command isn't always right, because it could have
|
||||
been remapped. And certain modes (cua comes to mind) will change their
|
||||
remapping based on state. So a command that changes the state will afterwards
|
||||
not be recognized through the command-remapping lookup."
|
||||
(unless mc--executing-command-for-fake-cursor
|
||||
(let ((cmd (or (command-remapping this-original-command)
|
||||
this-original-command)))
|
||||
(setq mc--this-command (and (not (eq cmd 'god-mode-self-insert))
|
||||
cmd)))))
|
||||
|
||||
(defun mc/execute-this-command-for-all-cursors ()
|
||||
"Wrap around `mc/execute-this-command-for-all-cursors-1' to protect hook."
|
||||
(condition-case error
|
||||
(mc/execute-this-command-for-all-cursors-1)
|
||||
(error
|
||||
(message "[mc] problem in `mc/execute-this-command-for-all-cursors': %s"
|
||||
(error-message-string error)))))
|
||||
|
||||
;; execute-kbd-macro should never be run for fake cursors. The real cursor will
|
||||
;; execute the keyboard macro, resulting in new commands in the command loop,
|
||||
;; and the fake cursors can pick up on those instead.
|
||||
(defadvice execute-kbd-macro (around skip-fake-cursors activate)
|
||||
(unless mc--executing-command-for-fake-cursor
|
||||
ad-do-it))
|
||||
|
||||
(defun mc/execute-this-command-for-all-cursors-1 ()
|
||||
"Used with post-command-hook to execute supported commands for all cursors.
|
||||
|
||||
It uses two lists of commands to know what to do: the run-once
|
||||
list and the run-for-all list. If a command is in neither of these lists,
|
||||
it will prompt for the proper action and then save that preference.
|
||||
|
||||
Some commands are so unsupported that they are even prevented for
|
||||
the original cursor, to inform about the lack of support."
|
||||
(unless mc--executing-command-for-fake-cursor
|
||||
|
||||
(if (eq 1 (mc/num-cursors)) ;; no fake cursors? disable mc-mode
|
||||
(multiple-cursors-mode 0)
|
||||
(when this-original-command
|
||||
(let ((original-command (or mc--this-command
|
||||
(command-remapping this-original-command)
|
||||
this-original-command)))
|
||||
|
||||
;; skip keyboard macros, since they will generate actual commands that are
|
||||
;; also run in the command loop - we'll handle those later instead.
|
||||
(when (functionp original-command)
|
||||
|
||||
;; if it's a lambda, we can't know if it's supported or not
|
||||
;; - so go ahead and assume it's ok, because we're just optimistic like that
|
||||
(if (or (not (symbolp original-command))
|
||||
;; lambda registered by smartrep
|
||||
(string-prefix-p "(" (symbol-name original-command)))
|
||||
(mc/execute-command-for-all-fake-cursors original-command)
|
||||
|
||||
;; smartrep `intern's commands into own obarray to help
|
||||
;; `describe-bindings'. So, let's re-`intern' here to
|
||||
;; make the command comparable by `eq'.
|
||||
(setq original-command (intern (symbol-name original-command)))
|
||||
|
||||
;; otherwise it's a symbol, and we can be more thorough
|
||||
(if (get original-command 'mc--unsupported)
|
||||
(message "%S is not supported with multiple cursors%s"
|
||||
original-command
|
||||
(get original-command 'mc--unsupported))
|
||||
|
||||
;; lazy-load the user's list file
|
||||
(mc/load-lists)
|
||||
|
||||
(when (and original-command
|
||||
(not (memq original-command mc--default-cmds-to-run-once))
|
||||
(not (memq original-command mc/cmds-to-run-once))
|
||||
(or mc/always-run-for-all
|
||||
(memq original-command mc--default-cmds-to-run-for-all)
|
||||
(memq original-command mc/cmds-to-run-for-all)
|
||||
(mc/prompt-for-inclusion-in-whitelist original-command)))
|
||||
(mc/execute-command-for-all-fake-cursors original-command))))))))))
|
||||
|
||||
(defun mc/remove-fake-cursors ()
|
||||
"Remove all fake cursors.
|
||||
Do not use to conclude editing with multiple cursors. For that
|
||||
you should disable multiple-cursors-mode."
|
||||
(mc/for-each-fake-cursor
|
||||
(mc/remove-fake-cursor cursor))
|
||||
(when mc--max-cursors-original
|
||||
(setq mc/max-cursors mc--max-cursors-original))
|
||||
(setq mc--max-cursors-original nil))
|
||||
|
||||
(defun mc/keyboard-quit ()
|
||||
"Deactivate mark if there are any active, otherwise exit multiple-cursors-mode."
|
||||
(interactive)
|
||||
(if (not (use-region-p))
|
||||
(multiple-cursors-mode 0)
|
||||
(deactivate-mark)))
|
||||
|
||||
(defun mc/repeat-command ()
|
||||
"Run last command from `command-history' for every fake cursor."
|
||||
(interactive)
|
||||
(when (or mc/always-repeat-command
|
||||
(y-or-n-p (format "[mc] repeat complex command: %s? " (caar command-history))))
|
||||
(mc/execute-command-for-all-fake-cursors
|
||||
(lambda () (interactive)
|
||||
(cl-letf (((symbol-function 'read-from-minibuffer)
|
||||
(lambda (p &optional i k r h d m) (read i))))
|
||||
(repeat-complex-command 0))))))
|
||||
|
||||
(defvar mc/keymap nil
|
||||
"Keymap while multiple cursors are active.
|
||||
Main goal of the keymap is to rebind C-g and <return> to conclude
|
||||
multiple cursors editing.")
|
||||
(unless mc/keymap
|
||||
(setq mc/keymap (make-sparse-keymap))
|
||||
(define-key mc/keymap (kbd "C-g") 'mc/keyboard-quit)
|
||||
(define-key mc/keymap (kbd "<return>") 'multiple-cursors-mode)
|
||||
(define-key mc/keymap (kbd "C-:") 'mc/repeat-command)
|
||||
(when (fboundp 'phi-search)
|
||||
(define-key mc/keymap (kbd "C-s") 'phi-search))
|
||||
(when (fboundp 'phi-search-backward)
|
||||
(define-key mc/keymap (kbd "C-r") 'phi-search-backward)))
|
||||
|
||||
(defun mc--all-equal (list)
|
||||
"Are all the items in LIST equal?"
|
||||
(let ((first (car list))
|
||||
(all-equal t))
|
||||
(while (and all-equal list)
|
||||
(setq all-equal (equal first (car list)))
|
||||
(setq list (cdr list)))
|
||||
all-equal))
|
||||
|
||||
(defun mc--kill-ring-entries ()
|
||||
"Return the latest kill-ring entry for each cursor.
|
||||
The entries are returned in the order they are found in the buffer."
|
||||
(let (entries)
|
||||
(mc/for-each-cursor-ordered
|
||||
(setq entries (cons (car (overlay-get cursor 'kill-ring)) entries)))
|
||||
(reverse entries)))
|
||||
|
||||
(defun mc--maybe-set-killed-rectangle ()
|
||||
"Add the latest kill-ring entry for each cursor to killed-rectangle.
|
||||
So you can paste it in later with `yank-rectangle'."
|
||||
(let ((entries (let (mc/max-cursors) (mc--kill-ring-entries))))
|
||||
(unless (mc--all-equal entries)
|
||||
(setq killed-rectangle entries))))
|
||||
|
||||
(defvar mc/unsupported-minor-modes '(company-mode auto-complete-mode flyspell-mode jedi-mode)
|
||||
"List of minor-modes that does not play well with multiple-cursors.
|
||||
They are temporarily disabled when multiple-cursors are active.")
|
||||
|
||||
(defvar mc/temporarily-disabled-minor-modes nil
|
||||
"The list of temporarily disabled minor-modes.")
|
||||
(make-variable-buffer-local 'mc/temporarily-disabled-minor-modes)
|
||||
|
||||
(defun mc/temporarily-disable-minor-mode (mode)
|
||||
"If MODE is available and turned on, remember that and turn it off."
|
||||
(when (and (boundp mode) (eval mode))
|
||||
(add-to-list 'mc/temporarily-disabled-minor-modes mode)
|
||||
(funcall mode -1)))
|
||||
|
||||
(defun mc/temporarily-disable-unsupported-minor-modes ()
|
||||
(mapc 'mc/temporarily-disable-minor-mode mc/unsupported-minor-modes))
|
||||
|
||||
(defun mc/enable-minor-mode (mode)
|
||||
(funcall mode 1))
|
||||
|
||||
(defun mc/enable-temporarily-disabled-minor-modes ()
|
||||
(mapc 'mc/enable-minor-mode mc/temporarily-disabled-minor-modes)
|
||||
(setq mc/temporarily-disabled-minor-modes nil))
|
||||
|
||||
(defcustom mc/mode-line
|
||||
`(" mc:" (:eval (format ,(propertize "%d" 'face 'font-lock-warning-face)
|
||||
(mc/num-cursors))))
|
||||
"What to display in the mode line while multiple-cursors-mode is active."
|
||||
:group 'multiple-cursors)
|
||||
(put 'mc/mode-line 'risky-local-variable t)
|
||||
|
||||
;;;###autoload
|
||||
(define-minor-mode multiple-cursors-mode
|
||||
"Mode while multiple cursors are active."
|
||||
nil mc/mode-line mc/keymap
|
||||
(if multiple-cursors-mode
|
||||
(progn
|
||||
(mc/temporarily-disable-unsupported-minor-modes)
|
||||
(add-hook 'pre-command-hook 'mc/make-a-note-of-the-command-being-run nil t)
|
||||
(add-hook 'post-command-hook 'mc/execute-this-command-for-all-cursors t t)
|
||||
(run-hooks 'multiple-cursors-mode-enabled-hook))
|
||||
(remove-hook 'post-command-hook 'mc/execute-this-command-for-all-cursors t)
|
||||
(remove-hook 'pre-command-hook 'mc/make-a-note-of-the-command-being-run t)
|
||||
(setq mc--this-command nil)
|
||||
(mc--maybe-set-killed-rectangle)
|
||||
(mc/remove-fake-cursors)
|
||||
(mc/enable-temporarily-disabled-minor-modes)
|
||||
(run-hooks 'multiple-cursors-mode-disabled-hook)))
|
||||
|
||||
(add-hook 'after-revert-hook #'(lambda () (multiple-cursors-mode 0)))
|
||||
|
||||
(defun mc/maybe-multiple-cursors-mode ()
|
||||
"Enable multiple-cursors-mode if there is more than one currently active cursor."
|
||||
(if (> (mc/num-cursors) 1)
|
||||
(multiple-cursors-mode 1)
|
||||
(multiple-cursors-mode 0)))
|
||||
|
||||
(defmacro unsupported-cmd (cmd msg)
|
||||
"Adds command to list of unsupported commands and prevents it
|
||||
from being executed if in multiple-cursors-mode."
|
||||
`(progn
|
||||
(put (quote ,cmd) 'mc--unsupported ,msg)
|
||||
(defadvice ,cmd (around unsupported-advice activate)
|
||||
"command isn't supported with multiple cursors"
|
||||
(unless (and multiple-cursors-mode (called-interactively-p 'any))
|
||||
ad-do-it))))
|
||||
|
||||
;; Commands that does not work with multiple-cursors
|
||||
(unsupported-cmd isearch-forward ". Feel free to add a compatible version.")
|
||||
(unsupported-cmd isearch-backward ". Feel free to add a compatible version.")
|
||||
|
||||
;; Make sure pastes from other programs are added to all kill-rings when yanking
|
||||
(defadvice current-kill (before interprogram-paste-for-all-cursors
|
||||
(n &optional do-not-move) activate)
|
||||
(let ((interprogram-paste (and (= n 0)
|
||||
interprogram-paste-function
|
||||
(funcall interprogram-paste-function))))
|
||||
(when interprogram-paste
|
||||
;; Add interprogram-paste to normal kill ring, just
|
||||
;; like current-kill usually does for itself.
|
||||
;; We have to do the work for it though, since the funcall only returns
|
||||
;; something once. It is not a pure function.
|
||||
(let ((interprogram-cut-function nil))
|
||||
(if (listp interprogram-paste)
|
||||
(mapc 'kill-new (nreverse interprogram-paste))
|
||||
(kill-new interprogram-paste))
|
||||
;; And then add interprogram-paste to the kill-rings
|
||||
;; of all the other cursors too.
|
||||
(mc/for-each-fake-cursor
|
||||
(let ((kill-ring (overlay-get cursor 'kill-ring))
|
||||
(kill-ring-yank-pointer (overlay-get cursor 'kill-ring-yank-pointer)))
|
||||
(if (listp interprogram-paste)
|
||||
(mapc 'kill-new (nreverse interprogram-paste))
|
||||
(kill-new interprogram-paste))
|
||||
(overlay-put cursor 'kill-ring kill-ring)
|
||||
(overlay-put cursor 'kill-ring-yank-pointer kill-ring-yank-pointer)))))))
|
||||
|
||||
(defcustom mc/list-file (locate-user-emacs-file ".mc-lists.el")
|
||||
"The position of the file that keeps track of your preferences
|
||||
for running commands with multiple cursors."
|
||||
:type 'file
|
||||
:group 'multiple-cursors)
|
||||
|
||||
(defvar mc--list-file-loaded nil
|
||||
"Whether the list file has already been loaded.")
|
||||
|
||||
(defun mc/load-lists ()
|
||||
"Loads preferences for running commands with multiple cursors from `mc/list-file'"
|
||||
(unless mc--list-file-loaded
|
||||
(load mc/list-file 'noerror 'nomessage)
|
||||
(setq mc--list-file-loaded t)))
|
||||
|
||||
(defun mc/dump-list (list-symbol)
|
||||
"Insert (setq 'LIST-SYMBOL LIST-VALUE) to current buffer."
|
||||
(cl-symbol-macrolet ((value (symbol-value list-symbol)))
|
||||
(insert "(setq " (symbol-name list-symbol) "\n"
|
||||
" '(")
|
||||
(newline-and-indent)
|
||||
(set list-symbol
|
||||
(sort value (lambda (x y) (string-lessp (symbol-name x)
|
||||
(symbol-name y)))))
|
||||
(mapc #'(lambda (cmd) (insert (format "%S" cmd)) (newline-and-indent))
|
||||
value)
|
||||
(insert "))")
|
||||
(newline)))
|
||||
|
||||
(defun mc/save-lists ()
|
||||
"Saves preferences for running commands with multiple cursors to `mc/list-file'"
|
||||
(with-temp-file mc/list-file
|
||||
(emacs-lisp-mode)
|
||||
(insert ";; This file is automatically generated by the multiple-cursors extension.")
|
||||
(newline)
|
||||
(insert ";; It keeps track of your preferences for running commands with multiple cursors.")
|
||||
(newline)
|
||||
(newline)
|
||||
(mc/dump-list 'mc/cmds-to-run-for-all)
|
||||
(newline)
|
||||
(mc/dump-list 'mc/cmds-to-run-once)))
|
||||
|
||||
(defvar mc/cmds-to-run-once nil
|
||||
"Commands to run only once in multiple-cursors-mode.")
|
||||
|
||||
(defvar mc--default-cmds-to-run-once nil
|
||||
"Default set of commands to run only once in multiple-cursors-mode.")
|
||||
|
||||
(setq mc--default-cmds-to-run-once '(mc/edit-lines
|
||||
mc/edit-ends-of-lines
|
||||
mc/edit-beginnings-of-lines
|
||||
mc/mark-next-like-this
|
||||
mc/mark-next-like-this-word
|
||||
mc/mark-next-like-this-symbol
|
||||
mc/mark-next-word-like-this
|
||||
mc/mark-next-symbol-like-this
|
||||
mc/mark-previous-like-this
|
||||
mc/mark-previous-like-this-word
|
||||
mc/mark-previous-like-this-symbol
|
||||
mc/mark-previous-word-like-this
|
||||
mc/mark-previous-symbol-like-this
|
||||
mc/mark-all-like-this
|
||||
mc/mark-all-words-like-this
|
||||
mc/mark-all-symbols-like-this
|
||||
mc/mark-more-like-this-extended
|
||||
mc/mark-all-like-this-in-defun
|
||||
mc/mark-all-words-like-this-in-defun
|
||||
mc/mark-all-symbols-like-this-in-defun
|
||||
mc/mark-all-like-this-dwim
|
||||
mc/mark-all-dwim
|
||||
mc/mark-sgml-tag-pair
|
||||
mc/insert-numbers
|
||||
mc/insert-letters
|
||||
mc/sort-regions
|
||||
mc/reverse-regions
|
||||
mc/cycle-forward
|
||||
mc/cycle-backward
|
||||
mc/add-cursor-on-click
|
||||
mc/mark-pop
|
||||
mc/add-cursors-to-all-matches
|
||||
mc/mmlte--left
|
||||
mc/mmlte--right
|
||||
mc/mmlte--up
|
||||
mc/mmlte--down
|
||||
mc/unmark-next-like-this
|
||||
mc/unmark-previous-like-this
|
||||
mc/skip-to-next-like-this
|
||||
mc/skip-to-previous-like-this
|
||||
rrm/switch-to-multiple-cursors
|
||||
mc-hide-unmatched-lines-mode
|
||||
mc/repeat-command
|
||||
hum/keyboard-quit
|
||||
hum/unhide-invisible-overlays
|
||||
save-buffer
|
||||
ido-exit-minibuffer
|
||||
ivy-done
|
||||
exit-minibuffer
|
||||
minibuffer-complete-and-exit
|
||||
execute-extended-command
|
||||
eval-expression
|
||||
undo
|
||||
redo
|
||||
undo-tree-undo
|
||||
undo-tree-redo
|
||||
universal-argument
|
||||
universal-argument-more
|
||||
universal-argument-other-key
|
||||
negative-argument
|
||||
digit-argument
|
||||
top-level
|
||||
recenter-top-bottom
|
||||
describe-mode
|
||||
describe-key-1
|
||||
describe-function
|
||||
describe-bindings
|
||||
describe-prefix-bindings
|
||||
view-echo-area-messages
|
||||
other-window
|
||||
kill-buffer-and-window
|
||||
split-window-right
|
||||
split-window-below
|
||||
delete-other-windows
|
||||
toggle-window-split
|
||||
mwheel-scroll
|
||||
scroll-up-command
|
||||
scroll-down-command
|
||||
mouse-set-point
|
||||
mouse-drag-region
|
||||
quit-window
|
||||
toggle-read-only
|
||||
windmove-left
|
||||
windmove-right
|
||||
windmove-up
|
||||
windmove-down
|
||||
repeat-complex-command))
|
||||
|
||||
(defvar mc--default-cmds-to-run-for-all nil
|
||||
"Default set of commands that should be mirrored by all cursors")
|
||||
|
||||
(setq mc--default-cmds-to-run-for-all '(mc/keyboard-quit
|
||||
self-insert-command
|
||||
quoted-insert
|
||||
previous-line
|
||||
next-line
|
||||
newline
|
||||
newline-and-indent
|
||||
open-line
|
||||
delete-blank-lines
|
||||
transpose-chars
|
||||
transpose-lines
|
||||
transpose-paragraphs
|
||||
transpose-regions
|
||||
join-line
|
||||
right-char
|
||||
right-word
|
||||
forward-char
|
||||
forward-word
|
||||
left-char
|
||||
left-word
|
||||
backward-char
|
||||
backward-word
|
||||
forward-paragraph
|
||||
backward-paragraph
|
||||
upcase-word
|
||||
downcase-word
|
||||
capitalize-word
|
||||
forward-list
|
||||
backward-list
|
||||
hippie-expand
|
||||
hippie-expand-lines
|
||||
yank
|
||||
yank-pop
|
||||
append-next-kill
|
||||
kill-word
|
||||
kill-line
|
||||
kill-whole-line
|
||||
backward-kill-word
|
||||
backward-delete-char-untabify
|
||||
delete-char delete-forward-char
|
||||
delete-backward-char
|
||||
py-electric-backspace
|
||||
c-electric-backspace
|
||||
org-delete-backward-char
|
||||
cperl-electric-backspace
|
||||
python-indent-dedent-line-backspace
|
||||
paredit-backward-delete
|
||||
autopair-backspace
|
||||
just-one-space
|
||||
zap-to-char
|
||||
end-of-line
|
||||
set-mark-command
|
||||
exchange-point-and-mark
|
||||
cua-set-mark
|
||||
cua-replace-region
|
||||
cua-delete-region
|
||||
move-end-of-line
|
||||
beginning-of-line
|
||||
move-beginning-of-line
|
||||
kill-ring-save
|
||||
back-to-indentation
|
||||
subword-forward
|
||||
subword-backward
|
||||
subword-mark
|
||||
subword-kill
|
||||
subword-backward-kill
|
||||
subword-transpose
|
||||
subword-capitalize
|
||||
subword-upcase
|
||||
subword-downcase
|
||||
er/expand-region
|
||||
er/contract-region
|
||||
smart-forward
|
||||
smart-backward
|
||||
smart-up
|
||||
smart-down))
|
||||
|
||||
(defvar mc/cmds-to-run-for-all nil
|
||||
"Commands to run for all cursors in multiple-cursors-mode")
|
||||
|
||||
(provide 'multiple-cursors-core)
|
||||
|
||||
;; Local Variables:
|
||||
;; coding: utf-8
|
||||
;; End:
|
||||
|
||||
;;; multiple-cursors-core.el ends here
|
BIN
elpa/multiple-cursors-20191210.1759/multiple-cursors-core.elc
Normal file
BIN
elpa/multiple-cursors-20191210.1759/multiple-cursors-core.elc
Normal file
Binary file not shown.
|
@ -0,0 +1,5 @@
|
|||
(define-package "multiple-cursors" "20191210.1759" "Multiple cursors for Emacs."
|
||||
'((cl-lib "0.5")))
|
||||
;; Local Variables:
|
||||
;; no-byte-compile: t
|
||||
;; End:
|
203
elpa/multiple-cursors-20191210.1759/multiple-cursors.el
Normal file
203
elpa/multiple-cursors-20191210.1759/multiple-cursors.el
Normal file
|
@ -0,0 +1,203 @@
|
|||
;;; multiple-cursors.el --- Multiple cursors for emacs.
|
||||
|
||||
;; Copyright (C) 2012-2016 Magnar Sveen
|
||||
|
||||
;; Author: Magnar Sveen <magnars@gmail.com>
|
||||
;; Version: 1.4.0
|
||||
;; Keywords: editing cursors
|
||||
|
||||
;; This program is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation, either version 3 of the License, or
|
||||
;; (at your option) any later version.
|
||||
|
||||
;; This program is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; Multiple cursors for Emacs. This is some pretty crazy functionality, so yes,
|
||||
;; there are kinks. Don't be afraid though, I've been using it since 2011 with
|
||||
;; great success and much merriment.
|
||||
|
||||
;; ## Basic usage
|
||||
|
||||
;; Start out with:
|
||||
|
||||
;; (require 'multiple-cursors)
|
||||
|
||||
;; Then you have to set up your keybindings - multiple-cursors doesn't presume to
|
||||
;; know how you'd like them laid out. Here are some examples:
|
||||
|
||||
;; When you have an active region that spans multiple lines, the following will
|
||||
;; add a cursor to each line:
|
||||
|
||||
;; (global-set-key (kbd "C-S-c C-S-c") 'mc/edit-lines)
|
||||
|
||||
;; When you want to add multiple cursors not based on continuous lines, but based on
|
||||
;; keywords in the buffer, use:
|
||||
|
||||
;; (global-set-key (kbd "C->") 'mc/mark-next-like-this)
|
||||
;; (global-set-key (kbd "C-<") 'mc/mark-previous-like-this)
|
||||
;; (global-set-key (kbd "C-c C-<") 'mc/mark-all-like-this)
|
||||
|
||||
;; First mark the word, then add more cursors.
|
||||
|
||||
;; To get out of multiple-cursors-mode, press `<return>` or `C-g`. The latter will
|
||||
;; first disable multiple regions before disabling multiple cursors. If you want to
|
||||
;; insert a newline in multiple-cursors-mode, use `C-j`.
|
||||
|
||||
;; ## Video
|
||||
|
||||
;; You can [watch an intro to multiple-cursors at Emacs Rocks](http://emacsrocks.com/e13.html).
|
||||
|
||||
;; ## Command overview
|
||||
|
||||
;; ### Mark one more occurrence
|
||||
|
||||
;; - `mc/mark-next-like-this`: Adds a cursor and region at the next part of the buffer forwards that matches the current region.
|
||||
;; - `mc/mark-next-like-this-word`: Adds a cursor and region at the next part of the buffer forwards that matches the current region, if no region is selected it selects the word at the point.
|
||||
;; - `mc/mark-next-like-this-symbol`: Adds a cursor and region at the next part of the buffer forwards that matches the current region, if no region is selected it selects the symbol at the point.
|
||||
;; - `mc/mark-next-word-like-this`: Like `mc/mark-next-like-this` but only for whole words.
|
||||
;; - `mc/mark-next-symbol-like-this`: Like `mc/mark-next-like-this` but only for whole symbols.
|
||||
;; - `mc/mark-previous-like-this`: Adds a cursor and region at the next part of the buffer backwards that matches the current region.
|
||||
;; - `mc/mark-previous-word-like-this`: Like `mc/mark-previous-like-this` but only for whole words.
|
||||
;; - `mc/mark-previous-symbol-like-this`: Like `mc/mark-previous-like-this` but only for whole symbols.
|
||||
;; - `mc/mark-more-like-this-extended`: Use arrow keys to quickly mark/skip next/previous occurrences.
|
||||
;; - `mc/add-cursor-on-click`: Bind to a mouse event to add cursors by clicking. See tips-section.
|
||||
|
||||
;; ### Mark many occurrences
|
||||
|
||||
;; - `mc/mark-all-like-this`: Marks all parts of the buffer that matches the current region.
|
||||
;; - `mc/mark-all-words-like-this`: Like `mc/mark-all-like-this` but only for whole words.
|
||||
;; - `mc/mark-all-symbols-like-this`: Like `mc/mark-all-like-this` but only for whole symbols.
|
||||
;; - `mc/mark-all-in-region`: Prompts for a string to match in the region, adding cursors to all of them.
|
||||
;; - `mc/mark-all-like-this-in-defun`: Marks all parts of the current defun that matches the current region.
|
||||
;; - `mc/mark-all-words-like-this-in-defun`: Like `mc/mark-all-like-this-in-defun` but only for whole words.
|
||||
;; - `mc/mark-all-symbols-like-this-in-defun`: Like `mc/mark-all-like-this-in-defun` but only for whole symbols.
|
||||
;; - `mc/mark-all-like-this-dwim`: Tries to be smart about marking everything you want. Can be pressed multiple times.
|
||||
|
||||
;; ### Special
|
||||
|
||||
;; - `set-rectangular-region-anchor`: Think of this one as `set-mark` except you're marking a rectangular region.
|
||||
;; - `mc/mark-sgml-tag-pair`: Mark the current opening and closing tag.
|
||||
;; - `mc/insert-numbers`: Insert increasing numbers for each cursor, top to bottom.
|
||||
;; - `mc/insert-letters`: Insert increasing letters for each cursor, top to bottom.
|
||||
;; - `mc/sort-regions`: Sort the marked regions alphabetically.
|
||||
;; - `mc/reverse-regions`: Reverse the order of the marked regions.
|
||||
|
||||
;; ## Tips and tricks
|
||||
|
||||
;; - To get out of multiple-cursors-mode, press `<return>` or `C-g`. The latter will
|
||||
;; first disable multiple regions before disabling multiple cursors. If you want to
|
||||
;; insert a newline in multiple-cursors-mode, use `C-j`.
|
||||
;;
|
||||
;; - Sometimes you end up with cursors outside of your view. You can
|
||||
;; scroll the screen to center on each cursor with `C-v` and `M-v`.
|
||||
;;
|
||||
;; - Try pressing `mc/mark-next-like-this` with no region selected. It will just add a cursor
|
||||
;; on the next line.
|
||||
;;
|
||||
;; - Try pressing `mc/mark-next-like-this-word` or
|
||||
;; `mc/mark-next-like-this-symbol` with no region selected. It will
|
||||
;; mark the symbol and add a cursor at the next occurrence
|
||||
;;
|
||||
;; - Try pressing `mc/mark-all-like-this-dwim` on a tagname in html-mode.
|
||||
;;
|
||||
;; - Notice that the number of cursors active can be seen in the modeline.
|
||||
;;
|
||||
;; - If you get out of multiple-cursors-mode and yank - it will yank only
|
||||
;; from the kill-ring of main cursor. To yank from the kill-rings of
|
||||
;; every cursor use yank-rectangle, normally found at C-x r y.
|
||||
;;
|
||||
;; - You can use `mc/reverse-regions` with nothing selected and just one cursor.
|
||||
;; It will then flip the sexp at point and the one below it.
|
||||
;;
|
||||
;; - If you would like to keep the global bindings clean, and get custom keybindings
|
||||
;; when the region is active, you can try [region-bindings-mode](https://github.com/fgallina/region-bindings-mode).
|
||||
;;
|
||||
;; BTW, I highly recommend adding `mc/mark-next-like-this` to a key binding that's
|
||||
;; right next to the key for `er/expand-region`.
|
||||
|
||||
;; ### Binding mouse events
|
||||
|
||||
;; To override a mouse event, you will likely have to also unbind the
|
||||
;; `down-mouse` part of the event. Like this:
|
||||
;;
|
||||
;; (global-unset-key (kbd "M-<down-mouse-1>"))
|
||||
;; (global-set-key (kbd "M-<mouse-1>") 'mc/add-cursor-on-click)
|
||||
;;
|
||||
;; Or you can do like me and find an unused, but less convenient, binding:
|
||||
;;
|
||||
;; (global-set-key (kbd "C-S-<mouse-1>") 'mc/add-cursor-on-click)
|
||||
|
||||
;; ## Unknown commands
|
||||
|
||||
;; Multiple-cursors uses two lists of commands to know what to do: the run-once list
|
||||
;; and the run-for-all list. It comes with a set of defaults, but it would be beyond silly
|
||||
;; to try and include all the known Emacs commands.
|
||||
|
||||
;; So that's why multiple-cursors occasionally asks what to do about a command. It will
|
||||
;; then remember your choice by saving it in `~/.emacs.d/.mc-lists.el`. You can change
|
||||
;; the location with:
|
||||
|
||||
;; (setq mc/list-file "/my/preferred/file")
|
||||
|
||||
;; ## Known limitations
|
||||
|
||||
;; * isearch-forward and isearch-backward aren't supported with multiple cursors.
|
||||
;; You should feel free to add a simplified version that can work with it.
|
||||
;; * Commands run with `M-x` won't be repeated for all cursors.
|
||||
;; * All key bindings that refer to lambdas are always run for all cursors. If you
|
||||
;; need to limit it, you will have to give it a name.
|
||||
;; * Redo might screw with your cursors. Undo works very well.
|
||||
|
||||
;; ## Contribute
|
||||
|
||||
;; Yes, please do. There's a suite of tests, so remember to add tests for your
|
||||
;; specific feature, or I might break it later.
|
||||
|
||||
;; You'll find the repo at:
|
||||
|
||||
;; https://github.com/magnars/multiple-cursors.el
|
||||
|
||||
;; To fetch the test dependencies:
|
||||
|
||||
;; $ cd /path/to/multiple-cursors
|
||||
;; $ git submodule update --init
|
||||
|
||||
;; Run the tests with:
|
||||
|
||||
;; $ ./util/ecukes/ecukes --graphical
|
||||
|
||||
;; ## Contributors
|
||||
|
||||
;; * [Takafumi Arakaki](https://github.com/tkf) made .mc-lists.el diff friendly
|
||||
;; * [Marco Baringer](https://github.com/segv) contributed looping to mc/cycle and adding cursors without region for mark-more.
|
||||
;; * [Ivan Andrus](https://github.com/gvol) added showing number of cursors in mode-line
|
||||
;; * [Fuco](https://github.com/Fuco1) added the first version of `mc/mark-all-like-this-dwim`
|
||||
|
||||
;; Thanks!
|
||||
|
||||
;;; Code:
|
||||
|
||||
(defgroup multiple-cursors nil
|
||||
"Multiple cursors for emacs."
|
||||
:group 'editing)
|
||||
|
||||
(require 'mc-edit-lines)
|
||||
(require 'mc-cycle-cursors)
|
||||
(require 'mc-mark-more)
|
||||
(require 'mc-mark-pop)
|
||||
(require 'rectangular-region-mode)
|
||||
(require 'mc-separate-operations)
|
||||
(require 'mc-hide-unmatched-lines-mode)
|
||||
|
||||
(provide 'multiple-cursors)
|
||||
|
||||
;;; multiple-cursors.el ends here
|
BIN
elpa/multiple-cursors-20191210.1759/multiple-cursors.elc
Normal file
BIN
elpa/multiple-cursors-20191210.1759/multiple-cursors.elc
Normal file
Binary file not shown.
125
elpa/multiple-cursors-20191210.1759/rectangular-region-mode.el
Normal file
125
elpa/multiple-cursors-20191210.1759/rectangular-region-mode.el
Normal file
|
@ -0,0 +1,125 @@
|
|||
;;; rectangular-region-mode.el
|
||||
|
||||
;; Copyright (C) 2012-2016 Magnar Sveen
|
||||
|
||||
;; Author: Magnar Sveen <magnars@gmail.com>
|
||||
;; Keywords: editing cursors
|
||||
|
||||
;; This program is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation, either version 3 of the License, or
|
||||
;; (at your option) any later version.
|
||||
|
||||
;; This program is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; (global-set-key (kbd "H-SPC") 'set-rectangular-region-anchor)
|
||||
|
||||
;; Think of this one as `set-mark` except you're marking a rectangular region. It is
|
||||
;; an exceedingly quick way of adding multiple cursors to multiple lines.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'multiple-cursors-core)
|
||||
|
||||
(defvar rrm/anchor (make-marker)
|
||||
"The position in the buffer that anchors the rectangular region.")
|
||||
|
||||
(defvar rectangular-region-mode-map (make-sparse-keymap)
|
||||
"Keymap for rectangular region is mainly for rebinding C-g")
|
||||
|
||||
(define-key rectangular-region-mode-map (kbd "C-g") 'rrm/keyboard-quit)
|
||||
(define-key rectangular-region-mode-map (kbd "<return>") 'rrm/switch-to-multiple-cursors)
|
||||
|
||||
(defvar rectangular-region-mode nil)
|
||||
|
||||
(defun rrm/keyboard-quit ()
|
||||
"Exit rectangular-region-mode."
|
||||
(interactive)
|
||||
(rectangular-region-mode 0)
|
||||
(rrm/remove-rectangular-region-overlays)
|
||||
(deactivate-mark))
|
||||
|
||||
;; Bind this to a key (for instance H-SPC) to start rectangular-region-mode
|
||||
;;;###autoload
|
||||
(defun set-rectangular-region-anchor ()
|
||||
"Anchors the rectangular region at point.
|
||||
|
||||
Think of this one as `set-mark' except you're marking a rectangular region. It is
|
||||
an exceedingly quick way of adding multiple cursors to multiple lines."
|
||||
(interactive)
|
||||
(set-marker rrm/anchor (point))
|
||||
(push-mark (point))
|
||||
(rectangular-region-mode 1))
|
||||
|
||||
(defun rrm/remove-rectangular-region-overlays ()
|
||||
"Remove all rectangular-region overlays."
|
||||
(mc/remove-fake-cursors)
|
||||
(mapc #'(lambda (o)
|
||||
(when (eq (overlay-get o 'type) 'additional-region)
|
||||
(delete-overlay o)))
|
||||
(overlays-in (point-min) (point-max))))
|
||||
|
||||
(defun rrm/repaint ()
|
||||
"Start from the anchor and draw a rectangle between it and point."
|
||||
(if (not rectangular-region-mode)
|
||||
(remove-hook 'post-command-hook 'rrm/repaint t)
|
||||
;; else
|
||||
(rrm/remove-rectangular-region-overlays)
|
||||
(let* ((annoying-arrows-mode nil)
|
||||
(point-column (current-column))
|
||||
(point-line (mc/line-number-at-pos))
|
||||
(anchor-column (save-excursion (goto-char rrm/anchor) (current-column)))
|
||||
(anchor-line (save-excursion (goto-char rrm/anchor) (mc/line-number-at-pos)))
|
||||
(left-column (if (< point-column anchor-column) point-column anchor-column))
|
||||
(right-column (if (> point-column anchor-column) point-column anchor-column))
|
||||
(navigation-step (if (< point-line anchor-line) 1 -1)))
|
||||
(move-to-column anchor-column)
|
||||
(set-mark (point))
|
||||
(move-to-column point-column)
|
||||
(mc/save-excursion
|
||||
(while (not (= anchor-line (mc/line-number-at-pos)))
|
||||
(forward-line navigation-step)
|
||||
(move-to-column anchor-column)
|
||||
(when (= anchor-column (current-column))
|
||||
(set-mark (point))
|
||||
(move-to-column point-column)
|
||||
(when (= point-column (current-column))
|
||||
(mc/create-fake-cursor-at-point))))))))
|
||||
|
||||
(defun rrm/switch-to-multiple-cursors (&rest forms)
|
||||
"Switch from rectangular-region-mode to multiple-cursors-mode."
|
||||
(interactive)
|
||||
(rectangular-region-mode 0)
|
||||
(multiple-cursors-mode 1))
|
||||
|
||||
(defadvice er/expand-region (before switch-from-rrm-to-mc activate)
|
||||
(when rectangular-region-mode
|
||||
(rrm/switch-to-multiple-cursors)))
|
||||
|
||||
(defadvice kill-ring-save (before switch-from-rrm-to-mc activate)
|
||||
(when rectangular-region-mode
|
||||
(rrm/switch-to-multiple-cursors)))
|
||||
|
||||
;;;###autoload
|
||||
(define-minor-mode rectangular-region-mode
|
||||
"A mode for creating a rectangular region to edit"
|
||||
nil " rr" rectangular-region-mode-map
|
||||
(if rectangular-region-mode
|
||||
(progn
|
||||
(add-hook 'after-change-functions 'rrm/switch-to-multiple-cursors t t)
|
||||
(add-hook 'post-command-hook 'rrm/repaint t t))
|
||||
(remove-hook 'after-change-functions 'rrm/switch-to-multiple-cursors t)
|
||||
(remove-hook 'post-command-hook 'rrm/repaint t)
|
||||
(set-marker rrm/anchor nil)))
|
||||
|
||||
(provide 'rectangular-region-mode)
|
||||
|
||||
;;; rectangular-region-mode.el ends here
|
BIN
elpa/multiple-cursors-20191210.1759/rectangular-region-mode.elc
Normal file
BIN
elpa/multiple-cursors-20191210.1759/rectangular-region-mode.elc
Normal file
Binary file not shown.
27
elpa/xref-js2-20190915.2032/xref-js2-autoloads.el
Normal file
27
elpa/xref-js2-20190915.2032/xref-js2-autoloads.el
Normal file
|
@ -0,0 +1,27 @@
|
|||
;;; xref-js2-autoloads.el --- automatically extracted autoloads
|
||||
;;
|
||||
;;; Code:
|
||||
|
||||
(add-to-list 'load-path (directory-file-name
|
||||
(or (file-name-directory #$) (car load-path))))
|
||||
|
||||
|
||||
;;;### (autoloads nil "xref-js2" "xref-js2.el" (0 0 0 0))
|
||||
;;; Generated autoloads from xref-js2.el
|
||||
|
||||
(autoload 'xref-js2-xref-backend "xref-js2" "\
|
||||
Xref-Js2 backend for Xref.
|
||||
|
||||
\(fn)" nil nil)
|
||||
|
||||
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "xref-js2" '("xref-js2-")))
|
||||
|
||||
;;;***
|
||||
|
||||
;; Local Variables:
|
||||
;; version-control: never
|
||||
;; no-byte-compile: t
|
||||
;; no-update-autoloads: t
|
||||
;; coding: utf-8
|
||||
;; End:
|
||||
;;; xref-js2-autoloads.el ends here
|
2
elpa/xref-js2-20190915.2032/xref-js2-pkg.el
Normal file
2
elpa/xref-js2-20190915.2032/xref-js2-pkg.el
Normal file
|
@ -0,0 +1,2 @@
|
|||
;;; -*- no-byte-compile: t -*-
|
||||
(define-package "xref-js2" "20190915.2032" "Jump to references/definitions using ag & js2-mode's AST" '((emacs "25") (js2-mode "20150909")) :commit "6f1ed5dae0c2485416196a51f2fa92f32e4b8262" :keywords '("javascript" "convenience" "tools") :authors '(("Nicolas Petton" . "nicolas@petton.fr")) :maintainer '("Nicolas Petton" . "nicolas@petton.fr") :url "https://github.com/NicolasPetton/xref-js2")
|
273
elpa/xref-js2-20190915.2032/xref-js2.el
Normal file
273
elpa/xref-js2-20190915.2032/xref-js2.el
Normal file
|
@ -0,0 +1,273 @@
|
|||
;;; xref-js2.el --- Jump to references/definitions using ag & js2-mode's AST -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2016 Nicolas Petton
|
||||
|
||||
;; Author: Nicolas Petton <nicolas@petton.fr>
|
||||
;; URL: https://github.com/NicolasPetton/xref-js2
|
||||
;; Package-Version: 20190915.2032
|
||||
;; Keywords: javascript, convenience, tools
|
||||
;; Version: 1.0
|
||||
;; Package: xref-js2
|
||||
;; Package-Requires: ((emacs "25") (js2-mode "20150909"))
|
||||
|
||||
;; 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:
|
||||
;;
|
||||
;; xref-js2 adds an xref backend for JavaScript files.
|
||||
;;
|
||||
;; Instead of using a tag system, it relies on `ag' to query the codebase of a
|
||||
;; project. This might sound crazy at first, but it turns out that `ag' is so
|
||||
;; fast that jumping using xref-js2 is most of the time instantaneous, even on
|
||||
;; fairly large JavaScript codebase (it successfully works with 50k lines of JS
|
||||
;; code).
|
||||
;;
|
||||
;; Because line by line regexp search has its downside, xref-js2 does a second
|
||||
;; pass on result candidates and eliminates possible false positives using
|
||||
;; `js2-mode''s AST, thus giving very accurate results.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'subr-x)
|
||||
(require 'xref)
|
||||
(require 'seq)
|
||||
(require 'map)
|
||||
(require 'js2-mode)
|
||||
(require 'vc)
|
||||
|
||||
(defcustom xref-js2-search-program 'ag
|
||||
"The backend program used for searching."
|
||||
:type 'symbol
|
||||
:group 'xref-js2
|
||||
:options '(ag rg))
|
||||
|
||||
(defcustom xref-js2-ag-arguments '("--js" "--noheading" "--nocolor")
|
||||
"Default arguments passed to ag."
|
||||
:type 'list
|
||||
:group 'xref-js2)
|
||||
|
||||
(defcustom xref-js2-js-extensions '("js" "mjs" "jsx" "ts" "tsx")
|
||||
"Extensions for file types xref-js2 is expected to search.
|
||||
warning, this is currently only supported by ripgrep, not ag.
|
||||
|
||||
if an empty-list/nil no filtering based on file extension will
|
||||
take place."
|
||||
:type 'list
|
||||
:group 'xref-js2)
|
||||
|
||||
(defcustom xref-js2-rg-arguments '("--no-heading"
|
||||
"--line-number" ; not activated by default on comint
|
||||
"--pcre2" ; provides regexp backtracking
|
||||
"--ignore-case" ; ag is case insensitive by default
|
||||
"--color" "never")
|
||||
"Default arguments passed to ripgrep."
|
||||
:type 'list
|
||||
:group 'xref-js2)
|
||||
|
||||
(defcustom xref-js2-ignored-dirs '("bower_components"
|
||||
"node_modules"
|
||||
"build"
|
||||
"lib")
|
||||
"List of directories to be ignored when performing a search."
|
||||
:type 'list
|
||||
:group 'xref-js2)
|
||||
|
||||
(defcustom xref-js2-ignored-files '("*.min.js")
|
||||
"List of files to be ignored when performing a search."
|
||||
:type 'list
|
||||
:group 'xref-js2)
|
||||
|
||||
(defcustom xref-js2-definitions-regexps '("\\b%s\\b[\\s]*[:=][^=]"
|
||||
"function[\\s]+\\b%s\\b"
|
||||
"class[\\s]+\\b%s\\b"
|
||||
"(?<!new)[^.]%s[\\s]*\\(")
|
||||
"List of regular expressions that match definitions of a symbol.
|
||||
In each regexp string, '%s' is expanded with the searched symbol."
|
||||
:type 'list
|
||||
:group 'xref-js2)
|
||||
|
||||
(defcustom xref-js2-references-regexps '("\\b%s\\b(?!\\s*[:=][^=])")
|
||||
"List of regular expressions that match references to a symbol.
|
||||
In each regexp string, '%s' is expanded with the searched symbol."
|
||||
:type 'list
|
||||
:group 'xref-js2)
|
||||
|
||||
;;;###autoload
|
||||
(defun xref-js2-xref-backend ()
|
||||
"Xref-Js2 backend for Xref."
|
||||
'xref-js2)
|
||||
|
||||
(cl-defmethod xref-backend-identifier-at-point ((_backend (eql xref-js2)))
|
||||
(symbol-name (symbol-at-point)))
|
||||
|
||||
(cl-defmethod xref-backend-definitions ((_backend (eql xref-js2)) symbol)
|
||||
(xref-js2--xref-find-definitions symbol))
|
||||
|
||||
(cl-defmethod xref-backend-references ((_backend (eql xref-js2)) symbol)
|
||||
(xref-js2--xref-find-references symbol))
|
||||
|
||||
(defun xref-js2--xref-find-definitions (symbol)
|
||||
"Return a list of candidates matching SYMBOL."
|
||||
(seq-map (lambda (candidate)
|
||||
(xref-js2--make-xref candidate))
|
||||
(xref-js2--find-definitions symbol)))
|
||||
|
||||
(cl-defmethod xref-backend-identifier-completion-table ((_backend (eql xref-js2)))
|
||||
"Return a list of terms for completions taken from the symbols in the current buffer.
|
||||
|
||||
The current implementation returns all the words in the buffer,
|
||||
which is really sub optimal."
|
||||
(let (words)
|
||||
(save-excursion
|
||||
(save-restriction
|
||||
(widen)
|
||||
(goto-char (point-min))
|
||||
(while (re-search-forward "\\w+" nil t)
|
||||
(add-to-list 'words (match-string-no-properties 0)))
|
||||
(seq-uniq words)))))
|
||||
|
||||
(defun xref-js2--xref-find-references (symbol)
|
||||
"Return a list of reference candidates matching SYMBOL."
|
||||
(seq-map (lambda (candidate)
|
||||
(xref-js2--make-xref candidate))
|
||||
(xref-js2--find-references symbol)))
|
||||
|
||||
(defun xref-js2--make-xref (candidate)
|
||||
"Return a new Xref object built from CANDIDATE."
|
||||
(xref-make (map-elt candidate 'match)
|
||||
(xref-make-file-location (map-elt candidate 'file)
|
||||
(map-elt candidate 'line)
|
||||
0)))
|
||||
|
||||
(defun xref-js2--find-definitions (symbol)
|
||||
"Return a list of definitions for SYMBOL from an ag search."
|
||||
(xref-js2--find-candidates
|
||||
symbol
|
||||
(xref-js2--make-regexp symbol xref-js2-definitions-regexps)))
|
||||
|
||||
(defun xref-js2--find-references (symbol)
|
||||
"Return a list of references for SYMBOL from an ag search."
|
||||
(xref-js2--find-candidates
|
||||
symbol
|
||||
(xref-js2--make-regexp symbol xref-js2-references-regexps)))
|
||||
|
||||
(defun xref-js2--make-regexp (symbol regexps)
|
||||
"Return a regular expression to search for SYMBOL using REGEXPS.
|
||||
|
||||
REGEXPS must be a list of regular expressions, which are
|
||||
concatenated together into one regexp, expanding occurrences of
|
||||
'%s' with SYMBOL."
|
||||
(mapconcat #'identity
|
||||
(mapcar (lambda (str)
|
||||
(format str symbol))
|
||||
regexps) "|"))
|
||||
|
||||
(defun xref-js2--find-candidates (symbol regexp)
|
||||
(let ((default-directory (xref-js2--root-dir))
|
||||
matches)
|
||||
(with-temp-buffer
|
||||
(let* ((search-tuple (cond ;; => (prog-name . function-to-get-args)
|
||||
((eq xref-js2-search-program 'rg)
|
||||
'("rg" . xref-js2--search-rg-get-args))
|
||||
(t ;; (eq xref-js2-search-program 'ag)
|
||||
'("ag" . xref-js2--search-ag-get-args))))
|
||||
(search-program (car search-tuple))
|
||||
(search-args (remove nil ;; rm in case no search args given
|
||||
(funcall (cdr search-tuple) regexp))))
|
||||
(apply #'process-file (executable-find search-program) nil t nil search-args))
|
||||
|
||||
(goto-char (point-max)) ;; NOTE maybe redundant
|
||||
(while (re-search-backward "^\\(.+\\)$" nil t)
|
||||
(push (match-string-no-properties 1) matches)))
|
||||
(seq-remove #'xref-js2--false-positive
|
||||
(seq-map (lambda (match)
|
||||
(xref-js2--candidate symbol match))
|
||||
matches))))
|
||||
|
||||
(defun xref-js2--search-ag-get-args (regexp)
|
||||
"Aggregate command line arguments to search for REGEXP using ag."
|
||||
`(,@xref-js2-ag-arguments
|
||||
,@(seq-mapcat (lambda (dir)
|
||||
(list "--ignore-dir" dir))
|
||||
xref-js2-ignored-dirs)
|
||||
,@(seq-mapcat (lambda (file)
|
||||
(list "--ignore" file))
|
||||
xref-js2-ignored-files)
|
||||
,regexp))
|
||||
|
||||
(defun xref-js2--search-rg-get-args (regexp)
|
||||
"Aggregate command line arguments to search for REGEXP using ripgrep."
|
||||
`(,@xref-js2-rg-arguments
|
||||
,@(if (not xref-js2-js-extensions)
|
||||
nil ;; no filtering based on extension
|
||||
(seq-mapcat (lambda (ext)
|
||||
(list "-g" (concat "*." ext)))
|
||||
xref-js2-js-extensions))
|
||||
,@(seq-mapcat (lambda (dir)
|
||||
(list "-g" (concat "!" ; exclude not include
|
||||
dir ; directory string
|
||||
(unless (string-suffix-p "/" dir) ; pattern for a directory
|
||||
"/")))) ; must end with a slash
|
||||
xref-js2-ignored-dirs)
|
||||
,@(seq-mapcat (lambda (pattern)
|
||||
(list "-g" (concat "!" pattern)))
|
||||
xref-js2-ignored-files)
|
||||
,regexp))
|
||||
|
||||
(defun xref-js2--false-positive (candidate)
|
||||
"Return non-nil if CANDIDATE is a false positive.
|
||||
Filtering is done using the AST from js2-mode."
|
||||
(let* ((file (map-elt candidate 'file))
|
||||
(buffer-open (get-file-buffer file)))
|
||||
(prog1
|
||||
(with-current-buffer (find-file-noselect file t)
|
||||
(save-excursion
|
||||
(save-restriction
|
||||
(widen)
|
||||
(unless (or (eq major-mode 'js2-mode)
|
||||
(seq-contains (map-keys minor-mode-alist) 'js2-minor-mode))
|
||||
(js2-minor-mode 1))
|
||||
(goto-char (point-min))
|
||||
(forward-line (1- (map-elt candidate 'line)))
|
||||
(search-forward (map-elt candidate 'symbol) nil t)
|
||||
;; js2-mode fails to parse the AST for some minified files
|
||||
(ignore-errors
|
||||
(let ((node (js2-node-at-point)))
|
||||
(or (js2-string-node-p node)
|
||||
(js2-comment-node-p node))))))))))
|
||||
|
||||
(defun xref-js2--root-dir ()
|
||||
"Return the root directory of the project."
|
||||
(or (ignore-errors
|
||||
(projectile-project-root))
|
||||
(ignore-errors
|
||||
(vc-root-dir))
|
||||
(user-error "You are not in a project")))
|
||||
|
||||
(defun xref-js2--candidate (symbol match)
|
||||
"Return a candidate alist built from SYMBOL and a raw MATCH result.
|
||||
The MATCH is one output result from the ag search."
|
||||
(let* ((attrs (split-string match ":" t))
|
||||
(match (string-trim (mapconcat #'identity (cddr attrs) ":"))))
|
||||
;; Some minified JS files might match a search. To avoid cluttering the
|
||||
;; search result, we trim the output.
|
||||
(when (> (seq-length match) 100)
|
||||
(setq match (concat (seq-take match 100) "...")))
|
||||
(list (cons 'file (expand-file-name (car attrs) (xref-js2--root-dir)))
|
||||
(cons 'line (string-to-number (cadr attrs)))
|
||||
(cons 'symbol symbol)
|
||||
(cons 'match match))))
|
||||
|
||||
(provide 'xref-js2)
|
||||
;;; xref-js2.el ends here
|
BIN
elpa/xref-js2-20190915.2032/xref-js2.elc
Normal file
BIN
elpa/xref-js2-20190915.2032/xref-js2.elc
Normal file
Binary file not shown.
Loading…
Add table
Reference in a new issue