| @ -1,50 +0,0 @@ | |||||
| ;;; ac-js2-autoloads.el --- automatically extracted autoloads | |||||
| ;; | |||||
| ;;; Code: | |||||
| (add-to-list 'load-path (or (file-name-directory #$) (car load-path))) | |||||
| ;;;### (autoloads nil "ac-js2" "ac-js2.el" (21824 55291 0 0)) | |||||
| ;;; Generated autoloads from ac-js2.el | |||||
| (autoload 'ac-js2-expand-function "ac-js2" "\ | |||||
| Expand the function definition left of point. | |||||
| Expansion will only occur for candidates whose documentation | |||||
| string contain a function prototype. | |||||
| \(fn)" t nil) | |||||
| (autoload 'ac-js2-completion-function "ac-js2" "\ | |||||
| Function for `completions-at-point'. | |||||
| \(fn)" nil nil) | |||||
| (autoload 'ac-js2-company "ac-js2" "\ | |||||
| \(fn COMMAND &optional ARG &rest IGNORED)" t nil) | |||||
| (autoload 'ac-js2-jump-to-definition "ac-js2" "\ | |||||
| Jump to the definition of an object's property, variable or function. | |||||
| Navigation to a property definend in an Object literal isn't | |||||
| implemented. | |||||
| \(fn)" t nil) | |||||
| (autoload 'ac-js2-mode "ac-js2" "\ | |||||
| A minor mode that provides auto-completion and navigation for Js2-mode. | |||||
| \(fn &optional ARG)" t nil) | |||||
| ;;;*** | |||||
| ;;;### (autoloads nil nil ("ac-js2-pkg.el" "ac-js2-tests.el") (21824 | |||||
| ;;;;;; 55291 874082 0)) | |||||
| ;;;*** | |||||
| ;; Local Variables: | |||||
| ;; version-control: never | |||||
| ;; no-byte-compile: t | |||||
| ;; no-update-autoloads: t | |||||
| ;; End: | |||||
| ;;; ac-js2-autoloads.el ends here | |||||
| @ -1,7 +0,0 @@ | |||||
| (define-package "ac-js2" "20140906.442" "Auto-complete source for Js2-mode, with navigation" | |||||
| '((js2-mode "20090723") | |||||
| (skewer-mode "1.4")) | |||||
| :url "https://github.com/ScottyB/ac-js2") | |||||
| ;; Local Variables: | |||||
| ;; no-byte-compile: t | |||||
| ;; End: | |||||
| @ -1,76 +0,0 @@ | |||||
| ;;; Tests for ac-js2 | |||||
| (require 'ert) | |||||
| (require 'skewer-mode) | |||||
| (require 'js2-mode) | |||||
| (require 'ac-js2) | |||||
| ;;; Must have a skewer client connected before running the tests | |||||
| ;; Need to call httpd-stop from main Emacs if running tests in batch mode | |||||
| (unless skewer-clients | |||||
| (run-skewer)) | |||||
| (ert-deftest ac-js2-candidates-test () | |||||
| "Test the major function that returns candidates for all frontends." | |||||
| (let (property | |||||
| property-dot | |||||
| func-call | |||||
| var) | |||||
| (with-temp-buffer | |||||
| (insert " | |||||
| var temp = function(param1, param2) { | |||||
| var localParam = 15; | |||||
| return param1 + param2; | |||||
| }; | |||||
| var look; | |||||
| temp.aFun = function(lolParam) {}; | |||||
| temp.anotherFunction = function() { return {about: 3};}") | |||||
| (setq ac-js2-evaluate-calls t) | |||||
| (setq ac-js2-external-libraries nil) | |||||
| (js2-mode) | |||||
| (ac-js2-mode t) | |||||
| (js2-parse) | |||||
| (insert "tem") | |||||
| (ac-js2-candidates) | |||||
| (setq var ac-js2-skewer-candidates) | |||||
| (delete-char -3) | |||||
| (insert "temp.") | |||||
| (js2-parse) | |||||
| (ac-js2-candidates) | |||||
| (setq property-dot ac-js2-skewer-candidates) | |||||
| (delete-char -5) | |||||
| (insert "temp.aF") | |||||
| (js2-parse) | |||||
| (ac-js2-candidates) | |||||
| (setq property ac-js2-skewer-candidates)) | |||||
| (should (assoc 'anotherFunction property-dot)) | |||||
| (print property) | |||||
| (should (assoc 'aFun property)) | |||||
| (should (assoc 'temp var)))) | |||||
| (defmacro completion-frontend-test (test-name completion-function) | |||||
| "Utility for testing completion front ends. | |||||
| TODO: cover more cases" | |||||
| `(ert-deftest ,test-name () | |||||
| (let (var) | |||||
| (with-temp-buffer | |||||
| (insert "var testComplete = function(param1, param2) {};") | |||||
| (js2-mode) | |||||
| (ac-js2-mode t) | |||||
| (js2-parse) | |||||
| (insert "testComplet") | |||||
| (funcall ',completion-function) | |||||
| (setq var (thing-at-point 'word))) | |||||
| (should (string= var "testComplete"))))) | |||||
| (completion-frontend-test auto-complete-test auto-complete) | |||||
| (completion-frontend-test completion-at-point-test completion-at-point) | |||||
| @ -1,605 +0,0 @@ | |||||
| ;;; ac-js2.el --- Auto-complete source for Js2-mode, with navigation | |||||
| ;; Copyright (C) 2013 Scott Barnett | |||||
| ;; Author: Scott Barnett <scott.n.barnett@gmail.com> | |||||
| ;; URL: https://github.com/ScottyB/ac-js2 | |||||
| ;; Version: 1.0 | |||||
| ;; Package-Requires: ((js2-mode "20090723")(skewer-mode "1.4")) | |||||
| ;; 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: | |||||
| ;; An attempt to get context sensitive Javascript completion in Emacs. | |||||
| ;; Basic completions are obtained by parsing Javascript code with | |||||
| ;; Js2-mode's parser. | |||||
| ;; | |||||
| ;; Installation | |||||
| ;; | |||||
| ;; Easiest way to get ac-js2 is to install it from MELPA. You may need | |||||
| ;; this snippet | |||||
| ;; | |||||
| ;; `(add-to-list 'package-archives | |||||
| ;; '("melpa" . "http://melpa.milkbox.net/packages/") t)' | |||||
| ;; | |||||
| ;; if you don't have it already to fetch packages from MELPA. | |||||
| ;; | |||||
| ;; Enable ac-js2 in js2-mode as follows: | |||||
| ;; | |||||
| ;; (add-hook 'js2-mode-hook 'ac-js2-mode) | |||||
| ;; | |||||
| ;; Ac-js2 does not require auto-complete mode but I suggest you grab | |||||
| ;; it anyway as ac-js2 is designed to work with a completion frontend. | |||||
| ;; Support for Company mode is on its way. | |||||
| ;; | |||||
| ;; For more comprehensive completions you can opt to evaluate the code | |||||
| ;; for candidates. A browser needs to be connected to Emacs for the | |||||
| ;; evaluation completions to work. Put this in your init.el file. | |||||
| ;; | |||||
| ;; `(setq ac-js2-evaluate-calls t)' | |||||
| ;; | |||||
| ;; To add completions for external libraries add something like this: | |||||
| ;; | |||||
| ;; (add-to-list 'ac-js2-external-libraries "path/to/lib/library.js") | |||||
| ;; | |||||
| ;; Then connect a browser to Emacs by calling `(run-skewer)'. You may | |||||
| ;; need to save the buffer for completions to start. | |||||
| ;; | |||||
| ;; If auto-complete mode is installed on your system then completions | |||||
| ;; should start showing up otherwise use `completion-at-point'. | |||||
| ;; | |||||
| ;; Note: library completions will only work if `ac-js2-evaluate-calls' | |||||
| ;; is set and a browser is connected to Emacs. | |||||
| ;; | |||||
| ;; Bonus: M-. is bound to `ac-js2-jump-to-definition' which will jump | |||||
| ;; to Javascript definitions found in the same buffer. Given the | |||||
| ;; following proprety reference: | |||||
| ;; | |||||
| ;; foo.bar.baz(); | |||||
| ;; | |||||
| ;; placing the cursor on `foo', `bar' or `baz' and executing M-. will | |||||
| ;; take you straight to their respective definitions. Use M-, to jump | |||||
| ;; back to where you were. Also works for object literals. | |||||
| ;; | |||||
| ;; Recently added `ac-js2-expand-function' that will expand a function's | |||||
| ;; parameters bound to `C-c C-c`. Expansion will only work if the cursor | |||||
| ;; is after the function. | |||||
| ;; | |||||
| ;; If you have any issues or suggestions please create an issue on Github: | |||||
| ;; https://github.com/ScottyB/ac-js2 | |||||
| ;;; History: | |||||
| ;; Version 1.0 | |||||
| ;; * Navigation within current buffer | |||||
| ;; * Completion and docstring for objects via Skewer | |||||
| ;; * External library support | |||||
| ;; * Basic completions of objects in current buffer | |||||
| ;;; Code: | |||||
| (require 'js2-mode) | |||||
| (require 'skewer-mode) | |||||
| (require 'cl-lib) | |||||
| (require 'etags) | |||||
| (defgroup ac-js2 nil | |||||
| "Auto-completion for js2-mode." | |||||
| :group 'completion | |||||
| :prefix "ac-js2-") | |||||
| ;;; Configuration variables | |||||
| (defcustom ac-js2-add-ecma-262-externs t | |||||
| "If non-nil add `js2-ecma-262-externs' to completion candidates.") | |||||
| (defcustom ac-js2-add-browser-externs t | |||||
| "If non-nil add `js2-browser-externs' to completion candidates.") | |||||
| (defcustom ac-js2-add-keywords t | |||||
| "If non-nil add `js2-keywords' to completion candidates.") | |||||
| (defcustom ac-js2-add-prototype-completions t | |||||
| "When non-nil traverse the prototype chain adding to completion candidates.") | |||||
| (defcustom ac-js2-external-libraries '() | |||||
| "List of absolute paths to external Javascript libraries.") | |||||
| (defcustom ac-js2-evaluate-calls nil | |||||
| "Warning. When true function calls will be evaluated in the browser. | |||||
| This may cause undesired side effects however it will | |||||
| provide better completions. Use at your own risk.") | |||||
| (defcustom ac-js2-force-reparse t | |||||
| "Force Js2-mode to reparse buffer before fetching completion candidates.") | |||||
| ;;; Internal variables | |||||
| (defvar ac-js2-keywords '() | |||||
| "Cached string version of `js2-keywords'.") | |||||
| (defvar ac-js2-candidates '()) | |||||
| ;; Types of skewer completion methods available | |||||
| (defconst ac-js2-method-eval 0) | |||||
| (defconst ac-js2-method-global 1 | |||||
| "Return candidates for the global object. | |||||
| Only keys of the object are returned as the other properties come | |||||
| from js2-mode's externs.") | |||||
| (defvar ac-js2-data-root (file-name-directory load-file-name) | |||||
| "Location of data files needed for `ac-js2-on-skewer-load'.") | |||||
| ;;; Skewer integration | |||||
| (defvar ac-js2-skewer-candidates '() | |||||
| "Cadidates obtained from skewering.") | |||||
| (defun ac-js2-on-skewer-load () | |||||
| "Inject skewer addon and evaluate external libraries in browser." | |||||
| (insert-file-contents (expand-file-name "skewer-addon.js" ac-js2-data-root)) | |||||
| (and ac-js2-evaluate-calls | |||||
| (mapcar (lambda (library) | |||||
| (with-temp-buffer | |||||
| (insert-file-contents (expand-file-name library)) | |||||
| (skewer-eval (buffer-string) | |||||
| nil | |||||
| :type "complete"))) ac-js2-external-libraries))) | |||||
| (defun ac-js2-skewer-completion-candidates () | |||||
| "Get completions returned from skewer." | |||||
| (mapcar (lambda (candidate) (symbol-name (car candidate))) ac-js2-skewer-candidates)) | |||||
| (defun ac-js2-skewer-document-candidates (name) | |||||
| "Return document string for NAME from skewer." | |||||
| (let ((doc (cdr (assoc-string name ac-js2-skewer-candidates)))) | |||||
| (or (ac-js2-format-function doc) doc))) | |||||
| (defun ac-js2-get-object-properties (name) | |||||
| "Find properties of NAME for completion." | |||||
| (ac-js2-skewer-eval-wrapper name `((prototypes . ,ac-js2-add-prototype-completions)))) | |||||
| (defun ac-js2-skewer-result-callback (result) | |||||
| "Process the RESULT passed from the browser." | |||||
| (let ((value (cdr (assoc 'value result)))) | |||||
| (if (and (skewer-success-p result) value) | |||||
| (setq ac-js2-skewer-candidates (append value nil))))) | |||||
| (defun ac-js2-skewer-eval-wrapper (str &optional extras) | |||||
| "Wrap `skewer-eval-synchronously' to check if a skewer-client is avilable. | |||||
| STR is the text to send to the browser for evaluation. Extra | |||||
| parameters can be passed to the browser using EXTRAS. EXTRAS must | |||||
| be of the form (param-string . value) where param-string is the | |||||
| reference and value is the value that can be retrieved from the | |||||
| request object in Javacript." | |||||
| (setq ac-js2-skewer-candidates nil) | |||||
| (if skewer-clients | |||||
| (if (or ac-js2-evaluate-calls | |||||
| (not (ac-js2-has-function-calls str))) | |||||
| (ac-js2-skewer-result-callback | |||||
| (skewer-eval-synchronously str | |||||
| :type "complete" | |||||
| :extra extras))) | |||||
| (setq skewer-queue nil))) | |||||
| ;; Generate candidates | |||||
| (defun ac-js2-candidates () | |||||
| "Main function called to gather candidates for auto-completion." | |||||
| (if ac-js2-force-reparse (js2-reparse)) | |||||
| (let ((node (js2-node-parent (js2-node-at-point (1- (point))))) | |||||
| beg | |||||
| (prop-get-regex "[a-zA-Z)]\\.") | |||||
| name) | |||||
| (setq ac-js2-candidates nil) | |||||
| (cond | |||||
| ((looking-back "\\.") | |||||
| ;; TODO: Need to come up with a better way to extract object than this regex!! | |||||
| (save-excursion | |||||
| (setq beg (and (skip-chars-backward "[a-zA-Z_$][0-9a-zA-Z_$#\"())]+\\.") (point)))) | |||||
| (setq name (buffer-substring-no-properties beg (1- (point)))) | |||||
| (ac-js2-get-object-properties name) | |||||
| (setq node (ac-js2-initialized-node (if (string-match prop-get-regex name) | |||||
| (reverse (split-string name prop-get-regex)) name))) | |||||
| (if (js2-object-node-p node) | |||||
| (setq ac-js2-candidates | |||||
| (mapcar (lambda (elem) | |||||
| (ac-js2-format-node (js2-node-string (js2-object-prop-node-left elem)) | |||||
| elem)) | |||||
| (js2-object-node-elems node)))) | |||||
| (append (mapcar 'first ac-js2-candidates) | |||||
| (ac-js2-skewer-completion-candidates))) | |||||
| ((js2-prop-get-node-p node) | |||||
| (setq node (js2-prop-get-node-left node)) | |||||
| (setq name (js2-node-string node)) | |||||
| (ac-js2-get-object-properties name) | |||||
| (ac-js2-skewer-completion-candidates)) | |||||
| (t | |||||
| (ac-js2-skewer-eval-wrapper "" `((method . ,ac-js2-method-global))) | |||||
| (append (ac-js2-skewer-completion-candidates) | |||||
| (ac-js2-add-extra-completions | |||||
| (mapcar 'first (ac-js2-get-names-in-scope)))))))) | |||||
| (defun ac-js2-document (name) | |||||
| "Show documentation for NAME from local buffer if present | |||||
| otherwise use documentation obtained from skewer." | |||||
| (let* ((docs (cdr (assoc name ac-js2-candidates))) | |||||
| (doc (if (listp docs) (first docs) docs))) | |||||
| (if doc doc (ac-js2-skewer-document-candidates name)))) | |||||
| ;; Auto-complete settings | |||||
| (defun ac-js2-ac-candidates () | |||||
| "Completion candidates for auto-complete mode." | |||||
| (ac-js2-candidates)) | |||||
| (defun ac-js2-ac-document (name) | |||||
| "Documentation to be shown for auto-complete mode." | |||||
| (ac-js2-document name)) | |||||
| (defun ac-js2-ac-prefix() | |||||
| (or (ac-prefix-default) (ac-prefix-c-dot))) | |||||
| (defun ac-js2-save () | |||||
| "Called on `before-save-hook' to evaluate buffer." | |||||
| (interactive) | |||||
| (when (string= major-mode "js2-mode") | |||||
| (ac-js2-skewer-eval-wrapper (buffer-string))) | |||||
| t) | |||||
| ;;;###autoload | |||||
| (defun ac-js2-expand-function() | |||||
| "Expand the function definition left of point. | |||||
| Expansion will only occur for candidates whose documentation | |||||
| string contain a function prototype." | |||||
| (interactive) | |||||
| (let* ((word (progn | |||||
| (if (featurep 'auto-complete) (ac-complete)) | |||||
| (substring-no-properties (or (thing-at-point 'word) "")))) | |||||
| (candidate (ac-js2-ac-document word))) | |||||
| (if (and (looking-back word) (stringp candidate)) | |||||
| (when (string-match "^function" candidate) | |||||
| (cond ((featurep 'yasnippet) | |||||
| (yas-expand-snippet | |||||
| (concat "(" | |||||
| (replace-regexp-in-string "\\([a-zA-Z0-9]+\\)" | |||||
| (lambda (txt) (concat "${" txt "}")) | |||||
| (second (split-string candidate "[()]"))) | |||||
| ")$0")))))))) | |||||
| (defun ac-js2-setup-auto-complete-mode () | |||||
| "Setup ac-js2 to be used with auto-complete-mode." | |||||
| (add-to-list 'ac-sources 'ac-source-js2) | |||||
| (auto-complete-mode) | |||||
| (ac-define-source "js2" | |||||
| '((candidates . ac-js2-ac-candidates) | |||||
| (document . ac-js2-ac-document) | |||||
| (prefix . ac-js2-ac-prefix) | |||||
| (requires . -1)))) | |||||
| ;;; Completion at point function | |||||
| ;;;###autoload | |||||
| (defun ac-js2-completion-function () | |||||
| "Function for `completions-at-point'." | |||||
| (save-excursion | |||||
| (let ((bounds (if (looking-back "\\.") | |||||
| (cons (point) (point)) | |||||
| (bounds-of-thing-at-point 'word)))) | |||||
| (list (car bounds) (cdr bounds) (ac-js2-candidates))))) | |||||
| ;;; Company | |||||
| ;;;###autoload | |||||
| (defun ac-js2-company (command &optional arg &rest ignored) | |||||
| (interactive (list 'interactive)) | |||||
| (if (not (featurep 'company)) | |||||
| (message "Company is not installed") | |||||
| (case command | |||||
| (interactive (company-begin-backend 'ac-js2-company)) | |||||
| (prefix (when ac-js2-mode | |||||
| (or (company-grab-symbol) | |||||
| 'stop))) | |||||
| (candidates (all-completions arg (ac-js2-candidates))) | |||||
| (duplicates t) | |||||
| (meta (let ((doc (ac-js2-document arg))) | |||||
| (when doc | |||||
| (with-temp-buffer | |||||
| (insert doc) | |||||
| (js-mode) | |||||
| (font-lock-ensure) | |||||
| (buffer-string)))))))) | |||||
| ;;; Helper functions | |||||
| (defun ac-js2-build-prop-name-list (prop-node) | |||||
| "Build a list of names from a PROP-NODE." | |||||
| (let* (names | |||||
| left | |||||
| left-node) | |||||
| (unless (js2-prop-get-node-p prop-node) | |||||
| (error "Node is not a property prop-node")) | |||||
| (while (js2-prop-get-node-p prop-node) | |||||
| (push (js2-name-node-name (js2-prop-get-node-right prop-node)) names) | |||||
| (setq left-node (js2-prop-get-node-left prop-node)) | |||||
| (when (js2-name-node-p left-node) | |||||
| (setq left (js2-name-node-name left-node))) | |||||
| (setq prop-node (js2-node-parent prop-node))) | |||||
| (append names `(,left)))) | |||||
| (defun ac-js2-prop-names-left (name-node) | |||||
| "Create a list of all of the names in the property NAME-NODE. | |||||
| NAME-NODE must have a js2-prop-get-node as parent. Only adds | |||||
| properties to the left of point. This is so individual jump | |||||
| points can be found for each property in the chain." | |||||
| (let* (name | |||||
| (parent (js2-node-parent name-node)) | |||||
| left | |||||
| names) | |||||
| (unless (or (js2-prop-get-node-p parent) (js2-name-node-p name-node)) | |||||
| (error "Not a name node or doesn't have a prop-get-node as parent")) | |||||
| (setq name (js2-name-node-name name-node) | |||||
| left (js2-prop-get-node-left parent)) | |||||
| (if (and (js2-name-node-p left) | |||||
| (string= name (js2-name-node-name left))) | |||||
| (setq names name) | |||||
| (js2-visit-ast | |||||
| parent | |||||
| (lambda (node endp) | |||||
| (unless endp | |||||
| (if (js2-name-node-p node) | |||||
| (push (js2-name-node-name node) names) | |||||
| t)))) | |||||
| names))) | |||||
| (defun ac-js2-has-function-calls (string) | |||||
| "Check if the Javascript code in STRING has a Js2-call-node." | |||||
| (with-temp-buffer | |||||
| (insert string) | |||||
| (let* ((ast (js2-parse))) | |||||
| (catch 'call-node | |||||
| (js2-visit-ast-root | |||||
| ast | |||||
| (lambda (node end-p) | |||||
| (unless end-p | |||||
| (if (js2-call-node-p node) | |||||
| (throw 'call-node t) | |||||
| t)))))))) | |||||
| (defun ac-js2-add-extra-completions (completions) | |||||
| "Add extra candidates to COMPLETIONS." | |||||
| (append completions | |||||
| (if ac-js2-add-keywords (or ac-js2-keywords (setq ac-js2-keywords (mapcar 'symbol-name js2-keywords)))) | |||||
| (if ac-js2-add-ecma-262-externs js2-ecma-262-externs) | |||||
| (if ac-js2-add-browser-externs js2-browser-externs))) | |||||
| (defun ac-js2-root-or-node () | |||||
| "Return the current node or js2-ast-root node." | |||||
| (let ((node (js2-node-at-point))) | |||||
| (if (js2-ast-root-p node) | |||||
| node | |||||
| (js2-node-get-enclosing-scope node)))) | |||||
| (defun ac-js2-get-names-in-scope () | |||||
| "Fetches all symbols in scope and formats them for completion." | |||||
| (let* ((scope (ac-js2-root-or-node)) | |||||
| result) | |||||
| (while scope | |||||
| (setq result (append result | |||||
| (loop for item in (js2-scope-symbol-table scope) | |||||
| if (not (assoc (car item) result)) | |||||
| collect item))) | |||||
| (setq scope (js2-scope-parent-scope scope))) | |||||
| (setq ac-js2-candidates | |||||
| (mapcar #'(lambda (x) | |||||
| (let* ((name (symbol-name (car x))) | |||||
| (init (ac-js2-initialized-node name))) | |||||
| (ac-js2-format-node name init))) | |||||
| result)))) | |||||
| (defun ac-js2-initialized-node (name) | |||||
| "Return initial value assigned to NAME. | |||||
| NAME may be either a variable, a function or a variable that | |||||
| holds a function. NAME may also be a list of names that make up a | |||||
| object property. Returns nil if no initial value can be found." | |||||
| (let* ((node (if (listp name) (ac-js2-find-property name) | |||||
| (ac-js2-name-declaration name))) | |||||
| (parent (if node (js2-node-parent node))) | |||||
| (init (cond | |||||
| ((js2-function-node-p parent) | |||||
| parent) | |||||
| ((js2-function-node-p node) | |||||
| node) | |||||
| ((js2-var-init-node-p parent) | |||||
| (js2-var-init-node-initializer parent)) | |||||
| ((js2-assign-node-p parent) | |||||
| (js2-assign-node-right parent)) | |||||
| (t | |||||
| nil)))) | |||||
| init)) | |||||
| (defun ac-js2-name-declaration (name) | |||||
| "Return the declaration node for node named NAME." | |||||
| (let* ((node (ac-js2-root-or-node)) | |||||
| (scope-def (js2-get-defining-scope node name)) | |||||
| (scope (if scope-def (js2-scope-get-symbol scope-def name) nil)) | |||||
| (symbol (if scope (js2-symbol-ast-node scope) nil))) | |||||
| (if (not symbol) | |||||
| (ac-js2-get-function-node name scope-def) | |||||
| symbol))) | |||||
| ;;; Completion candidate formatting | |||||
| (defun ac-js2-format-node (name node) | |||||
| "Format NAME and NODE for completion. | |||||
| Returned format is a list where the first element is the NAME of | |||||
| the node (shown in completion candidate list) and the last | |||||
| element is the text to show as documentation." | |||||
| (let ((node (if (js2-object-prop-node-p node) (js2-object-prop-node-right node) node)) | |||||
| (name-format (replace-regexp-in-string "\"" "" name)) | |||||
| (doc (if (and (js2-function-node-p node) | |||||
| (cl-find name (js2-function-node-params node) | |||||
| :test '(lambda (name param) (string= name (js2-name-node-name param))))) | |||||
| "Function parameter" | |||||
| (ac-js2-format-node-doc node)))) | |||||
| `(,name-format . ,doc))) | |||||
| (defun ac-js2-format-object-node-doc (obj-node) | |||||
| "Format OBJ-NODE to display as documentation." | |||||
| (let (elems) | |||||
| (unless (js2-object-node-p obj-node) | |||||
| (error "Node is not an object node")) | |||||
| (setq elems (js2-object-node-elems obj-node)) | |||||
| (if (not elems) | |||||
| "{}" | |||||
| (mapconcat #'(lambda (x) (ac-js2-format-js2-object-prop-doc x)) elems "\n")))) | |||||
| (defun ac-js2-format-node-doc (node) | |||||
| "Format NODE for displaying in a document string." | |||||
| (let* ((node-above (and node (js2-node-at-point | |||||
| (save-excursion | |||||
| (goto-char (js2-node-abs-pos node)) | |||||
| (forward-line -1) | |||||
| (point))))) | |||||
| (comment (if (js2-comment-node-p node-above) | |||||
| (ac-js2-format-comment (js2-node-string node-above)))) | |||||
| (doc (cond | |||||
| ((js2-function-node-p node) | |||||
| (ac-js2-format-function node)) | |||||
| ((js2-object-node-p node) | |||||
| (ac-js2-format-object-node-doc node)) | |||||
| ((js2-object-prop-node-p node) | |||||
| (ac-js2-format-node-doc (js2-object-prop-node-right node))) | |||||
| (t | |||||
| (if (js2-node-p node) (js2-node-string node) ""))))) | |||||
| (if comment (concat comment "\n" doc) doc))) | |||||
| (defun ac-js2-format-js2-object-prop-doc (obj-prop) | |||||
| "Format an OBJ-PROP for displaying as a document string." | |||||
| (unless (js2-object-prop-node-p obj-prop) | |||||
| (error "Node is not an object property node")) | |||||
| (let* ((left (js2-object-prop-node-left obj-prop)) | |||||
| (right (js2-object-prop-node-right obj-prop))) | |||||
| (concat (js2-node-string left) " : " | |||||
| (ac-js2-format-node-doc right)))) | |||||
| (defun ac-js2-format-function (func) | |||||
| "Formats a function for a document string. | |||||
| FUNC can be either a function node or a string starting with | |||||
| 'function'. Returns nil if neither." | |||||
| (let ((str (or (and (js2-function-node-p func) (js2-node-string func)) | |||||
| (and (stringp func) (eq 0 (string-match "function" func)) func)))) | |||||
| (if str (substring str 0 (1+ (string-match ")" str)))))) | |||||
| (defun ac-js2-format-comment (comment) | |||||
| "Prepare a COMMENT node for displaying in a popup." | |||||
| (let* ((node-string (if (js2-comment-node-p comment) | |||||
| (js2-node-string comment) | |||||
| comment)) | |||||
| (string (replace-regexp-in-string "[ \t]$" "" | |||||
| (replace-regexp-in-string "^[ \t\n*/*]+" "" node-string)))) | |||||
| string)) | |||||
| ;;; Navigation commands for js2-mode | |||||
| (defun ac-js2-find-property (list-names) | |||||
| "Find the property definition that consists of LIST-NAMES. | |||||
| Supports navigation to 'foo.bar = 3' and 'foo = {bar: 3}'." | |||||
| (catch 'prop-found | |||||
| (js2-visit-ast-root | |||||
| js2-mode-ast | |||||
| (lambda (node endp) | |||||
| (let ((parent (js2-node-parent node))) | |||||
| (unless endp | |||||
| (if (or (and (js2-prop-get-node-p node) | |||||
| (not (or (js2-elem-get-node-p parent) (js2-call-node-p parent))) | |||||
| (equal list-names (ac-js2-build-prop-name-list node))) | |||||
| (and (js2-name-node-p node) | |||||
| (js2-object-prop-node-p parent) | |||||
| (string= (js2-name-node-name node) | |||||
| (first list-names)))) | |||||
| (throw 'prop-found node)) | |||||
| t)))))) | |||||
| (defun ac-js2-get-function-node (name scope) | |||||
| "Return node of function named NAME in SCOPE." | |||||
| (catch 'function-found | |||||
| (js2-visit-ast | |||||
| scope | |||||
| (lambda (node end-p) | |||||
| (when (and (not end-p) | |||||
| (string= name (ac-js2-get-function-name node))) | |||||
| (throw 'function-found node)) | |||||
| t)) | |||||
| nil)) | |||||
| ;;;###autoload | |||||
| (defun ac-js2-jump-to-definition () | |||||
| "Jump to the definition of an object's property, variable or function. | |||||
| Navigation to a property definend in an Object literal isn't | |||||
| implemented." | |||||
| (interactive) | |||||
| (ring-insert find-tag-marker-ring (point-marker)) | |||||
| (let* ((node (js2-node-at-point)) | |||||
| (parent (js2-node-parent node)) | |||||
| (prop-names (if (js2-prop-get-node-p parent) | |||||
| (ac-js2-prop-names-left node))) | |||||
| (name (if (and (js2-name-node-p node) | |||||
| (not (js2-object-prop-node-p parent))) | |||||
| (js2-name-node-name node) | |||||
| (error "Node is not a supported jump node"))) | |||||
| (node-init (if (and prop-names (listp prop-names)) | |||||
| (ac-js2-find-property prop-names) | |||||
| (ac-js2-name-declaration name)))) | |||||
| (unless node-init | |||||
| (pop-tag-mark) | |||||
| (error "No jump location found")) | |||||
| (goto-char (js2-node-abs-pos node-init)))) | |||||
| (defun ac-js2-get-function-name (fn-node) | |||||
| "Return the name of the function FN-NODE. | |||||
| Value may be either function name or the variable name that holds | |||||
| the function." | |||||
| (let ((parent (js2-node-parent fn-node))) | |||||
| (if (js2-function-node-p fn-node) | |||||
| (or (js2-function-name fn-node) | |||||
| (if (js2-var-init-node-p parent) | |||||
| (js2-name-node-name (js2-var-init-node-target parent))))))) | |||||
| (defvar ac-js2-mode-map | |||||
| (let ((map (make-sparse-keymap))) | |||||
| (define-key map (kbd "M-.") 'ac-js2-jump-to-definition) | |||||
| (define-key map (kbd "M-,") 'pop-tag-mark) | |||||
| (define-key map (kbd "C-c C-c") 'ac-js2-expand-function) | |||||
| map) | |||||
| "Keymap for `ac-js2-mode'.") | |||||
| ;;; Minor mode | |||||
| ;;;###autoload | |||||
| (define-minor-mode ac-js2-mode | |||||
| "A minor mode that provides auto-completion and navigation for Js2-mode." | |||||
| :keymap ac-js2-mode-map | |||||
| (if (featurep 'auto-complete) | |||||
| (ac-js2-setup-auto-complete-mode)) | |||||
| (set (make-local-variable 'completion-at-point-functions) | |||||
| (cons 'ac-js2-completion-function completion-at-point-functions)) | |||||
| (ac-js2-skewer-eval-wrapper (buffer-string)) | |||||
| (add-hook 'before-save-hook 'ac-js2-save nil t) | |||||
| (add-hook 'skewer-js-hook 'ac-js2-on-skewer-load)) | |||||
| (provide 'ac-js2) | |||||
| ;;; ac-js2.el ends here | |||||
| @ -1,116 +0,0 @@ | |||||
| /** | |||||
| * @fileOverview Completion request handler for skewer.js | |||||
| * @requires skewer | |||||
| * @version 1.0 | |||||
| */ | |||||
| /** | |||||
| * Handles a completion request from Emacs. | |||||
| * @param request The request object sent by Emacs | |||||
| * @returns The completions and init values to be returned to Emacs | |||||
| */ | |||||
| skewer.fn.complete = function(request) { | |||||
| var result = { | |||||
| type : request.type, | |||||
| id : request.id, | |||||
| strict : request.strict, | |||||
| status : "success" | |||||
| }, | |||||
| /** | |||||
| * Methods for generating candidates | |||||
| */ | |||||
| METHOD = { | |||||
| EVAL : 0, | |||||
| GLOBAL : 1 | |||||
| }, | |||||
| /** | |||||
| * Add the properties from object to extendObject. Properties | |||||
| * may be from the prototype but we still want to add them. | |||||
| */ | |||||
| extend = function(extendObject, object) { | |||||
| for(var key in object) { | |||||
| extendObject[key] = object[key]; | |||||
| } | |||||
| }, | |||||
| globalCompletion = function() { | |||||
| var global = Function('return this')(), | |||||
| keys = Object.keys(global); | |||||
| candidates = buildCandidates(global, keys); | |||||
| }, | |||||
| evalCompletion = function(evalObject) { | |||||
| var obj = (eval, eval)(evalObject); | |||||
| if (typeof obj === "object") { | |||||
| candidates = buildCandidates(obj) || {}; | |||||
| while (request.prototypes && (obj = Object.getPrototypeOf(obj)) !== null) { | |||||
| extend(candidates, buildCandidates(obj)); | |||||
| } | |||||
| } else if (typeof obj === "function"){ | |||||
| candidates = buildCandidates(obj) || {}; | |||||
| extend(candidates, buildCandidates(Object.getPrototypeOf(obj))); | |||||
| if (request.prototypes) { | |||||
| var protoObject = Object.getPrototypeOf(obj.prototype); | |||||
| if (protoObject !== null) { | |||||
| extend(candidates, buildCandidates(protoObject)); | |||||
| } else { | |||||
| extend(candidates, buildCandidates(obj.prototype)); | |||||
| } | |||||
| } | |||||
| } | |||||
| }, | |||||
| /** | |||||
| * Completion candidates sent back to Emacs. Keys are | |||||
| * completion candidates the values are the inital items or | |||||
| * function interfaces. | |||||
| */ | |||||
| candidates = {}, | |||||
| /** | |||||
| * Build the candiates to return to Emacs. | |||||
| * @param obj The object to get candidates from | |||||
| * @param items The selected keys from obj to create candidates for | |||||
| * @return object containing completion candidates and documentation strings | |||||
| */ | |||||
| buildCandidates = function(obj, items) { | |||||
| var keys = items || Object.getOwnPropertyNames(obj), values = {}; | |||||
| for (var i = 0; i < keys.length; i++) { | |||||
| var key = keys[i]; | |||||
| if (key === "callee" || key === "caller" || key === "arguments") continue; | |||||
| if (Object.prototype.toString.call(obj[key]) === "[object Function]") { | |||||
| values[key] = obj[key].toString(); | |||||
| } else if (typeof obj[key] === "object"){ | |||||
| values[key] = "[object Object]"; | |||||
| } else if (typeof obj[key] === "number") { | |||||
| if (!(obj instanceof Array)) { | |||||
| values[key] = obj[key].toString(); | |||||
| } | |||||
| } else if (typeof obj[key] === "string") { | |||||
| values[key] = obj[key].toString(); | |||||
| } else if(obj[key] === true) { | |||||
| values[key] = "true"; | |||||
| } else if (obj[key] === false) { | |||||
| values[key] = "false"; | |||||
| } else { | |||||
| values[key] = ""; | |||||
| } | |||||
| } | |||||
| return values; | |||||
| }; | |||||
| try { | |||||
| switch (request.method) { | |||||
| case METHOD.GLOBAL: | |||||
| globalCompletion(); | |||||
| break; | |||||
| default: | |||||
| evalCompletion(request.eval); | |||||
| } | |||||
| result.value = candidates; | |||||
| } catch (error){ | |||||
| skewer.errorResult(error, result, request); | |||||
| } | |||||
| return result; | |||||
| }; | |||||
| @ -1,50 +0,0 @@ | |||||
| ;;; company-abbrev.el --- company-mode completion backend for abbrev | |||||
| ;; Copyright (C) 2009-2011, 2015 Free Software Foundation, Inc. | |||||
| ;; Author: Nikolaj Schumacher | |||||
| ;; 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: | |||||
| ;; | |||||
| ;;; Code: | |||||
| (require 'company) | |||||
| (require 'cl-lib) | |||||
| (require 'abbrev) | |||||
| (defun company-abbrev-insert (match) | |||||
| "Replace MATCH with the expanded abbrev." | |||||
| (expand-abbrev)) | |||||
| ;;;###autoload | |||||
| (defun company-abbrev (command &optional arg &rest ignored) | |||||
| "`company-mode' completion backend for abbrev." | |||||
| (interactive (list 'interactive)) | |||||
| (cl-case command | |||||
| (interactive (company-begin-backend 'company-abbrev | |||||
| 'company-abbrev-insert)) | |||||
| (prefix (company-grab-symbol)) | |||||
| (candidates (nconc | |||||
| (delete "" (all-completions arg global-abbrev-table)) | |||||
| (delete "" (all-completions arg local-abbrev-table)))) | |||||
| (meta (abbrev-expansion arg)))) | |||||
| (provide 'company-abbrev) | |||||
| ;;; company-abbrev.el ends here | |||||
| @ -1,284 +0,0 @@ | |||||
| ;;; company-autoloads.el --- automatically extracted autoloads | |||||
| ;; | |||||
| ;;; Code: | |||||
| (add-to-list 'load-path (or (file-name-directory #$) (car load-path))) | |||||
| ;;;### (autoloads nil "company" "company.el" (22171 46580 0 0)) | |||||
| ;;; Generated autoloads from company.el | |||||
| (autoload 'company-mode "company" "\ | |||||
| \"complete anything\"; is an in-buffer completion framework. | |||||
| Completion starts automatically, depending on the values | |||||
| `company-idle-delay' and `company-minimum-prefix-length'. | |||||
| Completion can be controlled with the commands: | |||||
| `company-complete-common', `company-complete-selection', `company-complete', | |||||
| `company-select-next', `company-select-previous'. If these commands are | |||||
| called before `company-idle-delay', completion will also start. | |||||
| Completions can be searched with `company-search-candidates' or | |||||
| `company-filter-candidates'. These can be used while completion is | |||||
| inactive, as well. | |||||
| The completion data is retrieved using `company-backends' and displayed | |||||
| using `company-frontends'. If you want to start a specific backend, call | |||||
| it interactively or use `company-begin-backend'. | |||||
| By default, the completions list is sorted alphabetically, unless the | |||||
| backend chooses otherwise, or `company-transformers' changes it later. | |||||
| regular keymap (`company-mode-map'): | |||||
| \\{company-mode-map} | |||||
| keymap during active completions (`company-active-map'): | |||||
| \\{company-active-map} | |||||
| \(fn &optional ARG)" t nil) | |||||
| (defvar global-company-mode nil "\ | |||||
| Non-nil if Global-Company mode is enabled. | |||||
| See the command `global-company-mode' for a description of this minor mode. | |||||
| Setting this variable directly does not take effect; | |||||
| either customize it (see the info node `Easy Customization') | |||||
| or call the function `global-company-mode'.") | |||||
| (custom-autoload 'global-company-mode "company" nil) | |||||
| (autoload 'global-company-mode "company" "\ | |||||
| Toggle Company mode in all buffers. | |||||
| With prefix ARG, enable Global-Company mode if ARG is positive; | |||||
| otherwise, disable it. If called from Lisp, enable the mode if | |||||
| ARG is omitted or nil. | |||||
| Company mode is enabled in all buffers where | |||||
| `company-mode-on' would do it. | |||||
| See `company-mode' for more information on Company mode. | |||||
| \(fn &optional ARG)" t nil) | |||||
| ;;;*** | |||||
| ;;;### (autoloads nil "company-abbrev" "company-abbrev.el" (22171 | |||||
| ;;;;;; 46580 0 0)) | |||||
| ;;; Generated autoloads from company-abbrev.el | |||||
| (autoload 'company-abbrev "company-abbrev" "\ | |||||
| `company-mode' completion backend for abbrev. | |||||
| \(fn COMMAND &optional ARG &rest IGNORED)" t nil) | |||||
| ;;;*** | |||||
| ;;;### (autoloads nil "company-bbdb" "company-bbdb.el" (22171 46580 | |||||
| ;;;;;; 0 0)) | |||||
| ;;; Generated autoloads from company-bbdb.el | |||||
| (autoload 'company-bbdb "company-bbdb" "\ | |||||
| `company-mode' completion backend for BBDB. | |||||
| \(fn COMMAND &optional ARG &rest IGNORE)" t nil) | |||||
| ;;;*** | |||||
| ;;;### (autoloads nil "company-css" "company-css.el" (22171 46580 | |||||
| ;;;;;; 0 0)) | |||||
| ;;; Generated autoloads from company-css.el | |||||
| (autoload 'company-css "company-css" "\ | |||||
| `company-mode' completion backend for `css-mode'. | |||||
| \(fn COMMAND &optional ARG &rest IGNORED)" t nil) | |||||
| ;;;*** | |||||
| ;;;### (autoloads nil "company-dabbrev" "company-dabbrev.el" (22171 | |||||
| ;;;;;; 46580 0 0)) | |||||
| ;;; Generated autoloads from company-dabbrev.el | |||||
| (autoload 'company-dabbrev "company-dabbrev" "\ | |||||
| dabbrev-like `company-mode' completion backend. | |||||
| \(fn COMMAND &optional ARG &rest IGNORED)" t nil) | |||||
| ;;;*** | |||||
| ;;;### (autoloads nil "company-dabbrev-code" "company-dabbrev-code.el" | |||||
| ;;;;;; (22171 46580 0 0)) | |||||
| ;;; Generated autoloads from company-dabbrev-code.el | |||||
| (autoload 'company-dabbrev-code "company-dabbrev-code" "\ | |||||
| dabbrev-like `company-mode' backend for code. | |||||
| The backend looks for all symbols in the current buffer that aren't in | |||||
| comments or strings. | |||||
| \(fn COMMAND &optional ARG &rest IGNORED)" t nil) | |||||
| ;;;*** | |||||
| ;;;### (autoloads nil "company-elisp" "company-elisp.el" (22171 46580 | |||||
| ;;;;;; 0 0)) | |||||
| ;;; Generated autoloads from company-elisp.el | |||||
| (autoload 'company-elisp "company-elisp" "\ | |||||
| `company-mode' completion backend for Emacs Lisp. | |||||
| \(fn COMMAND &optional ARG &rest IGNORED)" t nil) | |||||
| ;;;*** | |||||
| ;;;### (autoloads nil "company-etags" "company-etags.el" (22171 46580 | |||||
| ;;;;;; 0 0)) | |||||
| ;;; Generated autoloads from company-etags.el | |||||
| (autoload 'company-etags "company-etags" "\ | |||||
| `company-mode' completion backend for etags. | |||||
| \(fn COMMAND &optional ARG &rest IGNORED)" t nil) | |||||
| ;;;*** | |||||
| ;;;### (autoloads nil "company-files" "company-files.el" (22171 46580 | |||||
| ;;;;;; 0 0)) | |||||
| ;;; Generated autoloads from company-files.el | |||||
| (autoload 'company-files "company-files" "\ | |||||
| `company-mode' completion backend existing file names. | |||||
| Completions works for proper absolute and relative files paths. | |||||
| File paths with spaces are only supported inside strings. | |||||
| \(fn COMMAND &optional ARG &rest IGNORED)" t nil) | |||||
| ;;;*** | |||||
| ;;;### (autoloads nil "company-gtags" "company-gtags.el" (22171 46580 | |||||
| ;;;;;; 0 0)) | |||||
| ;;; Generated autoloads from company-gtags.el | |||||
| (autoload 'company-gtags "company-gtags" "\ | |||||
| `company-mode' completion backend for GNU Global. | |||||
| \(fn COMMAND &optional ARG &rest IGNORED)" t nil) | |||||
| ;;;*** | |||||
| ;;;### (autoloads nil "company-ispell" "company-ispell.el" (22171 | |||||
| ;;;;;; 46580 0 0)) | |||||
| ;;; Generated autoloads from company-ispell.el | |||||
| (autoload 'company-ispell "company-ispell" "\ | |||||
| `company-mode' completion backend using Ispell. | |||||
| \(fn COMMAND &optional ARG &rest IGNORED)" t nil) | |||||
| ;;;*** | |||||
| ;;;### (autoloads nil "company-keywords" "company-keywords.el" (22171 | |||||
| ;;;;;; 46580 0 0)) | |||||
| ;;; Generated autoloads from company-keywords.el | |||||
| (autoload 'company-keywords "company-keywords" "\ | |||||
| `company-mode' backend for programming language keywords. | |||||
| \(fn COMMAND &optional ARG &rest IGNORED)" t nil) | |||||
| ;;;*** | |||||
| ;;;### (autoloads nil "company-nxml" "company-nxml.el" (22171 46580 | |||||
| ;;;;;; 0 0)) | |||||
| ;;; Generated autoloads from company-nxml.el | |||||
| (autoload 'company-nxml "company-nxml" "\ | |||||
| `company-mode' completion backend for `nxml-mode'. | |||||
| \(fn COMMAND &optional ARG &rest IGNORED)" t nil) | |||||
| ;;;*** | |||||
| ;;;### (autoloads nil "company-oddmuse" "company-oddmuse.el" (22171 | |||||
| ;;;;;; 46580 0 0)) | |||||
| ;;; Generated autoloads from company-oddmuse.el | |||||
| (autoload 'company-oddmuse "company-oddmuse" "\ | |||||
| `company-mode' completion backend for `oddmuse-mode'. | |||||
| \(fn COMMAND &optional ARG &rest IGNORED)" t nil) | |||||
| ;;;*** | |||||
| ;;;### (autoloads nil "company-semantic" "company-semantic.el" (22171 | |||||
| ;;;;;; 46580 0 0)) | |||||
| ;;; Generated autoloads from company-semantic.el | |||||
| (autoload 'company-semantic "company-semantic" "\ | |||||
| `company-mode' completion backend using CEDET Semantic. | |||||
| \(fn COMMAND &optional ARG &rest IGNORED)" t nil) | |||||
| ;;;*** | |||||
| ;;;### (autoloads nil "company-tempo" "company-tempo.el" (22171 46580 | |||||
| ;;;;;; 0 0)) | |||||
| ;;; Generated autoloads from company-tempo.el | |||||
| (autoload 'company-tempo "company-tempo" "\ | |||||
| `company-mode' completion backend for tempo. | |||||
| \(fn COMMAND &optional ARG &rest IGNORED)" t nil) | |||||
| ;;;*** | |||||
| ;;;### (autoloads nil "company-xcode" "company-xcode.el" (22171 46580 | |||||
| ;;;;;; 0 0)) | |||||
| ;;; Generated autoloads from company-xcode.el | |||||
| (autoload 'company-xcode "company-xcode" "\ | |||||
| `company-mode' completion backend for Xcode projects. | |||||
| \(fn COMMAND &optional ARG &rest IGNORED)" t nil) | |||||
| ;;;*** | |||||
| ;;;### (autoloads nil "company-yasnippet" "company-yasnippet.el" | |||||
| ;;;;;; (22171 46580 0 0)) | |||||
| ;;; Generated autoloads from company-yasnippet.el | |||||
| (autoload 'company-yasnippet "company-yasnippet" "\ | |||||
| `company-mode' backend for `yasnippet'. | |||||
| This backend should be used with care, because as long as there are | |||||
| snippets defined for the current major mode, this backend will always | |||||
| shadow backends that come after it. Recommended usages: | |||||
| * In a buffer-local value of `company-backends', grouped with a backend or | |||||
| several that provide actual text completions. | |||||
| (add-hook 'js-mode-hook | |||||
| (lambda () | |||||
| (set (make-local-variable 'company-backends) | |||||
| '((company-dabbrev-code company-yasnippet))))) | |||||
| * After keyword `:with', grouped with other backends. | |||||
| (push '(company-semantic :with company-yasnippet) company-backends) | |||||
| * Not in `company-backends', just bound to a key. | |||||
| (global-set-key (kbd \"C-c y\") 'company-yasnippet) | |||||
| \(fn COMMAND &optional ARG &rest IGNORE)" t nil) | |||||
| ;;;*** | |||||
| ;;;### (autoloads nil nil ("company-capf.el" "company-clang.el" "company-cmake.el" | |||||
| ;;;;;; "company-eclim.el" "company-pkg.el" "company-template.el") | |||||
| ;;;;;; (22171 46580 491198 0)) | |||||
| ;;;*** | |||||
| ;; Local Variables: | |||||
| ;; version-control: never | |||||
| ;; no-byte-compile: t | |||||
| ;; no-update-autoloads: t | |||||
| ;; End: | |||||
| ;;; company-autoloads.el ends here | |||||
| @ -1,61 +0,0 @@ | |||||
| ;;; company-bbdb.el --- company-mode completion backend for BBDB in message-mode | |||||
| ;; Copyright (C) 2013-2014, 2016 Free Software Foundation, Inc. | |||||
| ;; Author: Jan Tatarik <jan.tatarik@gmail.com> | |||||
| ;; 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/>. | |||||
| (require 'company) | |||||
| (require 'cl-lib) | |||||
| (declare-function bbdb-record-get-field "bbdb") | |||||
| (declare-function bbdb-records "bbdb") | |||||
| (declare-function bbdb-dwim-mail "bbdb-com") | |||||
| (declare-function bbdb-search "bbdb-com") | |||||
| (defgroup company-bbdb nil | |||||
| "Completion backend for BBDB." | |||||
| :group 'company) | |||||
| (defcustom company-bbdb-modes '(message-mode) | |||||
| "Major modes in which `company-bbdb' may complete." | |||||
| :type '(repeat (symbol :tag "Major mode")) | |||||
| :package-version '(company . "0.8.8")) | |||||
| (defun company-bbdb--candidates (arg) | |||||
| (cl-mapcan (lambda (record) | |||||
| (mapcar (lambda (mail) (bbdb-dwim-mail record mail)) | |||||
| (bbdb-record-get-field record 'mail))) | |||||
| (eval '(bbdb-search (bbdb-records) arg nil arg)))) | |||||
| ;;;###autoload | |||||
| (defun company-bbdb (command &optional arg &rest ignore) | |||||
| "`company-mode' completion backend for BBDB." | |||||
| (interactive (list 'interactive)) | |||||
| (cl-case command | |||||
| (interactive (company-begin-backend 'company-bbdb)) | |||||
| (prefix (and (memq major-mode company-bbdb-modes) | |||||
| (featurep 'bbdb-com) | |||||
| (looking-back "^\\(To\\|Cc\\|Bcc\\): *.*?\\([^,; ]*\\)" | |||||
| (line-beginning-position)) | |||||
| (match-string-no-properties 2))) | |||||
| (candidates (company-bbdb--candidates arg)) | |||||
| (sorted t) | |||||
| (no-cache t))) | |||||
| (provide 'company-bbdb) | |||||
| ;;; company-bbdb.el ends here | |||||
| @ -1,170 +0,0 @@ | |||||
| ;;; company-capf.el --- company-mode completion-at-point-functions backend -*- lexical-binding: t -*- | |||||
| ;; Copyright (C) 2013-2016 Free Software Foundation, Inc. | |||||
| ;; Author: Stefan Monnier <monnier@iro.umontreal.ca> | |||||
| ;; 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: | |||||
| ;; | |||||
| ;;; Code: | |||||
| (require 'company) | |||||
| (require 'cl-lib) | |||||
| (defvar company--capf-cache nil) | |||||
| (defun company--capf-data () | |||||
| (let ((cache company--capf-cache)) | |||||
| (if (and (equal (current-buffer) (car cache)) | |||||
| (equal (point) (car (setq cache (cdr cache)))) | |||||
| (equal (buffer-chars-modified-tick) (car (setq cache (cdr cache))))) | |||||
| (cadr cache) | |||||
| (let ((data (company--capf-data-real))) | |||||
| (setq company--capf-cache | |||||
| (list (current-buffer) (point) (buffer-chars-modified-tick) data)) | |||||
| data)))) | |||||
| (defun company--capf-data-real () | |||||
| (cl-letf* (((default-value 'completion-at-point-functions) | |||||
| ;; Ignore tags-completion-at-point-function because it subverts | |||||
| ;; company-etags in the default value of company-backends, where | |||||
| ;; the latter comes later. | |||||
| (remove 'tags-completion-at-point-function | |||||
| (default-value 'completion-at-point-functions))) | |||||
| (completion-at-point-functions (company--capf-workaround)) | |||||
| (data (run-hook-wrapped 'completion-at-point-functions | |||||
| ;; Ignore misbehaving functions. | |||||
| #'completion--capf-wrapper 'optimist))) | |||||
| (when (and (consp (cdr data)) (integer-or-marker-p (nth 1 data))) data))) | |||||
| (declare-function python-shell-get-process "python") | |||||
| (defun company--capf-workaround () | |||||
| ;; For http://debbugs.gnu.org/cgi/bugreport.cgi?bug=18067 | |||||
| (if (or (not (listp completion-at-point-functions)) | |||||
| (not (memq 'python-completion-complete-at-point completion-at-point-functions)) | |||||
| (python-shell-get-process)) | |||||
| completion-at-point-functions | |||||
| (remq 'python-completion-complete-at-point completion-at-point-functions))) | |||||
| (defun company-capf (command &optional arg &rest _args) | |||||
| "`company-mode' backend using `completion-at-point-functions'." | |||||
| (interactive (list 'interactive)) | |||||
| (pcase command | |||||
| (`interactive (company-begin-backend 'company-capf)) | |||||
| (`prefix | |||||
| (let ((res (company--capf-data))) | |||||
| (when res | |||||
| (let* ((f (plist-get (nthcdr 4 res) :company-prefix-length)) | |||||
| (beg (nth 1 res)) | |||||
| (end (nth 2 res)) | |||||
| (length (and f (funcall f beg (point)))) | |||||
| (prefix (buffer-substring-no-properties beg (point)))) | |||||
| (cond | |||||
| ((> end (point)) 'stop) | |||||
| (length (cons prefix length)) | |||||
| (t prefix)))))) | |||||
| (`candidates | |||||
| (let ((res (company--capf-data))) | |||||
| (when res | |||||
| (let* ((table (nth 3 res)) | |||||
| (pred (plist-get (nthcdr 4 res) :predicate)) | |||||
| (meta (completion-metadata | |||||
| (buffer-substring (nth 1 res) (nth 2 res)) | |||||
| table pred)) | |||||
| (sortfun (cdr (assq 'display-sort-function meta))) | |||||
| (candidates (completion-all-completions arg table pred (length arg))) | |||||
| (last (last candidates)) | |||||
| (base-size (and (numberp (cdr last)) (cdr last)))) | |||||
| (when base-size | |||||
| (setcdr last nil)) | |||||
| (when sortfun | |||||
| (setq candidates (funcall sortfun candidates))) | |||||
| (if (not (zerop (or base-size 0))) | |||||
| (let ((before (substring arg 0 base-size))) | |||||
| (mapcar (lambda (candidate) | |||||
| (concat before candidate)) | |||||
| candidates)) | |||||
| candidates))))) | |||||
| (`sorted | |||||
| (let ((res (company--capf-data))) | |||||
| (when res | |||||
| (let ((meta (completion-metadata | |||||
| (buffer-substring (nth 1 res) (nth 2 res)) | |||||
| (nth 3 res) (plist-get (nthcdr 4 res) :predicate)))) | |||||
| (cdr (assq 'display-sort-function meta)))))) | |||||
| (`match | |||||
| ;; Can't just use 0 when base-size (see above) is non-zero. | |||||
| (let ((start (if (get-text-property 0 'font-lock-face arg) | |||||
| 0 | |||||
| (next-single-property-change 0 'font-lock-face arg)))) | |||||
| (when start | |||||
| ;; completions-common-part comes first, but we can't just look for this | |||||
| ;; value because it can be in a list. | |||||
| (or | |||||
| (let ((value (get-text-property start 'font-lock-face arg))) | |||||
| (text-property-not-all start (length arg) | |||||
| 'font-lock-face value arg)) | |||||
| (length arg))))) | |||||
| (`duplicates t) | |||||
| (`no-cache t) ;Not much can be done here, as long as we handle | |||||
| ;non-prefix matches. | |||||
| (`meta | |||||
| (let ((f (plist-get (nthcdr 4 (company--capf-data)) :company-docsig))) | |||||
| (when f (funcall f arg)))) | |||||
| (`doc-buffer | |||||
| (let ((f (plist-get (nthcdr 4 (company--capf-data)) :company-doc-buffer))) | |||||
| (when f (funcall f arg)))) | |||||
| (`location | |||||
| (let ((f (plist-get (nthcdr 4 (company--capf-data)) :company-location))) | |||||
| (when f (funcall f arg)))) | |||||
| (`annotation | |||||
| (save-excursion | |||||
| ;; FIXME: `company-begin' sets `company-point' after calling | |||||
| ;; `company--begin-new'. We shouldn't rely on `company-point' here, | |||||
| ;; better to cache the capf-data value instead. However: we can't just | |||||
| ;; save the last capf-data value in `prefix', because that command can | |||||
| ;; get called more often than `candidates', and at any point in the | |||||
| ;; buffer (https://github.com/company-mode/company-mode/issues/153). | |||||
| ;; We could try propertizing the returned prefix string, but it's not | |||||
| ;; passed to `annotation', and `company-prefix' is set only after | |||||
| ;; `company--strip-duplicates' is called. | |||||
| (when company-point | |||||
| (goto-char company-point)) | |||||
| (let ((f (plist-get (nthcdr 4 (company--capf-data)) :annotation-function))) | |||||
| (when f (funcall f arg))))) | |||||
| (`require-match | |||||
| (plist-get (nthcdr 4 (company--capf-data)) :company-require-match)) | |||||
| (`init nil) ;Don't bother: plenty of other ways to initialize the code. | |||||
| (`post-completion | |||||
| (let* ((res (company--capf-data)) | |||||
| (exit-function (plist-get (nthcdr 4 res) :exit-function)) | |||||
| (table (nth 3 res)) | |||||
| (pred (plist-get (nthcdr 4 res) :predicate))) | |||||
| (if exit-function | |||||
| ;; Follow the example of `completion--done'. | |||||
| (funcall exit-function arg | |||||
| (if (eq (try-completion arg table pred) t) | |||||
| 'finished 'sole))))) | |||||
| )) | |||||
| (provide 'company-capf) | |||||
| ;;; company-capf.el ends here | |||||
| @ -1,331 +0,0 @@ | |||||
| ;;; company-clang.el --- company-mode completion backend for Clang -*- lexical-binding: t -*- | |||||
| ;; Copyright (C) 2009, 2011, 2013-2016 Free Software Foundation, Inc. | |||||
| ;; Author: Nikolaj Schumacher | |||||
| ;; 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: | |||||
| ;; | |||||
| ;;; Code: | |||||
| (require 'company) | |||||
| (require 'company-template) | |||||
| (require 'cl-lib) | |||||
| (defgroup company-clang nil | |||||
| "Completion backend for Clang." | |||||
| :group 'company) | |||||
| (defcustom company-clang-executable | |||||
| (executable-find "clang") | |||||
| "Location of clang executable." | |||||
| :type 'file) | |||||
| (defcustom company-clang-begin-after-member-access t | |||||
| "When non-nil, automatic completion will start whenever the current | |||||
| symbol is preceded by \".\", \"->\" or \"::\", ignoring | |||||
| `company-minimum-prefix-length'. | |||||
| If `company-begin-commands' is a list, it should include `c-electric-lt-gt' | |||||
| and `c-electric-colon', for automatic completion right after \">\" and | |||||
| \":\".") | |||||
| (defcustom company-clang-arguments nil | |||||
| "Additional arguments to pass to clang when completing. | |||||
| Prefix files (-include ...) can be selected with `company-clang-set-prefix' | |||||
| or automatically through a custom `company-clang-prefix-guesser'." | |||||
| :type '(repeat (string :tag "Argument"))) | |||||
| (defcustom company-clang-prefix-guesser 'company-clang-guess-prefix | |||||
| "A function to determine the prefix file for the current buffer." | |||||
| :type '(function :tag "Guesser function" nil)) | |||||
| (defvar company-clang-modes '(c-mode c++-mode objc-mode) | |||||
| "Major modes which clang may complete.") | |||||
| (defcustom company-clang-insert-arguments t | |||||
| "When non-nil, insert function arguments as a template after completion." | |||||
| :type 'boolean | |||||
| :package-version '(company . "0.8.0")) | |||||
| ;; prefix ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||||
| (defvar company-clang--prefix nil) | |||||
| (defsubst company-clang--guess-pch-file (file) | |||||
| (let ((dir (directory-file-name (file-name-directory file)))) | |||||
| (when (equal (file-name-nondirectory dir) "Classes") | |||||
| (setq dir (file-name-directory dir))) | |||||
| (car (directory-files dir t "\\([^.]h\\|[^h]\\).pch\\'" t)))) | |||||
| (defsubst company-clang--file-substring (file beg end) | |||||
| (with-temp-buffer | |||||
| (insert-file-contents-literally file nil beg end) | |||||
| (buffer-string))) | |||||
| (defun company-clang-guess-prefix () | |||||
| "Try to guess the prefix file for the current buffer." | |||||
| ;; Prefixes seem to be called .pch. Pre-compiled headers do, too. | |||||
| ;; So we look at the magic number to rule them out. | |||||
| (let* ((file (company-clang--guess-pch-file buffer-file-name)) | |||||
| (magic-number (and file (company-clang--file-substring file 0 4)))) | |||||
| (unless (member magic-number '("CPCH" "gpch")) | |||||
| file))) | |||||
| (defun company-clang-set-prefix (&optional prefix) | |||||
| "Use PREFIX as a prefix (-include ...) file for clang completion." | |||||
| (interactive (let ((def (funcall company-clang-prefix-guesser))) | |||||
| (unless (stringp def) | |||||
| (setq def default-directory)) | |||||
| (list (read-file-name "Prefix file: " | |||||
| (when def (file-name-directory def)) | |||||
| def t (when def (file-name-nondirectory def)))))) | |||||
| ;; TODO: pre-compile? | |||||
| (setq company-clang--prefix (and (stringp prefix) | |||||
| (file-regular-p prefix) | |||||
| prefix))) | |||||
| ;; Clean-up on exit. | |||||
| (add-hook 'kill-emacs-hook 'company-clang-set-prefix) | |||||
| ;; parsing ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||||
| ;; TODO: Handle Pattern (syntactic hints would be neat). | |||||
| ;; Do we ever see OVERLOAD (or OVERRIDE)? | |||||
| (defconst company-clang--completion-pattern | |||||
| "^COMPLETION: \\_<\\(%s[a-zA-Z0-9_:]*\\)\\(?: : \\(.*\\)$\\)?$") | |||||
| (defconst company-clang--error-buffer-name "*clang-error*") | |||||
| (defun company-clang--lang-option () | |||||
| (if (eq major-mode 'objc-mode) | |||||
| (if (string= "m" (file-name-extension buffer-file-name)) | |||||
| "objective-c" "objective-c++") | |||||
| (substring (symbol-name major-mode) 0 -5))) | |||||
| (defun company-clang--parse-output (prefix _objc) | |||||
| (goto-char (point-min)) | |||||
| (let ((pattern (format company-clang--completion-pattern | |||||
| (regexp-quote prefix))) | |||||
| (case-fold-search nil) | |||||
| lines match) | |||||
| (while (re-search-forward pattern nil t) | |||||
| (setq match (match-string-no-properties 1)) | |||||
| (unless (equal match "Pattern") | |||||
| (save-match-data | |||||
| (when (string-match ":" match) | |||||
| (setq match (substring match 0 (match-beginning 0))))) | |||||
| (let ((meta (match-string-no-properties 2))) | |||||
| (when (and meta (not (string= match meta))) | |||||
| (put-text-property 0 1 'meta | |||||
| (company-clang--strip-formatting meta) | |||||
| match))) | |||||
| (push match lines))) | |||||
| lines)) | |||||
| (defun company-clang--meta (candidate) | |||||
| (get-text-property 0 'meta candidate)) | |||||
| (defun company-clang--annotation (candidate) | |||||
| (let ((ann (company-clang--annotation-1 candidate))) | |||||
| (if (not (and ann (string-prefix-p "(*)" ann))) | |||||
| ann | |||||
| (with-temp-buffer | |||||
| (insert ann) | |||||
| (search-backward ")") | |||||
| (let ((pt (1+ (point)))) | |||||
| (re-search-forward ".\\_>" nil t) | |||||
| (delete-region pt (point))) | |||||
| (buffer-string))))) | |||||
| (defun company-clang--annotation-1 (candidate) | |||||
| (let ((meta (company-clang--meta candidate))) | |||||
| (cond | |||||
| ((null meta) nil) | |||||
| ((string-match "[^:]:[^:]" meta) | |||||
| (substring meta (1+ (match-beginning 0)))) | |||||
| ((string-match "\\((.*)[ a-z]*\\'\\)" meta) | |||||
| (let ((paren (match-beginning 1))) | |||||
| (if (not (eq (aref meta (1- paren)) ?>)) | |||||
| (match-string 1 meta) | |||||
| (with-temp-buffer | |||||
| (insert meta) | |||||
| (goto-char paren) | |||||
| (substring meta (1- (search-backward "<")))))))))) | |||||
| (defun company-clang--strip-formatting (text) | |||||
| (replace-regexp-in-string | |||||
| "#]" " " | |||||
| (replace-regexp-in-string "[<{[]#\\|#[>}]" "" text t) | |||||
| t)) | |||||
| (defun company-clang--handle-error (res args) | |||||
| (goto-char (point-min)) | |||||
| (let* ((buf (get-buffer-create company-clang--error-buffer-name)) | |||||
| (cmd (concat company-clang-executable " " (mapconcat 'identity args " "))) | |||||
| (pattern (format company-clang--completion-pattern "")) | |||||
| (err (if (re-search-forward pattern nil t) | |||||
| (buffer-substring-no-properties (point-min) | |||||
| (1- (match-beginning 0))) | |||||
| ;; Warn the user more aggressively if no match was found. | |||||
| (message "clang failed with error %d:\n%s" res cmd) | |||||
| (buffer-string)))) | |||||
| (with-current-buffer buf | |||||
| (let ((inhibit-read-only t)) | |||||
| (erase-buffer) | |||||
| (insert (current-time-string) | |||||
| (format "\nclang failed with error %d:\n" res) | |||||
| cmd "\n\n") | |||||
| (insert err) | |||||
| (setq buffer-read-only t) | |||||
| (goto-char (point-min)))))) | |||||
| (defun company-clang--start-process (prefix callback &rest args) | |||||
| (let ((objc (derived-mode-p 'objc-mode)) | |||||
| (buf (get-buffer-create "*clang-output*")) | |||||
| ;; Looks unnecessary in Emacs 25.1 and later. | |||||
| (process-adaptive-read-buffering nil)) | |||||
| (if (get-buffer-process buf) | |||||
| (funcall callback nil) | |||||
| (with-current-buffer buf | |||||
| (erase-buffer) | |||||
| (setq buffer-undo-list t)) | |||||
| (let ((process (apply #'start-process "company-clang" buf | |||||
| company-clang-executable args))) | |||||
| (set-process-sentinel | |||||
| process | |||||
| (lambda (proc status) | |||||
| (unless (string-match-p "hangup" status) | |||||
| (funcall | |||||
| callback | |||||
| (let ((res (process-exit-status proc))) | |||||
| (with-current-buffer buf | |||||
| (unless (eq 0 res) | |||||
| (company-clang--handle-error res args)) | |||||
| ;; Still try to get any useful input. | |||||
| (company-clang--parse-output prefix objc))))))) | |||||
| (unless (company-clang--auto-save-p) | |||||
| (send-region process (point-min) (point-max)) | |||||
| (send-string process "\n") | |||||
| (process-send-eof process)))))) | |||||
| (defsubst company-clang--build-location (pos) | |||||
| (save-excursion | |||||
| (goto-char pos) | |||||
| (format "%s:%d:%d" | |||||
| (if (company-clang--auto-save-p) buffer-file-name "-") | |||||
| (line-number-at-pos) | |||||
| (1+ (length | |||||
| (encode-coding-region | |||||
| (line-beginning-position) | |||||
| (point) | |||||
| 'utf-8 | |||||
| t)))))) | |||||
| (defsubst company-clang--build-complete-args (pos) | |||||
| (append '("-fsyntax-only" "-Xclang" "-code-completion-macros") | |||||
| (unless (company-clang--auto-save-p) | |||||
| (list "-x" (company-clang--lang-option))) | |||||
| company-clang-arguments | |||||
| (when (stringp company-clang--prefix) | |||||
| (list "-include" (expand-file-name company-clang--prefix))) | |||||
| (list "-Xclang" (format "-code-completion-at=%s" | |||||
| (company-clang--build-location pos))) | |||||
| (list (if (company-clang--auto-save-p) buffer-file-name "-")))) | |||||
| (defun company-clang--candidates (prefix callback) | |||||
| (and (company-clang--auto-save-p) | |||||
| (buffer-modified-p) | |||||
| (basic-save-buffer)) | |||||
| (when (null company-clang--prefix) | |||||
| (company-clang-set-prefix (or (funcall company-clang-prefix-guesser) | |||||
| 'none))) | |||||
| (apply 'company-clang--start-process | |||||
| prefix | |||||
| callback | |||||
| (company-clang--build-complete-args (- (point) (length prefix))))) | |||||
| (defun company-clang--prefix () | |||||
| (if company-clang-begin-after-member-access | |||||
| (company-grab-symbol-cons "\\.\\|->\\|::" 2) | |||||
| (company-grab-symbol))) | |||||
| ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||||
| (defconst company-clang-required-version 1.1) | |||||
| (defvar company-clang--version nil) | |||||
| (defun company-clang--auto-save-p () | |||||
| (< company-clang--version 2.9)) | |||||
| (defsubst company-clang-version () | |||||
| "Return the version of `company-clang-executable'." | |||||
| (with-temp-buffer | |||||
| (call-process company-clang-executable nil t nil "--version") | |||||
| (goto-char (point-min)) | |||||
| (if (re-search-forward "clang\\(?: version \\|-\\)\\([0-9.]+\\)" nil t) | |||||
| (let ((ver (string-to-number (match-string-no-properties 1)))) | |||||
| (if (> ver 100) | |||||
| (/ ver 100) | |||||
| ver)) | |||||
| 0))) | |||||
| (defun company-clang (command &optional arg &rest ignored) | |||||
| "`company-mode' completion backend for Clang. | |||||
| Clang is a parser for C and ObjC. Clang version 1.1 or newer is required. | |||||
| Additional command line arguments can be specified in | |||||
| `company-clang-arguments'. Prefix files (-include ...) can be selected | |||||
| with `company-clang-set-prefix' or automatically through a custom | |||||
| `company-clang-prefix-guesser'. | |||||
| With Clang versions before 2.9, we have to save the buffer before | |||||
| performing completion. With Clang 2.9 and later, buffer contents are | |||||
| passed via standard input." | |||||
| (interactive (list 'interactive)) | |||||
| (cl-case command | |||||
| (interactive (company-begin-backend 'company-clang)) | |||||
| (init (when (memq major-mode company-clang-modes) | |||||
| (unless company-clang-executable | |||||
| (error "Company found no clang executable")) | |||||
| (setq company-clang--version (company-clang-version)) | |||||
| (when (< company-clang--version company-clang-required-version) | |||||
| (error "Company requires clang version 1.1")))) | |||||
| (prefix (and (memq major-mode company-clang-modes) | |||||
| buffer-file-name | |||||
| company-clang-executable | |||||
| (not (company-in-string-or-comment)) | |||||
| (or (company-clang--prefix) 'stop))) | |||||
| (candidates (cons :async | |||||
| (lambda (cb) (company-clang--candidates arg cb)))) | |||||
| (meta (company-clang--meta arg)) | |||||
| (annotation (company-clang--annotation arg)) | |||||
| (post-completion (let ((anno (company-clang--annotation arg))) | |||||
| (when (and company-clang-insert-arguments anno) | |||||
| (insert anno) | |||||
| (if (string-match "\\`:[^:]" anno) | |||||
| (company-template-objc-templatify anno) | |||||
| (company-template-c-like-templatify | |||||
| (concat arg anno)))))))) | |||||
| (provide 'company-clang) | |||||
| ;;; company-clang.el ends here | |||||
| @ -1,198 +0,0 @@ | |||||
| ;;; company-cmake.el --- company-mode completion backend for CMake | |||||
| ;; Copyright (C) 2013-2014 Free Software Foundation, Inc. | |||||
| ;; Author: Chen Bin <chenbin DOT sh AT gmail> | |||||
| ;; Version: 0.2 | |||||
| ;; 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: | |||||
| ;; | |||||
| ;; company-cmake offers completions for module names, variable names and | |||||
| ;; commands used by CMake. And their descriptions. | |||||
| ;;; Code: | |||||
| (require 'company) | |||||
| (require 'cl-lib) | |||||
| (defgroup company-cmake nil | |||||
| "Completion backend for CMake." | |||||
| :group 'company) | |||||
| (defcustom company-cmake-executable | |||||
| (executable-find "cmake") | |||||
| "Location of cmake executable." | |||||
| :type 'file) | |||||
| (defvar company-cmake-executable-arguments | |||||
| '("--help-command-list" | |||||
| "--help-module-list" | |||||
| "--help-variable-list") | |||||
| "The arguments we pass to cmake, separately. | |||||
| They affect which types of symbols we get completion candidates for.") | |||||
| (defvar company-cmake--completion-pattern | |||||
| "^\\(%s[a-zA-Z0-9_<>]%s\\)$" | |||||
| "Regexp to match the candidates.") | |||||
| (defvar company-cmake-modes '(cmake-mode) | |||||
| "Major modes in which cmake may complete.") | |||||
| (defvar company-cmake--candidates-cache nil | |||||
| "Cache for the raw candidates.") | |||||
| (defvar company-cmake--meta-command-cache nil | |||||
| "Cache for command arguments to retrieve descriptions for the candidates.") | |||||
| (defun company-cmake--replace-tags (rlt) | |||||
| (setq rlt (replace-regexp-in-string | |||||
| "\\(.*?\\(IS_GNU\\)?\\)<LANG>\\(.*\\)" | |||||
| (lambda (_match) | |||||
| (mapconcat 'identity | |||||
| (if (match-beginning 2) | |||||
| '("\\1CXX\\3" "\\1C\\3" "\\1G77\\3") | |||||
| '("\\1CXX\\3" "\\1C\\3" "\\1Fortran\\3")) | |||||
| "\n")) | |||||
| rlt t)) | |||||
| (setq rlt (replace-regexp-in-string | |||||
| "\\(.*\\)<CONFIG>\\(.*\\)" | |||||
| (mapconcat 'identity '("\\1DEBUG\\2" "\\1RELEASE\\2" | |||||
| "\\1RELWITHDEBINFO\\2" "\\1MINSIZEREL\\2") | |||||
| "\n") | |||||
| rlt)) | |||||
| rlt) | |||||
| (defun company-cmake--fill-candidates-cache (arg) | |||||
| "Fill candidates cache if needed." | |||||
| (let (rlt) | |||||
| (unless company-cmake--candidates-cache | |||||
| (setq company-cmake--candidates-cache (make-hash-table :test 'equal))) | |||||
| ;; If hash is empty, fill it. | |||||
| (unless (gethash arg company-cmake--candidates-cache) | |||||
| (with-temp-buffer | |||||
| (let ((res (call-process company-cmake-executable nil t nil arg))) | |||||
| (unless (zerop res) | |||||
| (message "cmake executable exited with error=%d" res))) | |||||
| (setq rlt (buffer-string))) | |||||
| (setq rlt (company-cmake--replace-tags rlt)) | |||||
| (puthash arg rlt company-cmake--candidates-cache)) | |||||
| )) | |||||
| (defun company-cmake--parse (prefix content cmd) | |||||
| (let ((start 0) | |||||
| (pattern (format company-cmake--completion-pattern | |||||
| (regexp-quote prefix) | |||||
| (if (zerop (length prefix)) "+" "*"))) | |||||
| (lines (split-string content "\n")) | |||||
| match | |||||
| rlt) | |||||
| (dolist (line lines) | |||||
| (when (string-match pattern line) | |||||
| (let ((match (match-string 1 line))) | |||||
| (when match | |||||
| (puthash match cmd company-cmake--meta-command-cache) | |||||
| (push match rlt))))) | |||||
| rlt)) | |||||
| (defun company-cmake--candidates (prefix) | |||||
| (let (results | |||||
| cmd-opts | |||||
| str) | |||||
| (unless company-cmake--meta-command-cache | |||||
| (setq company-cmake--meta-command-cache (make-hash-table :test 'equal))) | |||||
| (dolist (arg company-cmake-executable-arguments) | |||||
| (company-cmake--fill-candidates-cache arg) | |||||
| (setq cmd-opts (replace-regexp-in-string "-list$" "" arg) ) | |||||
| (setq str (gethash arg company-cmake--candidates-cache)) | |||||
| (when str | |||||
| (setq results (nconc results | |||||
| (company-cmake--parse prefix str cmd-opts))))) | |||||
| results)) | |||||
| (defun company-cmake--unexpand-candidate (candidate) | |||||
| (cond | |||||
| ((string-match "^CMAKE_\\(C\\|CXX\\|Fortran\\)\\(_.*\\)$" candidate) | |||||
| (setq candidate (concat "CMAKE_<LANG>" (match-string 2 candidate)))) | |||||
| ;; C flags | |||||
| ((string-match "^\\(.*_\\)IS_GNU\\(C\\|CXX\\|G77\\)$" candidate) | |||||
| (setq candidate (concat (match-string 1 candidate) "IS_GNU<LANG>"))) | |||||
| ;; C flags | |||||
| ((string-match "^\\(.*_\\)OVERRIDE_\\(C\\|CXX\\|Fortran\\)$" candidate) | |||||
| (setq candidate (concat (match-string 1 candidate) "OVERRIDE_<LANG>"))) | |||||
| ((string-match "^\\(.*\\)\\(_DEBUG\\|_RELEASE\\|_RELWITHDEBINFO\\|_MINSIZEREL\\)\\(.*\\)$" candidate) | |||||
| (setq candidate (concat (match-string 1 candidate) | |||||
| "_<CONFIG>" | |||||
| (match-string 3 candidate))))) | |||||
| candidate) | |||||
| (defun company-cmake--meta (candidate) | |||||
| (let ((cmd-opts (gethash candidate company-cmake--meta-command-cache)) | |||||
| result) | |||||
| (setq candidate (company-cmake--unexpand-candidate candidate)) | |||||
| ;; Don't cache the documentation of every candidate (command) | |||||
| ;; Cache in this case will cost too much memory. | |||||
| (with-temp-buffer | |||||
| (call-process company-cmake-executable nil t nil cmd-opts candidate) | |||||
| ;; Go to the third line, trim it and return the result. | |||||
| ;; Tested with cmake 2.8.9. | |||||
| (goto-char (point-min)) | |||||
| (forward-line 2) | |||||
| (setq result (buffer-substring-no-properties (line-beginning-position) | |||||
| (line-end-position))) | |||||
| (setq result (replace-regexp-in-string "^[ \t\n\r]+" "" result)) | |||||
| result))) | |||||
| (defun company-cmake--doc-buffer (candidate) | |||||
| (let ((cmd-opts (gethash candidate company-cmake--meta-command-cache))) | |||||
| (setq candidate (company-cmake--unexpand-candidate candidate)) | |||||
| (with-temp-buffer | |||||
| (call-process company-cmake-executable nil t nil cmd-opts candidate) | |||||
| ;; Go to the third line, trim it and return the doc buffer. | |||||
| ;; Tested with cmake 2.8.9. | |||||
| (goto-char (point-min)) | |||||
| (forward-line 2) | |||||
| (company-doc-buffer | |||||
| (buffer-substring-no-properties (line-beginning-position) | |||||
| (point-max)))))) | |||||
| (defun company-cmake (command &optional arg &rest ignored) | |||||
| "`company-mode' completion backend for CMake. | |||||
| CMake is a cross-platform, open-source make system." | |||||
| (interactive (list 'interactive)) | |||||
| (cl-case command | |||||
| (interactive (company-begin-backend 'company-cmake)) | |||||
| (init (when (memq major-mode company-cmake-modes) | |||||
| (unless company-cmake-executable | |||||
| (error "Company found no cmake executable")))) | |||||
| (prefix (and (memq major-mode company-cmake-modes) | |||||
| (not (company-in-string-or-comment)) | |||||
| (company-grab-symbol))) | |||||
| (candidates (company-cmake--candidates arg)) | |||||
| (meta (company-cmake--meta arg)) | |||||
| (doc-buffer (company-cmake--doc-buffer arg)) | |||||
| )) | |||||
| (provide 'company-cmake) | |||||
| ;;; company-cmake.el ends here | |||||
| @ -1,442 +0,0 @@ | |||||
| ;;; company-css.el --- company-mode completion backend for css-mode -*- lexical-binding: t -*- | |||||
| ;; Copyright (C) 2009, 2011, 2014 Free Software Foundation, Inc. | |||||
| ;; Author: Nikolaj Schumacher | |||||
| ;; 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: | |||||
| ;;; Code: | |||||
| (require 'company) | |||||
| (require 'cl-lib) | |||||
| (declare-function web-mode-language-at-pos "web-mode" (&optional pos)) | |||||
| (defconst company-css-property-alist | |||||
| ;; see http://www.w3.org/TR/CSS21/propidx.html | |||||
| '(("azimuth" angle "left-side" "far-left" "left" "center-left" "center" | |||||
| "center-right" "right" "far-right" "right-side" "behind" "leftwards" | |||||
| "rightwards") | |||||
| ("background" background-color background-image background-repeat | |||||
| background-attachment background-position | |||||
| background-clip background-origin background-size) | |||||
| ("background-attachment" "scroll" "fixed") | |||||
| ("background-color" color "transparent") | |||||
| ("background-image" uri "none") | |||||
| ("background-position" percentage length "left" "center" "right" percentage | |||||
| length "top" "center" "bottom" "left" "center" "right" "top" "center" | |||||
| "bottom") | |||||
| ("background-repeat" "repeat" "repeat-x" "repeat-y" "no-repeat") | |||||
| ("border" border-width border-style border-color) | |||||
| ("border-bottom" border) | |||||
| ("border-bottom-color" border-color) | |||||
| ("border-bottom-style" border-style) | |||||
| ("border-bottom-width" border-width) | |||||
| ("border-collapse" "collapse" "separate") | |||||
| ("border-color" color "transparent") | |||||
| ("border-left" border) | |||||
| ("border-left-color" border-color) | |||||
| ("border-left-style" border-style) | |||||
| ("border-left-width" border-width) | |||||
| ("border-right" border) | |||||
| ("border-right-color" border-color) | |||||
| ("border-right-style" border-style) | |||||
| ("border-right-width" border-width) | |||||
| ("border-spacing" length length) | |||||
| ("border-style" border-style) | |||||
| ("border-top" border) | |||||
| ("border-top-color" border-color) | |||||
| ("border-top-style" border-style) | |||||
| ("border-top-width" border-width) | |||||
| ("border-width" border-width) | |||||
| ("bottom" length percentage "auto") | |||||
| ("caption-side" "top" "bottom") | |||||
| ("clear" "none" "left" "right" "both") | |||||
| ("clip" shape "auto") | |||||
| ("color" color) | |||||
| ("content" "normal" "none" string uri counter "attr()" "open-quote" | |||||
| "close-quote" "no-open-quote" "no-close-quote") | |||||
| ("counter-increment" identifier integer "none") | |||||
| ("counter-reset" identifier integer "none") | |||||
| ("cue" cue-before cue-after) | |||||
| ("cue-after" uri "none") | |||||
| ("cue-before" uri "none") | |||||
| ("cursor" uri "*" "auto" "crosshair" "default" "pointer" "move" "e-resize" | |||||
| "ne-resize" "nw-resize" "n-resize" "se-resize" "sw-resize" "s-resize" | |||||
| "w-resize" "text" "wait" "help" "progress") | |||||
| ("direction" "ltr" "rtl") | |||||
| ("display" "inline" "block" "list-item" "run-in" "inline-block" "table" | |||||
| "inline-table" "table-row-group" "table-header-group" "table-footer-group" | |||||
| "table-row" "table-column-group" "table-column" "table-cell" | |||||
| "table-caption" "none") | |||||
| ("elevation" angle "below" "level" "above" "higher" "lower") | |||||
| ("empty-cells" "show" "hide") | |||||
| ("float" "left" "right" "none") | |||||
| ("font" font-style font-weight font-size "/" line-height | |||||
| font-family "caption" "icon" "menu" "message-box" "small-caption" | |||||
| "status-bar" "normal" "small-caps" | |||||
| ;; CSS3 | |||||
| font-stretch) | |||||
| ("font-family" family-name generic-family) | |||||
| ("font-size" absolute-size relative-size length percentage) | |||||
| ("font-style" "normal" "italic" "oblique") | |||||
| ("font-weight" "normal" "bold" "bolder" "lighter" "100" "200" "300" "400" | |||||
| "500" "600" "700" "800" "900") | |||||
| ("height" length percentage "auto") | |||||
| ("left" length percentage "auto") | |||||
| ("letter-spacing" "normal" length) | |||||
| ("line-height" "normal" number length percentage) | |||||
| ("list-style" list-style-type list-style-position list-style-image) | |||||
| ("list-style-image" uri "none") | |||||
| ("list-style-position" "inside" "outside") | |||||
| ("list-style-type" "disc" "circle" "square" "decimal" "decimal-leading-zero" | |||||
| "lower-roman" "upper-roman" "lower-greek" "lower-latin" "upper-latin" | |||||
| "armenian" "georgian" "lower-alpha" "upper-alpha" "none") | |||||
| ("margin" margin-width) | |||||
| ("margin-bottom" margin-width) | |||||
| ("margin-left" margin-width) | |||||
| ("margin-right" margin-width) | |||||
| ("margin-top" margin-width) | |||||
| ("max-height" length percentage "none") | |||||
| ("max-width" length percentage "none") | |||||
| ("min-height" length percentage) | |||||
| ("min-width" length percentage) | |||||
| ("orphans" integer) | |||||
| ("outline" outline-color outline-style outline-width) | |||||
| ("outline-color" color "invert") | |||||
| ("outline-style" border-style) | |||||
| ("outline-width" border-width) | |||||
| ("overflow" "visible" "hidden" "scroll" "auto" | |||||
| ;; CSS3: | |||||
| "no-display" "no-content") | |||||
| ("padding" padding-width) | |||||
| ("padding-bottom" padding-width) | |||||
| ("padding-left" padding-width) | |||||
| ("padding-right" padding-width) | |||||
| ("padding-top" padding-width) | |||||
| ("page-break-after" "auto" "always" "avoid" "left" "right") | |||||
| ("page-break-before" "auto" "always" "avoid" "left" "right") | |||||
| ("page-break-inside" "avoid" "auto") | |||||
| ("pause" time percentage) | |||||
| ("pause-after" time percentage) | |||||
| ("pause-before" time percentage) | |||||
| ("pitch" frequency "x-low" "low" "medium" "high" "x-high") | |||||
| ("pitch-range" number) | |||||
| ("play-during" uri "mix" "repeat" "auto" "none") | |||||
| ("position" "static" "relative" "absolute" "fixed") | |||||
| ("quotes" string string "none") | |||||
| ("richness" number) | |||||
| ("right" length percentage "auto") | |||||
| ("speak" "normal" "none" "spell-out") | |||||
| ("speak-header" "once" "always") | |||||
| ("speak-numeral" "digits" "continuous") | |||||
| ("speak-punctuation" "code" "none") | |||||
| ("speech-rate" number "x-slow" "slow" "medium" "fast" "x-fast" "faster" | |||||
| "slower") | |||||
| ("stress" number) | |||||
| ("table-layout" "auto" "fixed") | |||||
| ("text-align" "left" "right" "center" "justify") | |||||
| ("text-indent" length percentage) | |||||
| ("text-transform" "capitalize" "uppercase" "lowercase" "none") | |||||
| ("top" length percentage "auto") | |||||
| ("unicode-bidi" "normal" "embed" "bidi-override") | |||||
| ("vertical-align" "baseline" "sub" "super" "top" "text-top" "middle" | |||||
| "bottom" "text-bottom" percentage length) | |||||
| ("visibility" "visible" "hidden" "collapse") | |||||
| ("voice-family" specific-voice generic-voice "*" specific-voice | |||||
| generic-voice) | |||||
| ("volume" number percentage "silent" "x-soft" "soft" "medium" "loud" | |||||
| "x-loud") | |||||
| ("white-space" "normal" "pre" "nowrap" "pre-wrap" "pre-line") | |||||
| ("widows" integer) | |||||
| ("width" length percentage "auto") | |||||
| ("word-spacing" "normal" length) | |||||
| ("z-index" "auto" integer) | |||||
| ;; CSS3 | |||||
| ("align-content" align-stretch "space-between" "space-around") | |||||
| ("align-items" align-stretch "baseline") | |||||
| ("align-self" align-items "auto") | |||||
| ("animation" animation-name animation-duration animation-timing-function | |||||
| animation-delay animation-iteration-count animation-direction | |||||
| animation-fill-mode) | |||||
| ("animation-delay" time) | |||||
| ("animation-direction" "normal" "reverse" "alternate" "alternate-reverse") | |||||
| ("animation-duration" time) | |||||
| ("animation-fill-mode" "none" "forwards" "backwards" "both") | |||||
| ("animation-iteration-count" integer "infinite") | |||||
| ("animation-name" "none") | |||||
| ("animation-play-state" "paused" "running") | |||||
| ("animation-timing-function" transition-timing-function | |||||
| "step-start" "step-end" "steps(,)") | |||||
| ("backface-visibility" "visible" "hidden") | |||||
| ("background-clip" background-origin) | |||||
| ("background-origin" "border-box" "padding-box" "content-box") | |||||
| ("background-size" length percentage "auto" "cover" "contain") | |||||
| ("border-image" border-image-outset border-image-repeat border-image-source | |||||
| border-image-slice border-image-width) | |||||
| ("border-image-outset" length) | |||||
| ("border-image-repeat" "stretch" "repeat" "round" "space") | |||||
| ("border-image-source" uri "none") | |||||
| ("border-image-slice" length) | |||||
| ("border-image-width" length percentage) | |||||
| ("border-radius" length) | |||||
| ("border-top-left-radius" length) | |||||
| ("border-top-right-radius" length) | |||||
| ("border-bottom-left-radius" length) | |||||
| ("border-bottom-right-radius" length) | |||||
| ("box-decoration-break" "slice" "clone") | |||||
| ("box-shadow" length color) | |||||
| ("box-sizing" "content-box" "border-box") | |||||
| ("break-after" "auto" "always" "avoid" "left" "right" "page" "column" | |||||
| "avoid-page" "avoid-column") | |||||
| ("break-before" break-after) | |||||
| ("break-inside" "avoid" "auto") | |||||
| ("columns" column-width column-count) | |||||
| ("column-count" integer) | |||||
| ("column-fill" "auto" "balance") | |||||
| ("column-gap" length "normal") | |||||
| ("column-rule" column-rule-width column-rule-style column-rule-color) | |||||
| ("column-rule-color" color) | |||||
| ("column-rule-style" border-style) | |||||
| ("column-rule-width" border-width) | |||||
| ("column-span" "all" "none") | |||||
| ("column-width" length "auto") | |||||
| ("filter" url "blur()" "brightness()" "contrast()" "drop-shadow()" | |||||
| "grayscale()" "hue-rotate()" "invert()" "opacity()" "saturate()" "sepia()") | |||||
| ("flex" flex-grow flex-shrink flex-basis) | |||||
| ("flex-basis" percentage length "auto") | |||||
| ("flex-direction" "row" "row-reverse" "column" "column-reverse") | |||||
| ("flex-flow" flex-direction flex-wrap) | |||||
| ("flex-grow" number) | |||||
| ("flex-shrink" number) | |||||
| ("flex-wrap" "nowrap" "wrap" "wrap-reverse") | |||||
| ("font-feature-setting" normal string number) | |||||
| ("font-kerning" "auto" "normal" "none") | |||||
| ("font-language-override" "normal" string) | |||||
| ("font-size-adjust" "none" number) | |||||
| ("font-stretch" "normal" "ultra-condensed" "extra-condensed" "condensed" | |||||
| "semi-condensed" "semi-expanded" "expanded" "extra-expanded" "ultra-expanded") | |||||
| ("font-synthesis" "none" "weight" "style") | |||||
| ("font-variant" font-variant-alternates font-variant-caps | |||||
| font-variant-east-asian font-variant-ligatures font-variant-numeric | |||||
| font-variant-position) | |||||
| ("font-variant-alternates" "normal" "historical-forms" "stylistic()" | |||||
| "styleset()" "character-variant()" "swash()" "ornaments()" "annotation()") | |||||
| ("font-variant-caps" "normal" "small-caps" "all-small-caps" "petite-caps" | |||||
| "all-petite-caps" "unicase" "titling-caps") | |||||
| ("font-variant-east-asian" "jis78" "jis83" "jis90" "jis04" "simplified" | |||||
| "traditional" "full-width" "proportional-width" "ruby") | |||||
| ("font-variant-ligatures" "normal" "none" "common-ligatures" | |||||
| "no-common-ligatures" "discretionary-ligatures" "no-discretionary-ligatures" | |||||
| "historical-ligatures" "no-historical-ligatures" "contextual" "no-contextual") | |||||
| ("font-variant-numeric" "normal" "ordinal" "slashed-zero" | |||||
| "lining-nums" "oldstyle-nums" "proportional-nums" "tabular-nums" | |||||
| "diagonal-fractions" "stacked-fractions") | |||||
| ("font-variant-position" "normal" "sub" "super") | |||||
| ("hyphens" "none" "manual" "auto") | |||||
| ("justify-content" align-common "space-between" "space-around") | |||||
| ("line-break" "auto" "loose" "normal" "strict") | |||||
| ("marquee-direction" "forward" "reverse") | |||||
| ("marquee-play-count" integer "infinite") | |||||
| ("marquee-speed" "slow" "normal" "fast") | |||||
| ("marquee-style" "scroll" "slide" "alternate") | |||||
| ("opacity" number) | |||||
| ("order" number) | |||||
| ("outline-offset" length) | |||||
| ("overflow-x" overflow) | |||||
| ("overflow-y" overflow) | |||||
| ("overflow-style" "auto" "marquee-line" "marquee-block") | |||||
| ("overflow-wrap" "normal" "break-word") | |||||
| ("perspective" "none" length) | |||||
| ("perspective-origin" percentage length "left" "center" "right" "top" "bottom") | |||||
| ("resize" "none" "both" "horizontal" "vertical") | |||||
| ("tab-size" integer length) | |||||
| ("text-align-last" "auto" "start" "end" "left" "right" "center" "justify") | |||||
| ("text-decoration" text-decoration-color text-decoration-line text-decoration-style) | |||||
| ("text-decoration-color" color) | |||||
| ("text-decoration-line" "none" "underline" "overline" "line-through" "blink") | |||||
| ("text-decoration-style" "solid" "double" "dotted" "dashed" "wavy") | |||||
| ("text-overflow" "clip" "ellipsis") | |||||
| ("text-shadow" color length) | |||||
| ("text-underline-position" "auto" "under" "left" "right") | |||||
| ("transform" "matrix(,,,,,)" "translate(,)" "translateX()" "translateY()" | |||||
| "scale()" "scaleX()" "scaleY()" "rotate()" "skewX()" "skewY()" "none") | |||||
| ("transform-origin" perspective-origin) | |||||
| ("transform-style" "flat" "preserve-3d") | |||||
| ("transition" transition-property transition-duration | |||||
| transition-timing-function transition-delay) | |||||
| ("transition-delay" time) | |||||
| ("transition-duration" time) | |||||
| ("transition-timing-function" | |||||
| "ease" "linear" "ease-in" "ease-out" "ease-in-out" "cubic-bezier(,,,)") | |||||
| ("transition-property" "none" "all" identifier) | |||||
| ("word-wrap" overflow-wrap) | |||||
| ("word-break" "normal" "break-all" "keep-all")) | |||||
| "A list of CSS properties and their possible values.") | |||||
| (defconst company-css-value-classes | |||||
| '((absolute-size "xx-small" "x-small" "small" "medium" "large" "x-large" | |||||
| "xx-large") | |||||
| (align-common "flex-start" "flex-end" "center") | |||||
| (align-stretch align-common "stretch") | |||||
| (border-style "none" "hidden" "dotted" "dashed" "solid" "double" "groove" | |||||
| "ridge" "inset" "outset") | |||||
| (border-width "thick" "medium" "thin") | |||||
| (color "aqua" "black" "blue" "fuchsia" "gray" "green" "lime" "maroon" "navy" | |||||
| "olive" "orange" "purple" "red" "silver" "teal" "white" "yellow") | |||||
| (counter "counter(,)") | |||||
| (family-name "Courier" "Helvetica" "Times") | |||||
| (generic-family "serif" "sans-serif" "cursive" "fantasy" "monospace") | |||||
| (generic-voice "male" "female" "child") | |||||
| (margin-width "auto") ;; length percentage | |||||
| (relative-size "larger" "smaller") | |||||
| (shape "rect(,,,)") | |||||
| (uri "url()")) | |||||
| "A list of CSS property value classes and their contents.") | |||||
| ;; missing, because not completable | |||||
| ;; <angle><frequency><identifier><integer><length><number><padding-width> | |||||
| ;; <percentage><specific-voice><string><time><uri> | |||||
| (defconst company-css-html-tags | |||||
| '("a" "abbr" "acronym" "address" "applet" "area" "b" "base" "basefont" "bdo" | |||||
| "big" "blockquote" "body" "br" "button" "caption" "center" "cite" "code" | |||||
| "col" "colgroup" "dd" "del" "dfn" "dir" "div" "dl" "dt" "em" "fieldset" | |||||
| "font" "form" "frame" "frameset" "h1" "h2" "h3" "h4" "h5" "h6" "head" "hr" | |||||
| "html" "i" "iframe" "img" "input" "ins" "isindex" "kbd" "label" "legend" | |||||
| "li" "link" "map" "menu" "meta" "noframes" "noscript" "object" "ol" | |||||
| "optgroup" "option" "p" "param" "pre" "q" "s" "samp" "script" "select" | |||||
| "small" "span" "strike" "strong" "style" "sub" "sup" "table" "tbody" "td" | |||||
| "textarea" "tfoot" "th" "thead" "title" "tr" "tt" "u" "ul" "var" | |||||
| ;; HTML5 | |||||
| "section" "article" "aside" "header" "footer" "nav" "figure" "figcaption" | |||||
| "time" "mark" "main") | |||||
| "A list of HTML tags for use in CSS completion.") | |||||
| (defconst company-css-pseudo-classes | |||||
| '("active" "after" "before" "first" "first-child" "first-letter" "first-line" | |||||
| "focus" "hover" "lang" "left" "link" "right" "visited") | |||||
| "Identifiers for CSS pseudo-elements and pseudo-classes.") | |||||
| (defconst company-css-property-cache (make-hash-table :size 115 :test 'equal)) | |||||
| (defun company-css-property-values (attribute) | |||||
| "Access the `company-css-property-alist' cached and flattened." | |||||
| (or (gethash attribute company-css-property-cache) | |||||
| (let (results) | |||||
| (dolist (value (cdr (assoc attribute company-css-property-alist))) | |||||
| (if (symbolp value) | |||||
| (dolist (child (or (cdr (assoc value company-css-value-classes)) | |||||
| (company-css-property-values | |||||
| (symbol-name value)))) | |||||
| (push child results)) | |||||
| (push value results))) | |||||
| (setq results (sort results 'string<)) | |||||
| (puthash attribute | |||||
| (if (fboundp 'delete-consecutive-dups) | |||||
| (delete-consecutive-dups results) | |||||
| (delete-dups results)) | |||||
| company-css-property-cache) | |||||
| results))) | |||||
| ;;; bracket detection | |||||
| (defconst company-css-braces-syntax-table | |||||
| (let ((table (make-syntax-table))) | |||||
| (setf (aref table ?{) '(4 . 125)) | |||||
| (setf (aref table ?}) '(5 . 123)) | |||||
| table) | |||||
| "A syntax table giving { and } paren syntax.") | |||||
| (defun company-css-inside-braces-p () | |||||
| "Return non-nil, if point is within matched { and }." | |||||
| (ignore-errors | |||||
| (with-syntax-table company-css-braces-syntax-table | |||||
| (let ((parse-sexp-ignore-comments t)) | |||||
| (scan-lists (point) -1 1))))) | |||||
| ;;; tags | |||||
| (defconst company-css-tag-regexp | |||||
| (concat "\\(?:\\`\\|}\\)[[:space:]]*" | |||||
| ;; multiple | |||||
| "\\(?:" | |||||
| ;; previous tags: | |||||
| "\\(?:#\\|\\_<[[:alpha:]]\\)[[:alnum:]-#]*\\(?:\\[[^]]*\\]\\)?" | |||||
| ;; space or selectors | |||||
| "\\(?:[[:space:]]+\\|[[:space:]]*[+,>][[:space:]]*\\)" | |||||
| "\\)*" | |||||
| "\\(\\(?:#\\|\\_<[[:alpha:]]\\)\\(?:[[:alnum:]-#]*\\_>\\)?\\_>\\|\\)" | |||||
| "\\=") | |||||
| "A regular expression matching CSS tags.") | |||||
| ;;; pseudo id | |||||
| (defconst company-css-pseudo-regexp | |||||
| (concat "\\(?:\\`\\|}\\)[[:space:]]*" | |||||
| ;; multiple | |||||
| "\\(?:" | |||||
| ;; previous tags: | |||||
| "\\(?:#\\|\\_<[[:alpha:]]\\)[[:alnum:]-#]*\\(?:\\[[^]]*\\]\\)?" | |||||
| ;; space or delimiters | |||||
| "\\(?:[[:space:]]+\\|[[:space:]]*[+,>][[:space:]]*\\)" | |||||
| "\\)*" | |||||
| "\\(?:\\(?:\\#\\|\\_<[[:alpha:]]\\)[[:alnum:]-#]*\\):" | |||||
| "\\([[:alpha:]-]+\\_>\\|\\)\\_>\\=") | |||||
| "A regular expression matching CSS pseudo classes.") | |||||
| ;;; properties | |||||
| (defun company-css-grab-property () | |||||
| "Return the CSS property before point, if any. | |||||
| Returns \"\" if no property found, but feasible at this position." | |||||
| (when (company-css-inside-braces-p) | |||||
| (company-grab-symbol))) | |||||
| ;;; values | |||||
| (defconst company-css-property-value-regexp | |||||
| "\\_<\\([[:alpha:]-]+\\):\\(?:[^{};]*[[:space:]]+\\)?\\([^{};]*\\_>\\|\\)\\=" | |||||
| "A regular expression matching CSS tags.") | |||||
| ;;;###autoload | |||||
| (defun company-css (command &optional arg &rest ignored) | |||||
| "`company-mode' completion backend for `css-mode'." | |||||
| (interactive (list 'interactive)) | |||||
| (cl-case command | |||||
| (interactive (company-begin-backend 'company-css)) | |||||
| (prefix (and (or (derived-mode-p 'css-mode) | |||||
| (and (derived-mode-p 'web-mode) | |||||
| (string= (web-mode-language-at-pos) "css"))) | |||||
| (or (company-grab company-css-tag-regexp 1) | |||||
| (company-grab company-css-pseudo-regexp 1) | |||||
| (company-grab company-css-property-value-regexp 2) | |||||
| (company-css-grab-property)))) | |||||
| (candidates | |||||
| (cond | |||||
| ((company-grab company-css-tag-regexp 1) | |||||
| (all-completions arg company-css-html-tags)) | |||||
| ((company-grab company-css-pseudo-regexp 1) | |||||
| (all-completions arg company-css-pseudo-classes)) | |||||
| ((company-grab company-css-property-value-regexp 2) | |||||
| (all-completions arg | |||||
| (company-css-property-values | |||||
| (company-grab company-css-property-value-regexp 1)))) | |||||
| ((company-css-grab-property) | |||||
| (all-completions arg company-css-property-alist)))) | |||||
| (sorted t))) | |||||
| (provide 'company-css) | |||||
| ;;; company-css.el ends here | |||||
| @ -1,104 +0,0 @@ | |||||
| ;;; company-dabbrev-code.el --- dabbrev-like company-mode backend for code -*- lexical-binding: t -*- | |||||
| ;; Copyright (C) 2009, 2011, 2014 Free Software Foundation, Inc. | |||||
| ;; Author: Nikolaj Schumacher | |||||
| ;; 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: | |||||
| ;; | |||||
| ;;; Code: | |||||
| (require 'company) | |||||
| (require 'company-dabbrev) | |||||
| (require 'cl-lib) | |||||
| (defgroup company-dabbrev-code nil | |||||
| "dabbrev-like completion backend for code." | |||||
| :group 'company) | |||||
| (defcustom company-dabbrev-code-modes | |||||
| '(prog-mode | |||||
| batch-file-mode csharp-mode css-mode erlang-mode haskell-mode jde-mode | |||||
| lua-mode python-mode) | |||||
| "Modes that use `company-dabbrev-code'. | |||||
| In all these modes (and their derivatives) `company-dabbrev-code' will | |||||
| complete only symbols, not text in comments or strings. In other modes | |||||
| `company-dabbrev-code' will pass control to other backends | |||||
| \(e.g. `company-dabbrev'\). Value t means complete in all modes." | |||||
| :type '(choice (repeat :tag "Some modes" (symbol :tag "Major mode")) | |||||
| (const :tag "All modes" t))) | |||||
| (defcustom company-dabbrev-code-other-buffers t | |||||
| "Determines whether `company-dabbrev-code' should search other buffers. | |||||
| If `all', search all other buffers, except the ignored ones. If t, search | |||||
| buffers with the same major mode. If `code', search all buffers with major | |||||
| modes in `company-dabbrev-code-modes', or derived from one of them. See | |||||
| also `company-dabbrev-code-time-limit'." | |||||
| :type '(choice (const :tag "Off" nil) | |||||
| (const :tag "Same major mode" t) | |||||
| (const :tag "Code major modes" code) | |||||
| (const :tag "All" all))) | |||||
| (defcustom company-dabbrev-code-time-limit .1 | |||||
| "Determines how long `company-dabbrev-code' should look for matches." | |||||
| :type '(choice (const :tag "Off" nil) | |||||
| (number :tag "Seconds"))) | |||||
| (defcustom company-dabbrev-code-everywhere nil | |||||
| "Non-nil to offer completions in comments and strings." | |||||
| :type 'boolean) | |||||
| (defcustom company-dabbrev-code-ignore-case nil | |||||
| "Non-nil to ignore case when collecting completion candidates." | |||||
| :type 'boolean) | |||||
| (defun company-dabbrev-code--make-regexp (prefix) | |||||
| (concat "\\_<" (if (equal prefix "") | |||||
| "\\([a-zA-Z]\\|\\s_\\)" | |||||
| (regexp-quote prefix)) | |||||
| "\\(\\sw\\|\\s_\\)*\\_>")) | |||||
| ;;;###autoload | |||||
| (defun company-dabbrev-code (command &optional arg &rest ignored) | |||||
| "dabbrev-like `company-mode' backend for code. | |||||
| The backend looks for all symbols in the current buffer that aren't in | |||||
| comments or strings." | |||||
| (interactive (list 'interactive)) | |||||
| (cl-case command | |||||
| (interactive (company-begin-backend 'company-dabbrev-code)) | |||||
| (prefix (and (or (eq t company-dabbrev-code-modes) | |||||
| (apply #'derived-mode-p company-dabbrev-code-modes)) | |||||
| (or company-dabbrev-code-everywhere | |||||
| (not (company-in-string-or-comment))) | |||||
| (or (company-grab-symbol) 'stop))) | |||||
| (candidates (let ((case-fold-search company-dabbrev-code-ignore-case)) | |||||
| (company-dabbrev--search | |||||
| (company-dabbrev-code--make-regexp arg) | |||||
| company-dabbrev-code-time-limit | |||||
| (pcase company-dabbrev-code-other-buffers | |||||
| (`t (list major-mode)) | |||||
| (`code company-dabbrev-code-modes) | |||||
| (`all `all)) | |||||
| t))) | |||||
| (ignore-case company-dabbrev-code-ignore-case) | |||||
| (duplicates t))) | |||||
| (provide 'company-dabbrev-code) | |||||
| ;;; company-dabbrev-code.el ends here | |||||
| @ -1,188 +0,0 @@ | |||||
| ;;; company-dabbrev.el --- dabbrev-like company-mode completion backend -*- lexical-binding: t -*- | |||||
| ;; Copyright (C) 2009, 2011, 2014, 2015 Free Software Foundation, Inc. | |||||
| ;; Author: Nikolaj Schumacher | |||||
| ;; 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: | |||||
| ;; | |||||
| ;;; Code: | |||||
| (require 'company) | |||||
| (require 'cl-lib) | |||||
| (defgroup company-dabbrev nil | |||||
| "dabbrev-like completion backend." | |||||
| :group 'company) | |||||
| (defcustom company-dabbrev-other-buffers 'all | |||||
| "Determines whether `company-dabbrev' should search other buffers. | |||||
| If `all', search all other buffers, except the ignored ones. If t, search | |||||
| buffers with the same major mode. See also `company-dabbrev-time-limit'." | |||||
| :type '(choice (const :tag "Off" nil) | |||||
| (const :tag "Same major mode" t) | |||||
| (const :tag "All" all))) | |||||
| (defcustom company-dabbrev-ignore-buffers "\\`[ *]" | |||||
| "Regexp matching the names of buffers to ignore." | |||||
| :type 'regexp) | |||||
| (defcustom company-dabbrev-time-limit .1 | |||||
| "Determines how many seconds `company-dabbrev' should look for matches." | |||||
| :type '(choice (const :tag "Off" nil) | |||||
| (number :tag "Seconds"))) | |||||
| (defcustom company-dabbrev-char-regexp "\\sw" | |||||
| "A regular expression matching the characters `company-dabbrev' looks for." | |||||
| :type 'regexp) | |||||
| (defcustom company-dabbrev-ignore-case 'keep-prefix | |||||
| "Non-nil to ignore case when collecting completion candidates. | |||||
| When it's `keep-prefix', the text before point will remain unchanged after | |||||
| candidate is inserted, even some of its characters have different case.") | |||||
| (defcustom company-dabbrev-downcase 'case-replace | |||||
| "Whether to downcase the returned candidates. | |||||
| The value of nil means keep them as-is. | |||||
| `case-replace' means use the value of `case-replace'. | |||||
| Any other value means downcase. | |||||
| If you set this value to nil, you may also want to set | |||||
| `company-dabbrev-ignore-case' to any value other than `keep-prefix'.") | |||||
| (defcustom company-dabbrev-minimum-length 4 | |||||
| "The minimum length for the completion candidate to be included. | |||||
| This variable affects both `company-dabbrev' and `company-dabbrev-code'." | |||||
| :type 'integer | |||||
| :package-version '(company . "0.8.3")) | |||||
| (defcustom company-dabbrev-ignore-invisible nil | |||||
| "Non-nil to skip invisible text." | |||||
| :type 'boolean | |||||
| :package-version '(company . "0.9.0")) | |||||
| (defmacro company-dabrev--time-limit-while (test start limit &rest body) | |||||
| (declare (indent 3) (debug t)) | |||||
| `(let ((company-time-limit-while-counter 0)) | |||||
| (catch 'done | |||||
| (while ,test | |||||
| ,@body | |||||
| (and ,limit | |||||
| (eq (cl-incf company-time-limit-while-counter) 25) | |||||
| (setq company-time-limit-while-counter 0) | |||||
| (> (float-time (time-since ,start)) ,limit) | |||||
| (throw 'done 'company-time-out)))))) | |||||
| (defun company-dabbrev--make-regexp (prefix) | |||||
| (concat (if (equal prefix "") | |||||
| (concat "\\(?:" company-dabbrev-char-regexp "\\)") | |||||
| (regexp-quote prefix)) | |||||
| "\\(?:" company-dabbrev-char-regexp "\\)*")) | |||||
| (defun company-dabbrev--search-buffer (regexp pos symbols start limit | |||||
| ignore-comments) | |||||
| (save-excursion | |||||
| (cl-labels ((maybe-collect-match | |||||
| () | |||||
| (let ((match (match-string-no-properties 0))) | |||||
| (when (and (>= (length match) company-dabbrev-minimum-length) | |||||
| (not (and company-dabbrev-ignore-invisible | |||||
| (invisible-p (match-beginning 0))))) | |||||
| (push match symbols))))) | |||||
| (goto-char (if pos (1- pos) (point-min))) | |||||
| ;; Search before pos. | |||||
| (let ((tmp-end (point))) | |||||
| (company-dabrev--time-limit-while (not (bobp)) | |||||
| start limit | |||||
| (ignore-errors | |||||
| (forward-char -10000)) | |||||
| (forward-line 0) | |||||
| (save-excursion | |||||
| ;; Before, we used backward search, but it matches non-greedily, and | |||||
| ;; that forced us to use the "beginning/end of word" anchors in | |||||
| ;; `company-dabbrev--make-regexp'. | |||||
| (while (re-search-forward regexp tmp-end t) | |||||
| (if (and ignore-comments (save-match-data (company-in-string-or-comment))) | |||||
| (re-search-forward "\\s>\\|\\s!\\|\\s\"" tmp-end t) | |||||
| (maybe-collect-match)))) | |||||
| (setq tmp-end (point)))) | |||||
| (goto-char (or pos (point-min))) | |||||
| ;; Search after pos. | |||||
| (company-dabrev--time-limit-while (re-search-forward regexp nil t) | |||||
| start limit | |||||
| (if (and ignore-comments (save-match-data (company-in-string-or-comment))) | |||||
| (re-search-forward "\\s>\\|\\s!\\|\\s\"" nil t) | |||||
| (maybe-collect-match))) | |||||
| symbols))) | |||||
| (defun company-dabbrev--search (regexp &optional limit other-buffer-modes | |||||
| ignore-comments) | |||||
| (let* ((start (current-time)) | |||||
| (symbols (company-dabbrev--search-buffer regexp (point) nil start limit | |||||
| ignore-comments))) | |||||
| (when other-buffer-modes | |||||
| (cl-dolist (buffer (delq (current-buffer) (buffer-list))) | |||||
| (with-current-buffer buffer | |||||
| (when (if (eq other-buffer-modes 'all) | |||||
| (not (string-match-p company-dabbrev-ignore-buffers | |||||
| (buffer-name))) | |||||
| (apply #'derived-mode-p other-buffer-modes)) | |||||
| (setq symbols | |||||
| (company-dabbrev--search-buffer regexp nil symbols start | |||||
| limit ignore-comments)))) | |||||
| (and limit | |||||
| (> (float-time (time-since start)) limit) | |||||
| (cl-return)))) | |||||
| symbols)) | |||||
| (defun company-dabbrev--prefix () | |||||
| ;; Not in the middle of a word. | |||||
| (unless (looking-at company-dabbrev-char-regexp) | |||||
| ;; Emacs can't do greedy backward-search. | |||||
| (company-grab-line (format "\\(?:^\\| \\)[^ ]*?\\(\\(?:%s\\)*\\)" | |||||
| company-dabbrev-char-regexp) | |||||
| 1))) | |||||
| ;;;###autoload | |||||
| (defun company-dabbrev (command &optional arg &rest ignored) | |||||
| "dabbrev-like `company-mode' completion backend." | |||||
| (interactive (list 'interactive)) | |||||
| (cl-case command | |||||
| (interactive (company-begin-backend 'company-dabbrev)) | |||||
| (prefix (company-dabbrev--prefix)) | |||||
| (candidates | |||||
| (let* ((case-fold-search company-dabbrev-ignore-case) | |||||
| (words (company-dabbrev--search (company-dabbrev--make-regexp arg) | |||||
| company-dabbrev-time-limit | |||||
| (pcase company-dabbrev-other-buffers | |||||
| (`t (list major-mode)) | |||||
| (`all `all)))) | |||||
| (downcase-p (if (eq company-dabbrev-downcase 'case-replace) | |||||
| case-replace | |||||
| company-dabbrev-downcase))) | |||||
| (if downcase-p | |||||
| (mapcar 'downcase words) | |||||
| words))) | |||||
| (ignore-case company-dabbrev-ignore-case) | |||||
| (duplicates t))) | |||||
| (provide 'company-dabbrev) | |||||
| ;;; company-dabbrev.el ends here | |||||
| @ -1,185 +0,0 @@ | |||||
| ;;; company-eclim.el --- company-mode completion backend for Eclim | |||||
| ;; Copyright (C) 2009, 2011, 2013, 2015 Free Software Foundation, Inc. | |||||
| ;; Author: Nikolaj Schumacher | |||||
| ;; 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: | |||||
| ;; | |||||
| ;; Using `emacs-eclim' together with (or instead of) this backend is | |||||
| ;; recommended, as it allows you to use other Eclim features. | |||||
| ;; | |||||
| ;; The alternative backend provided by `emacs-eclim' uses `yasnippet' | |||||
| ;; instead of `company-template' to expand function calls, and it supports | |||||
| ;; some languages other than Java. | |||||
| ;;; Code: | |||||
| (require 'company) | |||||
| (require 'company-template) | |||||
| (require 'cl-lib) | |||||
| (defgroup company-eclim nil | |||||
| "Completion backend for Eclim." | |||||
| :group 'company) | |||||
| (defun company-eclim-executable-find () | |||||
| (let (file) | |||||
| (cl-dolist (eclipse-root '("/Applications/eclipse" "/usr/lib/eclipse" | |||||
| "/usr/local/lib/eclipse")) | |||||
| (and (file-exists-p (setq file (expand-file-name "plugins" eclipse-root))) | |||||
| (setq file (car (last (directory-files file t "^org.eclim_")))) | |||||
| (file-exists-p (setq file (expand-file-name "bin/eclim" file))) | |||||
| (cl-return file))))) | |||||
| (defcustom company-eclim-executable | |||||
| (or (bound-and-true-p eclim-executable) | |||||
| (executable-find "eclim") | |||||
| (company-eclim-executable-find)) | |||||
| "Location of eclim executable." | |||||
| :type 'file) | |||||
| (defcustom company-eclim-auto-save t | |||||
| "Determines whether to save the buffer when retrieving completions. | |||||
| eclim can only complete correctly when the buffer has been saved." | |||||
| :type '(choice (const :tag "Off" nil) | |||||
| (const :tag "On" t))) | |||||
| ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||||
| (defvar-local company-eclim--project-dir 'unknown) | |||||
| (defvar-local company-eclim--project-name nil) | |||||
| (declare-function json-read "json") | |||||
| (defvar json-array-type) | |||||
| (defun company-eclim--call-process (&rest args) | |||||
| (let ((coding-system-for-read 'utf-8) | |||||
| res) | |||||
| (require 'json) | |||||
| (with-temp-buffer | |||||
| (if (= 0 (setq res (apply 'call-process company-eclim-executable nil t nil | |||||
| "-command" args))) | |||||
| (let ((json-array-type 'list)) | |||||
| (goto-char (point-min)) | |||||
| (unless (eobp) | |||||
| (json-read))) | |||||
| (message "Company-eclim command failed with error %d:\n%s" res | |||||
| (buffer-substring (point-min) (point-max))) | |||||
| nil)))) | |||||
| (defun company-eclim--project-list () | |||||
| (company-eclim--call-process "project_list")) | |||||
| (defun company-eclim--project-dir () | |||||
| (if (eq company-eclim--project-dir 'unknown) | |||||
| (setq company-eclim--project-dir | |||||
| (directory-file-name | |||||
| (expand-file-name | |||||
| (locate-dominating-file buffer-file-name ".project")))) | |||||
| company-eclim--project-dir)) | |||||
| (defun company-eclim--project-name () | |||||
| (or company-eclim--project-name | |||||
| (let ((dir (company-eclim--project-dir))) | |||||
| (when dir | |||||
| (setq company-eclim--project-name | |||||
| (cl-loop for project in (company-eclim--project-list) | |||||
| when (equal (cdr (assoc 'path project)) dir) | |||||
| return (cdr (assoc 'name project)))))))) | |||||
| (defun company-eclim--candidates (prefix) | |||||
| (interactive "d") | |||||
| (let ((project-file (file-relative-name buffer-file-name | |||||
| (company-eclim--project-dir))) | |||||
| completions) | |||||
| (when company-eclim-auto-save | |||||
| (when (buffer-modified-p) | |||||
| (basic-save-buffer)) | |||||
| ;; FIXME: Sometimes this isn't finished when we complete. | |||||
| (company-eclim--call-process "java_src_update" | |||||
| "-p" (company-eclim--project-name) | |||||
| "-f" project-file)) | |||||
| (dolist (item (cdr (assoc 'completions | |||||
| (company-eclim--call-process | |||||
| "java_complete" "-p" (company-eclim--project-name) | |||||
| "-f" project-file | |||||
| "-o" (number-to-string | |||||
| (company-eclim--search-point prefix)) | |||||
| "-e" "utf-8" | |||||
| "-l" "standard")))) | |||||
| (let* ((meta (cdr (assoc 'info item))) | |||||
| (completion meta)) | |||||
| (when (string-match " ?[(:-]" completion) | |||||
| (setq completion (substring completion 0 (match-beginning 0)))) | |||||
| (put-text-property 0 1 'meta meta completion) | |||||
| (push completion completions))) | |||||
| (let ((completion-ignore-case nil)) | |||||
| (all-completions prefix completions)))) | |||||
| (defun company-eclim--search-point (prefix) | |||||
| (if (or (cl-plusp (length prefix)) (eq (char-before) ?.)) | |||||
| (1- (point)) | |||||
| (point))) | |||||
| (defun company-eclim--meta (candidate) | |||||
| (get-text-property 0 'meta candidate)) | |||||
| (defun company-eclim--annotation (candidate) | |||||
| (let ((meta (company-eclim--meta candidate))) | |||||
| (when (string-match "\\(([^-]*\\) -" meta) | |||||
| (substring meta (match-beginning 1) (match-end 1))))) | |||||
| (defun company-eclim--prefix () | |||||
| (let ((prefix (company-grab-symbol))) | |||||
| (when prefix | |||||
| ;; Completion candidates for annotations don't include '@'. | |||||
| (when (eq ?@ (string-to-char prefix)) | |||||
| (setq prefix (substring prefix 1))) | |||||
| prefix))) | |||||
| (defun company-eclim (command &optional arg &rest ignored) | |||||
| "`company-mode' completion backend for Eclim. | |||||
| Eclim provides access to Eclipse Java IDE features for other editors. | |||||
| Eclim version 1.7.13 or newer (?) is required. | |||||
| Completions only work correctly when the buffer has been saved. | |||||
| `company-eclim-auto-save' determines whether to do this automatically." | |||||
| (interactive (list 'interactive)) | |||||
| (cl-case command | |||||
| (interactive (company-begin-backend 'company-eclim)) | |||||
| (prefix (and (derived-mode-p 'java-mode 'jde-mode) | |||||
| buffer-file-name | |||||
| company-eclim-executable | |||||
| (company-eclim--project-name) | |||||
| (not (company-in-string-or-comment)) | |||||
| (or (company-eclim--prefix) 'stop))) | |||||
| (candidates (company-eclim--candidates arg)) | |||||
| (meta (company-eclim--meta arg)) | |||||
| ;; because "" doesn't return everything | |||||
| (no-cache (equal arg "")) | |||||
| (annotation (company-eclim--annotation arg)) | |||||
| (post-completion (let ((anno (company-eclim--annotation arg))) | |||||
| (when anno | |||||
| (insert anno) | |||||
| (company-template-c-like-templatify anno)))))) | |||||
| (provide 'company-eclim) | |||||
| ;;; company-eclim.el ends here | |||||
| @ -1,225 +0,0 @@ | |||||
| ;;; company-elisp.el --- company-mode completion backend for Emacs Lisp -*- lexical-binding: t -*- | |||||
| ;; Copyright (C) 2009, 2011-2013 Free Software Foundation, Inc. | |||||
| ;; Author: Nikolaj Schumacher | |||||
| ;; 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: | |||||
| ;; | |||||
| ;;; Code: | |||||
| (require 'company) | |||||
| (require 'cl-lib) | |||||
| (require 'help-mode) | |||||
| (require 'find-func) | |||||
| (defgroup company-elisp nil | |||||
| "Completion backend for Emacs Lisp." | |||||
| :group 'company) | |||||
| (defcustom company-elisp-detect-function-context t | |||||
| "If enabled, offer Lisp functions only in appropriate contexts. | |||||
| Functions are offered for completion only after ' and \(." | |||||
| :type '(choice (const :tag "Off" nil) | |||||
| (const :tag "On" t))) | |||||
| (defcustom company-elisp-show-locals-first t | |||||
| "If enabled, locally bound variables and functions are displayed | |||||
| first in the candidates list." | |||||
| :type '(choice (const :tag "Off" nil) | |||||
| (const :tag "On" t))) | |||||
| (defun company-elisp--prefix () | |||||
| (let ((prefix (company-grab-symbol))) | |||||
| (if prefix | |||||
| (when (if (company-in-string-or-comment) | |||||
| (= (char-before (- (point) (length prefix))) ?`) | |||||
| (company-elisp--should-complete)) | |||||
| prefix) | |||||
| 'stop))) | |||||
| (defun company-elisp--predicate (symbol) | |||||
| (or (boundp symbol) | |||||
| (fboundp symbol) | |||||
| (facep symbol) | |||||
| (featurep symbol))) | |||||
| (defun company-elisp--fns-regexp (&rest names) | |||||
| (concat "\\_<\\(?:cl-\\)?" (regexp-opt names) "\\*?\\_>")) | |||||
| (defvar company-elisp-parse-limit 30) | |||||
| (defvar company-elisp-parse-depth 100) | |||||
| (defvar company-elisp-defun-names '("defun" "defmacro" "defsubst")) | |||||
| (defvar company-elisp-var-binding-regexp | |||||
| (apply #'company-elisp--fns-regexp "let" "lambda" "lexical-let" | |||||
| company-elisp-defun-names) | |||||
| "Regular expression matching head of a multiple variable bindings form.") | |||||
| (defvar company-elisp-var-binding-regexp-1 | |||||
| (company-elisp--fns-regexp "dolist" "dotimes") | |||||
| "Regular expression matching head of a form with one variable binding.") | |||||
| (defvar company-elisp-fun-binding-regexp | |||||
| (company-elisp--fns-regexp "flet" "labels") | |||||
| "Regular expression matching head of a function bindings form.") | |||||
| (defvar company-elisp-defuns-regexp | |||||
| (concat "([ \t\n]*" | |||||
| (apply #'company-elisp--fns-regexp company-elisp-defun-names))) | |||||
| (defun company-elisp--should-complete () | |||||
| (let ((start (point)) | |||||
| (depth (car (syntax-ppss)))) | |||||
| (not | |||||
| (when (> depth 0) | |||||
| (save-excursion | |||||
| (up-list (- depth)) | |||||
| (when (looking-at company-elisp-defuns-regexp) | |||||
| (forward-char) | |||||
| (forward-sexp 1) | |||||
| (unless (= (point) start) | |||||
| (condition-case nil | |||||
| (let ((args-end (scan-sexps (point) 2))) | |||||
| (or (null args-end) | |||||
| (> args-end start))) | |||||
| (scan-error | |||||
| t))))))))) | |||||
| (defun company-elisp--locals (prefix functions-p) | |||||
| (let ((regexp (concat "[ \t\n]*\\(\\_<" (regexp-quote prefix) | |||||
| "\\(?:\\sw\\|\\s_\\)*\\_>\\)")) | |||||
| (pos (point)) | |||||
| res) | |||||
| (condition-case nil | |||||
| (save-excursion | |||||
| (dotimes (_ company-elisp-parse-depth) | |||||
| (up-list -1) | |||||
| (save-excursion | |||||
| (when (eq (char-after) ?\() | |||||
| (forward-char 1) | |||||
| (when (ignore-errors | |||||
| (save-excursion (forward-list) | |||||
| (<= (point) pos))) | |||||
| (skip-chars-forward " \t\n") | |||||
| (cond | |||||
| ((looking-at (if functions-p | |||||
| company-elisp-fun-binding-regexp | |||||
| company-elisp-var-binding-regexp)) | |||||
| (down-list 1) | |||||
| (condition-case nil | |||||
| (dotimes (_ company-elisp-parse-limit) | |||||
| (save-excursion | |||||
| (when (looking-at "[ \t\n]*(") | |||||
| (down-list 1)) | |||||
| (when (looking-at regexp) | |||||
| (cl-pushnew (match-string-no-properties 1) res))) | |||||
| (forward-sexp)) | |||||
| (scan-error nil))) | |||||
| ((unless functions-p | |||||
| (looking-at company-elisp-var-binding-regexp-1)) | |||||
| (down-list 1) | |||||
| (when (looking-at regexp) | |||||
| (cl-pushnew (match-string-no-properties 1) res))))))))) | |||||
| (scan-error nil)) | |||||
| res)) | |||||
| (defun company-elisp-candidates (prefix) | |||||
| (let* ((predicate (company-elisp--candidates-predicate prefix)) | |||||
| (locals (company-elisp--locals prefix (eq predicate 'fboundp))) | |||||
| (globals (company-elisp--globals prefix predicate)) | |||||
| (locals (cl-loop for local in locals | |||||
| when (not (member local globals)) | |||||
| collect local))) | |||||
| (if company-elisp-show-locals-first | |||||
| (append (sort locals 'string<) | |||||
| (sort globals 'string<)) | |||||
| (append locals globals)))) | |||||
| (defun company-elisp--globals (prefix predicate) | |||||
| (all-completions prefix obarray predicate)) | |||||
| (defun company-elisp--candidates-predicate (prefix) | |||||
| (let* ((completion-ignore-case nil) | |||||
| (beg (- (point) (length prefix))) | |||||
| (before (char-before beg))) | |||||
| (if (and company-elisp-detect-function-context | |||||
| (not (memq before '(?' ?`)))) | |||||
| (if (and (eq before ?\() | |||||
| (not | |||||
| (save-excursion | |||||
| (ignore-errors | |||||
| (goto-char (1- beg)) | |||||
| (or (company-elisp--before-binding-varlist-p) | |||||
| (progn | |||||
| (up-list -1) | |||||
| (company-elisp--before-binding-varlist-p))))))) | |||||
| 'fboundp | |||||
| 'boundp) | |||||
| 'company-elisp--predicate))) | |||||
| (defun company-elisp--before-binding-varlist-p () | |||||
| (save-excursion | |||||
| (and (prog1 (search-backward "(") | |||||
| (forward-char 1)) | |||||
| (looking-at company-elisp-var-binding-regexp)))) | |||||
| (defun company-elisp--doc (symbol) | |||||
| (let* ((symbol (intern symbol)) | |||||
| (doc (if (fboundp symbol) | |||||
| (documentation symbol t) | |||||
| (documentation-property symbol 'variable-documentation t)))) | |||||
| (and (stringp doc) | |||||
| (string-match ".*$" doc) | |||||
| (match-string 0 doc)))) | |||||
| ;;;###autoload | |||||
| (defun company-elisp (command &optional arg &rest ignored) | |||||
| "`company-mode' completion backend for Emacs Lisp." | |||||
| (interactive (list 'interactive)) | |||||
| (cl-case command | |||||
| (interactive (company-begin-backend 'company-elisp)) | |||||
| (prefix (and (derived-mode-p 'emacs-lisp-mode 'inferior-emacs-lisp-mode) | |||||
| (company-elisp--prefix))) | |||||
| (candidates (company-elisp-candidates arg)) | |||||
| (sorted company-elisp-show-locals-first) | |||||
| (meta (company-elisp--doc arg)) | |||||
| (doc-buffer (let ((symbol (intern arg))) | |||||
| (save-window-excursion | |||||
| (ignore-errors | |||||
| (cond | |||||
| ((fboundp symbol) (describe-function symbol)) | |||||
| ((boundp symbol) (describe-variable symbol)) | |||||
| ((featurep symbol) (describe-package symbol)) | |||||
| ((facep symbol) (describe-face symbol)) | |||||
| (t (signal 'user-error nil))) | |||||
| (help-buffer))))) | |||||
| (location (let ((sym (intern arg))) | |||||
| (cond | |||||
| ((fboundp sym) (find-definition-noselect sym nil)) | |||||
| ((boundp sym) (find-definition-noselect sym 'defvar)) | |||||
| ((featurep sym) (cons (find-file-noselect (find-library-name | |||||
| (symbol-name sym))) | |||||
| 0)) | |||||
| ((facep sym) (find-definition-noselect sym 'defface))))))) | |||||
| (provide 'company-elisp) | |||||
| ;;; company-elisp.el ends here | |||||
| @ -1,107 +0,0 @@ | |||||
| ;;; company-etags.el --- company-mode completion backend for etags | |||||
| ;; Copyright (C) 2009-2011, 2014 Free Software Foundation, Inc. | |||||
| ;; Author: Nikolaj Schumacher | |||||
| ;; 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: | |||||
| ;; | |||||
| ;;; Code: | |||||
| (require 'company) | |||||
| (require 'cl-lib) | |||||
| (require 'etags) | |||||
| (defgroup company-etags nil | |||||
| "Completion backend for etags." | |||||
| :group 'company) | |||||
| (defcustom company-etags-use-main-table-list t | |||||
| "Always search `tags-table-list' if set. | |||||
| If this is disabled, `company-etags' will try to find the one table for each | |||||
| buffer automatically." | |||||
| :type '(choice (const :tag "off" nil) | |||||
| (const :tag "on" t))) | |||||
| (defcustom company-etags-ignore-case nil | |||||
| "Non-nil to ignore case in completion candidates." | |||||
| :type 'boolean | |||||
| :package-version '(company . "0.7.3")) | |||||
| (defcustom company-etags-everywhere nil | |||||
| "Non-nil to offer completions in comments and strings. | |||||
| Set it to t or to a list of major modes." | |||||
| :type '(choice (const :tag "Off" nil) | |||||
| (const :tag "Any supported mode" t) | |||||
| (repeat :tag "Some major modes" | |||||
| (symbol :tag "Major mode"))) | |||||
| :package-version '(company . "0.9.0")) | |||||
| (defvar company-etags-modes '(prog-mode c-mode objc-mode c++-mode java-mode | |||||
| jde-mode pascal-mode perl-mode python-mode)) | |||||
| (defvar-local company-etags-buffer-table 'unknown) | |||||
| (defun company-etags-find-table () | |||||
| (let ((file (expand-file-name | |||||
| "TAGS" | |||||
| (locate-dominating-file (or buffer-file-name | |||||
| default-directory) | |||||
| "TAGS")))) | |||||
| (when (and file (file-regular-p file)) | |||||
| (list file)))) | |||||
| (defun company-etags-buffer-table () | |||||
| (or (and company-etags-use-main-table-list tags-table-list) | |||||
| (if (eq company-etags-buffer-table 'unknown) | |||||
| (setq company-etags-buffer-table (company-etags-find-table)) | |||||
| company-etags-buffer-table))) | |||||
| (defun company-etags--candidates (prefix) | |||||
| (let ((tags-table-list (company-etags-buffer-table)) | |||||
| (completion-ignore-case company-etags-ignore-case)) | |||||
| (and (or tags-file-name tags-table-list) | |||||
| (fboundp 'tags-completion-table) | |||||
| (save-excursion | |||||
| (visit-tags-table-buffer) | |||||
| (all-completions prefix (tags-completion-table)))))) | |||||
| ;;;###autoload | |||||
| (defun company-etags (command &optional arg &rest ignored) | |||||
| "`company-mode' completion backend for etags." | |||||
| (interactive (list 'interactive)) | |||||
| (cl-case command | |||||
| (interactive (company-begin-backend 'company-etags)) | |||||
| (prefix (and (apply #'derived-mode-p company-etags-modes) | |||||
| (or (eq t company-etags-everywhere) | |||||
| (apply #'derived-mode-p company-etags-everywhere) | |||||
| (not (company-in-string-or-comment))) | |||||
| (company-etags-buffer-table) | |||||
| (or (company-grab-symbol) 'stop))) | |||||
| (candidates (company-etags--candidates arg)) | |||||
| (location (let ((tags-table-list (company-etags-buffer-table))) | |||||
| (when (fboundp 'find-tag-noselect) | |||||
| (save-excursion | |||||
| (let ((buffer (find-tag-noselect arg))) | |||||
| (cons buffer (with-current-buffer buffer (point)))))))) | |||||
| (ignore-case company-etags-ignore-case))) | |||||
| (provide 'company-etags) | |||||
| ;;; company-etags.el ends here | |||||
| @ -1,111 +0,0 @@ | |||||
| ;;; company-files.el --- company-mode completion backend for file paths | |||||
| ;; Copyright (C) 2009-2011, 2014-2015 Free Software Foundation, Inc. | |||||
| ;; Author: Nikolaj Schumacher | |||||
| ;; 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: | |||||
| ;; | |||||
| ;;; Code: | |||||
| (require 'company) | |||||
| (require 'cl-lib) | |||||
| (defun company-files--directory-files (dir prefix) | |||||
| (ignore-errors | |||||
| (if (equal prefix "") | |||||
| (directory-files dir nil "\\`[^.]\\|\\`.[^.]") | |||||
| (file-name-all-completions prefix dir)))) | |||||
| (defvar company-files--regexps | |||||
| (let* ((root (if (eq system-type 'windows-nt) | |||||
| "[a-zA-Z]:/" | |||||
| "/")) | |||||
| (begin (concat "\\(?:\\.\\{1,2\\}/\\|~/\\|" root "\\)"))) | |||||
| (list (concat "\"\\(" begin "[^\"\n]*\\)") | |||||
| (concat "\'\\(" begin "[^\'\n]*\\)") | |||||
| (concat "\\(?:[ \t]\\|^\\)\\(" begin "[^ \t\n]*\\)")))) | |||||
| (defun company-files--grab-existing-name () | |||||
| ;; Grab the file name. | |||||
| ;; When surrounded with quotes, it can include spaces. | |||||
| (let (file dir) | |||||
| (and (cl-dolist (regexp company-files--regexps) | |||||
| (when (setq file (company-grab-line regexp 1)) | |||||
| (cl-return file))) | |||||
| (company-files--connected-p file) | |||||
| (setq dir (file-name-directory file)) | |||||
| (not (string-match "//" dir)) | |||||
| (file-exists-p dir) | |||||
| (file-name-all-completions (file-name-nondirectory file) dir) | |||||
| file))) | |||||
| (defun company-files--connected-p (file) | |||||
| (or (not (file-remote-p file)) | |||||
| (file-remote-p file nil t))) | |||||
| (defvar company-files--completion-cache nil) | |||||
| (defun company-files--complete (prefix) | |||||
| (let* ((dir (file-name-directory prefix)) | |||||
| (key (list (file-name-nondirectory prefix) | |||||
| (expand-file-name dir) | |||||
| (nth 5 (file-attributes dir)))) | |||||
| (file (file-name-nondirectory prefix)) | |||||
| (completion-ignore-case read-file-name-completion-ignore-case) | |||||
| candidates directories) | |||||
| (unless (company-file--keys-match-p key (car company-files--completion-cache)) | |||||
| (dolist (file (company-files--directory-files dir file)) | |||||
| (setq file (concat dir file)) | |||||
| (when (company-files--connected-p file) | |||||
| (push file candidates) | |||||
| (when (file-directory-p file) | |||||
| (push file directories)))) | |||||
| (dolist (directory (reverse directories)) | |||||
| ;; Add one level of children. | |||||
| (dolist (child (company-files--directory-files directory "")) | |||||
| (push (concat directory | |||||
| (unless (eq (aref directory (1- (length directory))) ?/) "/") | |||||
| child) candidates))) | |||||
| (setq company-files--completion-cache (cons key (nreverse candidates)))) | |||||
| (all-completions prefix | |||||
| (cdr company-files--completion-cache)))) | |||||
| (defun company-file--keys-match-p (new old) | |||||
| (and (equal (cdr old) (cdr new)) | |||||
| (string-prefix-p (car old) (car new)))) | |||||
| ;;;###autoload | |||||
| (defun company-files (command &optional arg &rest ignored) | |||||
| "`company-mode' completion backend existing file names. | |||||
| Completions works for proper absolute and relative files paths. | |||||
| File paths with spaces are only supported inside strings." | |||||
| (interactive (list 'interactive)) | |||||
| (cl-case command | |||||
| (interactive (company-begin-backend 'company-files)) | |||||
| (prefix (company-files--grab-existing-name)) | |||||
| (candidates (company-files--complete arg)) | |||||
| (location (cons (dired-noselect | |||||
| (file-name-directory (directory-file-name arg))) 1)) | |||||
| (sorted t) | |||||
| (no-cache t))) | |||||
| (provide 'company-files) | |||||
| ;;; company-files.el ends here | |||||
| @ -1,116 +0,0 @@ | |||||
| ;;; company-gtags.el --- company-mode completion backend for GNU Global | |||||
| ;; Copyright (C) 2009-2011, 2014 Free Software Foundation, Inc. | |||||
| ;; Author: Nikolaj Schumacher | |||||
| ;; 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: | |||||
| ;; | |||||
| ;;; Code: | |||||
| (require 'company) | |||||
| (require 'company-template) | |||||
| (require 'cl-lib) | |||||
| (defgroup company-gtags nil | |||||
| "Completion backend for GNU Global." | |||||
| :group 'company) | |||||
| (defcustom company-gtags-executable | |||||
| (executable-find "global") | |||||
| "Location of GNU global executable." | |||||
| :type 'string) | |||||
| (define-obsolete-variable-alias | |||||
| 'company-gtags-gnu-global-program-name | |||||
| 'company-gtags-executable "earlier") | |||||
| (defcustom company-gtags-insert-arguments t | |||||
| "When non-nil, insert function arguments as a template after completion." | |||||
| :type 'boolean | |||||
| :package-version '(company . "0.8.1")) | |||||
| (defvar-local company-gtags--tags-available-p 'unknown) | |||||
| (defcustom company-gtags-modes '(prog-mode jde-mode) | |||||
| "Modes that use `company-gtags'. | |||||
| In all these modes (and their derivatives) `company-gtags' will perform | |||||
| completion." | |||||
| :type '(repeat (symbol :tag "Major mode")) | |||||
| :package-version '(company . "0.8.4")) | |||||
| (defun company-gtags--tags-available-p () | |||||
| (if (eq company-gtags--tags-available-p 'unknown) | |||||
| (setq company-gtags--tags-available-p | |||||
| (locate-dominating-file buffer-file-name "GTAGS")) | |||||
| company-gtags--tags-available-p)) | |||||
| (defun company-gtags--fetch-tags (prefix) | |||||
| (with-temp-buffer | |||||
| (let (tags) | |||||
| (when (= 0 (call-process company-gtags-executable nil | |||||
| (list (current-buffer) nil) nil "-xGq" (concat "^" prefix))) | |||||
| (goto-char (point-min)) | |||||
| (cl-loop while | |||||
| (re-search-forward (concat | |||||
| "^" | |||||
| "\\([^ ]*\\)" ;; completion | |||||
| "[ \t]+\\([[:digit:]]+\\)" ;; linum | |||||
| "[ \t]+\\([^ \t]+\\)" ;; file | |||||
| "[ \t]+\\(.*\\)" ;; definition | |||||
| "$" | |||||
| ) nil t) | |||||
| collect | |||||
| (propertize (match-string 1) | |||||
| 'meta (match-string 4) | |||||
| 'location (cons (expand-file-name (match-string 3)) | |||||
| (string-to-number (match-string 2))) | |||||
| )))))) | |||||
| (defun company-gtags--annotation (arg) | |||||
| (let ((meta (get-text-property 0 'meta arg))) | |||||
| (when (string-match (concat arg "\\((.*)\\).*") meta) | |||||
| (match-string 1 meta)))) | |||||
| ;;;###autoload | |||||
| (defun company-gtags (command &optional arg &rest ignored) | |||||
| "`company-mode' completion backend for GNU Global." | |||||
| (interactive (list 'interactive)) | |||||
| (cl-case command | |||||
| (interactive (company-begin-backend 'company-gtags)) | |||||
| (prefix (and company-gtags-executable | |||||
| buffer-file-name | |||||
| (apply #'derived-mode-p company-gtags-modes) | |||||
| (not (company-in-string-or-comment)) | |||||
| (company-gtags--tags-available-p) | |||||
| (or (company-grab-symbol) 'stop))) | |||||
| (candidates (company-gtags--fetch-tags arg)) | |||||
| (sorted t) | |||||
| (duplicates t) | |||||
| (annotation (company-gtags--annotation arg)) | |||||
| (meta (get-text-property 0 'meta arg)) | |||||
| (location (get-text-property 0 'location arg)) | |||||
| (post-completion (let ((anno (company-gtags--annotation arg))) | |||||
| (when (and company-gtags-insert-arguments anno) | |||||
| (insert anno) | |||||
| (company-template-c-like-templatify anno)))))) | |||||
| (provide 'company-gtags) | |||||
| ;;; company-gtags.el ends here | |||||
| @ -1,82 +0,0 @@ | |||||
| ;;; company-ispell.el --- company-mode completion backend using Ispell | |||||
| ;; Copyright (C) 2009-2011, 2013-2016 Free Software Foundation, Inc. | |||||
| ;; Author: Nikolaj Schumacher | |||||
| ;; 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: | |||||
| ;; | |||||
| ;;; Code: | |||||
| (require 'company) | |||||
| (require 'cl-lib) | |||||
| (require 'ispell) | |||||
| (defgroup company-ispell nil | |||||
| "Completion backend using Ispell." | |||||
| :group 'company) | |||||
| (defcustom company-ispell-dictionary nil | |||||
| "Dictionary to use for `company-ispell'. | |||||
| If nil, use `ispell-complete-word-dict'." | |||||
| :type '(choice (const :tag "default (nil)" nil) | |||||
| (file :tag "dictionary" t))) | |||||
| (defvar company-ispell-available 'unknown) | |||||
| (defalias 'company-ispell--lookup-words | |||||
| (if (fboundp 'ispell-lookup-words) | |||||
| 'ispell-lookup-words | |||||
| 'lookup-words)) | |||||
| (defun company-ispell-available () | |||||
| (when (eq company-ispell-available 'unknown) | |||||
| (condition-case err | |||||
| (progn | |||||
| (company-ispell--lookup-words "WHATEVER") | |||||
| (setq company-ispell-available t)) | |||||
| (error | |||||
| (message "Company: ispell-look-command not found") | |||||
| (setq company-ispell-available nil)))) | |||||
| company-ispell-available) | |||||
| ;;;###autoload | |||||
| (defun company-ispell (command &optional arg &rest ignored) | |||||
| "`company-mode' completion backend using Ispell." | |||||
| (interactive (list 'interactive)) | |||||
| (cl-case command | |||||
| (interactive (company-begin-backend 'company-ispell)) | |||||
| (prefix (when (company-ispell-available) | |||||
| (company-grab-word))) | |||||
| (candidates | |||||
| (let ((words (company-ispell--lookup-words | |||||
| arg | |||||
| (or company-ispell-dictionary ispell-complete-word-dict))) | |||||
| (completion-ignore-case t)) | |||||
| (if (string= arg "") | |||||
| ;; Small optimization. | |||||
| words | |||||
| ;; Work around issue #284. | |||||
| (all-completions arg words)))) | |||||
| (sorted t) | |||||
| (ignore-case 'keep-prefix))) | |||||
| (provide 'company-ispell) | |||||
| ;;; company-ispell.el ends here | |||||
| @ -1,242 +0,0 @@ | |||||
| ;;; company-keywords.el --- A company backend for programming language keywords | |||||
| ;; Copyright (C) 2009-2011 Free Software Foundation, Inc. | |||||
| ;; Author: Nikolaj Schumacher | |||||
| ;; 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: | |||||
| ;; | |||||
| ;;; Code: | |||||
| (require 'company) | |||||
| (require 'cl-lib) | |||||
| (defun company-keywords-upper-lower (&rest lst) | |||||
| ;; Upcase order is different for _. | |||||
| (nconc (sort (mapcar 'upcase lst) 'string<) lst)) | |||||
| (defvar company-keywords-alist | |||||
| ;; Please contribute corrections or additions. | |||||
| `((c++-mode | |||||
| "asm" "auto" "bool" "break" "case" "catch" "char" "class" "const" | |||||
| "const_cast" "continue" "default" "delete" "do" "double" "dynamic_cast" | |||||
| "else" "enum" "explicit" "export" "extern" "false" "float" "for" "friend" | |||||
| "goto" "if" "inline" "int" "long" "mutable" "namespace" "new" | |||||
| "operator" "private" "protected" "public" "register" "reinterpret_cast" | |||||
| "return" "short" "signed" "sizeof" "static" "static_cast" "struct" "switch" | |||||
| "template" "this" "throw" "true" "try" "typedef" "typeid" "typename" | |||||
| "union" "unsigned" "using" "virtual" "void" "volatile" "wchar_t" "while") | |||||
| (c-mode | |||||
| "auto" "break" "case" "char" "const" "continue" "default" "do" | |||||
| "double" "else" "enum" "extern" "float" "for" "goto" "if" "int" "long" | |||||
| "register" "return" "short" "signed" "sizeof" "static" "struct" | |||||
| "switch" "typedef" "union" "unsigned" "void" "volatile" "while") | |||||
| (csharp-mode | |||||
| "abstract" "add" "alias" "as" "base" "bool" "break" "byte" "case" | |||||
| "catch" "char" "checked" "class" "const" "continue" "decimal" "default" | |||||
| "delegate" "do" "double" "else" "enum" "event" "explicit" "extern" | |||||
| "false" "finally" "fixed" "float" "for" "foreach" "get" "global" "goto" | |||||
| "if" "implicit" "in" "int" "interface" "internal" "is" "lock" "long" | |||||
| "namespace" "new" "null" "object" "operator" "out" "override" "params" | |||||
| "partial" "private" "protected" "public" "readonly" "ref" "remove" | |||||
| "return" "sbyte" "sealed" "set" "short" "sizeof" "stackalloc" "static" | |||||
| "string" "struct" "switch" "this" "throw" "true" "try" "typeof" "uint" | |||||
| "ulong" "unchecked" "unsafe" "ushort" "using" "value" "var" "virtual" | |||||
| "void" "volatile" "where" "while" "yield") | |||||
| (d-mode | |||||
| ;; from http://www.digitalmars.com/d/2.0/lex.html | |||||
| "abstract" "alias" "align" "asm" | |||||
| "assert" "auto" "body" "bool" "break" "byte" "case" "cast" "catch" | |||||
| "cdouble" "cent" "cfloat" "char" "class" "const" "continue" "creal" | |||||
| "dchar" "debug" "default" "delegate" "delete" "deprecated" "do" | |||||
| "double" "else" "enum" "export" "extern" "false" "final" "finally" | |||||
| "float" "for" "foreach" "foreach_reverse" "function" "goto" "idouble" | |||||
| "if" "ifloat" "import" "in" "inout" "int" "interface" "invariant" | |||||
| "ireal" "is" "lazy" "long" "macro" "mixin" "module" "new" "nothrow" | |||||
| "null" "out" "override" "package" "pragma" "private" "protected" | |||||
| "public" "pure" "real" "ref" "return" "scope" "short" "static" "struct" | |||||
| "super" "switch" "synchronized" "template" "this" "throw" "true" "try" | |||||
| "typedef" "typeid" "typeof" "ubyte" "ucent" "uint" "ulong" "union" | |||||
| "unittest" "ushort" "version" "void" "volatile" "wchar" "while" "with") | |||||
| (f90-mode . | |||||
| ;; from f90.el | |||||
| ;; ".AND." ".GE." ".GT." ".LT." ".LE." ".NE." ".OR." ".TRUE." ".FALSE." | |||||
| ,(company-keywords-upper-lower | |||||
| "abs" "abstract" "achar" "acos" "adjustl" "adjustr" "aimag" "aint" | |||||
| "align" "all" "all_prefix" "all_scatter" "all_suffix" "allocatable" | |||||
| "allocate" "allocated" "and" "anint" "any" "any_prefix" "any_scatter" | |||||
| "any_suffix" "asin" "assign" "assignment" "associate" "associated" | |||||
| "asynchronous" "atan" "atan2" "backspace" "bind" "bit_size" "block" | |||||
| "btest" "c_alert" "c_associated" "c_backspace" "c_bool" | |||||
| "c_carriage_return" "c_char" "c_double" "c_double_complex" "c_f_pointer" | |||||
| "c_f_procpointer" "c_float" "c_float_complex" "c_form_feed" "c_funloc" | |||||
| "c_funptr" "c_horizontal_tab" "c_int" "c_int16_t" "c_int32_t" "c_int64_t" | |||||
| "c_int8_t" "c_int_fast16_t" "c_int_fast32_t" "c_int_fast64_t" | |||||
| "c_int_fast8_t" "c_int_least16_t" "c_int_least32_t" "c_int_least64_t" | |||||
| "c_int_least8_t" "c_intmax_t" "c_intptr_t" "c_loc" "c_long" | |||||
| "c_long_double" "c_long_double_complex" "c_long_long" "c_new_line" | |||||
| "c_null_char" "c_null_funptr" "c_null_ptr" "c_ptr" "c_short" | |||||
| "c_signed_char" "c_size_t" "c_vertical_tab" "call" "case" "ceiling" | |||||
| "char" "character" "character_storage_size" "class" "close" "cmplx" | |||||
| "command_argument_count" "common" "complex" "conjg" "contains" "continue" | |||||
| "copy_prefix" "copy_scatter" "copy_suffix" "cos" "cosh" "count" | |||||
| "count_prefix" "count_scatter" "count_suffix" "cpu_time" "cshift" | |||||
| "cycle" "cyclic" "data" "date_and_time" "dble" "deallocate" "deferred" | |||||
| "digits" "dim" "dimension" "distribute" "do" "dot_product" "double" | |||||
| "dprod" "dynamic" "elemental" "else" "elseif" "elsewhere" "end" "enddo" | |||||
| "endfile" "endif" "entry" "enum" "enumerator" "eoshift" "epsilon" "eq" | |||||
| "equivalence" "eqv" "error_unit" "exit" "exp" "exponent" "extends" | |||||
| "extends_type_of" "external" "extrinsic" "false" "file_storage_size" | |||||
| "final" "floor" "flush" "forall" "format" "fraction" "function" "ge" | |||||
| "generic" "get_command" "get_command_argument" "get_environment_variable" | |||||
| "goto" "grade_down" "grade_up" "gt" "hpf_alignment" "hpf_distribution" | |||||
| "hpf_template" "huge" "iachar" "iall" "iall_prefix" "iall_scatter" | |||||
| "iall_suffix" "iand" "iany" "iany_prefix" "iany_scatter" "iany_suffix" | |||||
| "ibclr" "ibits" "ibset" "ichar" "ieee_arithmetic" "ieee_exceptions" | |||||
| "ieee_features" "ieee_get_underflow_mode" "ieee_set_underflow_mode" | |||||
| "ieee_support_underflow_control" "ieor" "if" "ilen" "implicit" | |||||
| "import" "include" "independent" "index" "inherit" "input_unit" | |||||
| "inquire" "int" "integer" "intent" "interface" "intrinsic" "ior" | |||||
| "iostat_end" "iostat_eor" "iparity" "iparity_prefix" "iparity_scatter" | |||||
| "iparity_suffix" "ishft" "ishftc" "iso_c_binding" "iso_fortran_env" | |||||
| "kind" "lbound" "le" "leadz" "len" "len_trim" "lge" "lgt" "lle" "llt" | |||||
| "log" "log10" "logical" "lt" "matmul" "max" "maxexponent" "maxloc" | |||||
| "maxval" "maxval_prefix" "maxval_scatter" "maxval_suffix" "merge" | |||||
| "min" "minexponent" "minloc" "minval" "minval_prefix" "minval_scatter" | |||||
| "minval_suffix" "mod" "module" "modulo" "move_alloc" "mvbits" "namelist" | |||||
| "ne" "nearest" "neqv" "new" "new_line" "nint" "non_intrinsic" | |||||
| "non_overridable" "none" "nopass" "not" "null" "nullify" | |||||
| "number_of_processors" "numeric_storage_size" "only" "onto" "open" | |||||
| "operator" "optional" "or" "output_unit" "pack" "parameter" "parity" | |||||
| "parity_prefix" "parity_scatter" "parity_suffix" "pass" "pause" | |||||
| "pointer" "popcnt" "poppar" "precision" "present" "print" "private" | |||||
| "procedure" "processors" "processors_shape" "product" "product_prefix" | |||||
| "product_scatter" "product_suffix" "program" "protected" "public" | |||||
| "pure" "radix" "random_number" "random_seed" "range" "read" "real" | |||||
| "realign" "recursive" "redistribute" "repeat" "reshape" "result" | |||||
| "return" "rewind" "rrspacing" "same_type_as" "save" "scale" "scan" | |||||
| "select" "selected_char_kind" "selected_int_kind" "selected_real_kind" | |||||
| "sequence" "set_exponent" "shape" "sign" "sin" "sinh" "size" "spacing" | |||||
| "spread" "sqrt" "stop" "subroutine" "sum" "sum_prefix" "sum_scatter" | |||||
| "sum_suffix" "system_clock" "tan" "tanh" "target" "template" "then" | |||||
| "tiny" "transfer" "transpose" "trim" "true" "type" "ubound" "unpack" | |||||
| "use" "value" "verify" "volatile" "wait" "where" "while" "with" "write")) | |||||
| (java-mode | |||||
| "abstract" "assert" "boolean" "break" "byte" "case" "catch" "char" "class" | |||||
| "continue" "default" "do" "double" "else" "enum" "extends" "final" | |||||
| "finally" "float" "for" "if" "implements" "import" "instanceof" "int" | |||||
| "interface" "long" "native" "new" "package" "private" "protected" "public" | |||||
| "return" "short" "static" "strictfp" "super" "switch" "synchronized" | |||||
| "this" "throw" "throws" "transient" "try" "void" "volatile" "while") | |||||
| (javascript-mode | |||||
| "break" "catch" "const" "continue" "delete" "do" "else" "export" "for" | |||||
| "function" "if" "import" "in" "instanceOf" "label" "let" "new" "return" | |||||
| "switch" "this" "throw" "try" "typeof" "var" "void" "while" "with" "yield") | |||||
| (objc-mode | |||||
| "@catch" "@class" "@encode" "@end" "@finally" "@implementation" | |||||
| "@interface" "@private" "@protected" "@protocol" "@public" | |||||
| "@selector" "@synchronized" "@throw" "@try" "alloc" "autorelease" | |||||
| "bycopy" "byref" "in" "inout" "oneway" "out" "release" "retain") | |||||
| (perl-mode | |||||
| ;; from cperl.el | |||||
| "AUTOLOAD" "BEGIN" "CHECK" "CORE" "DESTROY" "END" "INIT" "__END__" | |||||
| "__FILE__" "__LINE__" "abs" "accept" "alarm" "and" "atan2" "bind" | |||||
| "binmode" "bless" "caller" "chdir" "chmod" "chomp" "chop" "chown" "chr" | |||||
| "chroot" "close" "closedir" "cmp" "connect" "continue" "cos" | |||||
| "crypt" "dbmclose" "dbmopen" "defined" "delete" "die" "do" "dump" "each" | |||||
| "else" "elsif" "endgrent" "endhostent" "endnetent" "endprotoent" | |||||
| "endpwent" "endservent" "eof" "eq" "eval" "exec" "exists" "exit" "exp" | |||||
| "fcntl" "fileno" "flock" "for" "foreach" "fork" "format" "formline" | |||||
| "ge" "getc" "getgrent" "getgrgid" "getgrnam" "gethostbyaddr" | |||||
| "gethostbyname" "gethostent" "getlogin" "getnetbyaddr" "getnetbyname" | |||||
| "getnetent" "getpeername" "getpgrp" "getppid" "getpriority" | |||||
| "getprotobyname" "getprotobynumber" "getprotoent" "getpwent" "getpwnam" | |||||
| "getpwuid" "getservbyname" "getservbyport" "getservent" "getsockname" | |||||
| "getsockopt" "glob" "gmtime" "goto" "grep" "gt" "hex" "if" "index" "int" | |||||
| "ioctl" "join" "keys" "kill" "last" "lc" "lcfirst" "le" "length" | |||||
| "link" "listen" "local" "localtime" "lock" "log" "lstat" "lt" "map" | |||||
| "mkdir" "msgctl" "msgget" "msgrcv" "msgsnd" "my" "ne" "next" "no" | |||||
| "not" "oct" "open" "opendir" "or" "ord" "our" "pack" "package" "pipe" | |||||
| "pop" "pos" "print" "printf" "push" "q" "qq" "quotemeta" "qw" "qx" | |||||
| "rand" "read" "readdir" "readline" "readlink" "readpipe" "recv" "redo" | |||||
| "ref" "rename" "require" "reset" "return" "reverse" "rewinddir" "rindex" | |||||
| "rmdir" "scalar" "seek" "seekdir" "select" "semctl" "semget" "semop" | |||||
| "send" "setgrent" "sethostent" "setnetent" "setpgrp" "setpriority" | |||||
| "setprotoent" "setpwent" "setservent" "setsockopt" "shift" "shmctl" | |||||
| "shmget" "shmread" "shmwrite" "shutdown" "sin" "sleep" "socket" | |||||
| "socketpair" "sort" "splice" "split" "sprintf" "sqrt" "srand" "stat" | |||||
| "study" "sub" "substr" "symlink" "syscall" "sysopen" "sysread" "system" | |||||
| "syswrite" "tell" "telldir" "tie" "time" "times" "tr" "truncate" "uc" | |||||
| "ucfirst" "umask" "undef" "unless" "unlink" "unpack" "unshift" "untie" | |||||
| "until" "use" "utime" "values" "vec" "wait" "waitpid" | |||||
| "wantarray" "warn" "while" "write" "x" "xor" "y") | |||||
| (php-mode | |||||
| "__CLASS__" "__DIR__" "__FILE__" "__FUNCTION__" "__LINE__" "__METHOD__" | |||||
| "__NAMESPACE__" "_once" "abstract" "and" "array" "as" "break" "case" | |||||
| "catch" "cfunction" "class" "clone" "const" "continue" "declare" | |||||
| "default" "die" "do" "echo" "else" "elseif" "empty" "enddeclare" | |||||
| "endfor" "endforeach" "endif" "endswitch" "endwhile" "eval" "exception" | |||||
| "exit" "extends" "final" "for" "foreach" "function" "global" | |||||
| "goto" "if" "implements" "include" "instanceof" "interface" | |||||
| "isset" "list" "namespace" "new" "old_function" "or" "php_user_filter" | |||||
| "print" "private" "protected" "public" "require" "require_once" "return" | |||||
| "static" "switch" "this" "throw" "try" "unset" "use" "var" "while" "xor") | |||||
| (python-mode | |||||
| "and" "assert" "break" "class" "continue" "def" "del" "elif" "else" | |||||
| "except" "exec" "finally" "for" "from" "global" "if" "import" "in" "is" | |||||
| "lambda" "not" "or" "pass" "print" "raise" "return" "try" "while" "yield") | |||||
| (ruby-mode | |||||
| "BEGIN" "END" "alias" "and" "begin" "break" "case" "class" "def" "defined?" | |||||
| "do" "else" "elsif" "end" "ensure" "false" "for" "if" "in" "module" | |||||
| "next" "nil" "not" "or" "redo" "rescue" "retry" "return" "self" "super" | |||||
| "then" "true" "undef" "unless" "until" "when" "while" "yield") | |||||
| (scala-mode | |||||
| "abstract" "case" "catch" "class" "def" "do" "else" "extends" "false" | |||||
| "final" "finally" "for" "forSome" "if" "implicit" "import" "lazy" "match" | |||||
| "new" "null" "object" "override" "package" "private" "protected" | |||||
| "return" "sealed" "super" "this" "throw" "trait" "true" "try" "type" "val" | |||||
| "var" "while" "with" "yield") | |||||
| ;; aliases | |||||
| (js2-mode . javascript-mode) | |||||
| (espresso-mode . javascript-mode) | |||||
| (js-mode . javascript-mode) | |||||
| (cperl-mode . perl-mode) | |||||
| (jde-mode . java-mode)) | |||||
| "Alist mapping major-modes to sorted keywords for `company-keywords'.") | |||||
| ;;;###autoload | |||||
| (defun company-keywords (command &optional arg &rest ignored) | |||||
| "`company-mode' backend for programming language keywords." | |||||
| (interactive (list 'interactive)) | |||||
| (cl-case command | |||||
| (interactive (company-begin-backend 'company-keywords)) | |||||
| (prefix (and (assq major-mode company-keywords-alist) | |||||
| (not (company-in-string-or-comment)) | |||||
| (or (company-grab-symbol) 'stop))) | |||||
| (candidates | |||||
| (let ((completion-ignore-case nil) | |||||
| (symbols (cdr (assq major-mode company-keywords-alist)))) | |||||
| (all-completions arg (if (consp symbols) | |||||
| symbols | |||||
| (cdr (assq symbols company-keywords-alist)))))) | |||||
| (sorted t))) | |||||
| (provide 'company-keywords) | |||||
| ;;; company-keywords.el ends here | |||||
| @ -1,142 +0,0 @@ | |||||
| ;;; company-nxml.el --- company-mode completion backend for nxml-mode | |||||
| ;; Copyright (C) 2009-2011, 2013 Free Software Foundation, Inc. | |||||
| ;; Author: Nikolaj Schumacher | |||||
| ;; 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: | |||||
| ;; | |||||
| ;;; Code: | |||||
| (require 'company) | |||||
| (require 'cl-lib) | |||||
| (defvar rng-open-elements) | |||||
| (defvar rng-validate-mode) | |||||
| (defvar rng-in-attribute-regex) | |||||
| (defvar rng-in-attribute-value-regex) | |||||
| (declare-function rng-set-state-after "rng-nxml") | |||||
| (declare-function rng-match-possible-start-tag-names "rng-match") | |||||
| (declare-function rng-adjust-state-for-attribute "rng-nxml") | |||||
| (declare-function rng-match-possible-attribute-names "rng-match") | |||||
| (declare-function rng-adjust-state-for-attribute-value "rng-nxml") | |||||
| (declare-function rng-match-possible-value-strings "rng-match") | |||||
| (defconst company-nxml-token-regexp | |||||
| "\\(?:[_[:alpha:]][-._[:alnum:]]*\\_>\\)") | |||||
| (defvar company-nxml-in-attribute-value-regexp | |||||
| (replace-regexp-in-string "w" company-nxml-token-regexp | |||||
| "<w\\(?::w\\)?\ | |||||
| \\(?:[ \t\r\n]+w\\(?::w\\)?[ \t\r\n]*=\ | |||||
| \[ \t\r\n]*\\(?:\"[^\"]*\"\\|'[^']*'\\)\\)*\ | |||||
| \[ \t\r\n]+\\(w\\(:w\\)?\\)[ \t\r\n]*=[ \t\r\n]*\ | |||||
| \\(\"\\([^\"]*\\>\\)\\|'\\([^']*\\>\\)\\)\\=" | |||||
| t t)) | |||||
| (defvar company-nxml-in-tag-name-regexp | |||||
| (replace-regexp-in-string "w" company-nxml-token-regexp | |||||
| "<\\(/?w\\(?::w?\\)?\\)?\\=" t t)) | |||||
| (defun company-nxml-all-completions (prefix alist) | |||||
| (let ((candidates (mapcar 'cdr alist)) | |||||
| (case-fold-search nil) | |||||
| filtered) | |||||
| (when (cdar rng-open-elements) | |||||
| (push (concat "/" (cdar rng-open-elements)) candidates)) | |||||
| (setq candidates (sort (all-completions prefix candidates) 'string<)) | |||||
| (while candidates | |||||
| (unless (equal (car candidates) (car filtered)) | |||||
| (push (car candidates) filtered)) | |||||
| (pop candidates)) | |||||
| (nreverse filtered))) | |||||
| (defmacro company-nxml-prepared (&rest body) | |||||
| (declare (indent 0) (debug t)) | |||||
| `(let ((lt-pos (save-excursion (search-backward "<" nil t))) | |||||
| xmltok-dtd) | |||||
| (when (and lt-pos (= (rng-set-state-after lt-pos) lt-pos)) | |||||
| ,@body))) | |||||
| (defun company-nxml-tag (command &optional arg &rest ignored) | |||||
| (cl-case command | |||||
| (prefix (and (derived-mode-p 'nxml-mode) | |||||
| rng-validate-mode | |||||
| (company-grab company-nxml-in-tag-name-regexp 1))) | |||||
| (candidates (company-nxml-prepared | |||||
| (company-nxml-all-completions | |||||
| arg (rng-match-possible-start-tag-names)))) | |||||
| (sorted t))) | |||||
| (defun company-nxml-attribute (command &optional arg &rest ignored) | |||||
| (cl-case command | |||||
| (prefix (and (derived-mode-p 'nxml-mode) | |||||
| rng-validate-mode | |||||
| (memq (char-after) '(?\ ?\t ?\n)) ;; outside word | |||||
| (company-grab rng-in-attribute-regex 1))) | |||||
| (candidates (company-nxml-prepared | |||||
| (and (rng-adjust-state-for-attribute | |||||
| lt-pos (- (point) (length arg))) | |||||
| (company-nxml-all-completions | |||||
| arg (rng-match-possible-attribute-names))))) | |||||
| (sorted t))) | |||||
| (defun company-nxml-attribute-value (command &optional arg &rest ignored) | |||||
| (cl-case command | |||||
| (prefix (and (derived-mode-p 'nxml-mode) | |||||
| rng-validate-mode | |||||
| (and (memq (char-after) '(?' ?\" ?\ ?\t ?\n)) ;; outside word | |||||
| (looking-back company-nxml-in-attribute-value-regexp) | |||||
| (or (match-string-no-properties 4) | |||||
| (match-string-no-properties 5) | |||||
| "")))) | |||||
| (candidates (company-nxml-prepared | |||||
| (let (attr-start attr-end colon) | |||||
| (and (looking-back rng-in-attribute-value-regex lt-pos) | |||||
| (setq colon (match-beginning 2) | |||||
| attr-start (match-beginning 1) | |||||
| attr-end (match-end 1)) | |||||
| (rng-adjust-state-for-attribute lt-pos attr-start) | |||||
| (rng-adjust-state-for-attribute-value | |||||
| attr-start colon attr-end) | |||||
| (all-completions | |||||
| arg (rng-match-possible-value-strings)))))))) | |||||
| ;;;###autoload | |||||
| (defun company-nxml (command &optional arg &rest ignored) | |||||
| "`company-mode' completion backend for `nxml-mode'." | |||||
| (interactive (list 'interactive)) | |||||
| (cl-case command | |||||
| (interactive (company-begin-backend 'company-nxml)) | |||||
| (prefix (or (company-nxml-tag 'prefix) | |||||
| (company-nxml-attribute 'prefix) | |||||
| (company-nxml-attribute-value 'prefix))) | |||||
| (candidates (cond | |||||
| ((company-nxml-tag 'prefix) | |||||
| (company-nxml-tag 'candidates arg)) | |||||
| ((company-nxml-attribute 'prefix) | |||||
| (company-nxml-attribute 'candidates arg)) | |||||
| ((company-nxml-attribute-value 'prefix) | |||||
| (sort (company-nxml-attribute-value 'candidates arg) | |||||
| 'string<)))) | |||||
| (sorted t))) | |||||
| (provide 'company-nxml) | |||||
| ;;; company-nxml.el ends here | |||||
| @ -1,57 +0,0 @@ | |||||
| ;;; company-oddmuse.el --- company-mode completion backend for oddmuse-mode | |||||
| ;; Copyright (C) 2009-2011, 2014 Free Software Foundation, Inc. | |||||
| ;; Author: Nikolaj Schumacher | |||||
| ;; 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: | |||||
| ;; | |||||
| ;;; Code: | |||||
| (require 'company) | |||||
| (require 'cl-lib) | |||||
| (eval-when-compile (require 'yaooddmuse nil t)) | |||||
| (eval-when-compile (require 'oddmuse nil t)) | |||||
| (defvar company-oddmuse-link-regexp | |||||
| "\\(\\<[A-Z][[:alnum:]]*\\>\\)\\|\\[\\[\\([[:alnum:]]+\\>\\|\\)") | |||||
| (defun company-oddmuse-get-page-table () | |||||
| (cl-case major-mode | |||||
| (yaoddmuse-mode (with-no-warnings | |||||
| (yaoddmuse-get-pagename-table yaoddmuse-wikiname))) | |||||
| (oddmuse-mode (with-no-warnings | |||||
| (oddmuse-make-completion-table oddmuse-wiki))))) | |||||
| ;;;###autoload | |||||
| (defun company-oddmuse (command &optional arg &rest ignored) | |||||
| "`company-mode' completion backend for `oddmuse-mode'." | |||||
| (interactive (list 'interactive)) | |||||
| (cl-case command | |||||
| (interactive (company-begin-backend 'company-oddmuse)) | |||||
| (prefix (let ((case-fold-search nil)) | |||||
| (and (memq major-mode '(oddmuse-mode yaoddmuse-mode)) | |||||
| (looking-back company-oddmuse-link-regexp (point-at-bol)) | |||||
| (or (match-string 1) | |||||
| (match-string 2))))) | |||||
| (candidates (all-completions arg (company-oddmuse-get-page-table))))) | |||||
| (provide 'company-oddmuse) | |||||
| ;;; company-oddmuse.el ends here | |||||
| @ -1,8 +0,0 @@ | |||||
| (define-package "company" "20160117.321" "Modular text completion framework" | |||||
| '((emacs "24.1") | |||||
| (cl-lib "0.5")) | |||||
| :url "http://company-mode.github.io/" :keywords | |||||
| '("abbrev" "convenience" "matching")) | |||||
| ;; Local Variables: | |||||
| ;; no-byte-compile: t | |||||
| ;; End: | |||||
| @ -1,167 +0,0 @@ | |||||
| ;;; company-semantic.el --- company-mode completion backend using Semantic | |||||
| ;; Copyright (C) 2009-2011, 2013-2016 Free Software Foundation, Inc. | |||||
| ;; Author: Nikolaj Schumacher | |||||
| ;; 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: | |||||
| ;; | |||||
| ;;; Code: | |||||
| (require 'company) | |||||
| (require 'company-template) | |||||
| (require 'cl-lib) | |||||
| (defvar semantic-idle-summary-function) | |||||
| (declare-function semantic-documentation-for-tag "semantic/doc" ) | |||||
| (declare-function semantic-analyze-current-context "semantic/analyze") | |||||
| (declare-function semantic-analyze-possible-completions "semantic/complete") | |||||
| (declare-function semantic-analyze-find-tags-by-prefix "semantic/analyze/fcn") | |||||
| (declare-function semantic-tag-class "semantic/tag") | |||||
| (declare-function semantic-tag-name "semantic/tag") | |||||
| (declare-function semantic-tag-start "semantic/tag") | |||||
| (declare-function semantic-tag-buffer "semantic/tag") | |||||
| (declare-function semantic-active-p "semantic") | |||||
| (declare-function semantic-format-tag-prototype "semantic/format") | |||||
| (defgroup company-semantic nil | |||||
| "Completion backend using Semantic." | |||||
| :group 'company) | |||||
| (defcustom company-semantic-metadata-function 'company-semantic-summary-and-doc | |||||
| "The function turning a semantic tag into doc information." | |||||
| :type 'function) | |||||
| (defcustom company-semantic-begin-after-member-access t | |||||
| "When non-nil, automatic completion will start whenever the current | |||||
| symbol is preceded by \".\", \"->\" or \"::\", ignoring | |||||
| `company-minimum-prefix-length'. | |||||
| If `company-begin-commands' is a list, it should include `c-electric-lt-gt' | |||||
| and `c-electric-colon', for automatic completion right after \">\" and | |||||
| \":\".") | |||||
| (defcustom company-semantic-insert-arguments t | |||||
| "When non-nil, insert function arguments as a template after completion." | |||||
| :type 'boolean | |||||
| :package-version '(company . "0.9.0")) | |||||
| (defvar company-semantic-modes '(c-mode c++-mode jde-mode java-mode)) | |||||
| (defvar-local company-semantic--current-tags nil | |||||
| "Tags for the current context.") | |||||
| (defun company-semantic-documentation-for-tag (tag) | |||||
| (when (semantic-tag-buffer tag) | |||||
| ;; When TAG's buffer is unknown, the function below raises an error. | |||||
| (semantic-documentation-for-tag tag))) | |||||
| (defun company-semantic-doc-or-summary (tag) | |||||
| (or (company-semantic-documentation-for-tag tag) | |||||
| (and (require 'semantic-idle nil t) | |||||
| (require 'semantic/idle nil t) | |||||
| (funcall semantic-idle-summary-function tag nil t)))) | |||||
| (defun company-semantic-summary-and-doc (tag) | |||||
| (let ((doc (company-semantic-documentation-for-tag tag)) | |||||
| (summary (funcall semantic-idle-summary-function tag nil t))) | |||||
| (and (stringp doc) | |||||
| (string-match "\n*\\(.*\\)$" doc) | |||||
| (setq doc (match-string 1 doc))) | |||||
| (concat summary | |||||
| (when doc | |||||
| (if (< (+ (length doc) (length summary) 4) (window-width)) | |||||
| " -- " | |||||
| "\n")) | |||||
| doc))) | |||||
| (defun company-semantic-doc-buffer (tag) | |||||
| (let ((doc (company-semantic-documentation-for-tag tag))) | |||||
| (when doc | |||||
| (company-doc-buffer | |||||
| (concat (funcall semantic-idle-summary-function tag nil t) | |||||
| "\n" | |||||
| doc))))) | |||||
| (defsubst company-semantic-completions (prefix) | |||||
| (ignore-errors | |||||
| (let ((completion-ignore-case nil) | |||||
| (context (semantic-analyze-current-context))) | |||||
| (setq company-semantic--current-tags | |||||
| (semantic-analyze-possible-completions context 'no-unique)) | |||||
| (all-completions prefix company-semantic--current-tags)))) | |||||
| (defun company-semantic-completions-raw (prefix) | |||||
| (setq company-semantic--current-tags nil) | |||||
| (dolist (tag (semantic-analyze-find-tags-by-prefix prefix)) | |||||
| (unless (eq (semantic-tag-class tag) 'include) | |||||
| (push tag company-semantic--current-tags))) | |||||
| (delete "" (mapcar 'semantic-tag-name company-semantic--current-tags))) | |||||
| (defun company-semantic-annotation (argument tags) | |||||
| (let* ((tag (assq argument tags)) | |||||
| (kind (when tag (elt tag 1)))) | |||||
| (cl-case kind | |||||
| (function (let* ((prototype (semantic-format-tag-prototype tag nil nil)) | |||||
| (par-pos (string-match "(" prototype))) | |||||
| (when par-pos (substring prototype par-pos))))))) | |||||
| (defun company-semantic--prefix () | |||||
| (if company-semantic-begin-after-member-access | |||||
| (company-grab-symbol-cons "\\.\\|->\\|::" 2) | |||||
| (company-grab-symbol))) | |||||
| ;;;###autoload | |||||
| (defun company-semantic (command &optional arg &rest ignored) | |||||
| "`company-mode' completion backend using CEDET Semantic." | |||||
| (interactive (list 'interactive)) | |||||
| (cl-case command | |||||
| (interactive (company-begin-backend 'company-semantic)) | |||||
| (prefix (and (featurep 'semantic) | |||||
| (semantic-active-p) | |||||
| (memq major-mode company-semantic-modes) | |||||
| (not (company-in-string-or-comment)) | |||||
| (or (company-semantic--prefix) 'stop))) | |||||
| (candidates (if (and (equal arg "") | |||||
| (not (looking-back "->\\|\\." (- (point) 2)))) | |||||
| (company-semantic-completions-raw arg) | |||||
| (company-semantic-completions arg))) | |||||
| (meta (funcall company-semantic-metadata-function | |||||
| (assoc arg company-semantic--current-tags))) | |||||
| (annotation (company-semantic-annotation arg | |||||
| company-semantic--current-tags)) | |||||
| (doc-buffer (company-semantic-doc-buffer | |||||
| (assoc arg company-semantic--current-tags))) | |||||
| ;; Because "" is an empty context and doesn't return local variables. | |||||
| (no-cache (equal arg "")) | |||||
| (duplicates t) | |||||
| (location (let ((tag (assoc arg company-semantic--current-tags))) | |||||
| (when (buffer-live-p (semantic-tag-buffer tag)) | |||||
| (cons (semantic-tag-buffer tag) | |||||
| (semantic-tag-start tag))))) | |||||
| (post-completion (let ((anno (company-semantic-annotation | |||||
| arg company-semantic--current-tags))) | |||||
| (when (and company-semantic-insert-arguments anno) | |||||
| (insert anno) | |||||
| (company-template-c-like-templatify (concat arg anno))) | |||||
| )))) | |||||
| (provide 'company-semantic) | |||||
| ;;; company-semantic.el ends here | |||||
| @ -1,214 +0,0 @@ | |||||
| ;;; company-template.el --- utility library for template expansion | |||||
| ;; Copyright (C) 2009, 2010, 2014-2016 Free Software Foundation, Inc. | |||||
| ;; Author: Nikolaj Schumacher | |||||
| ;; 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/>. | |||||
| ;;; Code: | |||||
| (require 'cl-lib) | |||||
| (defface company-template-field | |||||
| '((((background dark)) (:background "yellow" :foreground "black")) | |||||
| (((background light)) (:background "orange" :foreground "black"))) | |||||
| "Face used for editable text in template fields." | |||||
| :group 'company) | |||||
| (defvar company-template-nav-map | |||||
| (let ((keymap (make-sparse-keymap))) | |||||
| (define-key keymap [tab] 'company-template-forward-field) | |||||
| (define-key keymap (kbd "TAB") 'company-template-forward-field) | |||||
| keymap)) | |||||
| (defvar-local company-template--buffer-templates nil) | |||||
| ;; interactive ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||||
| (defun company-template-templates-at (pos) | |||||
| (let (os) | |||||
| (dolist (o (overlays-at pos)) | |||||
| ;; FIXME: Always return the whole list of templates? | |||||
| ;; We remove templates not at point after every command. | |||||
| (when (memq o company-template--buffer-templates) | |||||
| (push o os))) | |||||
| os)) | |||||
| (defun company-template-move-to-first (templ) | |||||
| (interactive) | |||||
| (goto-char (overlay-start templ)) | |||||
| (company-template-forward-field)) | |||||
| (defun company-template-forward-field () | |||||
| (interactive) | |||||
| (let* ((start (point)) | |||||
| (templates (company-template-templates-at (point))) | |||||
| (minimum (apply 'max (mapcar 'overlay-end templates))) | |||||
| (fields (cl-loop for templ in templates | |||||
| append (overlay-get templ 'company-template-fields)))) | |||||
| (dolist (pos (mapcar 'overlay-start fields)) | |||||
| (and pos | |||||
| (> pos (point)) | |||||
| (< pos minimum) | |||||
| (setq minimum pos))) | |||||
| (push-mark) | |||||
| (goto-char minimum) | |||||
| (company-template-remove-field (company-template-field-at start)))) | |||||
| (defun company-template-field-at (&optional point) | |||||
| (cl-loop for ovl in (overlays-at (or point (point))) | |||||
| when (overlay-get ovl 'company-template-parent) | |||||
| return ovl)) | |||||
| ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||||
| (defun company-template-declare-template (beg end) | |||||
| (let ((ov (make-overlay beg end))) | |||||
| ;; (overlay-put ov 'face 'highlight) | |||||
| (overlay-put ov 'keymap company-template-nav-map) | |||||
| (overlay-put ov 'priority 101) | |||||
| (overlay-put ov 'evaporate t) | |||||
| (push ov company-template--buffer-templates) | |||||
| (add-hook 'post-command-hook 'company-template-post-command nil t) | |||||
| ov)) | |||||
| (defun company-template-remove-template (templ) | |||||
| (mapc 'company-template-remove-field | |||||
| (overlay-get templ 'company-template-fields)) | |||||
| (setq company-template--buffer-templates | |||||
| (delq templ company-template--buffer-templates)) | |||||
| (delete-overlay templ)) | |||||
| (defun company-template-add-field (templ beg end &optional display) | |||||
| "Add new field to template TEMPL spanning from BEG to END. | |||||
| When DISPLAY is non-nil, set the respective property on the overlay. | |||||
| Leave point at the end of the field." | |||||
| (cl-assert templ) | |||||
| (when (> end (overlay-end templ)) | |||||
| (move-overlay templ (overlay-start templ) end)) | |||||
| (let ((ov (make-overlay beg end)) | |||||
| (siblings (overlay-get templ 'company-template-fields))) | |||||
| ;; (overlay-put ov 'evaporate t) | |||||
| (overlay-put ov 'intangible t) | |||||
| (overlay-put ov 'face 'company-template-field) | |||||
| (when display | |||||
| (overlay-put ov 'display display)) | |||||
| (overlay-put ov 'company-template-parent templ) | |||||
| (overlay-put ov 'insert-in-front-hooks '(company-template-insert-hook)) | |||||
| (push ov siblings) | |||||
| (overlay-put templ 'company-template-fields siblings))) | |||||
| (defun company-template-remove-field (ovl &optional clear) | |||||
| (when (overlayp ovl) | |||||
| (when (overlay-buffer ovl) | |||||
| (when clear | |||||
| (delete-region (overlay-start ovl) (overlay-end ovl))) | |||||
| (delete-overlay ovl)) | |||||
| (let* ((templ (overlay-get ovl 'company-template-parent)) | |||||
| (siblings (overlay-get templ 'company-template-fields))) | |||||
| (setq siblings (delq ovl siblings)) | |||||
| (overlay-put templ 'company-template-fields siblings)))) | |||||
| (defun company-template-clean-up (&optional pos) | |||||
| "Clean up all templates that don't contain POS." | |||||
| (let ((local-ovs (overlays-at (or pos (point))))) | |||||
| (dolist (templ company-template--buffer-templates) | |||||
| (unless (memq templ local-ovs) | |||||
| (company-template-remove-template templ))))) | |||||
| ;; hooks ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||||
| (defun company-template-insert-hook (ovl after-p &rest _ignore) | |||||
| "Called when a snippet input prompt is modified." | |||||
| (unless after-p | |||||
| (company-template-remove-field ovl t))) | |||||
| (defun company-template-post-command () | |||||
| (company-template-clean-up) | |||||
| (unless company-template--buffer-templates | |||||
| (remove-hook 'post-command-hook 'company-template-post-command t))) | |||||
| ;; common ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||||
| (defun company-template-c-like-templatify (call) | |||||
| (let* ((end (point-marker)) | |||||
| (beg (- (point) (length call))) | |||||
| (templ (company-template-declare-template beg end)) | |||||
| paren-open paren-close) | |||||
| (with-syntax-table (make-syntax-table (syntax-table)) | |||||
| (modify-syntax-entry ?< "(") | |||||
| (modify-syntax-entry ?> ")") | |||||
| (when (search-backward ")" beg t) | |||||
| (setq paren-close (point-marker)) | |||||
| (forward-char 1) | |||||
| (delete-region (point) end) | |||||
| (backward-sexp) | |||||
| (forward-char 1) | |||||
| (setq paren-open (point-marker))) | |||||
| (when (search-backward ">" beg t) | |||||
| (let ((angle-close (point-marker))) | |||||
| (forward-char 1) | |||||
| (backward-sexp) | |||||
| (forward-char) | |||||
| (company-template--c-like-args templ angle-close))) | |||||
| (when (looking-back "\\((\\*)\\)(" (line-beginning-position)) | |||||
| (delete-region (match-beginning 1) (match-end 1))) | |||||
| (when paren-open | |||||
| (goto-char paren-open) | |||||
| (company-template--c-like-args templ paren-close))) | |||||
| (if (overlay-get templ 'company-template-fields) | |||||
| (company-template-move-to-first templ) | |||||
| (company-template-remove-template templ) | |||||
| (goto-char end)))) | |||||
| (defun company-template--c-like-args (templ end) | |||||
| (let ((last-pos (point))) | |||||
| (while (re-search-forward "\\([^,]+\\),?" end 'move) | |||||
| (when (zerop (car (parse-partial-sexp last-pos (point)))) | |||||
| (company-template-add-field templ last-pos (match-end 1)) | |||||
| (skip-chars-forward " ") | |||||
| (setq last-pos (point)))))) | |||||
| ;; objc ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||||
| (defun company-template-objc-templatify (selector) | |||||
| (let* ((end (point-marker)) | |||||
| (beg (- (point) (length selector) 1)) | |||||
| (templ (company-template-declare-template beg end)) | |||||
| (cnt 0)) | |||||
| (save-excursion | |||||
| (goto-char beg) | |||||
| (catch 'stop | |||||
| (while (search-forward ":" end t) | |||||
| (if (looking-at "\\(([^)]*)\\) ?") | |||||
| (company-template-add-field templ (point) (match-end 1)) | |||||
| ;; Not sure which conditions this case manifests under, but | |||||
| ;; apparently it did before, when I wrote the first test for this | |||||
| ;; function. FIXME: Revisit it. | |||||
| (company-template-add-field templ (point) | |||||
| (progn | |||||
| (insert (format "arg%d" cnt)) | |||||
| (point))) | |||||
| (when (< (point) end) | |||||
| (insert " ")) | |||||
| (cl-incf cnt)) | |||||
| (when (>= (point) end) | |||||
| (throw 'stop t))))) | |||||
| (company-template-move-to-first templ))) | |||||
| (provide 'company-template) | |||||
| ;;; company-template.el ends here | |||||
| @ -1,62 +0,0 @@ | |||||
| ;;; company-tempo.el --- company-mode completion backend for tempo | |||||
| ;; Copyright (C) 2009-2011, 2015 Free Software Foundation, Inc. | |||||
| ;; Author: Nikolaj Schumacher | |||||
| ;; 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: | |||||
| ;; | |||||
| ;;; Code: | |||||
| (require 'company) | |||||
| (require 'cl-lib) | |||||
| (require 'tempo) | |||||
| (defsubst company-tempo-lookup (match) | |||||
| (cdr (assoc match (tempo-build-collection)))) | |||||
| (defun company-tempo-insert (match) | |||||
| "Replace MATCH with the expanded tempo template." | |||||
| (search-backward match) | |||||
| (goto-char (match-beginning 0)) | |||||
| (replace-match "") | |||||
| (call-interactively (company-tempo-lookup match))) | |||||
| (defsubst company-tempo-meta (match) | |||||
| (let ((templ (company-tempo-lookup match)) | |||||
| doc) | |||||
| (and templ | |||||
| (setq doc (documentation templ t)) | |||||
| (car (split-string doc "\n" t))))) | |||||
| ;;;###autoload | |||||
| (defun company-tempo (command &optional arg &rest ignored) | |||||
| "`company-mode' completion backend for tempo." | |||||
| (interactive (list 'interactive)) | |||||
| (cl-case command | |||||
| (interactive (company-begin-backend 'company-tempo | |||||
| 'company-tempo-insert)) | |||||
| (prefix (or (car (tempo-find-match-string tempo-match-finder)) "")) | |||||
| (candidates (all-completions arg (tempo-build-collection))) | |||||
| (meta (company-tempo-meta arg)) | |||||
| (sorted t))) | |||||
| (provide 'company-tempo) | |||||
| ;;; company-tempo.el ends here | |||||
| @ -1,123 +0,0 @@ | |||||
| ;;; company-xcode.el --- company-mode completion backend for Xcode projects | |||||
| ;; Copyright (C) 2009-2011, 2014 Free Software Foundation, Inc. | |||||
| ;; Author: Nikolaj Schumacher | |||||
| ;; 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: | |||||
| ;; | |||||
| ;;; Code: | |||||
| (require 'company) | |||||
| (require 'cl-lib) | |||||
| (defgroup company-xcode nil | |||||
| "Completion backend for Xcode projects." | |||||
| :group 'company) | |||||
| (defcustom company-xcode-xcodeindex-executable (executable-find "xcodeindex") | |||||
| "Location of xcodeindex executable." | |||||
| :type 'file) | |||||
| (defvar company-xcode-tags nil) | |||||
| (defun company-xcode-reset () | |||||
| "Reset the cached tags." | |||||
| (interactive) | |||||
| (setq company-xcode-tags nil)) | |||||
| (defcustom company-xcode-types | |||||
| '("Class" "Constant" "Enum" "Macro" "Modeled Class" "Structure" | |||||
| "Type" "Union" "Function") | |||||
| "The types of symbols offered by `company-xcode'. | |||||
| No context-enabled completion is available. Types like methods will be | |||||
| offered regardless of whether the class supports them. The defaults should be | |||||
| valid in most contexts." | |||||
| :set (lambda (variable value) | |||||
| (set variable value) | |||||
| (company-xcode-reset)) | |||||
| :type '(set (const "Category") (const "Class") (const "Class Method") | |||||
| (const "Class Variable") (const "Constant") (const "Enum") | |||||
| (const "Field") (const "Instance Method") | |||||
| (const "Instance Variable") (const "Macro") | |||||
| (const "Modeled Class") (const "Modeled Method") | |||||
| (const "Modeled Property") (const "Property") (const "Protocol") | |||||
| (const "Structure") (const "Type") (const "Union") | |||||
| (const "Variable") (const "Function"))) | |||||
| (defvar-local company-xcode-project 'unknown) | |||||
| ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||||
| (defun company-xcode-fetch (project-bundle) | |||||
| (setq project-bundle (directory-file-name project-bundle)) | |||||
| (message "Retrieving dump from %s..." project-bundle) | |||||
| (with-temp-buffer | |||||
| (let ((default-directory (file-name-directory project-bundle))) | |||||
| (call-process company-xcode-xcodeindex-executable nil (current-buffer) | |||||
| nil "dump" "-project" | |||||
| (file-name-nondirectory project-bundle) "-quiet") | |||||
| (goto-char (point-min)) | |||||
| (let ((regexp (concat "^\\([^\t\n]*\\)\t[^\t\n]*\t" | |||||
| (regexp-opt company-xcode-types) | |||||
| "\t[^\t\n]*\t[^\t\n]*")) | |||||
| candidates) | |||||
| (while (re-search-forward regexp nil t) | |||||
| (cl-pushnew (match-string 1) candidates :test #'equal)) | |||||
| (message "Retrieving dump from %s...done" project-bundle) | |||||
| candidates)))) | |||||
| (defun company-xcode-find-project () | |||||
| (let ((dir (if buffer-file-name | |||||
| (file-name-directory buffer-file-name) | |||||
| (expand-file-name default-directory))) | |||||
| (prev-dir nil) | |||||
| file) | |||||
| (while (not (or file (equal dir prev-dir))) | |||||
| (setq file (car (directory-files dir t ".xcodeproj\\'" t)) | |||||
| prev-dir dir | |||||
| dir (file-name-directory (directory-file-name dir)))) | |||||
| file)) | |||||
| (defun company-xcode-tags () | |||||
| (when (eq company-xcode-project 'unknown) | |||||
| (setq company-xcode-project (company-xcode-find-project))) | |||||
| (when company-xcode-project | |||||
| (cdr (or (assoc company-xcode-project company-xcode-tags) | |||||
| (car (push (cons company-xcode-project | |||||
| (company-xcode-fetch company-xcode-project)) | |||||
| company-xcode-tags)))))) | |||||
| ;;;###autoload | |||||
| (defun company-xcode (command &optional arg &rest ignored) | |||||
| "`company-mode' completion backend for Xcode projects." | |||||
| (interactive (list 'interactive)) | |||||
| (cl-case command | |||||
| (interactive (company-begin-backend 'company-xcode)) | |||||
| (prefix (and company-xcode-xcodeindex-executable | |||||
| (company-xcode-tags) | |||||
| (not (company-in-string-or-comment)) | |||||
| (or (company-grab-symbol) 'stop))) | |||||
| (candidates (let ((completion-ignore-case nil)) | |||||
| (company-xcode-tags) | |||||
| (all-completions arg (company-xcode-tags)))))) | |||||
| (provide 'company-xcode) | |||||
| ;;; company-xcode.el ends here | |||||
| @ -1,147 +0,0 @@ | |||||
| ;;; company-yasnippet.el --- company-mode completion backend for Yasnippet | |||||
| ;; Copyright (C) 2014, 2015 Free Software Foundation, Inc. | |||||
| ;; Author: Dmitry Gutov | |||||
| ;; 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: | |||||
| ;; | |||||
| ;;; Code: | |||||
| (require 'company) | |||||
| (require 'cl-lib) | |||||
| (declare-function yas--table-hash "yasnippet") | |||||
| (declare-function yas--get-snippet-tables "yasnippet") | |||||
| (declare-function yas-expand-snippet "yasnippet") | |||||
| (declare-function yas--template-content "yasnippet") | |||||
| (declare-function yas--template-expand-env "yasnippet") | |||||
| (declare-function yas--warning "yasnippet") | |||||
| (defun company-yasnippet--key-prefixes () | |||||
| ;; Mostly copied from `yas--templates-for-key-at-point'. | |||||
| (defvar yas-key-syntaxes) | |||||
| (save-excursion | |||||
| (let ((original (point)) | |||||
| (methods yas-key-syntaxes) | |||||
| prefixes | |||||
| method) | |||||
| (while methods | |||||
| (unless (eq method (car methods)) | |||||
| (goto-char original)) | |||||
| (setq method (car methods)) | |||||
| (cond ((stringp method) | |||||
| (skip-syntax-backward method) | |||||
| (setq methods (cdr methods))) | |||||
| ((functionp method) | |||||
| (unless (eq (funcall method original) | |||||
| 'again) | |||||
| (setq methods (cdr methods)))) | |||||
| (t | |||||
| (setq methods (cdr methods)) | |||||
| (yas--warning "Invalid element `%s' in `yas-key-syntaxes'" method))) | |||||
| (let ((prefix (buffer-substring-no-properties (point) original))) | |||||
| (unless (equal prefix (car prefixes)) | |||||
| (push prefix prefixes)))) | |||||
| prefixes))) | |||||
| (defun company-yasnippet--candidates (prefix) | |||||
| ;; Process the prefixes in reverse: unlike Yasnippet, we look for prefix | |||||
| ;; matches, so the longest prefix with any matches should be the most useful. | |||||
| (cl-loop with tables = (yas--get-snippet-tables) | |||||
| for key-prefix in (company-yasnippet--key-prefixes) | |||||
| ;; Only consider keys at least as long as the symbol at point. | |||||
| when (>= (length key-prefix) (length prefix)) | |||||
| thereis (company-yasnippet--completions-for-prefix prefix | |||||
| key-prefix | |||||
| tables))) | |||||
| (defun company-yasnippet--completions-for-prefix (prefix key-prefix tables) | |||||
| (cl-mapcan | |||||
| (lambda (table) | |||||
| (let ((keyhash (yas--table-hash table)) | |||||
| res) | |||||
| (when keyhash | |||||
| (maphash | |||||
| (lambda (key value) | |||||
| (when (and (stringp key) | |||||
| (string-prefix-p key-prefix key)) | |||||
| (maphash | |||||
| (lambda (name template) | |||||
| (push | |||||
| (propertize key | |||||
| 'yas-annotation name | |||||
| 'yas-template template | |||||
| 'yas-prefix-offset (- (length key-prefix) | |||||
| (length prefix))) | |||||
| res)) | |||||
| value))) | |||||
| keyhash)) | |||||
| res)) | |||||
| tables)) | |||||
| ;;;###autoload | |||||
| (defun company-yasnippet (command &optional arg &rest ignore) | |||||
| "`company-mode' backend for `yasnippet'. | |||||
| This backend should be used with care, because as long as there are | |||||
| snippets defined for the current major mode, this backend will always | |||||
| shadow backends that come after it. Recommended usages: | |||||
| * In a buffer-local value of `company-backends', grouped with a backend or | |||||
| several that provide actual text completions. | |||||
| (add-hook 'js-mode-hook | |||||
| (lambda () | |||||
| (set (make-local-variable 'company-backends) | |||||
| '((company-dabbrev-code company-yasnippet))))) | |||||
| * After keyword `:with', grouped with other backends. | |||||
| (push '(company-semantic :with company-yasnippet) company-backends) | |||||
| * Not in `company-backends', just bound to a key. | |||||
| (global-set-key (kbd \"C-c y\") 'company-yasnippet) | |||||
| " | |||||
| (interactive (list 'interactive)) | |||||
| (cl-case command | |||||
| (interactive (company-begin-backend 'company-yasnippet)) | |||||
| (prefix | |||||
| ;; Should probably use `yas--current-key', but that's bound to be slower. | |||||
| ;; How many trigger keys start with non-symbol characters anyway? | |||||
| (and (bound-and-true-p yas-minor-mode) | |||||
| (company-grab-symbol))) | |||||
| (annotation | |||||
| (concat | |||||
| (unless company-tooltip-align-annotations " -> ") | |||||
| (get-text-property 0 'yas-annotation arg))) | |||||
| (candidates (company-yasnippet--candidates arg)) | |||||
| (no-cache t) | |||||
| (post-completion | |||||
| (let ((template (get-text-property 0 'yas-template arg)) | |||||
| (prefix-offset (get-text-property 0 'yas-prefix-offset arg))) | |||||
| (yas-expand-snippet (yas--template-content template) | |||||
| (- (point) (length arg) prefix-offset) | |||||
| (point) | |||||
| (yas--template-expand-env template)))))) | |||||
| (provide 'company-yasnippet) | |||||
| ;;; company-yasnippet.el ends here | |||||
| @ -0,0 +1,35 @@ | |||||
| ;;; dockerfile-mode-autoloads.el --- automatically extracted autoloads | |||||
| ;; | |||||
| ;;; Code: | |||||
| (add-to-list 'load-path (or (file-name-directory #$) (car load-path))) | |||||
| ;;;### (autoloads nil "dockerfile-mode" "dockerfile-mode.el" (22199 | |||||
| ;;;;;; 30453 0 0)) | |||||
| ;;; Generated autoloads from dockerfile-mode.el | |||||
| (autoload 'dockerfile-build-buffer "dockerfile-mode" "\ | |||||
| Build an image based upon the buffer | |||||
| \(fn IMAGE-NAME)" t nil) | |||||
| (autoload 'dockerfile-build-no-cache-buffer "dockerfile-mode" "\ | |||||
| Build an image based upon the buffer without cache | |||||
| \(fn IMAGE-NAME)" t nil) | |||||
| (autoload 'dockerfile-mode "dockerfile-mode" "\ | |||||
| A major mode to edit Dockerfiles. | |||||
| \\{dockerfile-mode-map} | |||||
| \(fn)" t nil) | |||||
| (add-to-list 'auto-mode-alist '("Dockerfile.*\\'" . dockerfile-mode)) | |||||
| ;;;*** | |||||
| ;; Local Variables: | |||||
| ;; version-control: never | |||||
| ;; no-byte-compile: t | |||||
| ;; no-update-autoloads: t | |||||
| ;; End: | |||||
| ;;; dockerfile-mode-autoloads.el ends here | |||||
| @ -0,0 +1 @@ | |||||
| (define-package "dockerfile-mode" "20160128.951" "Major mode for editing Docker's Dockerfiles" 'nil) | |||||
| @ -0,0 +1,136 @@ | |||||
| ;;; dockerfile-mode.el --- Major mode for editing Docker's Dockerfiles | |||||
| ;; Package-Version: 20160128.951 | |||||
| ;; Copyright (c) 2013 Spotify AB | |||||
| ;; | |||||
| ;; Licensed under the Apache License, Version 2.0 (the "License"); you may not | |||||
| ;; use this file except in compliance with the License. You may obtain a copy of | |||||
| ;; the License at | |||||
| ;; | |||||
| ;; http://www.apache.org/licenses/LICENSE-2.0 | |||||
| ;; | |||||
| ;; Unless required by applicable law or agreed to in writing, software | |||||
| ;; distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | |||||
| ;; WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | |||||
| ;; License for the specific language governing permissions and limitations under | |||||
| ;; the License. | |||||
| ;;; Code: | |||||
| (require 'sh-script) | |||||
| (require 'rx) | |||||
| (defvar docker-image-name nil) | |||||
| (defgroup dockerfile nil | |||||
| "dockerfile code editing commands for Emacs." | |||||
| :link '(custom-group-link :tag "Font Lock Faces group" font-lock-faces) | |||||
| :prefix "dockerfile-" | |||||
| :group 'languages) | |||||
| (defcustom dockerfile-mode-hook nil | |||||
| "*Hook called by `dockerfile-mode'." | |||||
| :type 'hook | |||||
| :group 'dockerfile) | |||||
| (defcustom dockerfile-use-sudo nil | |||||
| "Runs docker builder command with sudo.") | |||||
| (defvar dockerfile-font-lock-keywords | |||||
| `(,(cons (rx (or line-start "onbuild ") | |||||
| (group (or "from" "maintainer" "run" "cmd" "expose" "env" "arg" | |||||
| "add" "copy" "entrypoint" "volume" "user" "workdir" "onbuild" | |||||
| "label" "stopsignal")) | |||||
| word-boundary) | |||||
| font-lock-keyword-face) | |||||
| ,@(sh-font-lock-keywords) | |||||
| ,@(sh-font-lock-keywords-2) | |||||
| ,@(sh-font-lock-keywords-1)) | |||||
| "Default font-lock-keywords for `dockerfile mode'.") | |||||
| (defvar dockerfile-mode-map | |||||
| (let ((map (make-sparse-keymap)) | |||||
| (menu-map (make-sparse-keymap))) | |||||
| (define-key map "\C-c\C-b" 'dockerfile-build-buffer) | |||||
| (define-key map "\C-c\M-b" 'dockerfile-build-no-cache-buffer) | |||||
| (define-key map "\C-c\C-z" 'dockerfile-test-function) | |||||
| (define-key map "\C-c\C-c" 'comment-region) | |||||
| (define-key map [menu-bar dockerfile-mode] (cons "Dockerfile" menu-map)) | |||||
| (define-key menu-map [dfc] | |||||
| '(menu-item "Comment Region" comment-region | |||||
| :help "Comment Region")) | |||||
| (define-key menu-map [dfb] | |||||
| '(menu-item "Build" dockerfile-build-buffer | |||||
| :help "Send the Dockerfile to docker build")) | |||||
| (define-key menu-map [dfb] | |||||
| '(menu-item "Build without cache" dockerfile-build-no-cache-buffer | |||||
| :help "Send the Dockerfile to docker build without cache")) | |||||
| map)) | |||||
| (defvar dockerfile-mode-syntax-table | |||||
| (let ((table (make-syntax-table))) | |||||
| (modify-syntax-entry ?# "<" table) | |||||
| (modify-syntax-entry ?\n ">" table) | |||||
| (modify-syntax-entry ?' "\"" table) | |||||
| table) | |||||
| "Syntax table for `dockerfile-mode'.") | |||||
| (define-abbrev-table 'dockerfile-mode-abbrev-table nil | |||||
| "Abbrev table used while in `dockerfile-mode'.") | |||||
| (unless dockerfile-mode-abbrev-table | |||||
| (define-abbrev-table 'dockerfile-mode-abbrev-table ())) | |||||
| ;;;###autoload | |||||
| (defun dockerfile-build-buffer (image-name) | |||||
| "Build an image based upon the buffer" | |||||
| (interactive | |||||
| (if (null docker-image-name) | |||||
| (list (read-string "image-name: " nil nil)) | |||||
| (list docker-image-name))) | |||||
| (save-buffer) | |||||
| (if (stringp image-name) | |||||
| (async-shell-command | |||||
| (format "%sdocker build -t %s -f \"%s\" \"%s\"" (if dockerfile-use-sudo "sudo " "") image-name (buffer-file-name) (file-name-directory (buffer-file-name))) | |||||
| "*docker-build-output*") | |||||
| (print "docker-image-name must be a string, consider surrounding it with double quotes"))) | |||||
| ;;;###autoload | |||||
| (defun dockerfile-build-no-cache-buffer (image-name) | |||||
| "Build an image based upon the buffer without cache" | |||||
| (interactive | |||||
| (if (null docker-image-name) | |||||
| (list (read-string "image-name: " nil nil)) | |||||
| (list docker-image-name))) | |||||
| (save-buffer) | |||||
| (if (stringp image-name) | |||||
| (async-shell-command | |||||
| (format "%s docker build --no-cache -t %s -f \"%s\" \"%s\"" (if dockerfile-use-sudo "sudo" "") image-name (buffer-file-name) (file-name-directory (buffer-file-name))) | |||||
| "*docker-build-output*") | |||||
| (print "docker-image-name must be a string, consider surrounding it with double quotes"))) | |||||
| ;; Handle emacs < 24, which does not have prog-mode | |||||
| (defalias 'dockerfile-parent-mode | |||||
| (if (fboundp 'prog-mode) 'prog-mode 'fundamental-mode)) | |||||
| ;;;###autoload | |||||
| (define-derived-mode dockerfile-mode dockerfile-parent-mode "Dockerfile" | |||||
| "A major mode to edit Dockerfiles. | |||||
| \\{dockerfile-mode-map} | |||||
| " | |||||
| (set-syntax-table dockerfile-mode-syntax-table) | |||||
| (set (make-local-variable 'require-final-newline) mode-require-final-newline) | |||||
| (set (make-local-variable 'comment-start) "#") | |||||
| (set (make-local-variable 'comment-end) "") | |||||
| (set (make-local-variable 'comment-start-skip) "#+ *") | |||||
| (set (make-local-variable 'parse-sexp-ignore-comments) t) | |||||
| (set (make-local-variable 'font-lock-defaults) | |||||
| '(dockerfile-font-lock-keywords nil t)) | |||||
| (setq local-abbrev-table dockerfile-mode-abbrev-table)) | |||||
| ;;;###autoload | |||||
| (add-to-list 'auto-mode-alist '("Dockerfile.*\\'" . dockerfile-mode)) | |||||
| (provide 'dockerfile-mode) | |||||
| ;;; dockerfile-mode.el ends here | |||||
| @ -0,0 +1,18 @@ | |||||
| This is the file .../info/dir, which contains the | |||||
| topmost node of the Info hierarchy, called (dir)Top. | |||||
| The first time you invoke Info you start off looking at this node. | |||||
| File: dir, Node: Top This is the top of the INFO tree | |||||
| This (the Directory node) gives a menu of major topics. | |||||
| Typing "q" exits, "?" lists all Info commands, "d" returns here, | |||||
| "h" gives a primer for first-timers, | |||||
| "mEmacs<Return>" visits the Emacs manual, etc. | |||||
| In Emacs, you can click mouse button 2 on a menu item or cross reference | |||||
| to select it. | |||||
| * Menu: | |||||
| Emacs | |||||
| * Flycheck: (flycheck). Modern on-the-fly syntax checking | |||||
| @ -0,0 +1,484 @@ | |||||
| This is fdl-1.3.info, produced by makeinfo version 5.2 from | |||||
| fdl-1.3.texi. | |||||
| Version 1.3, 3 November 2008 | |||||
| Copyright (C) 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc. | |||||
| <http://fsf.org/> | |||||
| Everyone is permitted to copy and distribute verbatim copies | |||||
| of this license document, but changing it is not allowed. | |||||
| 0. PREAMBLE | |||||
| The purpose of this License is to make a manual, textbook, or other | |||||
| functional and useful document "free" in the sense of freedom: to | |||||
| assure everyone the effective freedom to copy and redistribute it, | |||||
| with or without modifying it, either commercially or | |||||
| noncommercially. Secondarily, this License preserves for the | |||||
| author and publisher a way to get credit for their work, while not | |||||
| being considered responsible for modifications made by others. | |||||
| This License is a kind of "copyleft", which means that derivative | |||||
| works of the document must themselves be free in the same sense. | |||||
| It complements the GNU General Public License, which is a copyleft | |||||
| license designed for free software. | |||||
| We have designed this License in order to use it for manuals for | |||||
| free software, because free software needs free documentation: a | |||||
| free program should come with manuals providing the same freedoms | |||||
| that the software does. But this License is not limited to | |||||
| software manuals; it can be used for any textual work, regardless | |||||
| of subject matter or whether it is published as a printed book. We | |||||
| recommend this License principally for works whose purpose is | |||||
| instruction or reference. | |||||
| 1. APPLICABILITY AND DEFINITIONS | |||||
| This License applies to any manual or other work, in any medium, | |||||
| that contains a notice placed by the copyright holder saying it can | |||||
| be distributed under the terms of this License. Such a notice | |||||
| grants a world-wide, royalty-free license, unlimited in duration, | |||||
| to use that work under the conditions stated herein. The | |||||
| "Document", below, refers to any such manual or work. Any member | |||||
| of the public is a licensee, and is addressed as "you". You accept | |||||
| the license if you copy, modify or distribute the work in a way | |||||
| requiring permission under copyright law. | |||||
| A "Modified Version" of the Document means any work containing the | |||||
| Document or a portion of it, either copied verbatim, or with | |||||
| modifications and/or translated into another language. | |||||
| A "Secondary Section" is a named appendix or a front-matter section | |||||
| of the Document that deals exclusively with the relationship of the | |||||
| publishers or authors of the Document to the Document's overall | |||||
| subject (or to related matters) and contains nothing that could | |||||
| fall directly within that overall subject. (Thus, if the Document | |||||
| is in part a textbook of mathematics, a Secondary Section may not | |||||
| explain any mathematics.) The relationship could be a matter of | |||||
| historical connection with the subject or with related matters, or | |||||
| of legal, commercial, philosophical, ethical or political position | |||||
| regarding them. | |||||
| The "Invariant Sections" are certain Secondary Sections whose | |||||
| titles are designated, as being those of Invariant Sections, in the | |||||
| notice that says that the Document is released under this License. | |||||
| If a section does not fit the above definition of Secondary then it | |||||
| is not allowed to be designated as Invariant. The Document may | |||||
| contain zero Invariant Sections. If the Document does not identify | |||||
| any Invariant Sections then there are none. | |||||
| The "Cover Texts" are certain short passages of text that are | |||||
| listed, as Front-Cover Texts or Back-Cover Texts, in the notice | |||||
| that says that the Document is released under this License. A | |||||
| Front-Cover Text may be at most 5 words, and a Back-Cover Text may | |||||
| be at most 25 words. | |||||
| A "Transparent" copy of the Document means a machine-readable copy, | |||||
| represented in a format whose specification is available to the | |||||
| general public, that is suitable for revising the document | |||||
| straightforwardly with generic text editors or (for images composed | |||||
| of pixels) generic paint programs or (for drawings) some widely | |||||
| available drawing editor, and that is suitable for input to text | |||||
| formatters or for automatic translation to a variety of formats | |||||
| suitable for input to text formatters. A copy made in an otherwise | |||||
| Transparent file format whose markup, or absence of markup, has | |||||
| been arranged to thwart or discourage subsequent modification by | |||||
| readers is not Transparent. An image format is not Transparent if | |||||
| used for any substantial amount of text. A copy that is not | |||||
| "Transparent" is called "Opaque". | |||||
| Examples of suitable formats for Transparent copies include plain | |||||
| ASCII without markup, Texinfo input format, LaTeX input format, | |||||
| SGML or XML using a publicly available DTD, and standard-conforming | |||||
| simple HTML, PostScript or PDF designed for human modification. | |||||
| Examples of transparent image formats include PNG, XCF and JPG. | |||||
| Opaque formats include proprietary formats that can be read and | |||||
| edited only by proprietary word processors, SGML or XML for which | |||||
| the DTD and/or processing tools are not generally available, and | |||||
| the machine-generated HTML, PostScript or PDF produced by some word | |||||
| processors for output purposes only. | |||||
| The "Title Page" means, for a printed book, the title page itself, | |||||
| plus such following pages as are needed to hold, legibly, the | |||||
| material this License requires to appear in the title page. For | |||||
| works in formats which do not have any title page as such, "Title | |||||
| Page" means the text near the most prominent appearance of the | |||||
| work's title, preceding the beginning of the body of the text. | |||||
| The "publisher" means any person or entity that distributes copies | |||||
| of the Document to the public. | |||||
| A section "Entitled XYZ" means a named subunit of the Document | |||||
| whose title either is precisely XYZ or contains XYZ in parentheses | |||||
| following text that translates XYZ in another language. (Here XYZ | |||||
| stands for a specific section name mentioned below, such as | |||||
| "Acknowledgements", "Dedications", "Endorsements", or "History".) | |||||
| To "Preserve the Title" of such a section when you modify the | |||||
| Document means that it remains a section "Entitled XYZ" according | |||||
| to this definition. | |||||
| The Document may include Warranty Disclaimers next to the notice | |||||
| which states that this License applies to the Document. These | |||||
| Warranty Disclaimers are considered to be included by reference in | |||||
| this License, but only as regards disclaiming warranties: any other | |||||
| implication that these Warranty Disclaimers may have is void and | |||||
| has no effect on the meaning of this License. | |||||
| 2. VERBATIM COPYING | |||||
| You may copy and distribute the Document in any medium, either | |||||
| commercially or noncommercially, provided that this License, the | |||||
| copyright notices, and the license notice saying this License | |||||
| applies to the Document are reproduced in all copies, and that you | |||||
| add no other conditions whatsoever to those of this License. You | |||||
| may not use technical measures to obstruct or control the reading | |||||
| or further copying of the copies you make or distribute. However, | |||||
| you may accept compensation in exchange for copies. If you | |||||
| distribute a large enough number of copies you must also follow the | |||||
| conditions in section 3. | |||||
| You may also lend copies, under the same conditions stated above, | |||||
| and you may publicly display copies. | |||||
| 3. COPYING IN QUANTITY | |||||
| If you publish printed copies (or copies in media that commonly | |||||
| have printed covers) of the Document, numbering more than 100, and | |||||
| the Document's license notice requires Cover Texts, you must | |||||
| enclose the copies in covers that carry, clearly and legibly, all | |||||
| these Cover Texts: Front-Cover Texts on the front cover, and | |||||
| Back-Cover Texts on the back cover. Both covers must also clearly | |||||
| and legibly identify you as the publisher of these copies. The | |||||
| front cover must present the full title with all words of the title | |||||
| equally prominent and visible. You may add other material on the | |||||
| covers in addition. Copying with changes limited to the covers, as | |||||
| long as they preserve the title of the Document and satisfy these | |||||
| conditions, can be treated as verbatim copying in other respects. | |||||
| If the required texts for either cover are too voluminous to fit | |||||
| legibly, you should put the first ones listed (as many as fit | |||||
| reasonably) on the actual cover, and continue the rest onto | |||||
| adjacent pages. | |||||
| If you publish or distribute Opaque copies of the Document | |||||
| numbering more than 100, you must either include a machine-readable | |||||
| Transparent copy along with each Opaque copy, or state in or with | |||||
| each Opaque copy a computer-network location from which the general | |||||
| network-using public has access to download using public-standard | |||||
| network protocols a complete Transparent copy of the Document, free | |||||
| of added material. If you use the latter option, you must take | |||||
| reasonably prudent steps, when you begin distribution of Opaque | |||||
| copies in quantity, to ensure that this Transparent copy will | |||||
| remain thus accessible at the stated location until at least one | |||||
| year after the last time you distribute an Opaque copy (directly or | |||||
| through your agents or retailers) of that edition to the public. | |||||
| It is requested, but not required, that you contact the authors of | |||||
| the Document well before redistributing any large number of copies, | |||||
| to give them a chance to provide you with an updated version of the | |||||
| Document. | |||||
| 4. MODIFICATIONS | |||||
| You may copy and distribute a Modified Version of the Document | |||||
| under the conditions of sections 2 and 3 above, provided that you | |||||
| release the Modified Version under precisely this License, with the | |||||
| Modified Version filling the role of the Document, thus licensing | |||||
| distribution and modification of the Modified Version to whoever | |||||
| possesses a copy of it. In addition, you must do these things in | |||||
| the Modified Version: | |||||
| A. Use in the Title Page (and on the covers, if any) a title | |||||
| distinct from that of the Document, and from those of previous | |||||
| versions (which should, if there were any, be listed in the | |||||
| History section of the Document). You may use the same title | |||||
| as a previous version if the original publisher of that | |||||
| version gives permission. | |||||
| B. List on the Title Page, as authors, one or more persons or | |||||
| entities responsible for authorship of the modifications in | |||||
| the Modified Version, together with at least five of the | |||||
| principal authors of the Document (all of its principal | |||||
| authors, if it has fewer than five), unless they release you | |||||
| from this requirement. | |||||
| C. State on the Title page the name of the publisher of the | |||||
| Modified Version, as the publisher. | |||||
| D. Preserve all the copyright notices of the Document. | |||||
| E. Add an appropriate copyright notice for your modifications | |||||
| adjacent to the other copyright notices. | |||||
| F. Include, immediately after the copyright notices, a license | |||||
| notice giving the public permission to use the Modified | |||||
| Version under the terms of this License, in the form shown in | |||||
| the Addendum below. | |||||
| G. Preserve in that license notice the full lists of Invariant | |||||
| Sections and required Cover Texts given in the Document's | |||||
| license notice. | |||||
| H. Include an unaltered copy of this License. | |||||
| I. Preserve the section Entitled "History", Preserve its Title, | |||||
| and add to it an item stating at least the title, year, new | |||||
| authors, and publisher of the Modified Version as given on the | |||||
| Title Page. If there is no section Entitled "History" in the | |||||
| Document, create one stating the title, year, authors, and | |||||
| publisher of the Document as given on its Title Page, then add | |||||
| an item describing the Modified Version as stated in the | |||||
| previous sentence. | |||||
| J. Preserve the network location, if any, given in the Document | |||||
| for public access to a Transparent copy of the Document, and | |||||
| likewise the network locations given in the Document for | |||||
| previous versions it was based on. These may be placed in the | |||||
| "History" section. You may omit a network location for a work | |||||
| that was published at least four years before the Document | |||||
| itself, or if the original publisher of the version it refers | |||||
| to gives permission. | |||||
| K. For any section Entitled "Acknowledgements" or "Dedications", | |||||
| Preserve the Title of the section, and preserve in the section | |||||
| all the substance and tone of each of the contributor | |||||
| acknowledgements and/or dedications given therein. | |||||
| L. Preserve all the Invariant Sections of the Document, unaltered | |||||
| in their text and in their titles. Section numbers or the | |||||
| equivalent are not considered part of the section titles. | |||||
| M. Delete any section Entitled "Endorsements". Such a section | |||||
| may not be included in the Modified Version. | |||||
| N. Do not retitle any existing section to be Entitled | |||||
| "Endorsements" or to conflict in title with any Invariant | |||||
| Section. | |||||
| O. Preserve any Warranty Disclaimers. | |||||
| If the Modified Version includes new front-matter sections or | |||||
| appendices that qualify as Secondary Sections and contain no | |||||
| material copied from the Document, you may at your option designate | |||||
| some or all of these sections as invariant. To do this, add their | |||||
| titles to the list of Invariant Sections in the Modified Version's | |||||
| license notice. These titles must be distinct from any other | |||||
| section titles. | |||||
| You may add a section Entitled "Endorsements", provided it contains | |||||
| nothing but endorsements of your Modified Version by various | |||||
| parties--for example, statements of peer review or that the text | |||||
| has been approved by an organization as the authoritative | |||||
| definition of a standard. | |||||
| You may add a passage of up to five words as a Front-Cover Text, | |||||
| and a passage of up to 25 words as a Back-Cover Text, to the end of | |||||
| the list of Cover Texts in the Modified Version. Only one passage | |||||
| of Front-Cover Text and one of Back-Cover Text may be added by (or | |||||
| through arrangements made by) any one entity. If the Document | |||||
| already includes a cover text for the same cover, previously added | |||||
| by you or by arrangement made by the same entity you are acting on | |||||
| behalf of, you may not add another; but you may replace the old | |||||
| one, on explicit permission from the previous publisher that added | |||||
| the old one. | |||||
| The author(s) and publisher(s) of the Document do not by this | |||||
| License give permission to use their names for publicity for or to | |||||
| assert or imply endorsement of any Modified Version. | |||||
| 5. COMBINING DOCUMENTS | |||||
| You may combine the Document with other documents released under | |||||
| this License, under the terms defined in section 4 above for | |||||
| modified versions, provided that you include in the combination all | |||||
| of the Invariant Sections of all of the original documents, | |||||
| unmodified, and list them all as Invariant Sections of your | |||||
| combined work in its license notice, and that you preserve all | |||||
| their Warranty Disclaimers. | |||||
| The combined work need only contain one copy of this License, and | |||||
| multiple identical Invariant Sections may be replaced with a single | |||||
| copy. If there are multiple Invariant Sections with the same name | |||||
| but different contents, make the title of each such section unique | |||||
| by adding at the end of it, in parentheses, the name of the | |||||
| original author or publisher of that section if known, or else a | |||||
| unique number. Make the same adjustment to the section titles in | |||||
| the list of Invariant Sections in the license notice of the | |||||
| combined work. | |||||
| In the combination, you must combine any sections Entitled | |||||
| "History" in the various original documents, forming one section | |||||
| Entitled "History"; likewise combine any sections Entitled | |||||
| "Acknowledgements", and any sections Entitled "Dedications". You | |||||
| must delete all sections Entitled "Endorsements." | |||||
| 6. COLLECTIONS OF DOCUMENTS | |||||
| You may make a collection consisting of the Document and other | |||||
| documents released under this License, and replace the individual | |||||
| copies of this License in the various documents with a single copy | |||||
| that is included in the collection, provided that you follow the | |||||
| rules of this License for verbatim copying of each of the documents | |||||
| in all other respects. | |||||
| You may extract a single document from such a collection, and | |||||
| distribute it individually under this License, provided you insert | |||||
| a copy of this License into the extracted document, and follow this | |||||
| License in all other respects regarding verbatim copying of that | |||||
| document. | |||||
| 7. AGGREGATION WITH INDEPENDENT WORKS | |||||
| A compilation of the Document or its derivatives with other | |||||
| separate and independent documents or works, in or on a volume of a | |||||
| storage or distribution medium, is called an "aggregate" if the | |||||
| copyright resulting from the compilation is not used to limit the | |||||
| legal rights of the compilation's users beyond what the individual | |||||
| works permit. When the Document is included in an aggregate, this | |||||
| License does not apply to the other works in the aggregate which | |||||
| are not themselves derivative works of the Document. | |||||
| If the Cover Text requirement of section 3 is applicable to these | |||||
| copies of the Document, then if the Document is less than one half | |||||
| of the entire aggregate, the Document's Cover Texts may be placed | |||||
| on covers that bracket the Document within the aggregate, or the | |||||
| electronic equivalent of covers if the Document is in electronic | |||||
| form. Otherwise they must appear on printed covers that bracket | |||||
| the whole aggregate. | |||||
| 8. TRANSLATION | |||||
| Translation is considered a kind of modification, so you may | |||||
| distribute translations of the Document under the terms of section | |||||
| 4. Replacing Invariant Sections with translations requires special | |||||
| permission from their copyright holders, but you may include | |||||
| translations of some or all Invariant Sections in addition to the | |||||
| original versions of these Invariant Sections. You may include a | |||||
| translation of this License, and all the license notices in the | |||||
| Document, and any Warranty Disclaimers, provided that you also | |||||
| include the original English version of this License and the | |||||
| original versions of those notices and disclaimers. In case of a | |||||
| disagreement between the translation and the original version of | |||||
| this License or a notice or disclaimer, the original version will | |||||
| prevail. | |||||
| If a section in the Document is Entitled "Acknowledgements", | |||||
| "Dedications", or "History", the requirement (section 4) to | |||||
| Preserve its Title (section 1) will typically require changing the | |||||
| actual title. | |||||
| 9. TERMINATION | |||||
| You may not copy, modify, sublicense, or distribute the Document | |||||
| except as expressly provided under this License. Any attempt | |||||
| otherwise to copy, modify, sublicense, or distribute it is void, | |||||
| and will automatically terminate your rights under this License. | |||||
| However, if you cease all violation of this License, then your | |||||
| license from a particular copyright holder is reinstated (a) | |||||
| provisionally, unless and until the copyright holder explicitly and | |||||
| finally terminates your license, and (b) permanently, if the | |||||
| copyright holder fails to notify you of the violation by some | |||||
| reasonable means prior to 60 days after the cessation. | |||||
| Moreover, your license from a particular copyright holder is | |||||
| reinstated permanently if the copyright holder notifies you of the | |||||
| violation by some reasonable means, this is the first time you have | |||||
| received notice of violation of this License (for any work) from | |||||
| that copyright holder, and you cure the violation prior to 30 days | |||||
| after your receipt of the notice. | |||||
| Termination of your rights under this section does not terminate | |||||
| the licenses of parties who have received copies or rights from you | |||||
| under this License. If your rights have been terminated and not | |||||
| permanently reinstated, receipt of a copy of some or all of the | |||||
| same material does not give you any rights to use it. | |||||
| 10. FUTURE REVISIONS OF THIS LICENSE | |||||
| The Free Software Foundation may publish new, revised versions of | |||||
| the GNU Free Documentation License from time to time. Such new | |||||
| versions will be similar in spirit to the present version, but may | |||||
| differ in detail to address new problems or concerns. See | |||||
| <http://www.gnu.org/copyleft/>. | |||||
| Each version of the License is given a distinguishing version | |||||
| number. If the Document specifies that a particular numbered | |||||
| version of this License "or any later version" applies to it, you | |||||
| have the option of following the terms and conditions either of | |||||
| that specified version or of any later version that has been | |||||
| published (not as a draft) by the Free Software Foundation. If the | |||||
| Document does not specify a version number of this License, you may | |||||
| choose any version ever published (not as a draft) by the Free | |||||
| Software Foundation. If the Document specifies that a proxy can | |||||
| decide which future versions of this License can be used, that | |||||
| proxy's public statement of acceptance of a version permanently | |||||
| authorizes you to choose that version for the Document. | |||||
| 11. RELICENSING | |||||
| "Massive Multiauthor Collaboration Site" (or "MMC Site") means any | |||||
| World Wide Web server that publishes copyrightable works and also | |||||
| provides prominent facilities for anybody to edit those works. A | |||||
| public wiki that anybody can edit is an example of such a server. | |||||
| A "Massive Multiauthor Collaboration" (or "MMC") contained in the | |||||
| site means any set of copyrightable works thus published on the MMC | |||||
| site. | |||||
| "CC-BY-SA" means the Creative Commons Attribution-Share Alike 3.0 | |||||
| license published by Creative Commons Corporation, a not-for-profit | |||||
| corporation with a principal place of business in San Francisco, | |||||
| California, as well as future copyleft versions of that license | |||||
| published by that same organization. | |||||
| "Incorporate" means to publish or republish a Document, in whole or | |||||
| in part, as part of another Document. | |||||
| An MMC is "eligible for relicensing" if it is licensed under this | |||||
| License, and if all works that were first published under this | |||||
| License somewhere other than this MMC, and subsequently | |||||
| incorporated in whole or in part into the MMC, (1) had no cover | |||||
| texts or invariant sections, and (2) were thus incorporated prior | |||||
| to November 1, 2008. | |||||
| The operator of an MMC Site may republish an MMC contained in the | |||||
| site under CC-BY-SA on the same site at any time before August 1, | |||||
| 2009, provided the MMC is eligible for relicensing. | |||||
| ADDENDUM: How to use this License for your documents | |||||
| ==================================================== | |||||
| To use this License in a document you have written, include a copy of | |||||
| the License in the document and put the following copyright and license | |||||
| notices just after the title page: | |||||
| Copyright (C) YEAR YOUR NAME. | |||||
| Permission is granted to copy, distribute and/or modify this document | |||||
| under the terms of the GNU Free Documentation License, Version 1.3 | |||||
| or any later version published by the Free Software Foundation; | |||||
| with no Invariant Sections, no Front-Cover Texts, and no Back-Cover | |||||
| Texts. A copy of the license is included in the section entitled ``GNU | |||||
| Free Documentation License''. | |||||
| If you have Invariant Sections, Front-Cover Texts and Back-Cover | |||||
| Texts, replace the "with...Texts." line with this: | |||||
| with the Invariant Sections being LIST THEIR TITLES, with | |||||
| the Front-Cover Texts being LIST, and with the Back-Cover Texts | |||||
| being LIST. | |||||
| If you have Invariant Sections without Cover Texts, or some other | |||||
| combination of the three, merge those two alternatives to suit the | |||||
| situation. | |||||
| If your document contains nontrivial examples of program code, we | |||||
| recommend releasing these examples in parallel under your choice of free | |||||
| software license, such as the GNU General Public License, to permit | |||||
| their use in free software. | |||||
| Tag Table: | |||||
| End Tag Table | |||||
| @ -0,0 +1,238 @@ | |||||
| ;;; flycheck-autoloads.el --- automatically extracted autoloads | |||||
| ;; | |||||
| ;;; Code: | |||||
| (add-to-list 'load-path (or (file-name-directory #$) (car load-path))) | |||||
| ;;;### (autoloads nil "flycheck" "flycheck.el" (22223 32728 0 0)) | |||||
| ;;; Generated autoloads from flycheck.el | |||||
| (autoload 'flycheck-info "flycheck" "\ | |||||
| Open the Flycheck manual. | |||||
| \(fn)" t nil) | |||||
| (autoload 'flycheck-mode "flycheck" "\ | |||||
| Minor mode for on-the-fly syntax checking. | |||||
| When called interactively, toggle `flycheck-mode'. With prefix | |||||
| ARG, enable `flycheck-mode' if ARG is positive, otherwise disable | |||||
| it. | |||||
| When called from Lisp, enable `flycheck-mode' if ARG is omitted, | |||||
| nil or positive. If ARG is `toggle', toggle `flycheck-mode'. | |||||
| Otherwise behave as if called interactively. | |||||
| In `flycheck-mode' the buffer is automatically syntax-checked | |||||
| using the first suitable syntax checker from `flycheck-checkers'. | |||||
| Use `flycheck-select-checker' to select a checker for the current | |||||
| buffer manually. | |||||
| \\{flycheck-mode-map} | |||||
| \(fn &optional ARG)" t nil) | |||||
| (defvar global-flycheck-mode nil "\ | |||||
| Non-nil if Global-Flycheck mode is enabled. | |||||
| See the command `global-flycheck-mode' for a description of this minor mode. | |||||
| Setting this variable directly does not take effect; | |||||
| either customize it (see the info node `Easy Customization') | |||||
| or call the function `global-flycheck-mode'.") | |||||
| (custom-autoload 'global-flycheck-mode "flycheck" nil) | |||||
| (autoload 'global-flycheck-mode "flycheck" "\ | |||||
| Toggle Flycheck mode in all buffers. | |||||
| With prefix ARG, enable Global-Flycheck mode if ARG is positive; | |||||
| otherwise, disable it. If called from Lisp, enable the mode if | |||||
| ARG is omitted or nil. | |||||
| Flycheck mode is enabled in all buffers where | |||||
| `flycheck-mode-on-safe' would do it. | |||||
| See `flycheck-mode' for more information on Flycheck mode. | |||||
| \(fn &optional ARG)" t nil) | |||||
| (autoload 'flycheck-define-error-level "flycheck" "\ | |||||
| Define a new error LEVEL with PROPERTIES. | |||||
| The following PROPERTIES constitute an error level: | |||||
| `:severity SEVERITY' | |||||
| A number denoting the severity of this level. The higher | |||||
| the number, the more severe is this level compared to other | |||||
| levels. Defaults to 0. | |||||
| The severity is used by `flycheck-error-level-<' to | |||||
| determine the ordering of errors according to their levels. | |||||
| `:compilation-level LEVEL' | |||||
| A number indicating the broad class of messages that errors | |||||
| at this level belong to: one of 0 (info), 1 (warning), or | |||||
| 2 or nil (error). Defaults to nil. | |||||
| This is used by `flycheck-checker-pattern-to-error-regexp' | |||||
| to map error levels into `compilation-mode''s hierarchy and | |||||
| to get proper highlighting of errors in `compilation-mode'. | |||||
| `:overlay-category CATEGORY' | |||||
| A symbol denoting the overlay category to use for error | |||||
| highlight overlays for this level. See Info | |||||
| node `(elisp)Overlay Properties' for more information about | |||||
| overlay categories. | |||||
| A category for an error level overlay should at least define | |||||
| the `face' property, for error highlighting. Another useful | |||||
| property for error level categories is `priority', to | |||||
| influence the stacking of multiple error level overlays. | |||||
| `:fringe-bitmap BITMAP' | |||||
| A fringe bitmap symbol denoting the bitmap to use for fringe | |||||
| indicators for this level. See Info node `(elisp)Fringe | |||||
| Bitmaps' for more information about fringe bitmaps, | |||||
| including a list of built-in fringe bitmaps. | |||||
| `:fringe-face FACE' | |||||
| A face symbol denoting the face to use for fringe indicators | |||||
| for this level. | |||||
| `:error-list-face FACE' | |||||
| A face symbol denoting the face to use for messages of this | |||||
| level in the error list. See `flycheck-list-errors'. | |||||
| \(fn LEVEL &rest PROPERTIES)" nil nil) | |||||
| (put 'flycheck-define-error-level 'lisp-indent-function '1) | |||||
| (autoload 'flycheck-define-command-checker "flycheck" "\ | |||||
| Define SYMBOL as syntax checker to run a command. | |||||
| Define SYMBOL as generic syntax checker via | |||||
| `flycheck-define-generic-checker', which uses an external command | |||||
| to check the buffer. SYMBOL and DOCSTRING are the same as for | |||||
| `flycheck-define-generic-checker'. | |||||
| In addition to the properties understood by | |||||
| `flycheck-define-generic-checker', the following PROPERTIES | |||||
| constitute a command syntax checker. Unless otherwise noted, all | |||||
| properties are mandatory. Note that the default `:error-filter' | |||||
| of command checkers is `flycheck-sanitize-errors'. | |||||
| `:command COMMAND' | |||||
| The command to run for syntax checking. | |||||
| COMMAND is a list of the form `(EXECUTABLE [ARG ...])'. | |||||
| EXECUTABLE is a string with the executable of this syntax | |||||
| checker. It can be overridden with the variable | |||||
| `flycheck-SYMBOL-executable'. Note that this variable is | |||||
| NOT implicitly defined by this function. Use | |||||
| `flycheck-def-executable-var' to define this variable. | |||||
| Each ARG is an argument to the executable, either as string, | |||||
| or as special symbol or form for | |||||
| `flycheck-substitute-argument', which see. | |||||
| `:error-patterns PATTERNS' | |||||
| A list of patterns to parse the output of the `:command'. | |||||
| Each ITEM in PATTERNS is a list `(LEVEL SEXP ...)', where | |||||
| LEVEL is a Flycheck error level (see | |||||
| `flycheck-define-error-level'), followed by one or more RX | |||||
| `SEXP's which parse an error of that level and extract line, | |||||
| column, file name and the message. | |||||
| See `rx' for general information about RX, and | |||||
| `flycheck-rx-to-string' for some special RX forms provided | |||||
| by Flycheck. | |||||
| All patterns are applied in the order of declaration to the | |||||
| whole output of the syntax checker. Output already matched | |||||
| by a pattern will not be matched by subsequent patterns. In | |||||
| other words, the first pattern wins. | |||||
| This property is optional. If omitted, however, an | |||||
| `:error-parser' is mandatory. | |||||
| `:error-parser FUNCTION' | |||||
| A function to parse errors with. | |||||
| The function shall accept three arguments OUTPUT CHECKER | |||||
| BUFFER. OUTPUT is the syntax checker output as string, | |||||
| CHECKER the syntax checker that was used, and BUFFER a | |||||
| buffer object representing the checked buffer. The function | |||||
| must return a list of `flycheck-error' objects parsed from | |||||
| OUTPUT. | |||||
| This property is optional. If omitted, it defaults to | |||||
| `flycheck-parse-with-patterns'. In this case, | |||||
| `:error-patterns' is mandatory. | |||||
| `:standard-input t' | |||||
| Whether to send the buffer contents on standard input. | |||||
| If this property is given and has a non-nil value, send the | |||||
| contents of the buffer on standard input. | |||||
| Defaults to nil. | |||||
| Note that you may not give `:start', `:interrupt', and | |||||
| `:print-doc' for a command checker. You can give a custom | |||||
| `:verify' function, though, whose results will be appended to the | |||||
| default `:verify' function of command checkers. | |||||
| \(fn SYMBOL DOCSTRING &rest PROPERTIES)" nil nil) | |||||
| (put 'flycheck-define-command-checker 'lisp-indent-function '1) | |||||
| (put 'flycheck-define-command-checker 'doc-string-elt '2) | |||||
| (autoload 'flycheck-def-config-file-var "flycheck" "\ | |||||
| Define SYMBOL as config file variable for CHECKER, with default FILE-NAME. | |||||
| SYMBOL is declared as customizable variable using `defcustom', to | |||||
| provide a configuration file for the given syntax CHECKER. | |||||
| CUSTOM-ARGS are forwarded to `defcustom'. | |||||
| FILE-NAME is the initial value of the new variable. If omitted, | |||||
| the default value is nil. | |||||
| Use this together with the `config-file' form in the `:command' | |||||
| argument to `flycheck-define-checker'. | |||||
| \(fn SYMBOL CHECKER &optional FILE-NAME &rest CUSTOM-ARGS)" nil t) | |||||
| (put 'flycheck-def-config-file-var 'lisp-indent-function '3) | |||||
| (autoload 'flycheck-def-option-var "flycheck" "\ | |||||
| Define SYMBOL as option variable with INIT-VALUE for CHECKER. | |||||
| SYMBOL is declared as customizable variable using `defcustom', to | |||||
| provide an option for the given syntax CHECKERS (a checker or a | |||||
| list of checkers). INIT-VALUE is the initial value of the | |||||
| variable, and DOCSTRING is its docstring. CUSTOM-ARGS are | |||||
| forwarded to `defcustom'. | |||||
| Use this together with the `option', `option-list' and | |||||
| `option-flag' forms in the `:command' argument to | |||||
| `flycheck-define-checker'. | |||||
| \(fn SYMBOL INIT-VALUE CHECKERS DOCSTRING &rest CUSTOM-ARGS)" nil t) | |||||
| (put 'flycheck-def-option-var 'lisp-indent-function '3) | |||||
| (put 'flycheck-def-option-var 'doc-string-elt '4) | |||||
| ;;;*** | |||||
| ;;;### (autoloads nil nil ("flycheck-buttercup.el" "flycheck-ert.el" | |||||
| ;;;;;; "flycheck-pkg.el") (22223 32728 642676 0)) | |||||
| ;;;*** | |||||
| ;; Local Variables: | |||||
| ;; version-control: never | |||||
| ;; no-byte-compile: t | |||||
| ;; no-update-autoloads: t | |||||
| ;; End: | |||||
| ;;; flycheck-autoloads.el ends here | |||||
| @ -0,0 +1,99 @@ | |||||
| ;;; flycheck-buttercup.el --- Flycheck: Extensions to Buttercup -*- lexical-binding: t; -*- | |||||
| ;; Copyright (C) 2016 Sebastian Wiesner and Flycheck contributors | |||||
| ;; Author: Sebastian Wiesner <swiesner@lunaryorn.com> | |||||
| ;; Keywords: lisp, tools | |||||
| ;; This file is not part of GNU Emacs. | |||||
| ;; 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: | |||||
| ;; Extensions to Buttercup to write BDD tests for Flycheck. | |||||
| ;; | |||||
| ;; Buttercup is a BDD testing framework for Emacs, see URL | |||||
| ;; `https://github.com/jorgenschaefer/emacs-buttercup/'. Flycheck uses | |||||
| ;; Buttercup extensively for new tests. | |||||
| ;; | |||||
| ;; This library provides extensions to Buttercup to write Specs for Flycheck. | |||||
| ;; | |||||
| ;; * Custom matchers | |||||
| ;; | |||||
| ;; (expect 'foo :to-be-local) - Is `foo' a local variable in the current buffer? | |||||
| ;;; Code: | |||||
| (require 'buttercup) | |||||
| (require 'flycheck) | |||||
| (require 'seq) | |||||
| ;;; Buttercup helpers | |||||
| (defun flycheck-buttercup-format-error-list (errors) | |||||
| "Format ERRORS into a human-readable string." | |||||
| (mapconcat (lambda (e) (flycheck-error-format e 'with-file-name)) | |||||
| errors "\n")) | |||||
| ;;; Data matchers | |||||
| (buttercup-define-matcher :to-be-empty-string (s) | |||||
| (if (equal s "") | |||||
| (cons t (format "Expected %S not be an empty string" s)) | |||||
| (cons nil (format "Expected %S to be an empty string" s)))) | |||||
| (buttercup-define-matcher :to-match-with-group (re s index match) | |||||
| (let* ((matches? (string-match re s)) | |||||
| (result (and matches? (match-string index s)))) | |||||
| (if (and matches? (equal result match)) | |||||
| (cons t (format "Expected %S not to match %S with %S in group %s" | |||||
| re s match index)) | |||||
| (cons nil (format "Expected %S to match %S with %S in group %s, %s" | |||||
| re s match index | |||||
| (if matches? | |||||
| (format "but got %S" result) | |||||
| "but did not match")))))) | |||||
| ;;; Emacs feature matchers | |||||
| (buttercup-define-matcher :to-be-local (symbol) | |||||
| (if (local-variable-p symbol) | |||||
| (cons t (format "Expected %S not to be a local variable, but it is" | |||||
| symbol)) | |||||
| (cons nil (format "Expected %S to be a local variable, but it is not" | |||||
| symbol)))) | |||||
| ;;; Flycheck matchers | |||||
| (buttercup-define-matcher :to-be-equal-flycheck-errors (a b) | |||||
| (let ((a-formatted (flycheck-buttercup-format-error-list a)) | |||||
| (b-formatted (flycheck-buttercup-format-error-list b))) | |||||
| (if (equal a b) | |||||
| (cons t (format "Expected | |||||
| %s | |||||
| not to be equal to | |||||
| %s" a-formatted b-formatted)) | |||||
| (cons nil (format "Expected | |||||
| %s | |||||
| to be equal to | |||||
| %s" a-formatted b-formatted))))) | |||||
| (provide 'flycheck-buttercup) | |||||
| ;;; flycheck-buttercup.el ends here | |||||
| @ -0,0 +1,432 @@ | |||||
| ;;; flycheck-ert.el --- Flycheck: ERT extensions -*- lexical-binding: t; -*- | |||||
| ;; Copyright (C) 2013-2016 Sebastian Wiesner and Flycheck contributors | |||||
| ;; Author: Sebastian Wiesner <swiesner@lunaryorn.com> | |||||
| ;; Maintainer: Sebastian Wiesner <swiesner@lunaryorn.com> | |||||
| ;; URL: https://github.com/flycheck/flycheck | |||||
| ;; This file is not part of GNU Emacs. | |||||
| ;; 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: | |||||
| ;; Unit testing library for Flycheck, the modern on-the-fly syntax checking | |||||
| ;; extension for GNU Emacs. | |||||
| ;; Provide various utility functions and unit test helpers to test Flycheck and | |||||
| ;; Flycheck extensions. | |||||
| ;;; Code: | |||||
| (require 'flycheck) | |||||
| (require 'ert) | |||||
| (require 'macroexp) ; For macro utilities | |||||
| ;;; Compatibility | |||||
| (eval-and-compile | |||||
| ;; Provide `ert-skip' and friends for Emacs 24.3 | |||||
| (defconst flycheck-ert-ert-can-skip (fboundp 'ert-skip) | |||||
| "Whether ERT supports test skipping.") | |||||
| (unless flycheck-ert-ert-can-skip | |||||
| ;; Fake skipping | |||||
| (setf (get 'flycheck-ert-skipped 'error-message) "Test skipped") | |||||
| (setf (get 'flycheck-ert-skipped 'error-conditions) '(error)) | |||||
| (defun ert-skip (data) | |||||
| (signal 'flycheck-ert-skipped data)) | |||||
| (defmacro skip-unless (form) | |||||
| `(unless (ignore-errors ,form) | |||||
| (signal 'flycheck-ert-skipped ',form))) | |||||
| (defun ert-test-skipped-p (result) | |||||
| (and (ert-test-failed-p result) | |||||
| (eq (car (ert-test-failed-condition result)) | |||||
| 'flycheck-ert-skipped))))) | |||||
| ;;; Internal variables | |||||
| (defvar flycheck-ert--resource-directory nil | |||||
| "The directory to get resources from in this test suite.") | |||||
| ;;; Resource management macros | |||||
| (defmacro flycheck-ert-with-temp-buffer (&rest body) | |||||
| "Eval BODY within a temporary buffer. | |||||
| Like `with-temp-buffer', but resets the modification state of the | |||||
| temporary buffer to make sure that it is properly killed even if | |||||
| it has a backing file and is modified." | |||||
| (declare (indent 0)) | |||||
| `(with-temp-buffer | |||||
| (unwind-protect | |||||
| ,(macroexp-progn body) | |||||
| ;; Reset modification state of the buffer, and unlink it from its backing | |||||
| ;; file, if any, because Emacs refuses to kill modified buffers with | |||||
| ;; backing files, even if they are temporary. | |||||
| (set-buffer-modified-p nil) | |||||
| (set-visited-file-name nil 'no-query)))) | |||||
| (defmacro flycheck-ert-with-file-buffer (file-name &rest body) | |||||
| "Create a buffer from FILE-NAME and eval BODY. | |||||
| BODY is evaluated with `current-buffer' being a buffer with the | |||||
| contents FILE-NAME." | |||||
| (declare (indent 1)) | |||||
| `(let ((file-name ,file-name)) | |||||
| (unless (file-exists-p file-name) | |||||
| (error "%s does not exist" file-name)) | |||||
| (flycheck-ert-with-temp-buffer | |||||
| (insert-file-contents file-name 'visit) | |||||
| (set-visited-file-name file-name 'no-query) | |||||
| (cd (file-name-directory file-name)) | |||||
| ;; Mark the buffer as not modified, because we just loaded the file up to | |||||
| ;; now. | |||||
| (set-buffer-modified-p nil) | |||||
| ,@body))) | |||||
| (defmacro flycheck-ert-with-help-buffer (&rest body) | |||||
| "Execute BODY and kill the help buffer afterwards. | |||||
| Use this macro to test functions that create a Help buffer." | |||||
| (declare (indent 0)) | |||||
| `(unwind-protect | |||||
| ,(macroexp-progn body) | |||||
| (when (buffer-live-p (get-buffer (help-buffer))) | |||||
| (kill-buffer (help-buffer))))) | |||||
| (defmacro flycheck-ert-with-global-mode (&rest body) | |||||
| "Execute BODY with Global Flycheck Mode enabled. | |||||
| After BODY, restore the old state of Global Flycheck Mode." | |||||
| (declare (indent 0)) | |||||
| `(let ((old-state global-flycheck-mode)) | |||||
| (unwind-protect | |||||
| (progn | |||||
| (global-flycheck-mode 1) | |||||
| ,@body) | |||||
| (global-flycheck-mode (if old-state 1 -1))))) | |||||
| (defmacro flycheck-ert-with-env (env &rest body) | |||||
| "Add ENV to `process-environment' in BODY. | |||||
| Execute BODY with a `process-environment' with contains all | |||||
| variables from ENV added. | |||||
| ENV is an alist, where each cons cell `(VAR . VALUE)' is a | |||||
| environment variable VAR to be added to `process-environment' | |||||
| with VALUE." | |||||
| (declare (indent 1)) | |||||
| `(let ((process-environment (copy-sequence process-environment))) | |||||
| (pcase-dolist (`(,var . ,value) ,env) | |||||
| (setenv var value)) | |||||
| ,@body)) | |||||
| ;;; Test resources | |||||
| (defun flycheck-ert-resource-filename (resource-file) | |||||
| "Determine the absolute file name of a RESOURCE-FILE. | |||||
| Relative file names are expanded against | |||||
| `flycheck-ert-resources-directory'." | |||||
| (expand-file-name resource-file flycheck-ert--resource-directory)) | |||||
| (defmacro flycheck-ert-with-resource-buffer (resource-file &rest body) | |||||
| "Create a temp buffer from a RESOURCE-FILE and execute BODY. | |||||
| The absolute file name of RESOURCE-FILE is determined with | |||||
| `flycheck-ert-resource-filename'." | |||||
| (declare (indent 1)) | |||||
| `(flycheck-ert-with-file-buffer | |||||
| (flycheck-ert-resource-filename ,resource-file) | |||||
| ,@body)) | |||||
| ;;; Test suite initialization | |||||
| (defun flycheck-ert-initialize (resource-dir) | |||||
| "Initialize a test suite with RESOURCE-DIR. | |||||
| RESOURCE-DIR is the directory, `flycheck-ert-resource-filename' | |||||
| should use to lookup resource files." | |||||
| (when flycheck-ert--resource-directory | |||||
| (error "Test suite already initialized")) | |||||
| (let ((tests (ert-select-tests t t))) | |||||
| ;; Select all tests | |||||
| (unless tests | |||||
| (error "No tests defined. Call `flycheck-ert-initialize' after defining all tests!")) | |||||
| (setq flycheck-ert--resource-directory resource-dir) | |||||
| ;; Emacs 24.3 don't support skipped tests, so we add poor man's test | |||||
| ;; skipping: We mark skipped tests as expected failures by adjusting the | |||||
| ;; expected result of all test cases. Not particularly pretty, but works :) | |||||
| (unless flycheck-ert-ert-can-skip | |||||
| (dolist (test tests) | |||||
| (let ((result (ert-test-expected-result-type test))) | |||||
| (setf (ert-test-expected-result-type test) | |||||
| `(or ,result (satisfies ert-test-skipped-p)))))))) | |||||
| ;;; Environment and version information | |||||
| (defun flycheck-ert-check-gpg () | |||||
| "Check whether GPG is available." | |||||
| (or (epg-check-configuration (epg-configuration)) t)) | |||||
| ;;; Test case definitions | |||||
| (defmacro flycheck-ert-def-checker-test (checker language name | |||||
| &rest keys-and-body) | |||||
| "Define a test case for a syntax CHECKER for LANGUAGE. | |||||
| CHECKER is a symbol or a list of symbols denoting syntax checkers | |||||
| being tested by the test. The test case is skipped, if any of | |||||
| these checkers cannot be used. LANGUAGE is a symbol or a list of | |||||
| symbols denoting the programming languages supported by the | |||||
| syntax checkers. This is currently only used for tagging the | |||||
| test appropriately. | |||||
| NAME is a symbol denoting the local name of the test. The test | |||||
| itself is ultimately named | |||||
| `flycheck-define-checker/CHECKER/NAME'. If CHECKER is a list, | |||||
| the first checker in the list is used for naming the test. | |||||
| Optionally, the keyword arguments `:tags' and `:expected-result' | |||||
| may be given. They have the same meaning as in `ert-deftest.', | |||||
| and are added to the tags and result expectations set up by this | |||||
| macro. | |||||
| The remaining forms KEYS-AND-BODY denote the body of the test | |||||
| case, including assertions and setup code." | |||||
| (declare (indent 3)) | |||||
| (unless checker | |||||
| (error "No syntax checkers specified")) | |||||
| (unless language | |||||
| (error "No languages specified")) | |||||
| (let* ((checkers (if (symbolp checker) (list checker) checker)) | |||||
| (checker (car checkers)) | |||||
| (languages (if (symbolp language) (list language) language)) | |||||
| (language-tags (mapcar (lambda (l) (intern (format "language-%s" l))) | |||||
| languages)) | |||||
| (checker-tags (mapcar (lambda (c) (intern (format "checker-%s" c))) | |||||
| checkers)) | |||||
| (local-name (or name 'default)) | |||||
| (full-name (intern (format "flycheck-define-checker/%s/%s" | |||||
| checker local-name))) | |||||
| (keys-and-body (ert--parse-keys-and-body keys-and-body)) | |||||
| (body (cadr keys-and-body)) | |||||
| (keys (car keys-and-body)) | |||||
| (default-tags '(syntax-checker external-tool))) | |||||
| `(ert-deftest ,full-name () | |||||
| :expected-result | |||||
| (list 'or | |||||
| '(satisfies flycheck-ert-syntax-check-timed-out-p) | |||||
| ,(or (plist-get keys :expected-result) :passed)) | |||||
| :tags (append ',(append default-tags language-tags checker-tags) | |||||
| ,(plist-get keys :tags)) | |||||
| ,@(mapcar (lambda (c) `(skip-unless | |||||
| ;; Ignore non-command checkers | |||||
| (or (not (flycheck-checker-get ',c 'command)) | |||||
| (executable-find (flycheck-checker-executable ',c))))) | |||||
| checkers) | |||||
| ,@body))) | |||||
| ;;; Test case results | |||||
| (defun flycheck-ert-syntax-check-timed-out-p (result) | |||||
| "Whether RESULT denotes a timed-out test. | |||||
| RESULT is an ERT test result object." | |||||
| (and (ert-test-failed-p result) | |||||
| (eq (car (ert-test-failed-condition result)) | |||||
| 'flycheck-ert-syntax-check-timed-out))) | |||||
| ;;; Syntax checking in tests | |||||
| (defvar-local flycheck-ert-syntax-checker-finished nil | |||||
| "Non-nil if the current checker has finished.") | |||||
| (add-hook 'flycheck-after-syntax-check-hook | |||||
| (lambda () (setq flycheck-ert-syntax-checker-finished t))) | |||||
| (defconst flycheck-ert-checker-wait-time 10 | |||||
| "Time to wait until a checker is finished in seconds. | |||||
| After this time has elapsed, the checker is considered to have | |||||
| failed, and the test aborted with failure.") | |||||
| (put 'flycheck-ert-syntax-check-timed-out 'error-message | |||||
| "Syntax check timed out.") | |||||
| (put 'flycheck-ert-syntax-check-timed-out 'error-conditions '(error)) | |||||
| (defun flycheck-ert-wait-for-syntax-checker () | |||||
| "Wait until the syntax check in the current buffer is finished." | |||||
| (let ((starttime (float-time))) | |||||
| (while (and (not flycheck-ert-syntax-checker-finished) | |||||
| (< (- (float-time) starttime) flycheck-ert-checker-wait-time)) | |||||
| (sleep-for 1)) | |||||
| (unless (< (- (float-time) starttime) flycheck-ert-checker-wait-time) | |||||
| (flycheck-stop) | |||||
| (signal 'flycheck-ert-syntax-check-timed-out nil))) | |||||
| (setq flycheck-ert-syntax-checker-finished nil)) | |||||
| (defun flycheck-ert-buffer-sync () | |||||
| "Like `flycheck-buffer', but synchronously." | |||||
| (setq flycheck-ert-syntax-checker-finished nil) | |||||
| (should (not (flycheck-running-p))) | |||||
| (flycheck-mode) ; This will only start a deferred check, | |||||
| (flycheck-buffer) ; so we need an explicit manual check | |||||
| ;; After starting the check, the checker should either be running now, or | |||||
| ;; already be finished (if it was fast). | |||||
| (should (or flycheck-current-syntax-check | |||||
| flycheck-ert-syntax-checker-finished)) | |||||
| ;; Also there should be no deferred check pending anymore | |||||
| (should-not (flycheck-deferred-check-p)) | |||||
| (flycheck-ert-wait-for-syntax-checker)) | |||||
| (defun flycheck-ert-ensure-clear () | |||||
| "Clear the current buffer. | |||||
| Raise an assertion error if the buffer is not clear afterwards." | |||||
| (flycheck-clear) | |||||
| (should (not flycheck-current-errors)) | |||||
| (should (not (-any? (lambda (ov) (overlay-get ov 'flycheck-overlay)) | |||||
| (overlays-in (point-min) (point-max)))))) | |||||
| ;;; Test assertions | |||||
| (defun flycheck-ert-should-overlay (error) | |||||
| "Test that ERROR has a proper overlay in the current buffer. | |||||
| ERROR is a Flycheck error object." | |||||
| (let* ((overlay (-first (lambda (ov) (equal (overlay-get ov 'flycheck-error) | |||||
| error)) | |||||
| (flycheck-overlays-in 0 (+ 1 (buffer-size))))) | |||||
| (region (flycheck-error-region-for-mode error 'symbols)) | |||||
| (level (flycheck-error-level error)) | |||||
| (category (flycheck-error-level-overlay-category level)) | |||||
| (face (get category 'face)) | |||||
| (fringe-bitmap (flycheck-error-level-fringe-bitmap level)) | |||||
| (fringe-face (flycheck-error-level-fringe-face level)) | |||||
| (fringe-icon (list 'left-fringe fringe-bitmap fringe-face))) | |||||
| (should overlay) | |||||
| (should (overlay-get overlay 'flycheck-overlay)) | |||||
| (should (= (overlay-start overlay) (car region))) | |||||
| (should (= (overlay-end overlay) (cdr region))) | |||||
| (should (eq (overlay-get overlay 'face) face)) | |||||
| (should (equal (get-char-property 0 'display | |||||
| (overlay-get overlay 'before-string)) | |||||
| fringe-icon)) | |||||
| (should (eq (overlay-get overlay 'category) category)) | |||||
| (should (equal (overlay-get overlay 'flycheck-error) error)))) | |||||
| (defun flycheck-ert-should-errors (&rest errors) | |||||
| "Test that the current buffers has ERRORS. | |||||
| ERRORS is a list of errors expected to be present in the current | |||||
| buffer. Each error is given as a list of arguments to | |||||
| `flycheck-error-new-at'. | |||||
| If ERRORS are omitted, test that there are no errors at all in | |||||
| the current buffer. | |||||
| With ERRORS, test that each error in ERRORS is present in the | |||||
| current buffer, and that the number of errors in the current | |||||
| buffer is equal to the number of given ERRORS. In other words, | |||||
| check that the buffer has all ERRORS, and no other errors." | |||||
| (let ((expected (mapcar (apply-partially #'apply #'flycheck-error-new-at) | |||||
| errors))) | |||||
| (should (equal expected flycheck-current-errors)) | |||||
| (mapc #'flycheck-ert-should-overlay expected)) | |||||
| (should (= (length errors) | |||||
| (length (flycheck-overlays-in (point-min) (point-max)))))) | |||||
| (defun flycheck-ert-should-syntax-check (resource-file modes &rest errors) | |||||
| "Test a syntax check in RESOURCE-FILE with MODES. | |||||
| RESOURCE-FILE is the file to check. MODES is a single major mode | |||||
| symbol or a list thereof, specifying the major modes to syntax | |||||
| check with. If more than one major mode is specified, the test | |||||
| is run for each mode separately, so if you give three major | |||||
| modes, the entire test will run three times. ERRORS is the list | |||||
| of expected errors, as in `flycheck-ert-should-errors'. If | |||||
| omitted, the syntax check must not emit any errors. The errors | |||||
| are cleared after each test. | |||||
| The syntax checker is selected via standard syntax checker | |||||
| selection. To test a specific checker, you need to set | |||||
| `flycheck-checker' or `flycheck-disabled-checkers' accordingly | |||||
| before using this predicate, depending on whether you want to use | |||||
| manual or automatic checker selection. | |||||
| During the syntax check, configuration files of syntax checkers | |||||
| are also searched in the `config-files' sub-directory of the | |||||
| resource directory." | |||||
| (when (symbolp modes) | |||||
| (setq modes (list modes))) | |||||
| (dolist (mode modes) | |||||
| (unless (fboundp mode) | |||||
| (ert-skip (format "%S missing" mode))) | |||||
| (flycheck-ert-with-resource-buffer resource-file | |||||
| (funcall mode) | |||||
| ;; Configure config file locating for unit tests | |||||
| (let ((process-hook-called 0)) | |||||
| (add-hook 'flycheck-process-error-functions | |||||
| (lambda (_err) | |||||
| (setq process-hook-called (1+ process-hook-called)) | |||||
| nil) | |||||
| nil :local) | |||||
| (flycheck-ert-buffer-sync) | |||||
| (apply #'flycheck-ert-should-errors errors) | |||||
| (should (= process-hook-called (length errors)))) | |||||
| (flycheck-ert-ensure-clear)))) | |||||
| (defun flycheck-ert-at-nth-error (n) | |||||
| "Determine whether point is at the N'th Flycheck error. | |||||
| Return non-nil if the point is at the N'th Flycheck error in the | |||||
| current buffer. Otherwise return nil." | |||||
| (let* ((error (nth (1- n) flycheck-current-errors)) | |||||
| (mode flycheck-highlighting-mode) | |||||
| (region (flycheck-error-region-for-mode error mode))) | |||||
| (and (member error (flycheck-overlay-errors-at (point))) | |||||
| (= (point) (car region))))) | |||||
| (defun flycheck-ert-explain--at-nth-error (n) | |||||
| "Explain a failed at-nth-error predicate at N." | |||||
| (let ((errors (flycheck-overlay-errors-at (point)))) | |||||
| (if (null errors) | |||||
| (format "Expected to be at error %s, but no error at point %s" | |||||
| n (point)) | |||||
| (let ((pos (cl-position (car errors) flycheck-current-errors))) | |||||
| (format "Expected to be at error %s, but point %s is at error %s" | |||||
| n (point) (1+ pos)))))) | |||||
| (put 'flycheck-ert-at-nth-error 'ert-explainer | |||||
| 'flycheck-ert-explain--at-nth-error) | |||||
| (provide 'flycheck-ert) | |||||
| ;;; flycheck-ert.el ends here | |||||
| @ -0,0 +1,11 @@ | |||||
| (define-package "flycheck" "20160224.642" "On-the-fly syntax checking" | |||||
| '((dash "2.12.1") | |||||
| (pkg-info "0.4") | |||||
| (let-alist "1.0.4") | |||||
| (seq "1.11") | |||||
| (emacs "24.3")) | |||||
| :url "https://www.flycheck.org" :keywords | |||||
| '("convenience" "languages" "tools")) | |||||
| ;; Local Variables: | |||||
| ;; no-byte-compile: t | |||||
| ;; End: | |||||
| @ -0,0 +1,7 @@ | |||||
| This is macros.info, produced by makeinfo version 5.2 from macros.texi. | |||||
| Tag Table: | |||||
| End Tag Table | |||||
| @ -0,0 +1,33 @@ | |||||
| ;;; json-mode-autoloads.el --- automatically extracted autoloads | |||||
| ;; | |||||
| ;;; Code: | |||||
| (add-to-list 'load-path (or (file-name-directory #$) (car load-path))) | |||||
| ;;;### (autoloads nil "json-mode" "json-mode.el" (22223 32448 0 0)) | |||||
| ;;; Generated autoloads from json-mode.el | |||||
| (autoload 'json-mode "json-mode" "\ | |||||
| Major mode for editing JSON files | |||||
| \(fn)" t nil) | |||||
| (add-to-list 'auto-mode-alist '("\\.json$" . json-mode)) | |||||
| (autoload 'json-mode-show-path "json-mode" "\ | |||||
| \(fn)" t nil) | |||||
| (autoload 'json-mode-beautify "json-mode" "\ | |||||
| Beautify / pretty-print the active region (or the entire buffer if no active region). | |||||
| \(fn)" t nil) | |||||
| ;;;*** | |||||
| ;; Local Variables: | |||||
| ;; version-control: never | |||||
| ;; no-byte-compile: t | |||||
| ;; no-update-autoloads: t | |||||
| ;; End: | |||||
| ;;; json-mode-autoloads.el ends here | |||||
| @ -0,0 +1 @@ | |||||
| (define-package "json-mode" "20151116.2000" "Major mode for editing JSON files" '((json-reformat "0.0.5") (json-snatcher "1.0.0")) :url "https://github.com/joshwnj/json-mode") | |||||
| @ -0,0 +1,104 @@ | |||||
| ;;; json-mode.el --- Major mode for editing JSON files | |||||
| ;; Copyright (C) 2011-2014 Josh Johnston | |||||
| ;; Author: Josh Johnston | |||||
| ;; URL: https://github.com/joshwnj/json-mode | |||||
| ;; Package-Version: 20151116.2000 | |||||
| ;; Version: 1.6.0 | |||||
| ;; Package-Requires: ((json-reformat "0.0.5") (json-snatcher "1.0.0")) | |||||
| ;; 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: | |||||
| ;; extend the builtin js-mode's syntax highlighting | |||||
| ;;; Code: | |||||
| (require 'js) | |||||
| (require 'rx) | |||||
| (require 'json-snatcher) | |||||
| (require 'json-reformat) | |||||
| (defconst json-mode-quoted-string-re | |||||
| (rx (group (char ?\") | |||||
| (zero-or-more (or (seq ?\\ ?\\) | |||||
| (seq ?\\ ?\") | |||||
| (seq ?\\ (not (any ?\" ?\\))) | |||||
| (not (any ?\" ?\\)))) | |||||
| (char ?\")))) | |||||
| (defconst json-mode-quoted-key-re | |||||
| (rx (group (char ?\") | |||||
| (zero-or-more (or (seq ?\\ ?\\) | |||||
| (seq ?\\ ?\") | |||||
| (seq ?\\ (not (any ?\" ?\\))) | |||||
| (not (any ?\" ?\\)))) | |||||
| (char ?\")) | |||||
| (zero-or-more blank) | |||||
| ?\:)) | |||||
| (defconst json-mode-number-re (rx (group (one-or-more digit) | |||||
| (optional ?\. (one-or-more digit))))) | |||||
| (defconst json-mode-keyword-re (rx (group (or "true" "false" "null")))) | |||||
| (defconst json-font-lock-keywords-1 | |||||
| (list | |||||
| (list json-mode-quoted-key-re 1 font-lock-keyword-face) | |||||
| (list json-mode-quoted-string-re 1 font-lock-string-face) | |||||
| (list json-mode-keyword-re 1 font-lock-constant-face) | |||||
| (list json-mode-number-re 1 font-lock-constant-face) | |||||
| ) | |||||
| "Level one font lock.") | |||||
| ;;;###autoload | |||||
| (define-derived-mode json-mode javascript-mode "JSON" | |||||
| "Major mode for editing JSON files" | |||||
| (set (make-local-variable 'font-lock-defaults) '(json-font-lock-keywords-1 t))) | |||||
| ;;;###autoload | |||||
| (add-to-list 'auto-mode-alist '("\\.json$" . json-mode)) | |||||
| (add-to-list 'auto-mode-alist '("\\.jsonld$" . json-mode)) | |||||
| ;;;###autoload | |||||
| (defun json-mode-show-path () | |||||
| (interactive) | |||||
| (let ((temp-name "*json-path*")) | |||||
| (with-output-to-temp-buffer temp-name (jsons-print-path)) | |||||
| (let ((temp-window (get-buffer-window temp-name))) | |||||
| ;; delete the window if we have one, | |||||
| ;; so we can recreate it in the correct position | |||||
| (if temp-window | |||||
| (delete-window temp-window)) | |||||
| ;; always put the temp window below the json window | |||||
| (set-window-buffer (split-window-below) temp-name)) | |||||
| )) | |||||
| (define-key json-mode-map (kbd "C-c C-p") 'json-mode-show-path) | |||||
| ;;;###autoload | |||||
| (defun json-mode-beautify () | |||||
| "Beautify / pretty-print the active region (or the entire buffer if no active region)." | |||||
| (interactive) | |||||
| (let ((json-reformat:indent-width js-indent-level)) | |||||
| (if (use-region-p) | |||||
| (json-reformat-region (region-beginning) (region-end)) | |||||
| (json-reformat-region (buffer-end -1) (buffer-end 1))))) | |||||
| (define-key json-mode-map (kbd "C-c C-f") 'json-mode-beautify) | |||||
| (provide 'json-mode) | |||||
| ;;; json-mode.el ends here | |||||
| @ -0,0 +1,26 @@ | |||||
| ;;; json-reformat-autoloads.el --- automatically extracted autoloads | |||||
| ;; | |||||
| ;;; Code: | |||||
| (add-to-list 'load-path (or (file-name-directory #$) (car load-path))) | |||||
| ;;;### (autoloads nil "json-reformat" "json-reformat.el" (22223 32447 | |||||
| ;;;;;; 0 0)) | |||||
| ;;; Generated autoloads from json-reformat.el | |||||
| (autoload 'json-reformat-region "json-reformat" "\ | |||||
| Reformat the JSON in the specified region. | |||||
| If you want to customize the reformat style, | |||||
| please see the documentation of `json-reformat:indent-width' | |||||
| and `json-reformat:pretty-string?'. | |||||
| \(fn BEGIN END)" t nil) | |||||
| ;;;*** | |||||
| ;; Local Variables: | |||||
| ;; version-control: never | |||||
| ;; no-byte-compile: t | |||||
| ;; no-update-autoloads: t | |||||
| ;; End: | |||||
| ;;; json-reformat-autoloads.el ends here | |||||
| @ -0,0 +1 @@ | |||||
| (define-package "json-reformat" "20160212.53" "Reformatting tool for JSON" 'nil :url "https://github.com/gongo/json-reformat" :keywords '("json")) | |||||
| @ -0,0 +1,221 @@ | |||||
| ;;; json-reformat.el --- Reformatting tool for JSON | |||||
| ;; Author: Wataru MIYAGUNI <gonngo@gmail.com> | |||||
| ;; URL: https://github.com/gongo/json-reformat | |||||
| ;; Package-Version: 20160212.53 | |||||
| ;; Version: 0.0.6 | |||||
| ;; Keywords: json | |||||
| ;; Copyright (c) 2012 Wataru MIYAGUNI | |||||
| ;; | |||||
| ;; MIT License | |||||
| ;; | |||||
| ;; Permission is hereby granted, free of charge, to any person obtaining | |||||
| ;; a copy of this software and associated documentation files (the | |||||
| ;; "Software"), to deal in the Software without restriction, including | |||||
| ;; without limitation the rights to use, copy, modify, merge, publish, | |||||
| ;; distribute, sublicense, and/or sell copies of the Software, and to | |||||
| ;; permit persons to whom the Software is furnished to do so, subject to | |||||
| ;; the following conditions: | |||||
| ;; | |||||
| ;; The above copyright notice and this permission notice shall be | |||||
| ;; included in all copies or substantial portions of the Software. | |||||
| ;; | |||||
| ;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||||
| ;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||||
| ;; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |||||
| ;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | |||||
| ;; LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | |||||
| ;; OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |||||
| ;; WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |||||
| ;;; Commentary: | |||||
| ;; json-reformat.el is a reformatting tool for JSON (http://json.org/). | |||||
| ;; | |||||
| ;; ## Usage | |||||
| ;; | |||||
| ;; 1. Specify region | |||||
| ;; 2. Call 'M-x json-reformat-region' | |||||
| ;; | |||||
| ;; ## Customize | |||||
| ;; | |||||
| ;; - `json-reformat:indent-width' | |||||
| ;; - `json-reformat:pretty-string?' | |||||
| ;; | |||||
| ;;; Code: | |||||
| (require 'json) | |||||
| (eval-when-compile (require 'cl)) | |||||
| (unless (require 'subr-x nil t) | |||||
| ;; built-in subr-x from 24.4 | |||||
| (defsubst hash-table-keys (hash-table) | |||||
| "Return a list of keys in HASH-TABLE." | |||||
| (let ((keys '())) | |||||
| (maphash (lambda (k _v) (push k keys)) hash-table) | |||||
| keys))) | |||||
| (put 'json-reformat-error 'error-message "JSON Reformat error") | |||||
| (put 'json-reformat-error 'error-conditions '(json-reformat-error error)) | |||||
| (defconst json-reformat:special-chars-as-pretty-string | |||||
| '((?\" . ?\") | |||||
| (?\\ . ?\\))) | |||||
| (defcustom json-reformat:indent-width 4 | |||||
| "How much indentation `json-reformat-region' should do at each level." | |||||
| :type 'integer | |||||
| :safe #'integerp | |||||
| :group 'json-reformat) | |||||
| (defcustom json-reformat:pretty-string? nil | |||||
| "Whether to decode the string. | |||||
| Example: | |||||
| {\"name\":\"foobar\",\"nick\":\"foo \\u00e4 bar\",\"description\":\"<pre>\\nbaz\\n</pre>\"} | |||||
| If nil: | |||||
| { | |||||
| \"name\": \"foobar\", | |||||
| \"nick\": \"foo \\u00e4 bar\", | |||||
| \"description\": \"<pre>\\nbaz\\n<\\/pre>\" | |||||
| } | |||||
| Else t: | |||||
| { | |||||
| \"name\": \"foobar\", | |||||
| \"nick\": \"foo ä bar\", | |||||
| \"description\": \"<pre> | |||||
| baz | |||||
| </pre>\" | |||||
| }" | |||||
| :type 'boolean | |||||
| :safe #'booleanp | |||||
| :group 'json-reformat) | |||||
| (defun json-reformat:indent (level) | |||||
| (make-string (* level json-reformat:indent-width) ? )) | |||||
| (defun json-reformat:number-to-string (val) | |||||
| (number-to-string val)) | |||||
| (defun json-reformat:symbol-to-string (val) | |||||
| (cond ((equal 't val) "true") | |||||
| ((equal json-false val) "false") | |||||
| (t (symbol-name val)))) | |||||
| (defun json-reformat:encode-char-as-pretty (char) | |||||
| (setq char (encode-char char 'ucs)) | |||||
| (let ((special-char (car (rassoc char json-reformat:special-chars-as-pretty-string)))) | |||||
| (if special-char | |||||
| (format "\\%c" special-char) | |||||
| (format "%c" char)))) | |||||
| (defun json-reformat:string-to-string (val) | |||||
| (if json-reformat:pretty-string? | |||||
| (format "\"%s\"" (mapconcat 'json-reformat:encode-char-as-pretty val "")) | |||||
| (json-encode-string val))) | |||||
| (defun json-reformat:vector-to-string (val level) | |||||
| (if (= (length val) 0) "[]" | |||||
| (concat "[\n" | |||||
| (mapconcat | |||||
| 'identity | |||||
| (loop for v across val | |||||
| collect (concat | |||||
| (json-reformat:indent (1+ level)) | |||||
| (json-reformat:print-node v (1+ level)) | |||||
| )) | |||||
| (concat ",\n")) | |||||
| "\n" (json-reformat:indent level) "]" | |||||
| ))) | |||||
| (defun json-reformat:print-node (val level) | |||||
| (cond ((hash-table-p val) (json-reformat:tree-to-string (json-reformat:tree-sibling-to-plist val) level)) | |||||
| ((numberp val) (json-reformat:number-to-string val)) | |||||
| ((vectorp val) (json-reformat:vector-to-string val level)) | |||||
| ((null val) "null") | |||||
| ((symbolp val) (json-reformat:symbol-to-string val)) | |||||
| (t (json-reformat:string-to-string val)))) | |||||
| (defun json-reformat:tree-sibling-to-plist (root) | |||||
| (let (pl) | |||||
| (dolist (key (reverse (hash-table-keys root)) pl) | |||||
| (setq pl (plist-put pl key (gethash key root)))))) | |||||
| (defun json-reformat:tree-to-string (root level) | |||||
| (concat "{\n" | |||||
| (let (key val str) | |||||
| (while root | |||||
| (setq key (car root) | |||||
| val (cadr root) | |||||
| root (cddr root)) | |||||
| (setq str | |||||
| (concat str (json-reformat:indent (1+ level)) | |||||
| "\"" key "\"" | |||||
| ": " | |||||
| (json-reformat:print-node val (1+ level)) | |||||
| (when root ",") | |||||
| "\n" | |||||
| ))) | |||||
| str) | |||||
| (json-reformat:indent level) | |||||
| "}")) | |||||
| (defun json-reformat-from-string (string) | |||||
| (with-temp-buffer | |||||
| (insert string) | |||||
| (goto-char (point-min)) | |||||
| (condition-case errvar | |||||
| (let ((json-key-type 'string) | |||||
| (json-object-type 'hash-table) | |||||
| json-tree) | |||||
| (setq json-tree (json-read)) | |||||
| (json-reformat:print-node json-tree 0)) | |||||
| (json-error | |||||
| (signal 'json-reformat-error | |||||
| (list (error-message-string errvar) | |||||
| (line-number-at-pos (point)) | |||||
| (point))))))) | |||||
| ;;;###autoload | |||||
| (defun json-reformat-region (begin end) | |||||
| "Reformat the JSON in the specified region. | |||||
| If you want to customize the reformat style, | |||||
| please see the documentation of `json-reformat:indent-width' | |||||
| and `json-reformat:pretty-string?'." | |||||
| (interactive "*r") | |||||
| (let ((start-line (line-number-at-pos begin)) | |||||
| (start-pos begin)) | |||||
| (save-excursion | |||||
| (save-restriction | |||||
| (narrow-to-region begin end) | |||||
| (goto-char (point-min)) | |||||
| (let (reformatted) | |||||
| (condition-case errvar | |||||
| (progn | |||||
| (setq reformatted | |||||
| (json-reformat-from-string | |||||
| (buffer-substring-no-properties (point-min) (point-max)))) | |||||
| (delete-region (point-min) (point-max)) | |||||
| (insert reformatted)) | |||||
| (json-reformat-error | |||||
| (let ((reason (nth 1 errvar)) | |||||
| (line (nth 2 errvar)) | |||||
| (position (nth 3 errvar))) | |||||
| (message | |||||
| "JSON parse error [Reason] %s [Position] In buffer, line %d (char %d)" | |||||
| reason | |||||
| (+ start-line line -1) | |||||
| (+ start-pos position -1)))))))))) | |||||
| (provide 'json-reformat) | |||||
| ;;; json-reformat.el ends here | |||||
| @ -0,0 +1,22 @@ | |||||
| ;;; json-snatcher-autoloads.el --- automatically extracted autoloads | |||||
| ;; | |||||
| ;;; Code: | |||||
| (add-to-list 'load-path (or (file-name-directory #$) (car load-path))) | |||||
| ;;;### (autoloads nil "json-snatcher" "json-snatcher.el" (22223 32445 | |||||
| ;;;;;; 0 0)) | |||||
| ;;; Generated autoloads from json-snatcher.el | |||||
| (autoload 'jsons-print-path "json-snatcher" "\ | |||||
| Print the path to the JSON value under point, and save it in the kill ring. | |||||
| \(fn)" t nil) | |||||
| ;;;*** | |||||
| ;; Local Variables: | |||||
| ;; version-control: never | |||||
| ;; no-byte-compile: t | |||||
| ;; no-update-autoloads: t | |||||
| ;; End: | |||||
| ;;; json-snatcher-autoloads.el ends here | |||||
| @ -0,0 +1 @@ | |||||
| (define-package "json-snatcher" "20150511.2047" "Grabs the path to JSON values in a JSON file" '((emacs "24")) :url "http://github.com/sterlingg/json-snatcher") | |||||
| @ -0,0 +1,351 @@ | |||||
| ;;; json-snatcher.el --- Grabs the path to JSON values in a JSON file -*- lexical-binding: t -*- | |||||
| ;; Copyright (C) 2013 Sterling Graham <sterlingrgraham@gmail.com> | |||||
| ;; Author: Sterling Graham <sterlingrgraham@gmail.com> | |||||
| ;; URL: http://github.com/sterlingg/json-snatcher | |||||
| ;; Package-Version: 20150511.2047 | |||||
| ;; Version: 1.0 | |||||
| ;; Package-Requires: ((emacs "24")) | |||||
| ;; This file is not part of GNU Emacs. | |||||
| ;;; Commentary: | |||||
| ;; | |||||
| ;; Well this was my first excursion into ELisp programmming. It didn't go too badly once | |||||
| ;; I fiddled around with a bunch of the functions. | |||||
| ;; | |||||
| ;; The process of getting the path to a JSON value at point starts with | |||||
| ;; a call to the jsons-print-path function. | |||||
| ;; | |||||
| ;; It works by parsing the current buffer into a list of parse tree nodes | |||||
| ;; if the buffer hasn't already been parsed in the current Emacs session. | |||||
| ;; While parsing, the region occupied by the node is recorded into the | |||||
| ;; jsons-parsed-regions hash table as a list.The list contains the location | |||||
| ;; of the first character occupied by the node, the location of the last | |||||
| ;; character occupied, and the path to the node. The parse tree is also stored | |||||
| ;; in the jsons-parsed list for possible future use. | |||||
| ;; | |||||
| ;; Once the buffer has been parsed, the node at point is looked up in the | |||||
| ;; jsons-curr-region list, which is the list of regions described in the | |||||
| ;; previous paragraph for the current buffer. If point is not in one of these | |||||
| ;; interval ranges nil is returned, otherwise the path to the value is returned | |||||
| ;; in the form [<key-string>] for objects, and [<loc-int>] for arrays. | |||||
| ;; eg: ['value1'][0]['value2'] gets the array at with name value1, then gets the | |||||
| ;; 0th element of the array (another object), then gets the value at 'value2'. | |||||
| ;; | |||||
| ;;; Installation: | |||||
| ;; | |||||
| ;; IMPORTANT: Works ONLY in Emacs 24 due to the use of the lexical-binding variable. | |||||
| ;; | |||||
| ;; To install add the json-snatcher.el file to your load-path, and | |||||
| ;; add the following lines to your .emacs file: | |||||
| ;;(require 'json-snatcher) | |||||
| ;; (defun js-mode-bindings () | |||||
| ;; "Sets a hotkey for using the json-snatcher plugin." | |||||
| ;; (when (string-match "\\.json$" (buffer-name)) | |||||
| ;; (local-set-key (kbd "C-c C-g") 'jsons-print-path))) | |||||
| ;; (add-hook 'js-mode-hook 'js-mode-bindings) | |||||
| ;; (add-hook 'js2-mode-hook 'js-mode-bindings) | |||||
| ;; | |||||
| ;; This binds the key to snatch the path to the JSON value to C-c C-g only | |||||
| ;; when either JS mode, or JS2 mode is active on a buffer ending with | |||||
| ;; the .json extension. | |||||
| ;;; License: | |||||
| ;; 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 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: | |||||
| (defvar jsons-curr-token 0 | |||||
| "The current character in the buffer being parsed.") | |||||
| (defvar jsons-parsed (make-hash-table :test 'equal) | |||||
| "Hashes each open buffer to the parse tree for that buffer.") | |||||
| (defvar jsons-parsed-regions (make-hash-table :test 'equal) | |||||
| "Hashes each open buffer to the ranges in the buffer for each of the parse trees nodes.") | |||||
| (defvar jsons-curr-region () "The node ranges in the current buffer.") | |||||
| (defvar jsons-path-printer 'jsons-print-path-python "Default jsons path printer") | |||||
| (add-hook 'kill-buffer-hook 'jsons-remove-buffer) | |||||
| (defun jsons-consume-token () | |||||
| "Return the next token in the stream." | |||||
| (goto-char jsons-curr-token) | |||||
| (let* ((delim_regex "\\([\][\\{\\}:,]\\)") | |||||
| ;; TODO: Improve this regex. Although now it SEEMS to be working, and can be | |||||
| ;; used to validate escapes if needed later. The second half of the string regex is pretty | |||||
| ;; pointless at the moment. I did it this way, so that the code closely mirrors | |||||
| ;; the RFC. | |||||
| (string_regex "\\(\"\\(\\([^\"\\\\\r\s\t\n]\\)*\\([\r\s\t\n]\\)*\\|\\(\\(\\\\\\\\\\)*\\\\\\(\\([^\r\s\t\n]\\|\\(u[0-9A-Fa-f]\\{4\\}\\)\\)\\)\\)\\)+\"\\)") | |||||
| (num_regex "\\(-?\\(0\\|\\([1-9][[:digit:]]*\\)\\)\\(\\.[[:digit:]]+\\)?\\([eE][-+]?[[:digit:]]+\\)?\\)") | |||||
| (literal_regex "\\(true\\|false\\|null\\)") | |||||
| (full_regex (concat "\\(" delim_regex "\\|" literal_regex "\\|" string_regex "\\|" num_regex "\\)"))) | |||||
| (if (re-search-forward full_regex (point-max) "Not nil") | |||||
| (progn | |||||
| (setq jsons-curr-token (match-end 0)) | |||||
| (buffer-substring-no-properties (match-beginning 0) (match-end 0))) | |||||
| (message "Reached EOF. Possibly invalid JSON.")))) | |||||
| (defun jsons-array (path) | |||||
| "Create a new json array object that contain the identifier \"json-array\". | |||||
| a list of the elements contained in the array, and the PATH to the array." | |||||
| (let*( | |||||
| (token (jsons-consume-token)) | |||||
| (array "json-array") | |||||
| (elements ()) | |||||
| (i 0)) | |||||
| (while (not (string= token "]")) | |||||
| (if (not (string= token ",")) | |||||
| (let ((json-val (jsons-value token path i))) | |||||
| (setq i (+ i 1)) | |||||
| (push json-val elements) | |||||
| (setq token (jsons-consume-token))) | |||||
| (setq token (jsons-consume-token)))) | |||||
| (list array (reverse elements) path))) | |||||
| (defun jsons-literal (token path) | |||||
| "Given a TOKEN and PATH, this function return the PATH to the literal." | |||||
| (let ((match_start (match-beginning 0)) | |||||
| (match_end (match-end 0))) | |||||
| (progn | |||||
| (setq jsons-curr-region (append (list (list match_start match_end path)) jsons-curr-region)) | |||||
| (list "json-literal" token path (list match_start match_end))))) | |||||
| (defun jsons-member (token path) | |||||
| "This function is called when a member in a JSON object needs to be parsed. | |||||
| Given the current TOKEN, and the PATH to this member." | |||||
| (let* ((member ()) | |||||
| (value token) | |||||
| (range_start (match-beginning 0)) | |||||
| (range_end (match-end 0)) | |||||
| ) | |||||
| (setq member (list "json-member" token)) | |||||
| (if (not (string= (jsons-consume-token) ":")) | |||||
| (error "Encountered token other than : in jsons-member") | |||||
| nil) | |||||
| (let ((json-val (jsons-value (jsons-consume-token) (cons value path) nil))) | |||||
| (setq member (list member (append json-val | |||||
| (list range_start range_end)))) | |||||
| (setq jsons-curr-region (append (list (list range_start range_end (elt json-val 2))) jsons-curr-region)) | |||||
| member))) | |||||
| (defun jsons-number (token path) | |||||
| "This function will return a json-number given by the current TOKEN. | |||||
| PATH points to the path to this number. A json-number is defined as per | |||||
| the num_regex in the `jsons-get-tokens' function." | |||||
| (progn | |||||
| (setq jsons-curr-region (append (list (list (match-beginning 0) (match-end 0) path)) jsons-curr-region)) | |||||
| (list "json-number" token path))) | |||||
| (defun jsons-object (path) | |||||
| "This function is called when a { is encountered while parsing. | |||||
| PATH is the path in the tree to this object." | |||||
| (let*( | |||||
| (token (jsons-consume-token)) | |||||
| (members (make-hash-table :test 'equal)) | |||||
| (object (list "json-object" members path))) | |||||
| (while (not (string= token "}")) | |||||
| (if (not (string= token ",")) | |||||
| (let ((json-mem (jsons-member token path))) | |||||
| (puthash (elt (elt json-mem 0) 1) (elt json-mem 1) (elt object 1)) | |||||
| (setq token (jsons-consume-token))) | |||||
| (setq token (jsons-consume-token)))) | |||||
| object)) | |||||
| (defun jsons-string (token path) | |||||
| "This function is called when a string is encountered while parsing. | |||||
| The TOKEN is the current token being examined. | |||||
| The PATH is the path to this string." | |||||
| (let ((match_start (match-beginning 0)) | |||||
| (match_end (match-end 0))) | |||||
| (progn | |||||
| (setq jsons-curr-region (append (list (list match_start match_end path)) jsons-curr-region)) | |||||
| (list "json-string" token path (list match_start match_end))))) | |||||
| (defun jsons-value (token path array-index) | |||||
| "A value, which is either an object, array, string, number, or literal. | |||||
| The is-array variable is nil if inside an array, or the index in | |||||
| the array that it occupies. | |||||
| TOKEN is the current token being parsed. | |||||
| PATH is the path to this value. | |||||
| ARRAY-INDEX is non-nil if the value is contained within an array, and | |||||
| points to the index of this value in the containing array." | |||||
| ;;TODO: Refactor the if array-index statement. | |||||
| (if array-index | |||||
| (if (jsons-is-number token) | |||||
| (list "json-value" (jsons-number token (cons array-index path)) (list (match-beginning 0) (match-end 0))) | |||||
| (cond | |||||
| ((string= token "{") (jsons-object (cons array-index path))) | |||||
| ((string= token "[") (jsons-array (cons array-index path))) | |||||
| ((string= (substring token 0 1) "\"") (jsons-string token (cons array-index path))) | |||||
| (t (jsons-literal token (cons array-index path))))) | |||||
| (if (jsons-is-number token) | |||||
| (list "json-value" (jsons-number token path) path (list (match-beginning 0) (match-end 0))) | |||||
| (cond | |||||
| ((string= token "{") (jsons-object path)) | |||||
| ((string= token "[") (jsons-array path)) | |||||
| ((string= (substring token 0 1) "\"") (jsons-string token path)) | |||||
| (t (jsons-literal token path)))))) | |||||
| (defun jsons-get-path () | |||||
| "Function to check whether we can grab the json path from the cursor position in the json file." | |||||
| (let ((i 0) | |||||
| (node nil)) | |||||
| (setq jsons-curr-region (gethash (current-buffer) jsons-parsed-regions)) | |||||
| (when (not (gethash (current-buffer) jsons-parsed)) | |||||
| (jsons-parse)) | |||||
| (while (< i (length jsons-curr-region)) | |||||
| (let* | |||||
| ((json_region (elt jsons-curr-region i)) | |||||
| (min_token (elt json_region 0)) | |||||
| (max_token (elt json_region 1))) | |||||
| (when (and (> (point) min_token) (< (point) max_token)) | |||||
| (setq node (elt json_region 2)))) | |||||
| (setq i (+ i 1))) | |||||
| node)) | |||||
| (defun jsons-is-number (str) | |||||
| "Test to see whether STR is a valid JSON number." | |||||
| (progn | |||||
| (match-end 0) | |||||
| (save-match-data | |||||
| (if (string-match "^\\(-?\\(0\\|\\([1-9][[:digit:]]*\\)\\)\\(\\.[[:digit:]]+\\)?\\([eE][-+]?[[:digit:]]+\\)?\\)$" str) | |||||
| (progn | |||||
| (match-end 0) | |||||
| t) | |||||
| nil)))) | |||||
| (defun jsons-parse () | |||||
| "Parse the file given in file, return a list of nodes representing the file." | |||||
| (save-excursion | |||||
| (setq jsons-curr-token 0) | |||||
| (setq jsons-curr-region ()) | |||||
| (if (not (gethash (current-buffer) jsons-parsed)) | |||||
| (let* ((token (jsons-consume-token)) | |||||
| (return_val nil)) | |||||
| (cond | |||||
| ((string= token "{") (setq return_val (jsons-object ()))) | |||||
| ((string= token "[") (setq return_val (jsons-array ()))) | |||||
| (t nil)) | |||||
| (puthash (current-buffer) return_val jsons-parsed) | |||||
| (puthash (current-buffer) jsons-curr-region jsons-parsed-regions) | |||||
| return_val) | |||||
| (gethash (current-buffer) jsons-parsed)))) | |||||
| (defun jsons-print-to-buffer (node buffer) | |||||
| "Prints the given NODE to the BUFFER specified in buffer argument. | |||||
| TODO: Remove extra comma printed after lists of object members, and lists of array members." | |||||
| (let ((id (elt node 0))) | |||||
| (cond | |||||
| ((string= id "json-array") | |||||
| (progn | |||||
| (jsons-put-string buffer "[") | |||||
| (mapc (lambda (x) (progn | |||||
| (jsons-print-to-buffer buffer x) | |||||
| (jsons-put-string buffer ",") )) (elt node 1)) | |||||
| (jsons-put-string buffer "]"))) | |||||
| ((string= id "json-literal") | |||||
| (jsons-put-string buffer (elt node 1))) | |||||
| ((string= id "json-member") | |||||
| (jsons-put-string buffer (elt node 1)) | |||||
| (jsons-put-string buffer ": ") | |||||
| (jsons-print-to-buffer buffer (elt node 2))) | |||||
| ((string= id "json-number") | |||||
| (jsons-put-string buffer (elt node 1))) | |||||
| ((string= id "json-object") | |||||
| (progn | |||||
| (jsons-put-string buffer "{") | |||||
| (maphash (lambda (key value) | |||||
| (progn | |||||
| (jsons-put-string buffer key) | |||||
| (jsons-put-string buffer ":") | |||||
| (jsons-print-to-buffer buffer value) | |||||
| (jsons-put-string buffer ","))) (elt node 1)) | |||||
| (jsons-put-string buffer "}"))) | |||||
| ((string= id "json-string") | |||||
| (jsons-put-string buffer (elt node 1))) | |||||
| ((string= id "json-value") | |||||
| (jsons-print-to-buffer buffer (elt node 1))) | |||||
| (t nil)))) | |||||
| (defun jsons-print-path-jq () | |||||
| "Print the jq path to the JSON value under point, and save it in the kill ring." | |||||
| (let* ((path (jsons-get-path)) | |||||
| (i 0) | |||||
| (jq_str ".") | |||||
| key) | |||||
| (setq path (reverse path)) | |||||
| (while (< i (length path)) | |||||
| (if (numberp (elt path i)) | |||||
| (progn | |||||
| (setq jq_str (concat jq_str "[" (number-to-string (elt path i)) "]")) | |||||
| (setq i (+ i 1))) | |||||
| (progn | |||||
| (setq key (elt path i)) | |||||
| (setq jq_str (concat jq_str (substring key 1 (- (length key) 1)))) | |||||
| (setq i (+ i 1)))) | |||||
| (when (elt path i) | |||||
| (unless (numberp (elt path i)) | |||||
| (setq jq_str (concat jq_str "."))))) | |||||
| (progn (kill-new jq_str) | |||||
| (princ jq_str)))) | |||||
| (defun jsons-print-path-python () | |||||
| "Print the python path to the JSON value under point, and save it in the kill ring." | |||||
| (let ((path (jsons-get-path)) | |||||
| (i 0) | |||||
| (python_str "")) | |||||
| (setq path (reverse path)) | |||||
| (while (< i (length path)) | |||||
| (if (numberp (elt path i)) | |||||
| (progn | |||||
| (setq python_str (concat python_str "[" (number-to-string (elt path i)) "]")) | |||||
| (setq i (+ i 1))) | |||||
| (progn | |||||
| (setq python_str (concat python_str "[" (elt path i) "]")) | |||||
| (setq i (+ i 1))))) | |||||
| (progn (kill-new python_str) | |||||
| (princ python_str)))) | |||||
| ;;;###autoload | |||||
| (defun jsons-print-path () | |||||
| "Print the path to the JSON value under point, and save it in the kill ring." | |||||
| (interactive) | |||||
| (funcall jsons-path-printer)) | |||||
| (defun jsons-put-string (buffer str) | |||||
| "Append STR to the BUFFER specified in the argument." | |||||
| (save-current-buffer | |||||
| (set-buffer (get-buffer-create buffer)) | |||||
| (insert (prin1-to-string str t)))) | |||||
| (defun jsons-remove-buffer () | |||||
| "Used to clean up the token regions, and parse tree used by the parser." | |||||
| (progn | |||||
| (remhash (current-buffer) jsons-parsed) | |||||
| (remhash (current-buffer) jsons-parsed-regions))) | |||||
| (provide 'json-snatcher) | |||||
| ;; Local-Variables: | |||||
| ;; indent-tabs-mode: nil | |||||
| ;; End: | |||||
| ;;; json-snatcher.el ends here | |||||
| @ -0,0 +1 @@ | |||||
| Good signature from 474F05837FBDEF9B GNU ELPA Signing Agent <elpasign@elpa.gnu.org> (trust undefined) created at 2015-06-12T05:05:02-0400 using DSA | |||||
| @ -0,0 +1,49 @@ | |||||
| ;;; let-alist-autoloads.el --- automatically extracted autoloads | |||||
| ;; | |||||
| ;;; Code: | |||||
| (add-to-list 'load-path (or (file-name-directory #$) (car load-path))) | |||||
| ;;;### (autoloads nil "let-alist" "let-alist.el" (22223 32727 0 0)) | |||||
| ;;; Generated autoloads from let-alist.el | |||||
| (autoload 'let-alist "let-alist" "\ | |||||
| Let-bind dotted symbols to their cdrs in ALIST and execute BODY. | |||||
| Dotted symbol is any symbol starting with a `.'. Only those present | |||||
| in BODY are let-bound and this search is done at compile time. | |||||
| For instance, the following code | |||||
| (let-alist alist | |||||
| (if (and .title .body) | |||||
| .body | |||||
| .site | |||||
| .site.contents)) | |||||
| essentially expands to | |||||
| (let ((.title (cdr (assq 'title alist))) | |||||
| (.body (cdr (assq 'body alist))) | |||||
| (.site (cdr (assq 'site alist))) | |||||
| (.site.contents (cdr (assq 'contents (cdr (assq 'site alist)))))) | |||||
| (if (and .title .body) | |||||
| .body | |||||
| .site | |||||
| .site.contents)) | |||||
| If you nest `let-alist' invocations, the inner one can't access | |||||
| the variables of the outer one. You can, however, access alists | |||||
| inside the original alist by using dots inside the symbol, as | |||||
| displayed in the example above. | |||||
| \(fn ALIST &rest BODY)" nil t) | |||||
| (put 'let-alist 'lisp-indent-function '1) | |||||
| ;;;*** | |||||
| ;; Local Variables: | |||||
| ;; version-control: never | |||||
| ;; no-byte-compile: t | |||||
| ;; no-update-autoloads: t | |||||
| ;; End: | |||||
| ;;; let-alist-autoloads.el ends here | |||||
| @ -0,0 +1 @@ | |||||
| (define-package "let-alist" "1.0.4" "Easily let-bind values of an assoc-list by their names" 'nil :url "http://elpa.gnu.org/packages/let-alist.html" :keywords '("extensions" "lisp")) | |||||
| @ -0,0 +1,170 @@ | |||||
| ;;; let-alist.el --- Easily let-bind values of an assoc-list by their names -*- lexical-binding: t; -*- | |||||
| ;; Copyright (C) 2014-2015 Free Software Foundation, Inc. | |||||
| ;; Author: Artur Malabarba <bruce.connor.am@gmail.com> | |||||
| ;; Maintainer: Artur Malabarba <bruce.connor.am@gmail.com> | |||||
| ;; Version: 1.0.4 | |||||
| ;; Keywords: extensions lisp | |||||
| ;; Prefix: let-alist | |||||
| ;; Separator: - | |||||
| ;; 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 offers a single macro, `let-alist'. This macro takes a | |||||
| ;; first argument (whose value must be an alist) and a body. | |||||
| ;; | |||||
| ;; The macro expands to a let form containing body, where each dotted | |||||
| ;; symbol inside body is let-bound to their cdrs in the alist. Dotted | |||||
| ;; symbol is any symbol starting with a `.'. Only those present in | |||||
| ;; the body are let-bound and this search is done at compile time. | |||||
| ;; | |||||
| ;; For instance, the following code | |||||
| ;; | |||||
| ;; (let-alist alist | |||||
| ;; (if (and .title .body) | |||||
| ;; .body | |||||
| ;; .site | |||||
| ;; .site.contents)) | |||||
| ;; | |||||
| ;; essentially expands to | |||||
| ;; | |||||
| ;; (let ((.title (cdr (assq 'title alist))) | |||||
| ;; (.body (cdr (assq 'body alist))) | |||||
| ;; (.site (cdr (assq 'site alist))) | |||||
| ;; (.site.contents (cdr (assq 'contents (cdr (assq 'site alist)))))) | |||||
| ;; (if (and .title .body) | |||||
| ;; .body | |||||
| ;; .site | |||||
| ;; .site.contents)) | |||||
| ;; | |||||
| ;; If you nest `let-alist' invocations, the inner one can't access | |||||
| ;; the variables of the outer one. You can, however, access alists | |||||
| ;; inside the original alist by using dots inside the symbol, as | |||||
| ;; displayed in the example above by the `.site.contents'. | |||||
| ;; | |||||
| ;;; Code: | |||||
| (defun let-alist--deep-dot-search (data) | |||||
| "Return alist of symbols inside DATA that start with a `.'. | |||||
| Perform a deep search and return an alist where each car is the | |||||
| symbol, and each cdr is the same symbol without the `.'." | |||||
| (cond | |||||
| ((symbolp data) | |||||
| (let ((name (symbol-name data))) | |||||
| (when (string-match "\\`\\." name) | |||||
| ;; Return the cons cell inside a list, so it can be appended | |||||
| ;; with other results in the clause below. | |||||
| (list (cons data (intern (replace-match "" nil nil name))))))) | |||||
| ((not (consp data)) nil) | |||||
| (t (append (let-alist--deep-dot-search (car data)) | |||||
| (let-alist--deep-dot-search (cdr data)))))) | |||||
| (defun let-alist--access-sexp (symbol variable) | |||||
| "Return a sexp used to access SYMBOL inside VARIABLE." | |||||
| (let* ((clean (let-alist--remove-dot symbol)) | |||||
| (name (symbol-name clean))) | |||||
| (if (string-match "\\`\\." name) | |||||
| clean | |||||
| (let-alist--list-to-sexp | |||||
| (mapcar #'intern (nreverse (split-string name "\\."))) | |||||
| variable)))) | |||||
| (defun let-alist--list-to-sexp (list var) | |||||
| "Turn symbols LIST into recursive calls to `cdr' `assq' on VAR." | |||||
| `(cdr (assq ',(car list) | |||||
| ,(if (cdr list) (let-alist--list-to-sexp (cdr list) var) | |||||
| var)))) | |||||
| (defun let-alist--remove-dot (symbol) | |||||
| "Return SYMBOL, sans an initial dot." | |||||
| (let ((name (symbol-name symbol))) | |||||
| (if (string-match "\\`\\." name) | |||||
| (intern (replace-match "" nil nil name)) | |||||
| symbol))) | |||||
| ;;; The actual macro. | |||||
| ;;;###autoload | |||||
| (defmacro let-alist (alist &rest body) | |||||
| "Let-bind dotted symbols to their cdrs in ALIST and execute BODY. | |||||
| Dotted symbol is any symbol starting with a `.'. Only those present | |||||
| in BODY are let-bound and this search is done at compile time. | |||||
| For instance, the following code | |||||
| (let-alist alist | |||||
| (if (and .title .body) | |||||
| .body | |||||
| .site | |||||
| .site.contents)) | |||||
| essentially expands to | |||||
| (let ((.title (cdr (assq 'title alist))) | |||||
| (.body (cdr (assq 'body alist))) | |||||
| (.site (cdr (assq 'site alist))) | |||||
| (.site.contents (cdr (assq 'contents (cdr (assq 'site alist)))))) | |||||
| (if (and .title .body) | |||||
| .body | |||||
| .site | |||||
| .site.contents)) | |||||
| If you nest `let-alist' invocations, the inner one can't access | |||||
| the variables of the outer one. You can, however, access alists | |||||
| inside the original alist by using dots inside the symbol, as | |||||
| displayed in the example above." | |||||
| (declare (indent 1) (debug t)) | |||||
| (let ((var (make-symbol "alist"))) | |||||
| `(let ((,var ,alist)) | |||||
| (let ,(mapcar (lambda (x) `(,(car x) ,(let-alist--access-sexp (car x) var))) | |||||
| (delete-dups (let-alist--deep-dot-search body))) | |||||
| ,@body)))) | |||||
| ;;;; ChangeLog: | |||||
| ;; 2015-06-11 Artur Malabarba <bruce.connor.am@gmail.com> | |||||
| ;; | |||||
| ;; * let-alist (let-alist--deep-dot-search): Fix cons | |||||
| ;; | |||||
| ;; 2015-03-07 Artur Malabarba <bruce.connor.am@gmail.com> | |||||
| ;; | |||||
| ;; let-alist: Update copyright | |||||
| ;; | |||||
| ;; 2014-12-22 Artur Malabarba <bruce.connor.am@gmail.com> | |||||
| ;; | |||||
| ;; packages/let-alist: Use `make-symbol' instead of `gensym'. | |||||
| ;; | |||||
| ;; 2014-12-20 Artur Malabarba <bruce.connor.am@gmail.com> | |||||
| ;; | |||||
| ;; packages/let-alist: Enable access to deeper alists | |||||
| ;; | |||||
| ;; 2014-12-14 Artur Malabarba <bruce.connor.am@gmail.com> | |||||
| ;; | |||||
| ;; let-alist.el: Add lexical binding. Version bump. | |||||
| ;; | |||||
| ;; 2014-12-11 Artur Malabarba <bruce.connor.am@gmail.com> | |||||
| ;; | |||||
| ;; let-alist: New package | |||||
| ;; | |||||
| (provide 'let-alist) | |||||
| ;;; let-alist.el ends here | |||||
| @ -0,0 +1 @@ | |||||
| Good signature from 474F05837FBDEF9B GNU ELPA Signing Agent <elpasign@elpa.gnu.org> (trust undefined) created at 2015-10-20T05:05:02-0400 using DSA | |||||
| @ -0,0 +1,15 @@ | |||||
| ;;; seq-autoloads.el --- automatically extracted autoloads | |||||
| ;; | |||||
| ;;; Code: | |||||
| (add-to-list 'load-path (or (file-name-directory #$) (car load-path))) | |||||
| ;;;### (autoloads nil nil ("seq.el") (22223 32726 870720 0)) | |||||
| ;;;*** | |||||
| ;; Local Variables: | |||||
| ;; version-control: never | |||||
| ;; no-byte-compile: t | |||||
| ;; no-update-autoloads: t | |||||
| ;; End: | |||||
| ;;; seq-autoloads.el ends here | |||||
| @ -0,0 +1 @@ | |||||
| (define-package "seq" "1.11" "Sequence manipulation functions" 'nil :url "http://elpa.gnu.org/packages/seq.html" :keywords '("sequences")) | |||||
| @ -0,0 +1,564 @@ | |||||
| ;;; seq.el --- Sequence manipulation functions -*- lexical-binding: t -*- | |||||
| ;; Copyright (C) 2014-2015 Free Software Foundation, Inc. | |||||
| ;; Author: Nicolas Petton <nicolas@petton.fr> | |||||
| ;; Keywords: sequences | |||||
| ;; Version: 1.11 | |||||
| ;; Package: seq | |||||
| ;; Maintainer: emacs-devel@gnu.org | |||||
| ;; 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: | |||||
| ;; Sequence-manipulation functions that complement basic functions | |||||
| ;; provided by subr.el. | |||||
| ;; | |||||
| ;; All functions are prefixed with "seq-". | |||||
| ;; | |||||
| ;; All provided functions work on lists, strings and vectors. | |||||
| ;; | |||||
| ;; Functions taking a predicate or iterating over a sequence using a | |||||
| ;; function as argument take the function as their first argument and | |||||
| ;; the sequence as their second argument. All other functions take | |||||
| ;; the sequence as their first argument. | |||||
| ;; | |||||
| ;; All functions are tested in test/automated/seq-tests.el | |||||
| ;;; Code: | |||||
| (defmacro seq-doseq (spec &rest body) | |||||
| "Loop over a sequence. | |||||
| Similar to `dolist' but can be applied to lists, strings, and vectors. | |||||
| Evaluate BODY with VAR bound to each element of SEQ, in turn. | |||||
| \(fn (VAR SEQ) BODY...)" | |||||
| (declare (indent 1) (debug ((symbolp form &optional form) body))) | |||||
| (let ((length (make-symbol "length")) | |||||
| (seq (make-symbol "seq")) | |||||
| (index (make-symbol "index"))) | |||||
| `(let* ((,seq ,(cadr spec)) | |||||
| (,length (if (listp ,seq) nil (seq-length ,seq))) | |||||
| (,index (if ,length 0 ,seq))) | |||||
| (while (if ,length | |||||
| (< ,index ,length) | |||||
| (consp ,index)) | |||||
| (let ((,(car spec) (if ,length | |||||
| (prog1 (seq-elt ,seq ,index) | |||||
| (setq ,index (+ ,index 1))) | |||||
| (pop ,index)))) | |||||
| ,@body))))) | |||||
| (if (fboundp 'pcase-defmacro) | |||||
| ;; Implementation of `seq-let' based on a `pcase' | |||||
| ;; pattern. Requires Emacs>=25.1. | |||||
| (progn | |||||
| (pcase-defmacro seq (&rest args) | |||||
| "pcase pattern matching sequence elements. | |||||
| Matches if the object is a sequence (list, string or vector), and | |||||
| binds each element of ARGS to the corresponding element of the | |||||
| sequence." | |||||
| `(and (pred seq-p) | |||||
| ,@(seq--make-pcase-bindings args))) | |||||
| (defmacro seq-let (args seq &rest body) | |||||
| "Bind the variables in ARGS to the elements of SEQ then evaluate BODY. | |||||
| ARGS can also include the `&rest' marker followed by a variable | |||||
| name to be bound to the rest of SEQ." | |||||
| (declare (indent 2) (debug t)) | |||||
| `(pcase-let ((,(seq--make-pcase-patterns args) ,seq)) | |||||
| ,@body))) | |||||
| ;; Implementation of `seq-let' compatible with Emacs<25.1. | |||||
| (defmacro seq-let (args seq &rest body) | |||||
| "Bind the variables in ARGS to the elements of SEQ then evaluate BODY. | |||||
| ARGS can also include the `&rest' marker followed by a variable | |||||
| name to be bound to the rest of SEQ." | |||||
| (declare (indent 2) (debug t)) | |||||
| (let ((seq-var (make-symbol "seq"))) | |||||
| `(let* ((,seq-var ,seq) | |||||
| ,@(seq--make-bindings args seq-var)) | |||||
| ,@body)))) | |||||
| (defun seq-drop (seq n) | |||||
| "Return a subsequence of SEQ without its first N elements. | |||||
| The result is a sequence of the same type as SEQ. | |||||
| If N is a negative integer or zero, SEQ is returned." | |||||
| (if (<= n 0) | |||||
| seq | |||||
| (if (listp seq) | |||||
| (seq--drop-list seq n) | |||||
| (let ((length (seq-length seq))) | |||||
| (seq-subseq seq (min n length) length))))) | |||||
| (defun seq-take (seq n) | |||||
| "Return a subsequence of SEQ with its first N elements. | |||||
| The result is a sequence of the same type as SEQ. | |||||
| If N is a negative integer or zero, an empty sequence is | |||||
| returned." | |||||
| (if (listp seq) | |||||
| (seq--take-list seq n) | |||||
| (seq-subseq seq 0 (min (max n 0) (seq-length seq))))) | |||||
| (defun seq-drop-while (pred seq) | |||||
| "Return a sequence from the first element for which (PRED element) is nil in SEQ. | |||||
| The result is a sequence of the same type as SEQ." | |||||
| (if (listp seq) | |||||
| (seq--drop-while-list pred seq) | |||||
| (seq-drop seq (seq--count-successive pred seq)))) | |||||
| (defun seq-take-while (pred seq) | |||||
| "Return the successive elements for which (PRED element) is non-nil in SEQ. | |||||
| The result is a sequence of the same type as SEQ." | |||||
| (if (listp seq) | |||||
| (seq--take-while-list pred seq) | |||||
| (seq-take seq (seq--count-successive pred seq)))) | |||||
| (defun seq-filter (pred seq) | |||||
| "Return a list of all the elements for which (PRED element) is non-nil in SEQ." | |||||
| (let ((exclude (make-symbol "exclude"))) | |||||
| (delq exclude (seq-map (lambda (elt) | |||||
| (if (funcall pred elt) | |||||
| elt | |||||
| exclude)) | |||||
| seq)))) | |||||
| (defun seq-remove (pred seq) | |||||
| "Return a list of all the elements for which (PRED element) is nil in SEQ." | |||||
| (seq-filter (lambda (elt) (not (funcall pred elt))) | |||||
| seq)) | |||||
| (defun seq-reduce (function seq initial-value) | |||||
| "Reduce the function FUNCTION across SEQ, starting with INITIAL-VALUE. | |||||
| Return the result of calling FUNCTION with INITIAL-VALUE and the | |||||
| first element of SEQ, then calling FUNCTION with that result and | |||||
| the second element of SEQ, then with that result and the third | |||||
| element of SEQ, etc. | |||||
| If SEQ is empty, return INITIAL-VALUE and FUNCTION is not called." | |||||
| (if (seq-empty-p seq) | |||||
| initial-value | |||||
| (let ((acc initial-value)) | |||||
| (seq-doseq (elt seq) | |||||
| (setq acc (funcall function acc elt))) | |||||
| acc))) | |||||
| (defun seq-some (pred seq) | |||||
| "Return the first value for which if (PRED element) is non-nil for in SEQ." | |||||
| (catch 'seq--break | |||||
| (seq-doseq (elt seq) | |||||
| (let ((result (funcall pred elt))) | |||||
| (when result | |||||
| (throw 'seq--break result)))) | |||||
| nil)) | |||||
| (defun seq-find (pred seq &optional default) | |||||
| "Return the first element for which (PRED element) is non-nil in SEQ. | |||||
| If no element is found, return DEFAULT. | |||||
| Note that `seq-find' has an ambiguity if the found element is | |||||
| identical to DEFAULT, as it cannot be known if an element was | |||||
| found or not." | |||||
| (catch 'seq--break | |||||
| (seq-doseq (elt seq) | |||||
| (when (funcall pred elt) | |||||
| (throw 'seq--break elt))) | |||||
| default)) | |||||
| (defun seq-every-p (pred seq) | |||||
| "Return non-nil if (PRED element) is non-nil for all elements of the sequence SEQ." | |||||
| (catch 'seq--break | |||||
| (seq-doseq (elt seq) | |||||
| (or (funcall pred elt) | |||||
| (throw 'seq--break nil))) | |||||
| t)) | |||||
| (defun seq-count (pred seq) | |||||
| "Return the number of elements for which (PRED element) is non-nil in SEQ." | |||||
| (let ((count 0)) | |||||
| (seq-doseq (elt seq) | |||||
| (when (funcall pred elt) | |||||
| (setq count (+ 1 count)))) | |||||
| count)) | |||||
| (defun seq-empty-p (seq) | |||||
| "Return non-nil if the sequence SEQ is empty, nil otherwise." | |||||
| (if (listp seq) | |||||
| (null seq) | |||||
| (= 0 (seq-length seq)))) | |||||
| (defun seq-sort (pred seq) | |||||
| "Return a sorted sequence comparing using PRED the elements of SEQ. | |||||
| The result is a sequence of the same type as SEQ." | |||||
| (if (listp seq) | |||||
| (sort (seq-copy seq) pred) | |||||
| (let ((result (seq-sort pred (append seq nil)))) | |||||
| (seq-into result (type-of seq))))) | |||||
| (defun seq-contains (seq elt &optional testfn) | |||||
| "Return the first element in SEQ that equals to ELT. | |||||
| Equality is defined by TESTFN if non-nil or by `equal' if nil." | |||||
| (seq-some (lambda (e) | |||||
| (funcall (or testfn #'equal) elt e)) | |||||
| seq)) | |||||
| (defun seq-position (seq elt &optional testfn) | |||||
| "Return the index of the first element in SEQ that is equal to ELT. | |||||
| Equality is defined by TESTFN if non-nil or by `equal' if nil." | |||||
| (let ((index 0)) | |||||
| (catch 'seq--break | |||||
| (seq-doseq (e seq) | |||||
| (when (funcall (or testfn #'equal) e elt) | |||||
| (throw 'seq--break index)) | |||||
| (setq index (1+ index))) | |||||
| nil))) | |||||
| (defun seq-uniq (seq &optional testfn) | |||||
| "Return a list of the elements of SEQ with duplicates removed. | |||||
| TESTFN is used to compare elements, or `equal' if TESTFN is nil." | |||||
| (let ((result '())) | |||||
| (seq-doseq (elt seq) | |||||
| (unless (seq-contains result elt testfn) | |||||
| (setq result (cons elt result)))) | |||||
| (nreverse result))) | |||||
| (defun seq-subseq (seq start &optional end) | |||||
| "Return the subsequence of SEQ from START to END. | |||||
| If END is omitted, it defaults to the length of the sequence. | |||||
| If START or END is negative, it counts from the end." | |||||
| (cond ((or (stringp seq) (vectorp seq)) (substring seq start end)) | |||||
| ((listp seq) | |||||
| (let (len (errtext (format "Bad bounding indices: %s, %s" start end))) | |||||
| (and end (< end 0) (setq end (+ end (setq len (seq-length seq))))) | |||||
| (if (< start 0) (setq start (+ start (or len (setq len (seq-length seq)))))) | |||||
| (when (> start 0) | |||||
| (setq seq (nthcdr (1- start) seq)) | |||||
| (or seq (error "%s" errtext)) | |||||
| (setq seq (cdr seq))) | |||||
| (if end | |||||
| (let ((res nil)) | |||||
| (while (and (>= (setq end (1- end)) start) seq) | |||||
| (push (pop seq) res)) | |||||
| (or (= (1+ end) start) (error "%s" errtext)) | |||||
| (nreverse res)) | |||||
| (seq-copy seq)))) | |||||
| (t (error "Unsupported sequence: %s" seq)))) | |||||
| (defun seq-concatenate (type &rest seqs) | |||||
| "Concatenate, into a sequence of type TYPE, the sequences SEQS. | |||||
| TYPE must be one of following symbols: vector, string or list. | |||||
| \n(fn TYPE SEQUENCE...)" | |||||
| (pcase type | |||||
| (`vector (apply #'vconcat seqs)) | |||||
| (`string (apply #'concat seqs)) | |||||
| (`list (apply #'append (append seqs '(nil)))) | |||||
| (t (error "Not a sequence type name: %S" type)))) | |||||
| (defun seq-mapcat (function seq &optional type) | |||||
| "Concatenate the result of applying FUNCTION to each element of SEQ. | |||||
| The result is a sequence of type TYPE, or a list if TYPE is nil." | |||||
| (apply #'seq-concatenate (or type 'list) | |||||
| (seq-map function seq))) | |||||
| (defun seq-partition (seq n) | |||||
| "Return a list of the elements of SEQ grouped into sub-sequences of length N. | |||||
| The last sequence may contain less than N elements. If N is a | |||||
| negative integer or 0, nil is returned." | |||||
| (unless (< n 1) | |||||
| (let ((result '())) | |||||
| (while (not (seq-empty-p seq)) | |||||
| (push (seq-take seq n) result) | |||||
| (setq seq (seq-drop seq n))) | |||||
| (nreverse result)))) | |||||
| (defun seq-intersection (seq1 seq2 &optional testfn) | |||||
| "Return a list of the elements that appear in both SEQ1 and SEQ2. | |||||
| Equality is defined by TESTFN if non-nil or by `equal' if nil." | |||||
| (seq-reduce (lambda (acc elt) | |||||
| (if (seq-contains seq2 elt testfn) | |||||
| (cons elt acc) | |||||
| acc)) | |||||
| (seq-reverse seq1) | |||||
| '())) | |||||
| (defun seq-difference (seq1 seq2 &optional testfn) | |||||
| "Return a list of the elements that appear in SEQ1 but not in SEQ2. | |||||
| Equality is defined by TESTFN if non-nil or by `equal' if nil." | |||||
| (seq-reduce (lambda (acc elt) | |||||
| (if (not (seq-contains seq2 elt testfn)) | |||||
| (cons elt acc) | |||||
| acc)) | |||||
| (seq-reverse seq1) | |||||
| '())) | |||||
| (defun seq-group-by (function seq) | |||||
| "Apply FUNCTION to each element of SEQ. | |||||
| Separate the elements of SEQ into an alist using the results as | |||||
| keys. Keys are compared using `equal'." | |||||
| (seq-reduce | |||||
| (lambda (acc elt) | |||||
| (let* ((key (funcall function elt)) | |||||
| (cell (assoc key acc))) | |||||
| (if cell | |||||
| (setcdr cell (push elt (cdr cell))) | |||||
| (push (list key elt) acc)) | |||||
| acc)) | |||||
| (seq-reverse seq) | |||||
| nil)) | |||||
| (defalias 'seq-reverse | |||||
| (if (ignore-errors (reverse [1 2])) | |||||
| #'reverse | |||||
| (lambda (seq) | |||||
| "Return the reversed copy of list, vector, or string SEQ. | |||||
| See also the function `nreverse', which is used more often." | |||||
| (let ((result '())) | |||||
| (seq-map (lambda (elt) (push elt result)) | |||||
| seq) | |||||
| (if (listp seq) | |||||
| result | |||||
| (seq-into result (type-of seq))))))) | |||||
| (defun seq-into (seq type) | |||||
| "Convert the sequence SEQ into a sequence of type TYPE. | |||||
| TYPE can be one of the following symbols: vector, string or list." | |||||
| (pcase type | |||||
| (`vector (vconcat seq)) | |||||
| (`string (concat seq)) | |||||
| (`list (append seq nil)) | |||||
| (t (error "Not a sequence type name: %S" type)))) | |||||
| (defun seq-min (seq) | |||||
| "Return the smallest element of SEQ. | |||||
| SEQ must be a sequence of numbers or markers." | |||||
| (apply #'min (seq-into seq 'list))) | |||||
| (defun seq-max (seq) | |||||
| "Return the largest element of SEQ. | |||||
| SEQ must be a sequence of numbers or markers." | |||||
| (apply #'max (seq-into seq 'list))) | |||||
| (defun seq--drop-list (list n) | |||||
| "Return a list from LIST without its first N elements. | |||||
| This is an optimization for lists in `seq-drop'." | |||||
| (while (and list (> n 0)) | |||||
| (setq list (cdr list) | |||||
| n (1- n))) | |||||
| list) | |||||
| (defun seq--take-list (list n) | |||||
| "Return a list from LIST made of its first N elements. | |||||
| This is an optimization for lists in `seq-take'." | |||||
| (let ((result '())) | |||||
| (while (and list (> n 0)) | |||||
| (setq n (1- n)) | |||||
| (push (pop list) result)) | |||||
| (nreverse result))) | |||||
| (defun seq--drop-while-list (pred list) | |||||
| "Return a list from the first element for which (PRED element) is nil in LIST. | |||||
| This is an optimization for lists in `seq-drop-while'." | |||||
| (while (and list (funcall pred (car list))) | |||||
| (setq list (cdr list))) | |||||
| list) | |||||
| (defun seq--take-while-list (pred list) | |||||
| "Return the successive elements for which (PRED element) is non-nil in LIST. | |||||
| This is an optimization for lists in `seq-take-while'." | |||||
| (let ((result '())) | |||||
| (while (and list (funcall pred (car list))) | |||||
| (push (pop list) result)) | |||||
| (nreverse result))) | |||||
| (defun seq--count-successive (pred seq) | |||||
| "Return the number of successive elements for which (PRED element) is non-nil in SEQ." | |||||
| (let ((n 0) | |||||
| (len (seq-length seq))) | |||||
| (while (and (< n len) | |||||
| (funcall pred (seq-elt seq n))) | |||||
| (setq n (+ 1 n))) | |||||
| n)) | |||||
| (defun seq--make-pcase-bindings (args) | |||||
| "Return a list of bindings of the variables in ARGS to the elements of a sequence." | |||||
| (let ((bindings '()) | |||||
| (index 0) | |||||
| (rest-marker nil)) | |||||
| (seq-doseq (name args) | |||||
| (unless rest-marker | |||||
| (pcase name | |||||
| (`&rest | |||||
| (progn (push `(app (pcase--flip seq-drop ,index) | |||||
| ,(seq--elt-safe args (1+ index))) | |||||
| bindings) | |||||
| (setq rest-marker t))) | |||||
| (t | |||||
| (push `(app (pcase--flip seq--elt-safe ,index) ,name) bindings)))) | |||||
| (setq index (1+ index))) | |||||
| bindings)) | |||||
| (defun seq--make-pcase-patterns (args) | |||||
| "Return a list of `(seq ...)' pcase patterns from the argument list ARGS." | |||||
| (cons 'seq | |||||
| (seq-map (lambda (elt) | |||||
| (if (seq-p elt) | |||||
| (seq--make-pcase-patterns elt) | |||||
| elt)) | |||||
| args))) | |||||
| ;; Helper function for the Backward-compatible version of `seq-let' | |||||
| ;; for Emacs<25.1. | |||||
| (defun seq--make-bindings (args seq &optional bindings) | |||||
| "Return a list of bindings of the variables in ARGS to the elements of a sequence. | |||||
| if BINDINGS is non-nil, append new bindings to it, and return | |||||
| BINDINGS." | |||||
| (let ((index 0) | |||||
| (rest-marker nil)) | |||||
| (seq-doseq (name args) | |||||
| (unless rest-marker | |||||
| (pcase name | |||||
| ((pred seq-p) | |||||
| (setq bindings (seq--make-bindings (seq--elt-safe args index) | |||||
| `(seq--elt-safe ,seq ,index) | |||||
| bindings))) | |||||
| (`&rest | |||||
| (progn (push `(,(seq--elt-safe args (1+ index)) | |||||
| (seq-drop ,seq ,index)) | |||||
| bindings) | |||||
| (setq rest-marker t))) | |||||
| (t | |||||
| (push `(,name (seq--elt-safe ,seq ,index)) bindings)))) | |||||
| (setq index (1+ index))) | |||||
| bindings)) | |||||
| (defun seq--elt-safe (seq n) | |||||
| "Return element of SEQ at the index N. | |||||
| If no element is found, return nil." | |||||
| (when (or (listp seq) | |||||
| (and (sequencep seq) | |||||
| (> (seq-length seq) n))) | |||||
| (seq-elt seq n))) | |||||
| (defun seq--activate-font-lock-keywords () | |||||
| "Activate font-lock keywords for some symbols defined in seq." | |||||
| (font-lock-add-keywords 'emacs-lisp-mode | |||||
| '("\\<seq-doseq\\>" "\\<seq-let\\>"))) | |||||
| (defalias 'seq-copy #'copy-sequence) | |||||
| (defalias 'seq-elt #'elt) | |||||
| (defalias 'seq-length #'length) | |||||
| (defalias 'seq-do #'mapc) | |||||
| (defalias 'seq-each #'seq-do) | |||||
| (defalias 'seq-map #'mapcar) | |||||
| (defalias 'seq-p #'sequencep) | |||||
| (unless (fboundp 'elisp--font-lock-flush-elisp-buffers) | |||||
| ;; In Emacs≥25, (via elisp--font-lock-flush-elisp-buffers and a few others) | |||||
| ;; we automatically highlight macros. | |||||
| (add-hook 'emacs-lisp-mode-hook #'seq--activate-font-lock-keywords)) | |||||
| ;;;; ChangeLog: | |||||
| ;; 2015-10-20 Nicolas Petton <nicolas@petton.fr> | |||||
| ;; | |||||
| ;; Update seq.el to version 1.11 | |||||
| ;; | |||||
| ;; * packages/seq/seq.el: | |||||
| ;; * packages/seq/tests/seq-tests.el: Update. | |||||
| ;; | |||||
| ;; 2015-09-18 Nicolas Petton <nicolas@petton.fr> | |||||
| ;; | |||||
| ;; Update seq.el to version 1.9 | |||||
| ;; | |||||
| ;; * packages/seq/seq.el: Update to version 1.9. | |||||
| ;; * packages/seq/tests/seq-tests.el: Update to version 1.9. | |||||
| ;; | |||||
| ;; 2015-07-09 Nicolas Petton <nicolas@petton.fr> | |||||
| ;; | |||||
| ;; Update seq.el to version 1.8 | |||||
| ;; | |||||
| ;; * packages/seq/seq.el: Update to version 1.8. | |||||
| ;; * packages/seq/tests/seq-tests.el: Update to version 1.8. | |||||
| ;; | |||||
| ;; 2015-05-15 Nicolas Petton <nicolas@petton.fr> | |||||
| ;; | |||||
| ;; Update seq.el to version 1.7 | |||||
| ;; | |||||
| ;; * packages/seq/seq.el: Update to version 1.7. | |||||
| ;; * packages/seq/tests/seq-tests.el: Update to version 1.7. | |||||
| ;; | |||||
| ;; 2015-04-27 Nicolas Petton <nicolas@petton.fr> | |||||
| ;; | |||||
| ;; * packages/seq/seq.el: Update seq.el to version 1.5. | |||||
| ;; | |||||
| ;; 2015-04-15 Nicolas Petton <nicolas@petton.fr> | |||||
| ;; | |||||
| ;; seq.el update | |||||
| ;; | |||||
| ;; * packages/seq/seq.el: Update seq.el to version 1.4 | |||||
| ;; * packages/seq/tests/seq-tests.el: Update seq.el to version 1.4 | |||||
| ;; | |||||
| ;; 2015-03-25 Nicolas Petton <nicolas@petton.fr> | |||||
| ;; | |||||
| ;; Rephrases a comment in seq.el about the order of the arguments | |||||
| ;; | |||||
| ;; * packages/seq/seq.el: Better comment about the order of the arguments | |||||
| ;; | |||||
| ;; 2015-03-09 Nicolas Petton <nicolas@petton.fr> | |||||
| ;; | |||||
| ;; Update seq.el to version 1.3 | |||||
| ;; | |||||
| ;; * packages/seq/seq.el: update to version 1.3 | |||||
| ;; * packages/seq/tests/seq-tests.el: update to version 1.3 | |||||
| ;; | |||||
| ;; 2015-02-11 Nicolas Petton <nicolas@petton.fr> | |||||
| ;; | |||||
| ;; Update seq.el to version 1.2 | |||||
| ;; | |||||
| ;; * package/seq/seq.el: Update to version 1.2 | |||||
| ;; * packages/seq/tests/seq-tests.el: Update to version 1.2 | |||||
| ;; | |||||
| ;; 2015-02-09 Nicolas Petton <nicolas@petton.fr> | |||||
| ;; | |||||
| ;; Update seq.el to version 1.1.1 | |||||
| ;; | |||||
| ;; * package/seq/seq.el: Update to version 1.1.1 | |||||
| ;; * packages/seq/tests/seq-tests.el: Update to version 1.1.1 | |||||
| ;; | |||||
| ;; 2015-02-06 Nicolas Petton <nicolas@petton.fr> | |||||
| ;; | |||||
| ;; Update seq.el to version 1.1 | |||||
| ;; | |||||
| ;; * packages/seq/seq.el: Update to version 1.1 | |||||
| ;; * packages/seq/tests/seq-tests.el: Update to version 1.1 | |||||
| ;; | |||||
| ;; 2015-01-14 Nicolas Petton <nicolas@petton.fr> | |||||
| ;; | |||||
| ;; packages/seq: New package | |||||
| ;; | |||||
| (provide 'seq) | |||||
| ;;; seq.el ends here | |||||
| @ -0,0 +1,26 @@ | |||||
| ;;; tern-autoloads.el --- automatically extracted autoloads | |||||
| ;; | |||||
| ;;; Code: | |||||
| (add-to-list 'load-path (or (file-name-directory #$) (car load-path))) | |||||
| ;;;### (autoloads nil "tern" "tern.el" (22223 33130 0 0)) | |||||
| ;;; Generated autoloads from tern.el | |||||
| (autoload 'tern-use-server "tern" "\ | |||||
| \(fn PORT SERVER)" t nil) | |||||
| (autoload 'tern-mode "tern" "\ | |||||
| Minor mode binding to the Tern JavaScript analyzer | |||||
| \(fn &optional ARG)" t nil) | |||||
| ;;;*** | |||||
| ;; Local Variables: | |||||
| ;; version-control: never | |||||
| ;; no-byte-compile: t | |||||
| ;; no-update-autoloads: t | |||||
| ;; End: | |||||
| ;;; tern-autoloads.el ends here | |||||
| @ -0,0 +1 @@ | |||||
| (define-package "tern" "20151228.511" "Tern-powered JavaScript integration" '((json "1.2") (cl-lib "0.5") (emacs "24")) :url "http://ternjs.net/") | |||||
| @ -0,0 +1,601 @@ | |||||
| ;;; tern.el --- Tern-powered JavaScript integration -*- lexical-binding: t -*- | |||||
| ;; Author: Marijn Haverbeke | |||||
| ;; URL: http://ternjs.net/ | |||||
| ;; Package-Version: 20151228.511 | |||||
| ;; Version: 0.0.1 | |||||
| ;; Package-Requires: ((json "1.2") (cl-lib "0.5") (emacs "24")) | |||||
| ;;; Code: | |||||
| (require 'cl-lib) | |||||
| (require 'json) | |||||
| (require 'url) | |||||
| (require 'url-http) | |||||
| (defvar tern-known-port nil) | |||||
| (defvar tern-server nil) | |||||
| (defvar tern-explicit-port nil) | |||||
| (defvar tern-project-dir nil) | |||||
| (defun tern-message (fmt &rest objects) | |||||
| (apply 'message fmt objects)) | |||||
| (defun tern-req (port doc c) | |||||
| (let* ((url-mime-charset-string nil) ; Suppress huge, useless header | |||||
| (url-request-method "POST") | |||||
| (deactivate-mark nil) ; Prevents json-encode from interfering with shift-selection-mode | |||||
| (url-request-data (encode-coding-string (json-encode doc) 'utf-8)) | |||||
| (url-show-status nil) | |||||
| (url (url-parse-make-urlobj "http" nil nil tern-server port "/" nil nil nil))) | |||||
| (url-http url #'tern-req-finished (list c)))) | |||||
| (defun tern-req-finished (c) | |||||
| (defvar url-http-process) | |||||
| (defvar url-callback-function) | |||||
| (let ((is-error (and (consp c) (eq (car c) :error))) | |||||
| (found-body (search-forward "\n\n" nil t)) | |||||
| (deactivate-mark nil)) | |||||
| (set-buffer-multibyte t) | |||||
| (if (or is-error (not found-body)) | |||||
| (let ((message (and found-body | |||||
| (buffer-substring-no-properties (point) (point-max)))) | |||||
| (url-callback-function #'ignore)) | |||||
| (delete-process url-http-process) | |||||
| (kill-buffer (current-buffer)) | |||||
| (funcall (if is-error (cddr c) c) | |||||
| (cons (and is-error (cadr c)) message) nil)) | |||||
| (let ((json (json-read))) | |||||
| (delete-process url-http-process) | |||||
| (kill-buffer (current-buffer)) | |||||
| (funcall c nil json))))) | |||||
| (defun tern-project-dir () | |||||
| (or tern-project-dir | |||||
| (and (not (buffer-file-name)) (setf tern-project-dir "")) | |||||
| (let ((project-dir (file-name-directory (buffer-file-name)))) | |||||
| (cl-loop for cur = project-dir then (let ((shorter (file-name-directory (substring cur 0 (1- (length cur)))))) | |||||
| (and (< (length shorter) (length cur)) shorter)) | |||||
| while cur do | |||||
| (when (file-exists-p (expand-file-name ".tern-project" cur)) | |||||
| (cl-return (setf project-dir cur)))) | |||||
| (setf tern-project-dir project-dir)))) | |||||
| (defun tern-find-server (c &optional ignore-port) | |||||
| (cl-block nil | |||||
| (when tern-known-port | |||||
| (cl-return (if (consp tern-known-port) | |||||
| (funcall c nil (cdr tern-known-port)) | |||||
| (funcall c tern-known-port nil)))) | |||||
| (if tern-explicit-port | |||||
| (funcall c tern-explicit-port nil) | |||||
| (unless (buffer-file-name) | |||||
| (cl-return (funcall c nil "Buffer is not associated with a file"))) | |||||
| (let ((deactivate-mark nil) | |||||
| (port-file (expand-file-name ".tern-port" (tern-project-dir)))) | |||||
| (when (file-exists-p port-file) | |||||
| (let ((port (string-to-number (with-temp-buffer | |||||
| (insert-file-contents port-file) | |||||
| (buffer-string))))) | |||||
| (unless (eq port ignore-port) | |||||
| (setf tern-known-port port) | |||||
| (cl-return (funcall c port nil)))))) | |||||
| (tern-start-server c)))) | |||||
| (defvar tern-command | |||||
| (let* ((script-file (or load-file-name | |||||
| (and (boundp 'bytecomp-filename) bytecomp-filename) | |||||
| buffer-file-name)) | |||||
| (bin-file (expand-file-name "../bin/tern" (file-name-directory (file-truename script-file)))) | |||||
| (tern-itself (list (if (file-exists-p bin-file) bin-file "tern")))) | |||||
| (if (eq system-type 'windows-nt) (cons "node" tern-itself) tern-itself)) | |||||
| "The command to be run to start the Tern server. Should be a | |||||
| list of strings, giving the binary name and arguments.") | |||||
| (defun tern-start-server (c) | |||||
| (let* ((default-directory tern-project-dir) | |||||
| (cmd (if (member "--strip-crs" tern-command) tern-command (append tern-command '("--strip-crs")))) | |||||
| (proc (apply #'start-process "Tern" nil cmd)) | |||||
| (all-output "")) | |||||
| (set-process-query-on-exit-flag proc nil) | |||||
| (set-process-sentinel proc (lambda (_proc _event) | |||||
| (delete-process proc) | |||||
| (setf tern-known-port (cons :failed (concat "Could not start Tern server\n" all-output))) | |||||
| (run-at-time "30 sec" nil | |||||
| (lambda (buf) | |||||
| (with-current-buffer buf | |||||
| (when (consp tern-known-port) (setf tern-known-port nil)))) | |||||
| (current-buffer)) | |||||
| (funcall c nil tern-known-port))) | |||||
| (set-process-filter proc (lambda (proc output) | |||||
| (if (not (string-match "Listening on port \\([0-9][0-9]*\\)" output)) | |||||
| (setf all-output (concat all-output output)) | |||||
| (setf tern-known-port (string-to-number (match-string 1 output))) | |||||
| (set-process-sentinel proc (lambda (proc _event) | |||||
| (delete-process proc) | |||||
| (setf tern-known-port nil))) | |||||
| (set-process-filter proc nil) | |||||
| (funcall c tern-known-port nil)))))) | |||||
| (defvar tern-command-generation 0) | |||||
| (defvar tern-activity-since-command -1) | |||||
| (defvar tern-last-point-pos nil) | |||||
| (defvar tern-last-completions nil) | |||||
| (defvar tern-last-argument-hints nil) | |||||
| (defvar tern-buffer-is-dirty nil) | |||||
| (defun tern-project-relative-file () | |||||
| (if (buffer-file-name) | |||||
| (substring (buffer-file-name) (length (tern-project-dir))) | |||||
| (buffer-name))) | |||||
| (defun tern-get-partial-file (at) | |||||
| (let* (min-indent start-pos end-pos | |||||
| (min-pos (max 0 (- at 2000)))) | |||||
| (save-excursion | |||||
| (goto-char at) | |||||
| (cl-loop | |||||
| (unless (re-search-backward "\\bfunction\\b" min-pos t) (cl-return)) | |||||
| (let ((indent (current-indentation)) | |||||
| (pos (line-beginning-position))) | |||||
| (when (or (not min-indent) (< indent min-indent)) | |||||
| (setf min-indent indent)) | |||||
| (goto-char pos) | |||||
| (when (<= pos min-pos) (cl-return)))) | |||||
| (unless start-pos (goto-char min-pos) (setf start-pos (line-beginning-position)))) | |||||
| (save-excursion | |||||
| (goto-char (min (+ at 1000) (point-max))) | |||||
| (let ((line-beg (line-beginning-position))) | |||||
| (setf end-pos (if (<= line-beg at) (line-end-position) line-beg)))) | |||||
| `((type . "part") | |||||
| (name . ,(tern-project-relative-file)) | |||||
| (offset . ,(1- start-pos)) | |||||
| (text . ,(buffer-substring-no-properties start-pos end-pos))))) | |||||
| (defun tern-modified-sibling-buffers () | |||||
| (let (found) | |||||
| (dolist (buf (buffer-list)) | |||||
| (when (and (not (eq buf (current-buffer))) | |||||
| (buffer-local-value 'tern-mode buf) | |||||
| (buffer-local-value 'tern-buffer-is-dirty buf) | |||||
| (equal tern-project-dir (buffer-local-value 'tern-project-dir buf))) | |||||
| (with-current-buffer buf | |||||
| (push `((type . "full") | |||||
| (name . ,(tern-project-relative-file)) | |||||
| (text . ,(buffer-string))) found)))) | |||||
| (nreverse found))) | |||||
| (defun tern-run-request (f doc) | |||||
| (let ((buffer (current-buffer)) | |||||
| (retrying nil) | |||||
| callback runner) | |||||
| (setf callback (lambda (port err) | |||||
| (if port | |||||
| (condition-case err | |||||
| (tern-req port doc runner) | |||||
| (error (funcall runner (list err) nil))) | |||||
| (funcall f err nil)))) | |||||
| (setf runner (lambda (err data) | |||||
| (with-current-buffer buffer | |||||
| (cond ((and err (not retrying) | |||||
| (or (eq (cl-cadar err) 'connection-failed) | |||||
| (eq (caar err) 'file-error))) | |||||
| (setf retrying t) | |||||
| (let ((old-port tern-known-port)) | |||||
| (setf tern-known-port nil) | |||||
| (if tern-explicit-port | |||||
| (funcall callback nil err) | |||||
| (tern-find-server callback old-port)))) | |||||
| (t (funcall f err data)))))) | |||||
| (tern-find-server callback))) | |||||
| (defun tern-run-query (f query pos &optional mode) | |||||
| (when (stringp query) (setf query `((type . ,query)))) | |||||
| (let ((generation (cl-incf tern-command-generation)) | |||||
| (doc `((query . ,query))) | |||||
| (files (and (eq mode :full-file) (tern-modified-sibling-buffers))) | |||||
| file-name | |||||
| (pos pos)) | |||||
| (cond | |||||
| ((not tern-buffer-is-dirty) (setf file-name (tern-project-relative-file))) | |||||
| ((and (not (eq mode :full-file)) (> (buffer-size) 8000)) | |||||
| (push (tern-get-partial-file pos) files) | |||||
| (setf file-name "#0") | |||||
| (cl-decf pos (cdr (assq 'offset (car files))))) | |||||
| (t | |||||
| (push `((type . "full") (text . ,(buffer-string)) (name . ,(tern-project-relative-file))) files) | |||||
| (setf file-name (tern-project-relative-file)))) | |||||
| (when files (push `(files . ,(apply #'vector files)) doc)) | |||||
| (push `(file . ,file-name) (cdr (assq 'query doc))) | |||||
| (push `(end . ,(1- pos)) (cdr (assq 'query doc))) | |||||
| (tern-run-request | |||||
| (lambda (err data) | |||||
| (when (< tern-activity-since-command generation) | |||||
| (cond ((not err) | |||||
| (dolist (file files) | |||||
| (when (equal (cdr (assq 'type file)) "full") | |||||
| (with-current-buffer (find-file-noselect (expand-file-name (cdr (assq 'name file)) tern-project-dir)) | |||||
| (setf tern-buffer-is-dirty nil)))) | |||||
| (funcall f data)) | |||||
| ((not (eq mode :silent)) (tern-message "Request failed: %s" err))))) | |||||
| doc))) | |||||
| (defun tern-send-buffer-to-server () | |||||
| (when (buffer-file-name) | |||||
| (tern-run-request (lambda (_err _data)) | |||||
| `((files . [((type . "full") | |||||
| (name . ,(tern-project-relative-file)) | |||||
| (text . ,(buffer-string)))]))))) | |||||
| ;; Completion | |||||
| (defun tern-completion-at-point-fn () | |||||
| (tern-run-query #'tern-do-complete '((type . "completions") (includeKeywords . t)) (point))) | |||||
| (defun tern-completion-at-point () | |||||
| (or (tern-completion-matches-last) | |||||
| ;; Do not return a closure, as calling car-safe (e.g. in | |||||
| ;; completion-at-point) on such an object returns 'closure | |||||
| ;; instead of nil. | |||||
| 'tern-completion-at-point-fn)) | |||||
| (defun tern-do-complete (data) | |||||
| (let ((cs (cl-loop for elt across (cdr (assq 'completions data)) collect elt)) | |||||
| (start (+ 1 (cdr (assq 'start data)))) | |||||
| (end (+ 1 (cdr (assq 'end data))))) | |||||
| (setf tern-last-completions (list (buffer-substring-no-properties start end) start end cs)) | |||||
| (let ((completion-in-region-mode-predicate nil)) | |||||
| (completion-in-region start end cs)))) | |||||
| (defun tern-completion-matches-last () | |||||
| (when tern-last-completions | |||||
| (cl-destructuring-bind (word start end list) tern-last-completions | |||||
| (and (<= end (point-max)) | |||||
| (equal word (buffer-substring-no-properties start end)) | |||||
| (if (= (point) end) | |||||
| (cdr tern-last-completions) | |||||
| (and (>= (point) end) | |||||
| (<= (point) (+ end 50)) | |||||
| (string-match-p "^[a-zA-Z0-9_$]*$" (buffer-substring-no-properties end (point))) | |||||
| (let ((new-word (buffer-substring-no-properties start (point)))) | |||||
| (list start (point) | |||||
| (cl-loop for elt in list | |||||
| when (eq (compare-strings word 0 (length word) new-word 0 (length word)) t) | |||||
| collect elt))))))))) | |||||
| ;; Argument hints | |||||
| (defvar tern-update-argument-hints-timer 500 "millisecond.") | |||||
| (defvar tern-update-argument-hints-async nil | |||||
| "[internal] If non-nil, `tern-update-argument-hints' will be called later.") | |||||
| (defun tern-update-argument-hints-async () | |||||
| (when tern-update-argument-hints-async | |||||
| (cancel-timer tern-update-argument-hints-async)) | |||||
| (setq tern-update-argument-hints-async | |||||
| (run-at-time | |||||
| (* 0.001 tern-update-argument-hints-timer) nil | |||||
| (lambda () | |||||
| (condition-case err | |||||
| (tern-update-argument-hints) | |||||
| (t (message "tern-update-argument-hints : %S" err))) | |||||
| (setq tern-update-argument-hints-async nil))))) | |||||
| (defun tern-update-argument-hints () | |||||
| (let ((opening-paren (cadr (syntax-ppss)))) | |||||
| (when (and opening-paren (equal (char-after opening-paren) ?\()) | |||||
| (if (and tern-last-argument-hints (eq (car tern-last-argument-hints) opening-paren)) | |||||
| (tern-show-argument-hints) | |||||
| (tern-run-query (lambda (data) | |||||
| (let ((type (tern-parse-function-type data))) | |||||
| (when type | |||||
| (setf tern-last-argument-hints (cons opening-paren type)) | |||||
| (tern-show-argument-hints)))) | |||||
| `((type . "type") | |||||
| (preferFunction . t)) | |||||
| opening-paren | |||||
| :silent))))) | |||||
| (defun tern-skip-matching-brackets (end-chars) | |||||
| (let ((depth 0) (end (+ (point) 500))) | |||||
| (cl-loop while (< (point) (point-max)) do | |||||
| (let ((next (char-after (point)))) | |||||
| (cond | |||||
| ((and (<= depth 0) (cl-find next end-chars)) (cl-return t)) | |||||
| ((or (eq next ?\)) (eq next ?\]) (eq next ?\})) (cl-decf depth)) | |||||
| ((or (eq next ?\() (eq next ?\[) (eq next ?\{)) (cl-incf depth)) | |||||
| ((> (point) end) (cl-return nil))) | |||||
| (forward-char))))) | |||||
| (defun tern-parse-function-type (data) | |||||
| (let ((type (cdr (assq 'type data))) | |||||
| (name (or (cdr (assq 'exprName data)) (cdr (assq 'name data)) "fn")) | |||||
| (deactivate-mark nil)) | |||||
| (when (string-match-p "^fn(" type) | |||||
| (with-temp-buffer | |||||
| (insert type) | |||||
| (goto-char 4) | |||||
| (let (args retval) | |||||
| (cl-loop until (eq (char-after (point)) ?\)) do | |||||
| (let ((name (when (looking-at "\\([a-zA-Z0-9_$?]*\\):\\s-*") | |||||
| (goto-char (match-end 0)) | |||||
| (match-string 1))) | |||||
| (typestart (point))) | |||||
| (tern-skip-matching-brackets '(?\) ?\,)) | |||||
| (push (cons name (buffer-substring typestart (point))) args)) | |||||
| (when (eq (char-after (point)) ?\,) (forward-char 2))) | |||||
| (when (looking-at ") -> ") | |||||
| (setf retval (buffer-substring (+ (point) 5) (point-max)))) | |||||
| (list name (nreverse args) retval)))))) | |||||
| (defun tern-find-current-arg (start) | |||||
| (when (< (point) (+ start 500)) | |||||
| (save-excursion | |||||
| (let ((cur-point (point))) | |||||
| (goto-char (1+ start)) | |||||
| (cl-loop for i from 0 do | |||||
| (let ((found-end (tern-skip-matching-brackets '(?\) ?\,)))) | |||||
| (when (>= (point) cur-point) (cl-return i)) | |||||
| (when (or (not found-end) (looking-at ")")) (cl-return nil)) | |||||
| (forward-char 1))))))) | |||||
| (defun tern-show-argument-hints () | |||||
| (cl-destructuring-bind (paren . type) tern-last-argument-hints | |||||
| (let ((parts ()) | |||||
| (current-arg (tern-find-current-arg paren))) | |||||
| (cl-destructuring-bind (name args ret) type | |||||
| (push (propertize name 'face 'font-lock-function-name-face) parts) | |||||
| (push "(" parts) | |||||
| (cl-loop for arg in args for i from 0 do | |||||
| (unless (zerop i) (push ", " parts)) | |||||
| (let ((name (or (car arg) "?"))) | |||||
| (push (if (eq i current-arg) (propertize name 'face 'highlight) name) parts)) | |||||
| (unless (equal (cdr arg) "?") | |||||
| (push ": " parts) | |||||
| (push (propertize (cdr arg) 'face 'font-lock-type-face) parts))) | |||||
| (push ")" parts) | |||||
| (when ret | |||||
| (push " -> " parts) | |||||
| (push (propertize ret 'face 'font-lock-type-face) parts))) | |||||
| (let (message-log-max) | |||||
| (tern-message (apply #'concat (nreverse parts))))))) | |||||
| ;; Refactoring ops | |||||
| (defun tern-do-refactor (data) | |||||
| (let ((per-file ()) | |||||
| (orig-buffer (current-buffer))) | |||||
| (cl-loop for change across (cdr (assq 'changes data)) do | |||||
| (let ((found (assoc-string (cdr (assq 'file change)) per-file))) | |||||
| (unless found (setf found (list (cdr (assq 'file change)))) (push found per-file)) | |||||
| (push change (cdr found)))) | |||||
| (cl-loop for (file . changes) in per-file do | |||||
| (setf changes (sort changes (lambda (a b) (> (cdr (assq 'start a)) (cdr (assq 'start b)))))) | |||||
| (find-file (expand-file-name file (tern-project-dir))) | |||||
| (cl-loop for change in changes do | |||||
| (let ((start (1+ (cdr (assq 'start change)))) | |||||
| (end (1+ (cdr (assq 'end change))))) | |||||
| (delete-region start end) | |||||
| (save-excursion | |||||
| (goto-char start) | |||||
| (insert (cdr (assq 'text change))))))) | |||||
| (switch-to-buffer orig-buffer))) | |||||
| (defun tern-rename-variable (new-name) | |||||
| (interactive "MNew variable name: ") | |||||
| (tern-run-query #'tern-do-refactor `((type . "rename") (newName . ,new-name)) (point) :full-file)) | |||||
| ;; Highlight references in scope | |||||
| (defvar tern-flash-timeout 0.5 "Delay before the highlight overlay disappears.") | |||||
| (defun tern-flash-region (start end) | |||||
| "Temporarily highlight region from START to END." | |||||
| (let ((overlay (make-overlay start end))) | |||||
| (overlay-put overlay 'face 'highlight) | |||||
| (run-with-timer tern-flash-timeout nil 'delete-overlay overlay))) | |||||
| (defun tern-do-highlight (data) | |||||
| (cl-loop for ref across (cdr (assq 'refs data)) do | |||||
| (let ((file (cdr (assq 'file ref)))) | |||||
| (when (string= buffer-file-name (expand-file-name file (tern-project-dir))) | |||||
| (let ((start (1+ (cdr (assq 'start ref)))) | |||||
| (end (1+ (cdr (assq 'end ref))))) | |||||
| (tern-flash-region start end)))))) | |||||
| (defun tern-highlight-refs () | |||||
| (interactive) | |||||
| (tern-run-query #'tern-do-highlight "refs" (point))) | |||||
| ;; Jump-to-definition | |||||
| (defvar tern-find-definition-stack ()) | |||||
| (defun tern-show-definition (data) | |||||
| (let* ((file (cdr (assq 'file data))) | |||||
| (found (and file (setf file (expand-file-name (cdr (assq 'file data)) (tern-project-dir))) | |||||
| (tern-find-position file data)))) | |||||
| (if found | |||||
| (progn | |||||
| (push (cons (buffer-file-name) (point)) tern-find-definition-stack) | |||||
| (let ((too-long (nthcdr 20 tern-find-definition-stack))) | |||||
| (when too-long (setf (cdr too-long) nil))) | |||||
| (tern-go-to-position file found)) | |||||
| (let ((url (cdr (assq 'url data)))) | |||||
| (if url | |||||
| (browse-url url) | |||||
| (tern-message "No definition found.")))))) | |||||
| (defun tern-at-interesting-expression () | |||||
| (if (member (get-text-property (point) 'face) | |||||
| '(font-lock-comment-face font-lock-comment-delimiter-face font-lock-string-face)) | |||||
| nil | |||||
| (let ((around (buffer-substring-no-properties (max 1 (1- (point))) (min (1+ (point)) (point-max))))) | |||||
| (string-match "\\sw\\|)\\|]\\|_" around)))) | |||||
| (defun tern-find-definition (&optional prompt-var) | |||||
| (interactive) | |||||
| (let ((varname (and (or prompt-var (not (tern-at-interesting-expression))) | |||||
| (read-from-minibuffer "Variable: ")))) | |||||
| (push-mark) | |||||
| (tern-run-query #'tern-show-definition `((type . "definition") (variable . ,varname)) (point)))) | |||||
| (defun tern-find-definition-by-name () | |||||
| (interactive) | |||||
| (tern-find-definition t)) | |||||
| (defun tern-find-position (file data) | |||||
| (with-current-buffer (find-file-noselect file) | |||||
| (let* ((start (1+ (cdr (assq 'start data)))) | |||||
| (cx-start (- start (cdr (assq 'contextOffset data)))) | |||||
| (cx (cdr (assq 'context data))) | |||||
| (cx-end (+ cx-start (length cx)))) | |||||
| (if (and (<= (point-max) cx-end) (equal (buffer-substring-no-properties cx-start cx-end) cx)) | |||||
| start | |||||
| (let (nearest nearest-dist) | |||||
| (save-excursion | |||||
| (goto-char (point-min)) | |||||
| (cl-loop | |||||
| (unless (search-forward cx nil t) (cl-return)) | |||||
| (let* ((here (- (point) (length cx))) | |||||
| (dist (abs (- cx-start here)))) | |||||
| (when (or (not nearest-dist) (< dist nearest-dist)) | |||||
| (setf nearest here nearest-dist dist))))) | |||||
| (when nearest | |||||
| (+ nearest (- start cx-start)))))))) | |||||
| (defun tern-pop-find-definition () | |||||
| (interactive) | |||||
| (when tern-find-definition-stack | |||||
| (cl-destructuring-bind (file . pos) (pop tern-find-definition-stack) | |||||
| (tern-go-to-position file pos)))) | |||||
| (defun tern-go-to-position (file pos) | |||||
| (find-file file) | |||||
| (goto-char (min pos (point-max))) | |||||
| (setf tern-last-point-pos (point))) | |||||
| ;; Query type | |||||
| (defun tern-get-type () | |||||
| (interactive) | |||||
| (tern-run-query (lambda (data) (tern-message (or (cdr (assq 'type data)) "Not found"))) | |||||
| "type" | |||||
| (point))) | |||||
| ;; Display docs | |||||
| (defvar tern-last-docs-url nil) | |||||
| (defun tern-get-docs () | |||||
| (interactive) | |||||
| (if (and tern-last-docs-url (eq last-command 'tern-get-docs)) | |||||
| (progn | |||||
| (browse-url tern-last-docs-url) | |||||
| (setf tern-last-docs-url nil)) | |||||
| (tern-run-query (lambda (data) | |||||
| (let ((url (cdr (assq 'url data))) (doc (cdr (assq 'doc data)))) | |||||
| (cond (doc | |||||
| (setf tern-last-docs-url url) | |||||
| (tern-message doc)) | |||||
| (url | |||||
| (browse-url url)) | |||||
| (t (tern-message "Not found"))))) | |||||
| "documentation" | |||||
| (point)))) | |||||
| ;; Connection management | |||||
| ;;;###autoload | |||||
| (defun tern-use-server (port server) | |||||
| (interactive "nPort to connect to: \nsServer: ") | |||||
| (setf tern-explicit-port port) | |||||
| (setf tern-known-port nil) | |||||
| (setf tern-server (if (string= server "") "127.0.0.1" server))) | |||||
| ;; Mode plumbing | |||||
| (defun tern-after-change (start end prev-length) | |||||
| "Track the dirty area of the buffer." | |||||
| (if tern-buffer-is-dirty | |||||
| (setf tern-buffer-is-dirty (cons (min start (car tern-buffer-is-dirty)) | |||||
| (max end (cdr tern-buffer-is-dirty)))) | |||||
| (setf tern-buffer-is-dirty (cons start end)))) | |||||
| (defvar tern-idle-time 2.5 | |||||
| "The time Emacs is allowed to idle before updating Tern's representation of the file.") | |||||
| (defvar tern-idle-timer nil | |||||
| "The timer on which `tern-reparse-on-idle' runs.") | |||||
| (defun tern-reparse-on-idle () | |||||
| "Do some mode plumbing and refresh tern's representation of the buffer." | |||||
| (when tern-mode | |||||
| (setf tern-last-point-pos nil) | |||||
| (when (and tern-last-argument-hints tern-buffer-is-dirty | |||||
| (<= (car tern-buffer-is-dirty) (car tern-last-argument-hints))) | |||||
| (setf tern-last-argument-hints nil)) | |||||
| (when (and tern-last-completions tern-buffer-is-dirty | |||||
| (<= (car tern-buffer-is-dirty) (cadr tern-last-completions))) | |||||
| (setf tern-last-completions nil)) | |||||
| (tern-send-buffer-to-server))) | |||||
| (defun tern-post-command () | |||||
| (unless (eq (point) tern-last-point-pos) | |||||
| (setf tern-last-point-pos (point)) | |||||
| (setf tern-activity-since-command tern-command-generation) | |||||
| (tern-update-argument-hints-async))) | |||||
| (defun tern-left-buffer () | |||||
| (when (and tern-buffer-is-dirty (not (buffer-file-name (car (buffer-list))))) | |||||
| (setf tern-buffer-is-dirty nil) | |||||
| (let ((buffer-list-update-hook ())) | |||||
| (tern-send-buffer-to-server)))) | |||||
| (defvar tern-mode-keymap (make-sparse-keymap)) | |||||
| (define-key tern-mode-keymap [(meta ?.)] 'tern-find-definition) | |||||
| (define-key tern-mode-keymap [(control meta ?.)] 'tern-find-definition-by-name) | |||||
| (define-key tern-mode-keymap [(meta ?,)] 'tern-pop-find-definition) | |||||
| (define-key tern-mode-keymap [(control ?c) (control ?r)] 'tern-rename-variable) | |||||
| (define-key tern-mode-keymap [(control ?c) (control ?c)] 'tern-get-type) | |||||
| (define-key tern-mode-keymap [(control ?c) (control ?d)] 'tern-get-docs) | |||||
| ;;;###autoload | |||||
| (define-minor-mode tern-mode | |||||
| "Minor mode binding to the Tern JavaScript analyzer" | |||||
| nil | |||||
| " Tern" | |||||
| tern-mode-keymap | |||||
| (if tern-mode (tern-mode-enable) (tern-mode-disable))) | |||||
| (defun tern-mode-enable () | |||||
| (set (make-local-variable 'tern-known-port) nil) | |||||
| (set (make-local-variable 'tern-server) "127.0.0.1") | |||||
| (set (make-local-variable 'tern-explicit-port) nil) | |||||
| (set (make-local-variable 'tern-project-dir) nil) | |||||
| (set (make-local-variable 'tern-last-point-pos) nil) | |||||
| (set (make-local-variable 'tern-last-completions) nil) | |||||
| (set (make-local-variable 'tern-last-argument-hints) nil) | |||||
| (set (make-local-variable 'tern-buffer-is-dirty) (and (buffer-modified-p) (cons (point-min) (point-max)))) | |||||
| (make-local-variable 'completion-at-point-functions) | |||||
| (push 'tern-completion-at-point completion-at-point-functions) | |||||
| (add-hook 'after-change-functions 'tern-after-change nil t) | |||||
| (when (null tern-idle-timer) | |||||
| (setq tern-idle-timer | |||||
| (run-with-idle-timer tern-idle-time t #'tern-reparse-on-idle))) | |||||
| (add-hook 'post-command-hook 'tern-post-command nil t) | |||||
| (add-hook 'buffer-list-update-hook 'tern-left-buffer nil t) | |||||
| (tern-send-buffer-to-server)) | |||||
| (defun tern-mode-disable () | |||||
| (setf completion-at-point-functions | |||||
| (remove 'tern-completion-at-point completion-at-point-functions)) | |||||
| (unless (null tern-idle-timer) | |||||
| (cancel-timer tern-idle-timer) | |||||
| (setq tern-idle-timer nil)) | |||||
| (remove-hook 'after-change-functions 'tern-after-change t) | |||||
| (remove-hook 'post-command-hook 'tern-post-command t) | |||||
| (remove-hook 'buffer-list-update-hook 'tern-left-buffer t)) | |||||
| (provide 'tern) | |||||
| ;;; tern.el ends here | |||||
| @ -0,0 +1,22 @@ | |||||
| ;;; tern-auto-complete-autoloads.el --- automatically extracted autoloads | |||||
| ;; | |||||
| ;;; Code: | |||||
| (add-to-list 'load-path (or (file-name-directory #$) (car load-path))) | |||||
| ;;;### (autoloads nil "tern-auto-complete" "tern-auto-complete.el" | |||||
| ;;;;;; (22223 33140 0 0)) | |||||
| ;;; Generated autoloads from tern-auto-complete.el | |||||
| (autoload 'tern-ac-setup "tern-auto-complete" "\ | |||||
| Setup auto-complete for tern-mode. | |||||
| \(fn)" t nil) | |||||
| ;;;*** | |||||
| ;; Local Variables: | |||||
| ;; version-control: never | |||||
| ;; no-byte-compile: t | |||||
| ;; no-update-autoloads: t | |||||
| ;; End: | |||||
| ;;; tern-auto-complete-autoloads.el ends here | |||||
| @ -0,0 +1 @@ | |||||
| (define-package "tern-auto-complete" "20151123.653" "Tern Completion by auto-complete.el" '((tern "0.0.1") (auto-complete "1.4") (cl-lib "0.5") (emacs "24"))) | |||||
| @ -0,0 +1,137 @@ | |||||
| ;;; tern-auto-complete.el --- Tern Completion by auto-complete.el -*- lexical-binding: t -*- | |||||
| ;; Author: <m.sakurai at kiwanami.net> | |||||
| ;; Version: 0.0.1 | |||||
| ;; Package-Version: 20151123.653 | |||||
| ;; Package-Requires: ((tern "0.0.1") (auto-complete "1.4") (cl-lib "0.5") (emacs "24")) | |||||
| ;;; Commentary: | |||||
| ;; Display completion items with its type and document. | |||||
| ;; If `tern-ac-on-dot' is non-nil (default), typing '.(dot)' invokes auto-complete with tern. | |||||
| ;; Calling the command `tern-ac-complete', you can invoke auto-complete manually. | |||||
| ;; This program does not provide an ac-source for arbitrary timing yet. | |||||
| ;;; Installation: | |||||
| ;; Add following lines below the tern setup code. | |||||
| ;; (eval-after-load 'tern | |||||
| ;; '(progn | |||||
| ;; (require 'tern-auto-complete) | |||||
| ;; (tern-ac-setup))) | |||||
| ;;; Code: | |||||
| (require 'cl-lib) | |||||
| (require 'tern) | |||||
| (require 'auto-complete) | |||||
| ;;; Completion | |||||
| (defcustom tern-ac-on-dot t | |||||
| "[AC] If t, tern enable completion by auto-completion." | |||||
| :type 'boolean | |||||
| :group 'auto-complete) | |||||
| (defcustom tern-ac-sync t | |||||
| "[AC] If t, auto-complete will wait for tern canditates before starting. | |||||
| This enables tern canditates to integrate automatically in auto-complete without | |||||
| the need for a separate keybinding. | |||||
| Remember to add ac-source-tern-completion to ac-sources." | |||||
| :type 'boolean | |||||
| :group 'auto-complete) | |||||
| (defvar tern-ac-complete-reply nil "[internal] tern-ac-complete-reply.") | |||||
| (defvar tern-ac-complete-request-point 0 | |||||
| "[internal] The point where `tern-ac-complete-request' is called.") | |||||
| (defun tern-ac-complete-request (cc) | |||||
| (setq tern-last-point-pos (point)) | |||||
| (setq tern-ac-complete-reply nil) | |||||
| (setq tern-ac-complete-request-point (point)) | |||||
| (tern-run-query | |||||
| (lambda (data) | |||||
| (tern-ac-complete-response data) | |||||
| (funcall cc)) | |||||
| `((type . "completions") (types . t) (docs . t) (caseInsensitive . t)) | |||||
| (point))) | |||||
| (defun tern-ac-complete-response (data) | |||||
| (let ((cs (cl-loop for elt across (cdr (assq 'completions data)) collect elt)) | |||||
| (start (+ 1 (cdr (assq 'start data)))) | |||||
| (end (+ 1 (cdr (assq 'end data))))) | |||||
| (setq tern-last-completions (list (buffer-substring-no-properties start end) start end cs)) | |||||
| (setq tern-ac-complete-reply cs))) | |||||
| (defun tern-ac-complete () | |||||
| "Complete code at point by tern." | |||||
| (interactive) | |||||
| (tern-ac-complete-request | |||||
| (lambda () | |||||
| (let ((ac-sources (cons 'ac-source-tern-completion ac-sources))) | |||||
| (ac-start))))) | |||||
| (defun tern-ac-dot-complete () | |||||
| "Insert dot and complete code at point by tern." | |||||
| (interactive) | |||||
| (insert ".") | |||||
| (unless (nth 4 (syntax-ppss)) | |||||
| (tern-ac-complete))) | |||||
| (defvar tern-ac-completion-truncate-length 22 | |||||
| "[AC] truncation length for type summary.") | |||||
| (defun tern-ac-completion-matches () | |||||
| (mapcar | |||||
| (lambda (item) | |||||
| (let ((doc (cdr (assq 'doc item))) | |||||
| (type (cdr (assq 'type item))) | |||||
| (name (cdr (assq 'name item)))) | |||||
| (popup-make-item | |||||
| name | |||||
| :symbol (if (null type) "?" (if (string-match "fn" type) "f" "v")) | |||||
| :summary (truncate-string-to-width | |||||
| (or type "?") tern-ac-completion-truncate-length 0 nil "...") | |||||
| :document (concat type "\n\n" doc)))) | |||||
| tern-ac-complete-reply)) | |||||
| (defun tern-ac-completion-prefix () | |||||
| (or (ac-prefix-default) | |||||
| (when (= tern-ac-complete-request-point (point)) | |||||
| tern-ac-complete-request-point))) | |||||
| ;; (makunbound 'ac-source-tern-completion) | |||||
| (ac-define-source tern-completion | |||||
| '((candidates . tern-ac-completion-matches) | |||||
| (prefix . tern-ac-completion-prefix) | |||||
| (requires . -1))) | |||||
| ;;;###autoload | |||||
| (defun tern-ac-setup () | |||||
| "Setup auto-complete for tern-mode." | |||||
| (interactive) | |||||
| (if tern-ac-on-dot | |||||
| (define-key tern-mode-keymap "." 'tern-ac-dot-complete) | |||||
| (define-key tern-mode-keymap "." nil))) | |||||
| (defvar tern-ac-js-major-modes '(js2-mode js-mode javascript-mode)) | |||||
| (defadvice auto-complete (around add-tern-ac-candidates first activate) | |||||
| "Load tern-js canditates before ac-start." | |||||
| (if (and tern-ac-sync | |||||
| (memq major-mode tern-ac-js-major-modes) | |||||
| (not (or (ac-menu-live-p) (ac-inline-live-p)))) | |||||
| (tern-ac-complete-request | |||||
| 'auto-complete-1) | |||||
| ad-do-it)) | |||||
| (provide 'tern-auto-complete) | |||||
| ;;; tern-auto-complete.el ends here | |||||