--- /dev/null
+;;; ob-restclient-autoloads.el --- automatically extracted autoloads
+;;
+;;; Code:
+(add-to-list 'load-path (directory-file-name (or (file-name-directory #$) (car load-path))))
+\f
+;;;### (autoloads nil "ob-restclient" "ob-restclient.el" (22903 17327
+;;;;;; 0 0))
+;;; Generated autoloads from ob-restclient.el
+
+(autoload 'org-babel-execute:restclient "ob-restclient" "\
+Execute a block of Restclient code with org-babel.
+This function is called by `org-babel-execute-src-block'
+
+\(fn BODY PARAMS)" nil nil)
+
+;;;***
+\f
+;; Local Variables:
+;; version-control: never
+;; no-byte-compile: t
+;; no-update-autoloads: t
+;; End:
+;;; ob-restclient-autoloads.el ends here
--- /dev/null
+;;; -*- no-byte-compile: t -*-
+(define-package "ob-restclient" "20160323.2305" "org-babel functions for restclient-mode" '((restclient "0")) :commit "08b82b9ea668631968ae4fb531fd74494630f840" :url "http://orgmode.org" :keywords '("literate programming" "reproducible research"))
--- /dev/null
+;;; ob-restclient.el --- org-babel functions for restclient-mode
+
+;; Copyright (C) Alf Lervåg
+
+;; Author: Alf Lervåg
+;; Keywords: literate programming, reproducible research
+;; Package-Version: 20160323.2305
+;; Homepage: http://orgmode.org
+;; Version: 0.02
+;; Package-Requires: ((restclient "0"))
+
+;;; 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, 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.
+
+;;; Commentary:
+;; This is a very simple first iteration at integrating restclient.el
+;; and org-mode.
+
+;;; Requirements:
+;; restclient.el
+
+;;; Code:
+(require 'ob)
+(require 'ob-ref)
+(require 'ob-comint)
+(require 'ob-eval)
+(require 'restclient)
+
+(defvar org-babel-default-header-args:restclient
+ `((:results . "raw"))
+ "Default arguments for evaluating a restclient block.")
+
+;;;###autoload
+(defun org-babel-execute:restclient (body params)
+ "Execute a block of Restclient code with org-babel.
+This function is called by `org-babel-execute-src-block'"
+ (message "executing Restclient source code block")
+ (with-temp-buffer
+ (let ((results-buffer (current-buffer))
+ (restclient-same-buffer-response t)
+ (restclient-same-buffer-response-name (buffer-name))
+ (display-buffer-alist
+ (cons
+ '("\\*temp\\*" display-buffer-no-window (allow-no-window . t))
+ display-buffer-alist)))
+
+ (insert (buffer-name))
+ (with-temp-buffer
+ (dolist (p params)
+ (let ((key (car p))
+ (value (cdr p)))
+ (when (eql key :var)
+ (insert (format ":%s = %s\n" (car value) (cdr value))))))
+ (insert body)
+ (restclient-http-parse-current-and-do 'restclient-http-do nil t))
+
+ (while restclient-within-call
+ (sit-for 0.05))
+
+ (goto-char (point-min))
+ (when (search-forward (buffer-name) nil t)
+ (error "Restclient encountered an error"))
+
+ (org-babel-restclient-wrap-result))))
+
+(defun org-babel-restclient-wrap-result ()
+ "Wrap the contents of the buffer in an `org-mode' src block."
+ (let ((mode-name (substring (symbol-name major-mode) 0 -5)))
+ (insert (format "#+BEGIN_SRC %s\n" mode-name))
+ (goto-char (point-max))
+ (insert "#+END_SRC\n")
+ (buffer-string)))
+
+(provide 'ob-restclient)
+;;; ob-restclient.el ends here
--- /dev/null
+This is a very simple first iteration at integrating restclient.el
+and org-mode.
+
+Requirements:
+restclient.el
--- /dev/null
+;;; request-autoloads.el --- automatically extracted autoloads
+;;
+;;; Code:
+(add-to-list 'load-path (directory-file-name (or (file-name-directory #$) (car load-path))))
+\f
+;;;### (autoloads nil nil ("request.el") (22555 30985 0 0))
+
+;;;***
+\f
+;; Local Variables:
+;; version-control: never
+;; no-byte-compile: t
+;; no-update-autoloads: t
+;; End:
+;;; request-autoloads.el ends here
--- /dev/null
+;;; -*- no-byte-compile: t -*-
+(define-package "request" "20160822.1659" "Compatible layer for URL request in Emacs" '((emacs "24") (cl-lib "0.5")))
--- /dev/null
+;;; request.el --- Compatible layer for URL request in Emacs -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2012 Takafumi Arakaki
+;; Copyright (C) 1985-1986, 1992, 1994-1995, 1999-2012
+;; Free Software Foundation, Inc.
+
+;; Author: Takafumi Arakaki <aka.tkf at gmail.com>
+;; Package-Requires: ((emacs "24") (cl-lib "0.5"))
+;; Package-Version: 20160822.1659
+;; Version: 0.2.0
+
+;; This file is NOT part of GNU Emacs.
+
+;; request.el 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.
+
+;; request.el 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 request.el.
+;; If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Request.el is a HTTP request library with multiple backends. It
+;; supports url.el which is shipped with Emacs and curl command line
+;; program. User can use curl when s/he has it, as curl is more reliable
+;; than url.el. Library author can use request.el to avoid imposing
+;; external dependencies such as curl to users while giving richer
+;; experience for users who have curl.
+
+;; Following functions are adapted from GNU Emacs source code.
+;; Free Software Foundation holds the copyright of them.
+;; * `request--process-live-p'
+;; * `request--url-default-expander'
+
+;;; Code:
+
+(eval-when-compile
+ (defvar url-http-method)
+ (defvar url-http-response-status))
+
+(require 'cl-lib)
+(require 'url)
+(require 'mail-utils)
+
+(defgroup request nil
+ "Compatible layer for URL request in Emacs."
+ :group 'comm
+ :prefix "request-")
+
+(defconst request-version "0.2.0")
+
+\f
+;;; Customize variables
+
+(defcustom request-storage-directory
+ (concat (file-name-as-directory user-emacs-directory) "request")
+ "Directory to store data related to request.el."
+ :type 'directory)
+
+(defcustom request-curl "curl"
+ "Executable for curl command."
+ :type 'string)
+
+(defcustom request-backend (if (executable-find request-curl)
+ 'curl
+ 'url-retrieve)
+ "Backend to be used for HTTP request.
+Automatically set to `curl' if curl command is found."
+ :type '(choice (const :tag "cURL backend" curl)
+ (const :tag "url-retrieve backend" url-retrieve)))
+
+(defcustom request-timeout nil
+ "Default request timeout in second.
+`nil' means no timeout."
+ :type '(choice (integer :tag "Request timeout seconds")
+ (boolean :tag "No timeout" nil)))
+
+(defcustom request-log-level -1
+ "Logging level for request.
+One of `error'/`warn'/`info'/`verbose'/`debug'.
+-1 means no logging."
+ :type '(choice (integer :tag "No logging" -1)
+ (const :tag "Level error" error)
+ (const :tag "Level warn" warn)
+ (const :tag "Level info" info)
+ (const :tag "Level Verbose" verbose)
+ (const :tag "Level DEBUG" debug)))
+
+(defcustom request-message-level 'warn
+ "Logging level for request.
+See `request-log-level'."
+ :type '(choice (integer :tag "No logging" -1)
+ (const :tag "Level error" error)
+ (const :tag "Level warn" warn)
+ (const :tag "Level info" info)
+ (const :tag "Level Verbose" verbose)
+ (const :tag "Level DEBUG" debug)))
+
+\f
+;;; Utilities
+
+(defun request--safe-apply (function &rest arguments)
+ (condition-case err
+ (apply #'apply function arguments)
+ ((debug error))))
+
+(defun request--safe-call (function &rest arguments)
+ (request--safe-apply function arguments))
+
+;; (defun request--url-no-cache (url)
+;; "Imitate `cache=false' of `jQuery.ajax'.
+;; See: http://api.jquery.com/jQuery.ajax/"
+;; ;; FIXME: parse URL before adding ?_=TIME.
+;; (concat url (format-time-string "?_=%s")))
+
+(defmacro request--document-function (function docstring)
+ "Document FUNCTION with DOCSTRING. Use this for defstruct accessor etc."
+ (declare (indent defun)
+ (doc-string 2))
+ `(put ',function 'function-documentation ,docstring))
+
+(defun request--process-live-p (process)
+ "Copied from `process-live-p' for backward compatibility (Emacs < 24).
+Adapted from lisp/subr.el.
+FSF holds the copyright of this function:
+ Copyright (C) 1985-1986, 1992, 1994-1995, 1999-2012
+ Free Software Foundation, Inc."
+ (memq (process-status process) '(run open listen connect stop)))
+
+\f
+;;; Logging
+
+(defconst request--log-level-def
+ '(;; debugging
+ (blather . 60) (trace . 50) (debug . 40)
+ ;; information
+ (verbose . 30) (info . 20)
+ ;; errors
+ (warn . 10) (error . 0))
+ "Named logging levels.")
+
+(defun request--log-level-as-int (level)
+ (if (integerp level)
+ level
+ (or (cdr (assq level request--log-level-def))
+ 0)))
+
+(defvar request-log-buffer-name " *request-log*")
+
+(defun request--log-buffer ()
+ (get-buffer-create request-log-buffer-name))
+
+(defmacro request-log (level fmt &rest args)
+ (declare (indent 1))
+ `(let ((level (request--log-level-as-int ,level))
+ (log-level (request--log-level-as-int request-log-level))
+ (msg-level (request--log-level-as-int request-message-level)))
+ (when (<= level (max log-level msg-level))
+ (let ((msg (format "[%s] %s" ,level
+ (condition-case err
+ (format ,fmt ,@args)
+ (error (format "
+!!! Logging error while executing:
+%S
+!!! Error:
+%S"
+ ',args err))))))
+ (when (<= level log-level)
+ (with-current-buffer (request--log-buffer)
+ (setq buffer-read-only t)
+ (let ((inhibit-read-only t))
+ (goto-char (point-max))
+ (insert msg "\n"))))
+ (when (<= level msg-level)
+ (message "REQUEST %s" msg))))))
+
+\f
+;;; HTTP specific utilities
+
+(defconst request--url-unreserved-chars
+ '(?a ?b ?c ?d ?e ?f ?g ?h ?i ?j ?k ?l ?m ?n ?o ?p ?q ?r ?s ?t ?u ?v ?w ?x ?y ?z
+ ?A ?B ?C ?D ?E ?F ?G ?H ?I ?J ?K ?L ?M ?N ?O ?P ?Q ?R ?S ?T ?U ?V ?W ?X ?Y ?Z
+ ?0 ?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9
+ ?- ?_ ?. ?~)
+ "`url-unreserved-chars' copied from Emacs 24.3 release candidate.
+This is used for making `request--urlencode-alist' RFC 3986 compliant
+for older Emacs versions.")
+
+(defun request--urlencode-alist (alist)
+ ;; FIXME: make monkey patching `url-unreserved-chars' optional
+ (let ((url-unreserved-chars request--url-unreserved-chars))
+ (cl-loop for sep = "" then "&"
+ for (k . v) in alist
+ concat sep
+ concat (url-hexify-string (format "%s" k))
+ concat "="
+ concat (url-hexify-string (format "%s" v)))))
+
+\f
+;;; Header parser
+
+(defun request--parse-response-at-point ()
+ "Parse the first header line such as \"HTTP/1.1 200 OK\"."
+ (when (re-search-forward "\\=[ \t\n]*HTTP/\\([0-9\\.]+\\) +\\([0-9]+\\)" nil t)
+ (list :version (match-string 1)
+ :code (string-to-number (match-string 2)))))
+
+(defun request--goto-next-body ()
+ (re-search-forward "^\r\n"))
+
+\f
+;;; Response object
+
+(cl-defstruct request-response
+ "A structure holding all relevant information of a request."
+ status-code history data error-thrown symbol-status url
+ done-p settings
+ ;; internal variables
+ -buffer -raw-header -timer -backend -tempfiles)
+
+(defmacro request--document-response (function docstring)
+ (declare (indent defun)
+ (doc-string 2))
+ `(request--document-function ,function ,(concat docstring "
+
+.. This is an accessor for `request-response' object.
+
+\(fn RESPONSE)")))
+
+(request--document-response request-response-status-code
+ "Integer HTTP response code (e.g., 200).")
+
+(request--document-response request-response-history
+ "Redirection history (a list of response object).
+The first element is the oldest redirection.
+
+You can use restricted portion of functions for the response
+objects in the history slot. It also depends on backend. Here
+is the table showing what functions you can use for the response
+objects in the history slot.
+
+==================================== ============== ==============
+Slots Backends
+------------------------------------ -----------------------------
+\\ curl url-retrieve
+==================================== ============== ==============
+request-response-url yes yes
+request-response-header yes no
+other functions no no
+==================================== ============== ==============
+")
+
+(request--document-response request-response-data
+ "Response parsed by the given parser.")
+
+(request--document-response request-response-error-thrown
+ "Error thrown during request.
+It takes the form of ``(ERROR-SYMBOL . DATA)``, which can be
+re-raised (`signal'ed) by ``(signal ERROR-SYMBOL DATA)``.")
+
+(request--document-response request-response-symbol-status
+ "A symbol representing the status of request (not HTTP response code).
+One of success/error/timeout/abort/parse-error.")
+
+(request--document-response request-response-url
+ "Final URL location of response.")
+
+(request--document-response request-response-done-p
+ "Return t when the request is finished or aborted.")
+
+(request--document-response request-response-settings
+ "Keyword arguments passed to `request' function.
+Some arguments such as HEADERS is changed to the one actually
+passed to the backend. Also, it has additional keywords such
+as URL which is the requested URL.")
+
+(defun request-response-header (response field-name)
+ "Fetch the values of RESPONSE header field named FIELD-NAME.
+
+It returns comma separated values when the header has multiple
+field with the same name, as :RFC:`2616` specifies.
+
+Examples::
+
+ (request-response-header response
+ \"content-type\") ; => \"text/html; charset=utf-8\"
+ (request-response-header response
+ \"unknown-field\") ; => nil
+"
+ (let ((raw-header (request-response--raw-header response)))
+ (when raw-header
+ (with-temp-buffer
+ (erase-buffer)
+ (insert raw-header)
+ ;; ALL=t to fetch all fields with the same name to get comma
+ ;; separated value [#rfc2616-sec4]_.
+ (mail-fetch-field field-name nil t)))))
+;; .. [#rfc2616-sec4] RFC2616 says this is the right thing to do
+;; (see http://tools.ietf.org/html/rfc2616.html#section-4.2).
+;; Python's requests module does this too.
+
+\f
+;;; Backend dispatcher
+
+(defconst request--backend-alist
+ '((url-retrieve
+ . ((request . request--url-retrieve)
+ (request-sync . request--url-retrieve-sync)
+ (terminate-process . delete-process)
+ (get-cookies . request--url-retrieve-get-cookies)))
+ (curl
+ . ((request . request--curl)
+ (request-sync . request--curl-sync)
+ (terminate-process . interrupt-process)
+ (get-cookies . request--curl-get-cookies))))
+ "Map backend and method name to actual method (symbol).
+
+It's alist of alist, of the following form::
+
+ ((BACKEND . ((METHOD . FUNCTION) ...)) ...)
+
+It would be nicer if I can use EIEIO. But as CEDET is included
+in Emacs by 23.2, using EIEIO means abandon older Emacs versions.
+It is probably necessary if I need to support more backends. But
+let's stick to manual dispatch for now.")
+;; See: (view-emacs-news "23.2")
+
+(defun request--choose-backend (method)
+ "Return `fucall'able object for METHOD of current `request-backend'."
+ (assoc-default
+ method
+ (or (assoc-default request-backend request--backend-alist)
+ (error "%S is not valid `request-backend'." request-backend))))
+
+\f
+;;; Cookie
+
+(defun request-cookie-string (host &optional localpart secure)
+ "Return cookie string (like `document.cookie').
+
+Example::
+
+ (request-cookie-string \"127.0.0.1\" \"/\") ; => \"key=value; key2=value2\"
+"
+ (mapconcat (lambda (nv) (concat (car nv) "=" (cdr nv)))
+ (request-cookie-alist host localpart secure)
+ "; "))
+
+(defun request-cookie-alist (host &optional localpart secure)
+ "Return cookies as an alist.
+
+Example::
+
+ (request-cookie-alist \"127.0.0.1\" \"/\") ; => ((\"key\" . \"value\") ...)
+"
+ (funcall (request--choose-backend 'get-cookies) host localpart secure))
+
+\f
+;;; Main
+
+(cl-defun request-default-error-callback (url &key symbol-status
+ &allow-other-keys)
+ (request-log 'error
+ "Error (%s) while connecting to %s." symbol-status url))
+
+(cl-defun request (url &rest settings
+ &key
+ (type "GET")
+ (params nil)
+ (data nil)
+ (files nil)
+ (parser nil)
+ (headers nil)
+ (success nil)
+ (error nil)
+ (complete nil)
+ (timeout request-timeout)
+ (status-code nil)
+ (sync nil)
+ (response (make-request-response))
+ (unix-socket nil))
+ "Send request to URL.
+
+Request.el has a single entry point. It is `request'.
+
+==================== ========================================================
+Keyword argument Explanation
+==================== ========================================================
+TYPE (string) type of request to make: POST/GET/PUT/DELETE
+PARAMS (alist) set \"?key=val\" part in URL
+DATA (string/alist) data to be sent to the server
+FILES (alist) files to be sent to the server (see below)
+PARSER (symbol) a function that reads current buffer and return data
+HEADERS (alist) additional headers to send with the request
+SUCCESS (function) called on success
+ERROR (function) called on error
+COMPLETE (function) called on both success and error
+TIMEOUT (number) timeout in second
+STATUS-CODE (alist) map status code (int) to callback
+SYNC (bool) If `t', wait until request is done. Default is `nil'.
+==================== ========================================================
+
+
+* Callback functions
+
+Callback functions STATUS, ERROR, COMPLETE and `cdr's in element of
+the alist STATUS-CODE take same keyword arguments listed below. For
+forward compatibility, these functions must ignore unused keyword
+arguments (i.e., it's better to use `&allow-other-keys' [#]_).::
+
+ (CALLBACK ; SUCCESS/ERROR/COMPLETE/STATUS-CODE
+ :data data ; whatever PARSER function returns, or nil
+ :error-thrown error-thrown ; (ERROR-SYMBOL . DATA), or nil
+ :symbol-status symbol-status ; success/error/timeout/abort/parse-error
+ :response response ; request-response object
+ ...)
+
+.. [#] `&allow-other-keys' is a special \"markers\" available in macros
+ in the CL library for function definition such as `cl-defun' and
+ `cl-function'. Without this marker, you need to specify all arguments
+ to be passed. This becomes problem when request.el adds new arguments
+ when calling callback functions. If you use `&allow-other-keys'
+ (or manually ignore other arguments), your code is free from this
+ problem. See info node `(cl) Argument Lists' for more information.
+
+Arguments data, error-thrown, symbol-status can be accessed by
+`request-response-data', `request-response-error-thrown',
+`request-response-symbol-status' accessors, i.e.::
+
+ (request-response-data RESPONSE) ; same as data
+
+Response object holds other information which can be accessed by
+the following accessors:
+`request-response-status-code',
+`request-response-url' and
+`request-response-settings'
+
+* STATUS-CODE callback
+
+STATUS-CODE is an alist of the following format::
+
+ ((N-1 . CALLBACK-1)
+ (N-2 . CALLBACK-2)
+ ...)
+
+Here, N-1, N-2,... are integer status codes such as 200.
+
+
+* FILES
+
+FILES is an alist of the following format::
+
+ ((NAME-1 . FILE-1)
+ (NAME-2 . FILE-2)
+ ...)
+
+where FILE-N is a list of the form::
+
+ (FILENAME &key PATH BUFFER STRING MIME-TYPE)
+
+FILE-N can also be a string (path to the file) or a buffer object.
+In that case, FILENAME is set to the file name or buffer name.
+
+Example FILES argument::
+
+ `((\"passwd\" . \"/etc/passwd\") ; filename = passwd
+ (\"scratch\" . ,(get-buffer \"*scratch*\")) ; filename = *scratch*
+ (\"passwd2\" . (\"password.txt\" :file \"/etc/passwd\"))
+ (\"scratch2\" . (\"scratch.txt\" :buffer ,(get-buffer \"*scratch*\")))
+ (\"data\" . (\"data.csv\" :data \"1,2,3\\n4,5,6\\n\")))
+
+.. note:: FILES is implemented only for curl backend for now.
+ As furl.el_ supports multipart POST, it should be possible to
+ support FILES in pure elisp by making furl.el_ another backend.
+ Contributions are welcome.
+
+ .. _furl.el: http://code.google.com/p/furl-el/
+
+
+* PARSER function
+
+PARSER function takes no argument and it is executed in the
+buffer with HTTP response body. The current position in the HTTP
+response buffer is at the beginning of the buffer. As the HTTP
+header is stripped off, the cursor is actually at the beginning
+of the response body. So, for example, you can pass `json-read'
+to parse JSON object in the buffer. To fetch whole response as a
+string, pass `buffer-string'.
+
+When using `json-read', it is useful to know that the returned
+type can be modified by `json-object-type', `json-array-type',
+`json-key-type', `json-false' and `json-null'. See docstring of
+each function for what it does. For example, to convert JSON
+objects to plist instead of alist, wrap `json-read' by `lambda'
+like this.::
+
+ (request
+ \"http://...\"
+ :parser (lambda ()
+ (let ((json-object-type 'plist))
+ (json-read)))
+ ...)
+
+This is analogous to the `dataType' argument of jQuery.ajax_.
+Only this function can access to the process buffer, which
+is killed immediately after the execution of this function.
+
+* SYNC
+
+Synchronous request is functional, but *please* don't use it
+other than testing or debugging. Emacs users have better things
+to do rather than waiting for HTTP request. If you want a better
+way to write callback chains, use `request-deferred'.
+
+If you can't avoid using it (e.g., you are inside of some hook
+which must return some value), make sure to set TIMEOUT to
+relatively small value.
+
+Due to limitation of `url-retrieve-synchronously', response slots
+`request-response-error-thrown', `request-response-history' and
+`request-response-url' are unknown (always `nil') when using
+synchronous request with `url-retrieve' backend.
+
+* Note
+
+API of `request' is somewhat mixture of jQuery.ajax_ (Javascript)
+and requests.request_ (Python).
+
+.. _jQuery.ajax: http://api.jquery.com/jQuery.ajax/
+.. _requests.request: http://docs.python-requests.org
+"
+ (request-log 'debug "REQUEST")
+ ;; FIXME: support CACHE argument (if possible)
+ ;; (unless cache
+ ;; (setq url (request--url-no-cache url)))
+ (unless error
+ (setq error (apply-partially #'request-default-error-callback url))
+ (setq settings (plist-put settings :error error)))
+ (unless (or (stringp data)
+ (null data)
+ (assoc-string "Content-Type" headers t))
+ (setq data (request--urlencode-alist data))
+ (setq settings (plist-put settings :data data)))
+ (when params
+ (cl-assert (listp params) nil "PARAMS must be an alist. Given: %S" params)
+ (setq url (concat url (if (string-match-p "\\?" url) "&" "?")
+ (request--urlencode-alist params))))
+ (setq settings (plist-put settings :url url))
+ (setq settings (plist-put settings :response response))
+ (setf (request-response-settings response) settings)
+ (setf (request-response-url response) url)
+ (setf (request-response--backend response) request-backend)
+ ;; Call `request--url-retrieve'(`-sync') or `request--curl'(`-sync').
+ (apply (if sync
+ (request--choose-backend 'request-sync)
+ (request--choose-backend 'request))
+ url settings)
+ (when timeout
+ (request-log 'debug "Start timer: timeout=%s sec" timeout)
+ (setf (request-response--timer response)
+ (run-at-time timeout nil
+ #'request-response--timeout-callback response)))
+ response)
+
+(defun request--clean-header (response)
+ "Strip off carriage returns in the header of REQUEST."
+ (request-log 'debug "-CLEAN-HEADER")
+ (let ((buffer (request-response--buffer response))
+ (backend (request-response--backend response))
+ sep-regexp)
+ (if (eq backend 'url-retrieve)
+ ;; FIXME: make this workaround optional.
+ ;; But it looks like sometimes `url-http-clean-headers'
+ ;; fails to cleanup. So, let's be bit permissive here...
+ (setq sep-regexp "^\r?$")
+ (setq sep-regexp "^\r$"))
+ (when (buffer-live-p buffer)
+ (with-current-buffer buffer
+ (request-log 'trace
+ "(buffer-string) at %S =\n%s" buffer (buffer-string))
+ (goto-char (point-min))
+ (when (and (re-search-forward sep-regexp nil t)
+ ;; Are \r characters stripped off already?:
+ (not (equal (match-string 0) "")))
+ (while (re-search-backward "\r$" (point-min) t)
+ (replace-match "")))))))
+
+(defun request--cut-header (response)
+ "Cut the first header part in the buffer of RESPONSE and move it to
+raw-header slot."
+ (request-log 'debug "-CUT-HEADER")
+ (let ((buffer (request-response--buffer response)))
+ (when (buffer-live-p buffer)
+ (with-current-buffer buffer
+ (goto-char (point-min))
+ (when (re-search-forward "^$" nil t)
+ (setf (request-response--raw-header response)
+ (buffer-substring (point-min) (point)))
+ (delete-region (point-min) (min (1+ (point)) (point-max))))))))
+
+(defun request--parse-data (response parser)
+ "Run PARSER in current buffer if ERROR-THROWN is nil,
+then kill the current buffer."
+ (request-log 'debug "-PARSE-DATA")
+ (let ((buffer (request-response--buffer response)))
+ (request-log 'debug "parser = %s" parser)
+ (when (and (buffer-live-p buffer) parser)
+ (with-current-buffer buffer
+ (request-log 'trace
+ "(buffer-string) at %S =\n%s" buffer (buffer-string))
+ (goto-char (point-min))
+ (setf (request-response-data response) (funcall parser))))))
+
+(cl-defun request--callback (buffer &key parser success error complete
+ timeout status-code response
+ &allow-other-keys)
+ (request-log 'debug "REQUEST--CALLBACK")
+ (request-log 'debug "(buffer-string) =\n%s"
+ (when (buffer-live-p buffer)
+ (with-current-buffer buffer (buffer-string))))
+
+ ;; Sometimes BUFFER given as the argument is different from the
+ ;; buffer already set in RESPONSE. That's why it is reset here.
+ ;; FIXME: Refactor how BUFFER is passed around.
+ (setf (request-response--buffer response) buffer)
+ (request-response--cancel-timer response)
+ (cl-symbol-macrolet
+ ((error-thrown (request-response-error-thrown response))
+ (symbol-status (request-response-symbol-status response))
+ (data (request-response-data response))
+ (done-p (request-response-done-p response)))
+
+ ;; Parse response header
+ (request--clean-header response)
+ (request--cut-header response)
+ ;; Note: Try to do this even `error-thrown' is set. For example,
+ ;; timeout error can occur while downloading response body and
+ ;; header is there in that case.
+
+ ;; Parse response body
+ (request-log 'debug "error-thrown = %S" error-thrown)
+ (condition-case err
+ (request--parse-data response parser)
+ (error
+ ;; If there was already an error (e.g. server timeout) do not set the
+ ;; status to `parse-error'.
+ (unless error-thrown
+ (setq symbol-status 'parse-error)
+ (setq error-thrown err)
+ (request-log 'error "Error from parser %S: %S" parser err))))
+ (kill-buffer buffer)
+ (request-log 'debug "data = %s" data)
+
+ ;; Determine `symbol-status'
+ (unless symbol-status
+ (setq symbol-status (if error-thrown 'error 'success)))
+ (request-log 'debug "symbol-status = %s" symbol-status)
+
+ ;; Call callbacks
+ (let ((args (list :data data
+ :symbol-status symbol-status
+ :error-thrown error-thrown
+ :response response)))
+ (let* ((success-p (eq symbol-status 'success))
+ (cb (if success-p success error))
+ (name (if success-p "success" "error")))
+ (when cb
+ (request-log 'debug "Executing %s callback." name)
+ (request--safe-apply cb args)))
+
+ (let ((cb (cdr (assq (request-response-status-code response)
+ status-code))))
+ (when cb
+ (request-log 'debug "Executing status-code callback.")
+ (request--safe-apply cb args)))
+
+ (when complete
+ (request-log 'debug "Executing complete callback.")
+ (request--safe-apply complete args)))
+
+ (setq done-p t)
+
+ ;; Remove temporary files
+ ;; FIXME: Make tempfile cleanup more reliable. It is possible
+ ;; callback is never called.
+ (request--safe-delete-files (request-response--tempfiles response))))
+
+(cl-defun request-response--timeout-callback (response)
+ (request-log 'debug "-TIMEOUT-CALLBACK")
+ (setf (request-response-symbol-status response) 'timeout)
+ (setf (request-response-error-thrown response) '(error . ("Timeout")))
+ (let* ((buffer (request-response--buffer response))
+ (proc (and (buffer-live-p buffer) (get-buffer-process buffer))))
+ (when proc
+ ;; This will call `request--callback':
+ (funcall (request--choose-backend 'terminate-process) proc))
+
+ (cl-symbol-macrolet ((done-p (request-response-done-p response)))
+ (unless done-p
+ ;; This code should never be executed. However, it occurs
+ ;; sometimes with `url-retrieve' backend.
+ ;; FIXME: In Emacs 24.3.50 or later, this is always executed in
+ ;; request-get-timeout test. Find out if it is fine.
+ (request-log 'error "Callback is not called when stopping process! \
+Explicitly calling from timer.")
+ (when (buffer-live-p buffer)
+ (cl-destructuring-bind (&key code &allow-other-keys)
+ (with-current-buffer buffer
+ (goto-char (point-min))
+ (request--parse-response-at-point))
+ (setf (request-response-status-code response) code)))
+ (apply #'request--callback
+ buffer
+ (request-response-settings response))
+ (setq done-p t)))))
+
+(defun request-response--cancel-timer (response)
+ (request-log 'debug "REQUEST-RESPONSE--CANCEL-TIMER")
+ (cl-symbol-macrolet ((timer (request-response--timer response)))
+ (when timer
+ (cancel-timer timer)
+ (setq timer nil))))
+
+
+(defun request-abort (response)
+ "Abort request for RESPONSE (the object returned by `request').
+Note that this function invoke ERROR and COMPLETE callbacks.
+Callbacks may not be called immediately but called later when
+associated process is exited."
+ (cl-symbol-macrolet ((buffer (request-response--buffer response))
+ (symbol-status (request-response-symbol-status response))
+ (done-p (request-response-done-p response)))
+ (let ((process (get-buffer-process buffer)))
+ (unless symbol-status ; should I use done-p here?
+ (setq symbol-status 'abort)
+ (setq done-p t)
+ (when (and
+ (processp process) ; process can be nil when buffer is killed
+ (request--process-live-p process))
+ (funcall (request--choose-backend 'terminate-process) process))))))
+
+\f
+;;; Backend: `url-retrieve'
+
+(cl-defun request--url-retrieve-preprocess-settings
+ (&rest settings &key type data files headers &allow-other-keys)
+ (when files
+ (error "`url-retrieve' backend does not support FILES."))
+ (when (and (equal type "POST")
+ data
+ (not (assoc-string "Content-Type" headers t)))
+ (push '("Content-Type" . "application/x-www-form-urlencoded") headers)
+ (setq settings (plist-put settings :headers headers)))
+ settings)
+
+(cl-defun request--url-retrieve (url &rest settings
+ &key type data timeout response
+ &allow-other-keys
+ &aux headers)
+ (setq settings (apply #'request--url-retrieve-preprocess-settings settings))
+ (setq headers (plist-get settings :headers))
+ (let* ((url-request-extra-headers headers)
+ (url-request-method type)
+ (url-request-data data)
+ (buffer (url-retrieve url #'request--url-retrieve-callback
+ (nconc (list :response response) settings)))
+ (proc (get-buffer-process buffer)))
+ (setf (request-response--buffer response) buffer)
+ (process-put proc :request-response response)
+ (request-log 'debug "Start querying: %s" url)
+ (set-process-query-on-exit-flag proc nil)))
+
+(cl-defun request--url-retrieve-callback (status &rest settings
+ &key response url
+ &allow-other-keys)
+ (declare (special url-http-method
+ url-http-response-status))
+ (request-log 'debug "-URL-RETRIEVE-CALLBACK")
+ (request-log 'debug "status = %S" status)
+ (request-log 'debug "url-http-method = %s" url-http-method)
+ (request-log 'debug "url-http-response-status = %s" url-http-response-status)
+
+ (setf (request-response-status-code response) url-http-response-status)
+ (let ((redirect (plist-get status :redirect)))
+ (when redirect
+ (setf (request-response-url response) redirect)))
+ ;; Construct history slot
+ (cl-loop for v in
+ (cl-loop with first = t
+ with l = nil
+ for (k v) on status by 'cddr
+ when (eq k :redirect)
+ if first
+ do (setq first nil)
+ else
+ do (push v l)
+ finally do (cons url l))
+ do (let ((r (make-request-response :-backend 'url-retrieve)))
+ (setf (request-response-url r) v)
+ (push r (request-response-history response))))
+
+ (cl-symbol-macrolet ((error-thrown (request-response-error-thrown response))
+ (status-error (plist-get status :error)))
+ (when (and error-thrown status-error)
+ (request-log 'warn
+ "Error %S thrown already but got another error %S from \
+`url-retrieve'. Ignoring it..." error-thrown status-error))
+ (unless error-thrown
+ (setq error-thrown status-error)))
+
+ (apply #'request--callback (current-buffer) settings))
+
+(cl-defun request--url-retrieve-sync (url &rest settings
+ &key type data timeout response
+ &allow-other-keys
+ &aux headers)
+ (setq settings (apply #'request--url-retrieve-preprocess-settings settings))
+ (setq headers (plist-get settings :headers))
+ (let* ((url-request-extra-headers headers)
+ (url-request-method type)
+ (url-request-data data)
+ (buffer (if timeout
+ (with-timeout
+ (timeout
+ (setf (request-response-symbol-status response)
+ 'timeout)
+ (setf (request-response-done-p response) t)
+ nil)
+ (url-retrieve-synchronously url))
+ (url-retrieve-synchronously url))))
+ (setf (request-response--buffer response) buffer)
+ ;; It seems there is no way to get redirects and URL here...
+ (when buffer
+ ;; Fetch HTTP response code
+ (with-current-buffer buffer
+ (goto-char (point-min))
+ (cl-destructuring-bind (&key version code)
+ (request--parse-response-at-point)
+ (setf (request-response-status-code response) code)))
+ ;; Parse response body, etc.
+ (apply #'request--callback buffer settings)))
+ response)
+
+(defun request--url-retrieve-get-cookies (host localpart secure)
+ (mapcar
+ (lambda (c) (cons (url-cookie-name c) (url-cookie-value c)))
+ (url-cookie-retrieve host localpart secure)))
+
+\f
+;;; Backend: curl
+
+(defvar request--curl-cookie-jar nil
+ "Override what the function `request--curl-cookie-jar' returns.
+Currently it is used only for testing.")
+
+(defun request--curl-cookie-jar ()
+ "Cookie storage for curl backend."
+ (or request--curl-cookie-jar
+ (expand-file-name "curl-cookie-jar" request-storage-directory)))
+
+(defconst request--curl-write-out-template
+ (if (eq system-type 'windows-nt)
+ "\\n(:num-redirects %{num_redirects} :url-effective %{url_effective})"
+ "\\n(:num-redirects %{num_redirects} :url-effective \"%{url_effective}\")"))
+
+(defun request--curl-mkdir-for-cookie-jar ()
+ (ignore-errors
+ (make-directory (file-name-directory (request--curl-cookie-jar)) t)))
+
+(cl-defun request--curl-command
+ (url &key type data headers timeout files* unix-socket
+ &allow-other-keys
+ &aux
+ (cookie-jar (convert-standard-filename
+ (expand-file-name (request--curl-cookie-jar)))))
+ (append
+ (list request-curl "--silent" "--include"
+ "--location"
+ ;; FIXME: test automatic decompression
+ "--compressed"
+ ;; FIMXE: this way of using cookie might be problem when
+ ;; running multiple requests.
+ "--cookie" cookie-jar "--cookie-jar" cookie-jar
+ "--write-out" request--curl-write-out-template)
+ (when unix-socket (list "--unix-socket" unix-socket))
+ (cl-loop for (name filename path mime-type) in files*
+ collect "--form"
+ collect (format "%s=@%s;filename=%s%s" name path filename
+ (if mime-type
+ (format ";type=%s" mime-type)
+ "")))
+ (when data (list "--data-binary" "@-"))
+ (when type (list "--request" type))
+ (cl-loop for (k . v) in headers
+ collect "--header"
+ collect (format "%s: %s" k v))
+ (list url)))
+
+(defun request--curl-normalize-files-1 (files get-temp-file)
+ (cl-loop for (name . item) in files
+ collect
+ (cl-destructuring-bind
+ (filename &key file buffer data mime-type)
+ (cond
+ ((stringp item) (list (file-name-nondirectory item) :file item))
+ ((bufferp item) (list (buffer-name item) :buffer item))
+ (t item))
+ (unless (= (cl-loop for v in (list file buffer data) if v sum 1) 1)
+ (error "Only one of :file/:buffer/:data must be given. Got: %S"
+ (cons name item)))
+ (cond
+ (file
+ (list name filename file mime-type))
+ (buffer
+ (let ((tf (funcall get-temp-file)))
+ (with-current-buffer buffer
+ (write-region (point-min) (point-max) tf nil 'silent))
+ (list name filename tf mime-type)))
+ (data
+ (let ((tf (funcall get-temp-file)))
+ (with-temp-buffer
+ (erase-buffer)
+ (insert data)
+ (write-region (point-min) (point-max) tf nil 'silent))
+ (list name filename tf mime-type)))))))
+
+(defun request--curl-normalize-files (files)
+ "Change FILES into a list of (NAME FILENAME PATH MIME-TYPE).
+This is to make `request--curl-command' cleaner by converting
+FILES to a homogeneous list. It returns a list (FILES* TEMPFILES)
+where FILES* is a converted FILES and TEMPFILES is a list of
+temporary file paths."
+ (let (tempfiles noerror)
+ (unwind-protect
+ (let* ((get-temp-file (lambda ()
+ (let ((tf (make-temp-file "emacs-request-")))
+ (push tf tempfiles)
+ tf)))
+ (files* (request--curl-normalize-files-1 files get-temp-file)))
+ (setq noerror t)
+ (list files* tempfiles))
+ (unless noerror
+ ;; Remove temporary files only when an error occurs
+ (request--safe-delete-files tempfiles)))))
+
+(defun request--safe-delete-files (files)
+ "Remove FILES but do not raise error when failed to do so."
+ (mapc (lambda (f) (condition-case err
+ (delete-file f)
+ (error (request-log 'error
+ "Failed delete file %s. Got: %S" f err))))
+ files))
+
+(cl-defun request--curl (url &rest settings
+ &key type data files headers timeout response
+ &allow-other-keys)
+ "cURL-based request backend.
+
+Redirection handling strategy
+-----------------------------
+
+curl follows redirection when --location is given. However,
+all headers are printed when it is used with --include option.
+Number of redirects is printed out sexp-based message using
+--write-out option (see `request--curl-write-out-template').
+This number is used for removing extra headers and parse
+location header from the last redirection header.
+
+Sexp at the end of buffer and extra headers for redirects are
+removed from the buffer before it is shown to the parser function.
+"
+ (request--curl-mkdir-for-cookie-jar)
+ (let* (;; Use pipe instead of pty. Otherwise, curl process hangs.
+ (process-connection-type nil)
+ ;; Avoid starting program in non-existing directory.
+ (home-directory (if (file-remote-p default-directory)
+ (with-parsed-tramp-file-name default-directory nil
+ (tramp-make-tramp-file-name method user host "~/"))
+ "~/"))
+ (default-directory (expand-file-name home-directory))
+ (buffer (generate-new-buffer " *request curl*"))
+ (command (cl-destructuring-bind
+ (files* tempfiles)
+ (request--curl-normalize-files files)
+ (setf (request-response--tempfiles response) tempfiles)
+ (apply #'request--curl-command url :files* files*
+ settings)))
+ (proc (apply #'start-file-process "request curl" buffer command)))
+ (request-log 'debug "Run: %s" (mapconcat 'identity command " "))
+ (setf (request-response--buffer response) buffer)
+ (process-put proc :request-response response)
+ (set-process-coding-system proc 'binary 'binary)
+ (set-process-query-on-exit-flag proc nil)
+ (set-process-sentinel proc #'request--curl-callback)
+ (when data
+ (process-send-string proc data)
+ (process-send-eof proc))))
+
+(defun request--curl-read-and-delete-tail-info ()
+ "Read a sexp at the end of buffer and remove it and preceding character.
+This function moves the point at the end of buffer by side effect.
+See also `request--curl-write-out-template'."
+ (let (forward-sexp-function)
+ (goto-char (point-max))
+ (forward-sexp -1)
+ (let ((beg (1- (point))))
+ (prog1
+ (read (current-buffer))
+ (delete-region beg (point-max))))))
+
+(defconst request--cookie-reserved-re
+ (mapconcat
+ (lambda (x) (concat "\\(^" x "\\'\\)"))
+ '("comment" "commenturl" "discard" "domain" "max-age" "path" "port"
+ "secure" "version" "expires")
+ "\\|")
+ "Uninterested keys in cookie.
+See \"set-cookie-av\" in http://www.ietf.org/rfc/rfc2965.txt")
+
+(defun request--consume-100-continue ()
+ "Remove \"HTTP/* 100 Continue\" header at the point."
+ (cl-destructuring-bind (&key code &allow-other-keys)
+ (save-excursion (request--parse-response-at-point))
+ (when (equal code 100)
+ (delete-region (point) (progn (request--goto-next-body) (point)))
+ ;; FIXME: Does this make sense? Is it possible to have multiple 100?
+ (request--consume-100-continue))))
+
+(defun request--consume-200-connection-established ()
+ "Remove \"HTTP/* 200 Connection established\" header at the point."
+ (when (looking-at-p "HTTP/1\\.0 200 Connection established")
+ (delete-region (point) (progn (request--goto-next-body) (point)))))
+
+(defun request--curl-preprocess ()
+ "Pre-process current buffer before showing it to user."
+ (let (history)
+ (cl-destructuring-bind (&key num-redirects url-effective)
+ (request--curl-read-and-delete-tail-info)
+ (goto-char (point-min))
+ (request--consume-100-continue)
+ (request--consume-200-connection-established)
+ (when (> num-redirects 0)
+ (cl-loop with case-fold-search = t
+ repeat num-redirects
+ ;; Do not store code=100 headers:
+ do (request--consume-100-continue)
+ do (let ((response (make-request-response
+ :-buffer (current-buffer)
+ :-backend 'curl)))
+ (request--clean-header response)
+ (request--cut-header response)
+ (push response history))))
+
+ (goto-char (point-min))
+ (nconc (list :num-redirects num-redirects :url-effective url-effective
+ :history (nreverse history))
+ (request--parse-response-at-point)))))
+
+(defun request--curl-absolutify-redirects (start-url redirects)
+ "Convert relative paths in REDIRECTS to absolute URLs.
+START-URL is the URL requested."
+ (cl-loop for prev-url = start-url then url
+ for url in redirects
+ unless (string-match url-nonrelative-link url)
+ do (setq url (url-expand-file-name url prev-url))
+ collect url))
+
+(defun request--curl-absolutify-location-history (start-url history)
+ "Convert relative paths in HISTORY to absolute URLs.
+START-URL is the URL requested."
+ (when history
+ (setf (request-response-url (car history)) start-url))
+ (cl-loop for url in (request--curl-absolutify-redirects
+ start-url
+ (mapcar (lambda (response)
+ (request-response-header response "location"))
+ history))
+ for response in (cdr history)
+ do (setf (request-response-url response) url)))
+
+(defun request--curl-callback (proc event)
+ (let* ((buffer (process-buffer proc))
+ (response (process-get proc :request-response))
+ (symbol-status (request-response-symbol-status response))
+ (settings (request-response-settings response)))
+ (request-log 'debug "REQUEST--CURL-CALLBACK event = %s" event)
+ (request-log 'debug "REQUEST--CURL-CALLBACK proc = %S" proc)
+ (request-log 'debug "REQUEST--CURL-CALLBACK buffer = %S" buffer)
+ (request-log 'debug "REQUEST--CURL-CALLBACK symbol-status = %S"
+ symbol-status)
+ (cond
+ ((and (memq (process-status proc) '(exit signal))
+ (/= (process-exit-status proc) 0))
+ (setf (request-response-error-thrown response) (cons 'error event))
+ (apply #'request--callback buffer settings))
+ ((equal event "finished\n")
+ (cl-destructuring-bind (&key version code num-redirects history error
+ url-effective)
+ (condition-case err
+ (with-current-buffer buffer
+ (request--curl-preprocess))
+ ((debug error)
+ (list :error err)))
+ (request--curl-absolutify-location-history (plist-get settings :url)
+ history)
+ (setf (request-response-status-code response) code)
+ (setf (request-response-url response) url-effective)
+ (setf (request-response-history response) history)
+ (setf (request-response-error-thrown response)
+ (or error (when (>= code 400) `(error . (http ,code)))))
+ (apply #'request--callback buffer settings))))))
+
+(cl-defun request--curl-sync (url &rest settings &key response &allow-other-keys)
+ ;; To make timeout work, use polling approach rather than using
+ ;; `call-process'.
+ (let (finished)
+ (prog1 (apply #'request--curl url
+ :complete (lambda (&rest _) (setq finished t))
+ settings)
+ (let ((proc (get-buffer-process (request-response--buffer response))))
+ (while (and (not finished) (request--process-live-p proc))
+ (accept-process-output proc))))))
+
+(defun request--curl-get-cookies (host localpart secure)
+ (request--netscape-get-cookies (request--curl-cookie-jar)
+ host localpart secure))
+
+\f
+;;; Netscape cookie.txt parser
+
+(defun request--netscape-cookie-parse ()
+ "Parse Netscape/Mozilla cookie format."
+ (goto-char (point-min))
+ (let ((tsv-re (concat "^\\="
+ (cl-loop repeat 6 concat "\\([^\t\n]+\\)\t")
+ "\\(.*\\)"))
+ cookies)
+ (while
+ (and
+ (cond
+ ((re-search-forward "^\\=#" nil t))
+ ((re-search-forward "^\\=$" nil t))
+ ((re-search-forward tsv-re)
+ (push (cl-loop for i from 1 to 7 collect (match-string i))
+ cookies)
+ t))
+ (= (forward-line 1) 0)
+ (not (= (point) (point-max)))))
+ (setq cookies (nreverse cookies))
+ (cl-loop for (domain flag path secure expiration name value) in cookies
+ collect (list domain
+ (equal flag "TRUE")
+ path
+ (equal secure "TRUE")
+ (string-to-number expiration)
+ name
+ value))))
+
+(defun request--netscape-filter-cookies (cookies host localpart secure)
+ (cl-loop for (domain flag path secure-1 expiration name value) in cookies
+ when (and (equal domain host)
+ (equal path localpart)
+ (or secure (not secure-1)))
+ collect (cons name value)))
+
+(defun request--netscape-get-cookies (filename host localpart secure)
+ (when (file-readable-p filename)
+ (with-temp-buffer
+ (erase-buffer)
+ (insert-file-contents filename)
+ (request--netscape-filter-cookies (request--netscape-cookie-parse)
+ host localpart secure))))
+
+\f
+;;; Monkey patches for url.el
+
+(defun request--url-default-expander (urlobj defobj)
+ "Adapted from lisp/url/url-expand.el.
+FSF holds the copyright of this function:
+ Copyright (C) 1999, 2004-2012 Free Software Foundation, Inc."
+ ;; The default expansion routine - urlobj is modified by side effect!
+ (if (url-type urlobj)
+ ;; Well, they told us the scheme, let's just go with it.
+ nil
+ (setf (url-type urlobj) (or (url-type urlobj) (url-type defobj)))
+ (setf (url-port urlobj) (or (url-portspec urlobj)
+ (and (string= (url-type urlobj)
+ (url-type defobj))
+ (url-port defobj))))
+ (if (not (string= "file" (url-type urlobj)))
+ (setf (url-host urlobj) (or (url-host urlobj) (url-host defobj))))
+ (if (string= "ftp" (url-type urlobj))
+ (setf (url-user urlobj) (or (url-user urlobj) (url-user defobj))))
+ (if (string= (url-filename urlobj) "")
+ (setf (url-filename urlobj) "/"))
+ ;; If the object we're expanding from is full, then we are now
+ ;; full.
+ (unless (url-fullness urlobj)
+ (setf (url-fullness urlobj) (url-fullness defobj)))
+ (if (string-match "^/" (url-filename urlobj))
+ nil
+ (let ((query nil)
+ (file nil)
+ (sepchar nil))
+ (if (string-match "[?#]" (url-filename urlobj))
+ (setq query (substring (url-filename urlobj) (match-end 0))
+ file (substring (url-filename urlobj) 0 (match-beginning 0))
+ sepchar (substring (url-filename urlobj) (match-beginning 0) (match-end 0)))
+ (setq file (url-filename urlobj)))
+ ;; We use concat rather than expand-file-name to combine
+ ;; directory and file name, since urls do not follow the same
+ ;; rules as local files on all platforms.
+ (setq file (url-expander-remove-relative-links
+ (concat (url-file-directory (url-filename defobj)) file)))
+ (setf (url-filename urlobj)
+ (if query (concat file sepchar query) file))))))
+
+(defadvice url-default-expander
+ (around request-monkey-patch-url-default-expander (urlobj defobj))
+ "Monkey patch `url-default-expander' to fix bug #12374.
+This patch is applied to Emacs trunk at revno 111291:
+ http://bzr.savannah.gnu.org/lh/emacs/trunk/revision/111291.
+Without this patch, port number is not treated when using
+`url-expand-file-name'.
+See: http://thread.gmane.org/gmane.emacs.devel/155698"
+ (setq ad-return-value (request--url-default-expander urlobj defobj)))
+
+(unless (equal (url-expand-file-name "/path" "http://127.0.0.1:8000")
+ "http://127.0.0.1:8000/path")
+ (ad-enable-advice 'url-default-expander
+ 'around
+ 'request-monkey-patch-url-default-expander)
+ (ad-activate 'url-default-expander))
+
+
+(eval-when-compile (require 'url-http)
+ (defvar url-http-no-retry)
+ (defvar url-http-extra-headers)
+ (defvar url-http-data)
+ (defvar url-callback-function)
+ (defvar url-callback-arguments))
+(declare-function url-http-idle-sentinel "url-http")
+(declare-function url-http-activate-callback "url-http")
+(declare-function url-http "url-http")
+(declare-function url-http-parse-headers "url-http")
+
+(defun request--url-http-end-of-document-sentinel (proc why)
+ "Adapted from lisp/url/url-http.el.
+FSF holds the copyright of this function:
+ Copyright (C) 1999, 2001, 2004-2012 Free Software Foundation, Inc."
+ (url-http-debug "url-http-end-of-document-sentinel in buffer (%s)"
+ (process-buffer proc))
+ (url-http-idle-sentinel proc why)
+ (when (buffer-name (process-buffer proc))
+ (with-current-buffer (process-buffer proc)
+ (goto-char (point-min))
+ (cond ((not (looking-at "HTTP/"))
+ (if url-http-no-retry
+ ;; HTTP/0.9 just gets passed back no matter what
+ (url-http-activate-callback)
+ ;; Call `url-http' again if our connection expired.
+ (erase-buffer)
+ (let ((url-request-method url-http-method)
+ (url-request-extra-headers url-http-extra-headers)
+ (url-request-data url-http-data))
+ (url-http url-current-object url-callback-function
+ url-callback-arguments (current-buffer)))))
+ ((url-http-parse-headers)
+ (url-http-activate-callback))))))
+
+(defadvice url-http-end-of-document-sentinel
+ (around request-monkey-patch-url-http-end-of-document-sentinel (proc why))
+ "Monkey patch `url-http-end-of-document-sentinel' to fix bug #11469.
+This patch is applied to Emacs trunk at revno 111291:
+ http://bzr.savannah.gnu.org/lh/emacs/trunk/revision/111291.
+Without this patch, PUT method fails every two times.
+See: http://thread.gmane.org/gmane.emacs.devel/155697"
+ (setq ad-return-value (request--url-http-end-of-document-sentinel proc why)))
+
+(when (and (version< "24" emacs-version)
+ (version< emacs-version "24.3.50.1"))
+ (ad-enable-advice 'url-http-end-of-document-sentinel
+ 'around
+ 'request-monkey-patch-url-http-end-of-document-sentinel)
+ (ad-activate 'url-http-end-of-document-sentinel))
+
+
+(provide 'request)
+
+;;; request.el ends here
+++ /dev/null
-Good signature from 474F05837FBDEF9B GNU ELPA Signing Agent <elpasignNOSPAMelpa.gnu.org> (trust undefined) created at 2015-10-20T11:05:02+0200 using DSA
\ No newline at end of file
+++ /dev/null
-;;; seq-autoloads.el --- automatically extracted autoloads
-;;
-;;; Code:
-(add-to-list 'load-path (or (file-name-directory #$) (car load-path)))
-\f
-;;;### (autoloads nil nil ("seq.el") (22218 52471 978369 0))
-
-;;;***
-\f
-;; Local Variables:
-;; version-control: never
-;; no-byte-compile: t
-;; no-update-autoloads: t
-;; End:
-;;; seq-autoloads.el ends here
+++ /dev/null
-(define-package "seq" "1.11" "Sequence manipulation functions" 'nil :url "http://elpa.gnu.org/packages/seq.html" :keywords '("sequences"))
+++ /dev/null
-;;; seq.el --- Sequence manipulation functions -*- lexical-binding: t -*-
-
-;; Copyright (C) 2014-2015 Free Software Foundation, Inc.
-
-;; Author: Nicolas Petton <nicolasNOSPAMpetton.fr>
-;; Keywords: sequences
-;; Version: 1.11
-;; Package: seq
-
-;; Maintainer: emacs-develNOSPAMgnu.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 <nicolasNOSPAMpetton.fr>
-;;
-;; Update seq.el to version 1.11
-;;
-;; * packages/seq/seq.el:
-;; * packages/seq/tests/seq-tests.el: Update.
-;;
-;; 2015-09-18 Nicolas Petton <nicolasNOSPAMpetton.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 <nicolasNOSPAMpetton.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 <nicolasNOSPAMpetton.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 <nicolasNOSPAMpetton.fr>
-;;
-;; * packages/seq/seq.el: Update seq.el to version 1.5.
-;;
-;; 2015-04-15 Nicolas Petton <nicolasNOSPAMpetton.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 <nicolasNOSPAMpetton.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 <nicolasNOSPAMpetton.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 <nicolasNOSPAMpetton.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 <nicolasNOSPAMpetton.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 <nicolasNOSPAMpetton.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 <nicolasNOSPAMpetton.fr>
-;;
-;; packages/seq: New package
-;;
-
-
-(provide 'seq)
-;;; seq.el ends here
--- /dev/null
+2016-10-25 Nicolas Petton <nicolasNOSPAMpetton.fr>
+
+ Fix seq-random-elt docstring
+
+ * packages/seq/seq-24.el:
+ * packages/seq/seq-25.el (seq-random-elt): Fix the docstring.
+
+2016-10-25 Nicolas Petton <nicolasNOSPAMpetton.fr>
+
+ Backport seq.el changes from Emacs master
+
+ * packages/seq/seq-24.el:
+ * packages/seq/seq-25.el (seq-random-elt): New function.
+ * packages/seq/seq.el: Bump version to 2.19.
+ * packages/seq/tests/seq-tests.el: Add tests for seq-random-elt.
+
+2016-09-02 Clément Pit--Claudel <clement.pitclaudelNOSPAMlive.com>
+
+ ; Fix documentation of seq-subseq
+
+2016-08-28 Nicolas Petton <nicolasNOSPAMpetton.fr>
+
+ * packages/seq/seq-24.el: Rename seq-p to seqp
+
+2016-06-12 Nicolas Petton <nicolasNOSPAMpetton.fr>
+
+ Update seq.el to 2.16
+
+ * packages/seq/seq-24.el:
+ * packages/seq/seq-25.el: Better implementation of seq-drop for lists.
+ * packages/seq/seq.el: Bump version number.
+
+2016-04-22 Stefan Monnier <monnierNOSPAMiro.umontreal.ca>
+
+ * seq-24.el (seq-concatenate,seq-into,seq--make-bindings): Use _
+
+ rather than t as catch-all for pcase.
+
+2016-03-31 Nicolas Petton <nicolasNOSPAMpetton.fr>
+
+ Update seq to version 2.15
+
+ * packages/seq/seq-25.el: Require cl-lib.
+ * packages/seq/seq.el: Bump version number.
+
+2016-03-29 Nicolas Petton <nicolasNOSPAMpetton.fr>
+
+ Update seq.el to version 2.14
+
+ * packages/seq/seq.el: Bump version number.
+ * packages/seq/seq-24.el (seq-sort-by): New function.
+ * packages/seq/seq-25.el (seq-sort-by): New function.
+ * packages/seq/tests/seq-tests.el: Add a test for seq-sort-by.
+
+2016-03-25 Nicolas Petton <nicolasNOSPAMpetton.fr>
+
+ * packages/seq/seq-25.el: Better declarations for seq--when-emacs-25-p
+
+2016-03-25 Nicolas Petton <nicolasNOSPAMpetton.fr>
+
+ Split seq.el into separate files for different versions of Emacs
+
+ All functions in seq-25.el are wrapped in a `seq--when-emacs-25-p' to
+ make sure that the byte compiler won't emit warnings or errors when the
+ file is byte compiled in Emacs < 25.
+
+ * packages/seq/seq-24.el:
+ * packages/seq/seq-25.el: New files.
+ * packages/seq/seq.el: Load seq-VERSION.el based on the version of
+ Emacs.
+ * packages/seq/test/seq.el-test.el: Backport a test from seq.el in Emacs
+ master.
+
+2015-11-30 Stefan Monnier <monnierNOSPAMiro.umontreal.ca>
+
+ * packages/seq: Don't define it as a :core package
+
+ Revert the removal of packages/seq/seq.el since it's different from the
+ one in lisp/emacs-lisp.
+ * .gitignore: Remove packages/seq.
+ * externals-list: Remove "seq" entry.
+
+2015-11-29 Stefan Monnier <monnierNOSPAMiro.umontreal.ca>
+
+ * externals-list: Add seq and python as :core packages
+
+ * .gitignore: Add packages/{seq,python}.
+ * packages/seq: Remove.
+
+2015-10-20 Nicolas Petton <nicolasNOSPAMpetton.fr>
+
+ Update seq.el to version 1.11
+
+ * packages/seq/seq.el:
+ * packages/seq/tests/seq-tests.el: Update.
+
+2015-09-18 Nicolas Petton <nicolasNOSPAMpetton.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 <nicolasNOSPAMpetton.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 <nicolasNOSPAMpetton.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 <nicolasNOSPAMpetton.fr>
+
+ * packages/seq/seq.el: Update seq.el to version 1.5.
+
+2015-04-15 Nicolas Petton <nicolasNOSPAMpetton.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 <nicolasNOSPAMpetton.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 <nicolasNOSPAMpetton.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 <nicolasNOSPAMpetton.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 <nicolasNOSPAMpetton.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 <nicolasNOSPAMpetton.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 <nicolasNOSPAMpetton.fr>
+
+ packages/seq: New package
+
--- /dev/null
+;;; seq-24.el --- seq.el implementation for Emacs 24.x -*- lexical-binding: t -*-
+
+;; Copyright (C) 2014-2016 Free Software Foundation, Inc.
+
+;; Author: Nicolas Petton <nicolasNOSPAMpetton.fr>
+;; Keywords: sequences
+
+;; Maintainer: emacs-develNOSPAMgnu.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.
+
+;;; 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)))))
+
+;; Implementation of `seq-let' compatible with Emacs<25.1.
+(defmacro seq-let (args sequence &rest body)
+ "Bind the variables in ARGS to the elements of SEQUENCE then evaluate BODY.
+
+ARGS can also include the `&rest' marker followed by a variable
+name to be bound to the rest of SEQUENCE."
+ (declare (indent 2) (debug t))
+ (let ((seq-var (make-symbol "seq")))
+ `(let* ((,seq-var ,sequence)
+ ,@(seq--make-bindings args seq-var))
+ ,@body)))
+
+(defun seq-drop (sequence n)
+ "Return a subsequence of SEQUENCE without its first N elements.
+The result is a sequence of the same type as SEQUENCE.
+
+If N is a negative integer or zero, SEQUENCE is returned."
+ (if (<= n 0)
+ sequence
+ (if (listp sequence)
+ (seq--drop-list sequence n)
+ (let ((length (seq-length sequence)))
+ (seq-subseq sequence (min n length) length)))))
+
+(defun seq-take (sequence n)
+ "Return a subsequence of SEQUENCE with its first N elements.
+The result is a sequence of the same type as SEQUENCE.
+
+If N is a negative integer or zero, an empty sequence is
+returned."
+ (if (listp sequence)
+ (seq--take-list sequence n)
+ (seq-subseq sequence 0 (min (max n 0) (seq-length sequence)))))
+
+(defun seq-drop-while (predicate sequence)
+ "Return a sequence from the first element for which (PREDICATE element) is nil in SEQUENCE.
+The result is a sequence of the same type as SEQUENCE."
+ (if (listp sequence)
+ (seq--drop-while-list predicate sequence)
+ (seq-drop sequence (seq--count-successive predicate sequence))))
+
+(defun seq-take-while (predicate sequence)
+ "Return the successive elements for which (PREDICATE element) is non-nil in SEQUENCE.
+The result is a sequence of the same type as SEQUENCE."
+ (if (listp sequence)
+ (seq--take-while-list predicate sequence)
+ (seq-take sequence (seq--count-successive predicate sequence))))
+
+(defun seq-filter (predicate sequence)
+ "Return a list of all the elements for which (PREDICATE element) is non-nil in SEQUENCE."
+ (let ((exclude (make-symbol "exclude")))
+ (delq exclude (seq-map (lambda (elt)
+ (if (funcall predicate elt)
+ elt
+ exclude))
+ sequence))))
+
+(defun seq-map-indexed (function sequence)
+ "Return the result of applying FUNCTION to each element of SEQUENCE.
+Unlike `seq-map', FUNCTION takes two arguments: the element of
+the sequence, and its index within the sequence."
+ (let ((index 0))
+ (seq-map (lambda (elt)
+ (prog1
+ (funcall function elt index)
+ (setq index (1+ index))))
+ sequence)))
+
+(defun seq-remove (predicate sequence)
+ "Return a list of all the elements for which (PREDICATE element) is nil in SEQUENCE."
+ (seq-filter (lambda (elt) (not (funcall predicate elt)))
+ sequence))
+
+(defun seq-reduce (function sequence initial-value)
+ "Reduce the function FUNCTION across SEQUENCE, starting with INITIAL-VALUE.
+
+Return the result of calling FUNCTION with INITIAL-VALUE and the
+first element of SEQUENCE, then calling FUNCTION with that result and
+the second element of SEQUENCE, then with that result and the third
+element of SEQUENCE, etc.
+
+If SEQUENCE is empty, return INITIAL-VALUE and FUNCTION is not called."
+ (if (seq-empty-p sequence)
+ initial-value
+ (let ((acc initial-value))
+ (seq-doseq (elt sequence)
+ (setq acc (funcall function acc elt)))
+ acc)))
+
+(defun seq-some (predicate sequence)
+ "Return the first value for which if (PREDICATE element) is non-nil for in SEQUENCE."
+ (catch 'seq--break
+ (seq-doseq (elt sequence)
+ (let ((result (funcall predicate elt)))
+ (when result
+ (throw 'seq--break result))))
+ nil))
+
+(defun seq-find (predicate sequence &optional default)
+ "Return the first element for which (PREDICATE element) is non-nil in SEQUENCE.
+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 sequence)
+ (when (funcall predicate elt)
+ (throw 'seq--break elt)))
+ default))
+
+(defun seq-every-p (predicate sequence)
+ "Return non-nil if (PREDICATE element) is non-nil for all elements of the sequence SEQUENCE."
+ (catch 'seq--break
+ (seq-doseq (elt sequence)
+ (or (funcall predicate elt)
+ (throw 'seq--break nil)))
+ t))
+
+(defun seq-count (predicate sequence)
+ "Return the number of elements for which (PREDICATE element) is non-nil in SEQUENCE."
+ (let ((count 0))
+ (seq-doseq (elt sequence)
+ (when (funcall predicate elt)
+ (setq count (+ 1 count))))
+ count))
+
+(defun seq-empty-p (sequence)
+ "Return non-nil if the sequence SEQUENCE is empty, nil otherwise."
+ (if (listp sequence)
+ (null sequence)
+ (= 0 (seq-length sequence))))
+
+(defun seq-sort (predicate sequence)
+ "Return a sorted sequence comparing using PREDICATE the elements of SEQUENCE.
+The result is a sequence of the same type as SEQUENCE."
+ (if (listp sequence)
+ (sort (seq-copy sequence) predicate)
+ (let ((result (seq-sort predicate (append sequence nil))))
+ (seq-into result (type-of sequence)))))
+
+(defun seq-sort-by (function pred sequence)
+ "Sort SEQUENCE using PRED as a comparison function.
+Elements of SEQUENCE are transformed by FUNCTION before being
+sorted. FUNCTION must be a function of one argument."
+ (seq-sort (lambda (a b)
+ (funcall pred
+ (funcall function a)
+ (funcall function b)))
+ sequence))
+
+(defun seq-contains (sequence elt &optional testfn)
+ "Return the first element in SEQUENCE 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))
+ sequence))
+
+(defun seq-position (sequence elt &optional testfn)
+ "Return the index of the first element in SEQUENCE 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 sequence)
+ (when (funcall (or testfn #'equal) e elt)
+ (throw 'seq--break index))
+ (setq index (1+ index)))
+ nil)))
+
+(defun seq-uniq (sequence &optional testfn)
+ "Return a list of the elements of SEQUENCE with duplicates removed.
+TESTFN is used to compare elements, or `equal' if TESTFN is nil."
+ (let ((result '()))
+ (seq-doseq (elt sequence)
+ (unless (seq-contains result elt testfn)
+ (setq result (cons elt result))))
+ (nreverse result)))
+
+(defun seq-subseq (sequence start &optional end)
+ "Return the subsequence of SEQUENCE 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 sequence) (vectorp sequence)) (substring sequence start end))
+ ((listp sequence)
+ (let (len (errtext (format "Bad bounding indices: %s, %s" start end)))
+ (and end (< end 0) (setq end (+ end (setq len (seq-length sequence)))))
+ (if (< start 0) (setq start (+ start (or len (setq len (seq-length sequence))))))
+ (when (> start 0)
+ (setq sequence (nthcdr (1- start) sequence))
+ (or sequence (error "%s" errtext))
+ (setq sequence (cdr sequence)))
+ (if end
+ (let ((res nil))
+ (while (and (>= (setq end (1- end)) start) sequence)
+ (push (pop sequence) res))
+ (or (= (1+ end) start) (error "%s" errtext))
+ (nreverse res))
+ (seq-copy sequence))))
+ (t (error "Unsupported sequence: %s" sequence))))
+
+(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))))
+ (_ (error "Not a sequence type name: %S" type))))
+
+(defun seq-mapcat (function sequence &optional type)
+ "Concatenate the result of applying FUNCTION to each element of SEQUENCE.
+The result is a sequence of type TYPE, or a list if TYPE is nil."
+ (apply #'seq-concatenate (or type 'list)
+ (seq-map function sequence)))
+
+(defun seq-mapn (function sequence &rest seqs)
+ "Like `seq-map' but FUNCTION is mapped over all SEQS.
+The arity of FUNCTION must match the number of SEQS, and the
+mapping stops on the shortest sequence.
+Return a list of the results.
+
+\(fn FUNCTION SEQS...)"
+ (let ((result nil)
+ (seqs (seq-map (lambda (s) (seq-into s 'list))
+ (cons sequence seqs))))
+ (while (not (memq nil seqs))
+ (push (apply function (seq-map #'car seqs)) result)
+ (setq seqs (seq-map #'cdr seqs)))
+ (nreverse result)))
+
+(defun seq-partition (sequence n)
+ "Return a list of the elements of SEQUENCE 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 sequence))
+ (push (seq-take sequence n) result)
+ (setq sequence (seq-drop sequence 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 sequence)
+ "Apply FUNCTION to each element of SEQUENCE.
+Separate the elements of SEQUENCE 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 sequence)
+ nil))
+
+(defalias 'seq-reverse
+ (if (ignore-errors (reverse [1 2]))
+ #'reverse
+ (lambda (sequence)
+ "Return the reversed copy of list, vector, or string SEQUENCE.
+See also the function `nreverse', which is used more often."
+ (let ((result '()))
+ (seq-map (lambda (elt) (push elt result))
+ sequence)
+ (if (listp sequence)
+ result
+ (seq-into result (type-of sequence)))))))
+
+(defun seq-into (sequence type)
+ "Convert the sequence SEQUENCE into a sequence of type TYPE.
+TYPE can be one of the following symbols: vector, string or list."
+ (pcase type
+ (`vector (vconcat sequence))
+ (`string (concat sequence))
+ (`list (append sequence nil))
+ (_ (error "Not a sequence type name: %S" type))))
+
+(defun seq-min (sequence)
+ "Return the smallest element of SEQUENCE.
+SEQUENCE must be a sequence of numbers or markers."
+ (apply #'min (seq-into sequence 'list)))
+
+(defun seq-max (sequence)
+ "Return the largest element of SEQUENCE.
+SEQUENCE must be a sequence of numbers or markers."
+ (apply #'max (seq-into sequence 'list)))
+
+(defun seq-random-elt (sequence)
+ "Return a random element from SEQUENCE.
+Signal an error if SEQUENCE is empty."
+ (if (seq-empty-p sequence)
+ (error "Sequence cannot be empty")
+ (seq-elt sequence (random (seq-length sequence)))))
+
+(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'."
+ (nthcdr 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 (predicate list)
+ "Return a list from the first element for which (PREDICATE element) is nil in LIST.
+This is an optimization for lists in `seq-drop-while'."
+ (while (and list (funcall predicate (car list)))
+ (setq list (cdr list)))
+ list)
+
+(defun seq--take-while-list (predicate list)
+ "Return the successive elements for which (PREDICATE element) is non-nil in LIST.
+This is an optimization for lists in `seq-take-while'."
+ (let ((result '()))
+ (while (and list (funcall predicate (car list)))
+ (push (pop list) result))
+ (nreverse result)))
+
+(defun seq--count-successive (predicate sequence)
+ "Return the number of successive elements for which (PREDICATE element) is non-nil in SEQUENCE."
+ (let ((n 0)
+ (len (seq-length sequence)))
+ (while (and (< n len)
+ (funcall predicate (seq-elt sequence n)))
+ (setq n (+ 1 n)))
+ n))
+
+;; Helper function for the Backward-compatible version of `seq-let'
+;; for Emacs<25.1.
+(defun seq--make-bindings (args sequence &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 seqp)
+ (setq bindings (seq--make-bindings (seq--elt-safe args index)
+ `(seq--elt-safe ,sequence ,index)
+ bindings)))
+ (`&rest
+ (progn (push `(,(seq--elt-safe args (1+ index))
+ (seq-drop ,sequence ,index))
+ bindings)
+ (setq rest-marker t)))
+ (_
+ (push `(,name (seq--elt-safe ,sequence ,index)) bindings))))
+ (setq index (1+ index)))
+ bindings))
+
+(defun seq--elt-safe (sequence n)
+ "Return element of SEQUENCE at the index N.
+If no element is found, return nil."
+ (when (or (listp sequence)
+ (and (sequencep sequence)
+ (> (seq-length sequence) n)))
+ (seq-elt sequence 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 'seqp #'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))
+
+(provide 'seq-24)
+;;; seq-24.el ends here
--- /dev/null
+;;; seq-25.el --- seq.el implementation for Emacs 25.x -*- lexical-binding: t -*-
+
+;; Copyright (C) 2014-2016 Free Software Foundation, Inc.
+
+;; Author: Nicolas Petton <nicolasNOSPAMpetton.fr>
+;; Keywords: sequences
+
+;; Maintainer: emacs-develNOSPAMgnu.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.
+;;
+;; seq.el can be extended to support new type of sequences. Here are
+;; the generic functions that must be implemented by new seq types:
+;; - `seq-elt'
+;; - `seq-length'
+;; - `seq-do'
+;; - `seqp'
+;; - `seq-subseq'
+;; - `seq-into-sequence'
+;; - `seq-copy'
+;; - `seq-into'
+
+;;; Code:
+
+;; When loading seq.el in Emacs 24.x, this file gets byte-compiled, even if
+;; never used. This takes care of byte-compilation warnings is emitted, by
+;; emitting nil in the macro expansion in Emacs 24.x.
+(defmacro seq--when-emacs-25-p (&rest body)
+ "Execute BODY if in Emacs>=25.x."
+ (declare (indent (lambda (&rest x) 0)) (debug t))
+ (when (version<= "25" emacs-version)
+ `(progn ,@body)))
+
+(seq--when-emacs-25-p
+
+(require 'cl-generic)
+(require 'cl-lib) ;; for cl-subseq
+
+(defmacro seq-doseq (spec &rest body)
+ "Loop over a sequence.
+Evaluate BODY with VAR bound to each element of SEQUENCE, in turn.
+
+Similar to `dolist' but can be applied to lists, strings, and vectors.
+
+\(fn (VAR SEQUENCE) BODY...)"
+ (declare (indent 1) (debug ((symbolp form &optional form) body)))
+ `(seq-do (lambda (,(car spec))
+ ,@body)
+ ,(cadr spec)))
+
+(pcase-defmacro seq (&rest patterns)
+ "Build a `pcase' pattern that matches elements of SEQUENCE.
+
+The `pcase' pattern will match each element of PATTERNS against the
+corresponding element of SEQUENCE.
+
+Extra elements of the sequence are ignored if fewer PATTERNS are
+given, and the match does not fail."
+ `(and (pred seqp)
+ ,@(seq--make-pcase-bindings patterns)))
+
+(defmacro seq-let (args sequence &rest body)
+ "Bind the variables in ARGS to the elements of SEQUENCE, then evaluate BODY.
+
+ARGS can also include the `&rest' marker followed by a variable
+name to be bound to the rest of SEQUENCE."
+ (declare (indent 2) (debug (sexp form body)))
+ `(pcase-let ((,(seq--make-pcase-patterns args) ,sequence))
+ ,@body))
+\f
+
+;;; Basic seq functions that have to be implemented by new sequence types
+(cl-defgeneric seq-elt (sequence n)
+ "Return Nth element of SEQUENCE."
+ (elt sequence n))
+
+;; Default gv setters for `seq-elt'.
+;; It can be a good idea for new sequence implementations to provide a
+;; "gv-setter" for `seq-elt'.
+(cl-defmethod (setf seq-elt) (store (sequence array) n)
+ (aset sequence n store))
+
+(cl-defmethod (setf seq-elt) (store (sequence cons) n)
+ (setcar (nthcdr n sequence) store))
+
+(cl-defgeneric seq-length (sequence)
+ "Return the number of elements of SEQUENCE."
+ (length sequence))
+
+(cl-defgeneric seq-do (function sequence)
+ "Apply FUNCTION to each element of SEQUENCE, presumably for side effects.
+Return SEQUENCE."
+ (mapc function sequence))
+
+(defalias 'seq-each #'seq-do)
+
+(cl-defgeneric seqp (sequence)
+ "Return non-nil if SEQUENCE is a sequence, nil otherwise."
+ (sequencep sequence))
+
+(cl-defgeneric seq-copy (sequence)
+ "Return a shallow copy of SEQUENCE."
+ (copy-sequence sequence))
+
+(cl-defgeneric seq-subseq (sequence start &optional end)
+ "Return the sequence of elements of SEQUENCE from START to END.
+END is exclusive.
+
+If END is omitted, it defaults to the length of the sequence. If
+START or END is negative, it counts from the end. Signal an
+error if START or END are outside of the sequence (i.e too large
+if positive or too small if negative)."
+ (cl-subseq sequence start end))
+
+\f
+(cl-defgeneric seq-map (function sequence)
+ "Return the result of applying FUNCTION to each element of SEQUENCE."
+ (let (result)
+ (seq-do (lambda (elt)
+ (push (funcall function elt) result))
+ sequence)
+ (nreverse result)))
+
+(defun seq-map-indexed (function sequence)
+ "Return the result of applying FUNCTION to each element of SEQUENCE.
+Unlike `seq-map', FUNCTION takes two arguments: the element of
+the sequence, and its index within the sequence."
+ (let ((index 0))
+ (seq-map (lambda (elt)
+ (prog1
+ (funcall function elt index)
+ (setq index (1+ index))))
+ sequence)))
+
+;; faster implementation for sequences (sequencep)
+(cl-defmethod seq-map (function (sequence sequence))
+ (mapcar function sequence))
+
+(cl-defgeneric seq-mapn (function sequence &rest sequences)
+ "Like `seq-map' but FUNCTION is mapped over all SEQUENCES.
+The arity of FUNCTION must match the number of SEQUENCES, and the
+mapping stops on the shortest sequence.
+Return a list of the results.
+
+\(fn FUNCTION SEQUENCES...)"
+ (let ((result nil)
+ (sequences (seq-map (lambda (s) (seq-into s 'list))
+ (cons sequence sequences))))
+ (while (not (memq nil sequences))
+ (push (apply function (seq-map #'car sequences)) result)
+ (setq sequences (seq-map #'cdr sequences)))
+ (nreverse result)))
+
+(cl-defgeneric seq-drop (sequence n)
+ "Remove the first N elements of SEQUENCE and return the result.
+The result is a sequence of the same type as SEQUENCE.
+
+If N is a negative integer or zero, SEQUENCE is returned."
+ (if (<= n 0)
+ sequence
+ (let ((length (seq-length sequence)))
+ (seq-subseq sequence (min n length) length))))
+
+(cl-defgeneric seq-take (sequence n)
+ "Take the first N elements of SEQUENCE and return the result.
+The result is a sequence of the same type as SEQUENCE.
+
+If N is a negative integer or zero, an empty sequence is
+returned."
+ (seq-subseq sequence 0 (min (max n 0) (seq-length sequence))))
+
+(cl-defgeneric seq-drop-while (pred sequence)
+ "Remove the successive elements of SEQUENCE for which PRED returns non-nil.
+PRED is a function of one argument. The result is a sequence of
+the same type as SEQUENCE."
+ (seq-drop sequence (seq--count-successive pred sequence)))
+
+(cl-defgeneric seq-take-while (pred sequence)
+ "Take the successive elements of SEQUENCE for which PRED returns non-nil.
+PRED is a function of one argument. The result is a sequence of
+the same type as SEQUENCE."
+ (seq-take sequence (seq--count-successive pred sequence)))
+
+(cl-defgeneric seq-empty-p (sequence)
+ "Return non-nil if the SEQUENCE is empty, nil otherwise."
+ (= 0 (seq-length sequence)))
+
+(cl-defgeneric seq-sort (pred sequence)
+ "Sort SEQUENCE using PRED as comparison function.
+The result is a sequence of the same type as SEQUENCE."
+ (let ((result (seq-sort pred (append sequence nil))))
+ (seq-into result (type-of sequence))))
+
+(defun seq-sort-by (function pred sequence)
+ "Sort SEQUENCE using PRED as a comparison function.
+Elements of SEQUENCE are transformed by FUNCTION before being
+sorted. FUNCTION must be a function of one argument."
+ (seq-sort (lambda (a b)
+ (funcall pred
+ (funcall function a)
+ (funcall function b)))
+ sequence))
+
+(cl-defmethod seq-sort (pred (list list))
+ (sort (seq-copy list) pred))
+
+(cl-defgeneric seq-reverse (sequence)
+ "Return a sequence with elements of SEQUENCE in reverse order."
+ (let ((result '()))
+ (seq-map (lambda (elt)
+ (push elt result))
+ sequence)
+ (seq-into result (type-of sequence))))
+
+;; faster implementation for sequences (sequencep)
+(cl-defmethod seq-reverse ((sequence sequence))
+ (reverse sequence))
+
+(cl-defgeneric seq-concatenate (type &rest sequences)
+ "Concatenate SEQUENCES into a single sequence of type TYPE.
+TYPE must be one of following symbols: vector, string or list.
+
+\n(fn TYPE SEQUENCE...)"
+ (apply #'cl-concatenate type (seq-map #'seq-into-sequence sequences)))
+
+(cl-defgeneric seq-into-sequence (sequence)
+ "Convert SEQUENCE into a sequence.
+
+The default implementation is to signal an error if SEQUENCE is not a
+sequence, specific functions should be implemented for new types
+of sequence."
+ (unless (sequencep sequence)
+ (error "Cannot convert %S into a sequence" sequence))
+ sequence)
+
+(cl-defgeneric seq-into (sequence type)
+ "Concatenate the elements of SEQUENCE into a sequence of type TYPE.
+TYPE can be one of the following symbols: vector, string or
+list."
+ (pcase type
+ (`vector (vconcat sequence))
+ (`string (concat sequence))
+ (`list (append sequence nil))
+ (_ (error "Not a sequence type name: %S" type))))
+
+(cl-defgeneric seq-filter (pred sequence)
+ "Return a list of all the elements for which (PRED element) is non-nil in SEQUENCE."
+ (let ((exclude (make-symbol "exclude")))
+ (delq exclude (seq-map (lambda (elt)
+ (if (funcall pred elt)
+ elt
+ exclude))
+ sequence))))
+
+(cl-defgeneric seq-remove (pred sequence)
+ "Return a list of all the elements for which (PRED element) is nil in SEQUENCE."
+ (seq-filter (lambda (elt) (not (funcall pred elt)))
+ sequence))
+
+(cl-defgeneric seq-reduce (function sequence initial-value)
+ "Reduce the function FUNCTION across SEQUENCE, starting with INITIAL-VALUE.
+
+Return the result of calling FUNCTION with INITIAL-VALUE and the
+first element of SEQUENCE, then calling FUNCTION with that result and
+the second element of SEQUENCE, then with that result and the third
+element of SEQUENCE, etc.
+
+If SEQUENCE is empty, return INITIAL-VALUE and FUNCTION is not called."
+ (if (seq-empty-p sequence)
+ initial-value
+ (let ((acc initial-value))
+ (seq-doseq (elt sequence)
+ (setq acc (funcall function acc elt)))
+ acc)))
+
+(cl-defgeneric seq-every-p (pred sequence)
+ "Return non-nil if (PRED element) is non-nil for all elements of SEQUENCE."
+ (catch 'seq--break
+ (seq-doseq (elt sequence)
+ (or (funcall pred elt)
+ (throw 'seq--break nil)))
+ t))
+
+(cl-defgeneric seq-some (pred sequence)
+ "Return the first value for which if (PRED element) is non-nil for in SEQUENCE."
+ (catch 'seq--break
+ (seq-doseq (elt sequence)
+ (let ((result (funcall pred elt)))
+ (when result
+ (throw 'seq--break result))))
+ nil))
+
+(cl-defgeneric seq-find (pred sequence &optional default)
+ "Return the first element for which (PRED element) is non-nil in SEQUENCE.
+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 sequence)
+ (when (funcall pred elt)
+ (throw 'seq--break elt)))
+ default))
+
+(cl-defgeneric seq-count (pred sequence)
+ "Return the number of elements for which (PRED element) is non-nil in SEQUENCE."
+ (let ((count 0))
+ (seq-doseq (elt sequence)
+ (when (funcall pred elt)
+ (setq count (+ 1 count))))
+ count))
+
+(cl-defgeneric seq-contains (sequence elt &optional testfn)
+ "Return the first element in SEQUENCE that is equal 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))
+ sequence))
+
+(cl-defgeneric seq-position (sequence elt &optional testfn)
+ "Return the index of the first element in SEQUENCE 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 sequence)
+ (when (funcall (or testfn #'equal) e elt)
+ (throw 'seq--break index))
+ (setq index (1+ index)))
+ nil)))
+
+(cl-defgeneric seq-uniq (sequence &optional testfn)
+ "Return a list of the elements of SEQUENCE with duplicates removed.
+TESTFN is used to compare elements, or `equal' if TESTFN is nil."
+ (let ((result '()))
+ (seq-doseq (elt sequence)
+ (unless (seq-contains result elt testfn)
+ (setq result (cons elt result))))
+ (nreverse result)))
+
+(cl-defgeneric seq-mapcat (function sequence &optional type)
+ "Concatenate the result of applying FUNCTION to each element of SEQUENCE.
+The result is a sequence of type TYPE, or a list if TYPE is nil."
+ (apply #'seq-concatenate (or type 'list)
+ (seq-map function sequence)))
+
+(cl-defgeneric seq-partition (sequence n)
+ "Return a list of the elements of SEQUENCE 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 sequence))
+ (push (seq-take sequence n) result)
+ (setq sequence (seq-drop sequence n)))
+ (nreverse result))))
+
+(cl-defgeneric seq-intersection (sequence1 sequence2 &optional testfn)
+ "Return a list of the elements that appear in both SEQUENCE1 and SEQUENCE2.
+Equality is defined by TESTFN if non-nil or by `equal' if nil."
+ (seq-reduce (lambda (acc elt)
+ (if (seq-contains sequence2 elt testfn)
+ (cons elt acc)
+ acc))
+ (seq-reverse sequence1)
+ '()))
+
+(cl-defgeneric seq-difference (sequence1 sequence2 &optional testfn)
+ "Return a list of the elements that appear in SEQUENCE1 but not in SEQUENCE2.
+Equality is defined by TESTFN if non-nil or by `equal' if nil."
+ (seq-reduce (lambda (acc elt)
+ (if (not (seq-contains sequence2 elt testfn))
+ (cons elt acc)
+ acc))
+ (seq-reverse sequence1)
+ '()))
+
+(cl-defgeneric seq-group-by (function sequence)
+ "Apply FUNCTION to each element of SEQUENCE.
+Separate the elements of SEQUENCE 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 sequence)
+ nil))
+
+(cl-defgeneric seq-min (sequence)
+ "Return the smallest element of SEQUENCE.
+SEQUENCE must be a sequence of numbers or markers."
+ (apply #'min (seq-into sequence 'list)))
+
+(cl-defgeneric seq-max (sequence)
+ "Return the largest element of SEQUENCE.
+SEQUENCE must be a sequence of numbers or markers."
+ (apply #'max (seq-into sequence 'list)))
+
+(defun seq--count-successive (pred sequence)
+ "Return the number of successive elements for which (PRED element) is non-nil in SEQUENCE."
+ (let ((n 0)
+ (len (seq-length sequence)))
+ (while (and (< n len)
+ (funcall pred (seq-elt sequence n)))
+ (setq n (+ 1 n)))
+ n))
+
+;;; Optimized implementations for lists
+
+(cl-defmethod seq-drop ((list list) n)
+ "Optimized implementation of `seq-drop' for lists."
+ (nthcdr n list))
+
+(cl-defmethod seq-take ((list list) n)
+ "Optimized implementation of `seq-take' for lists."
+ (let ((result '()))
+ (while (and list (> n 0))
+ (setq n (1- n))
+ (push (pop list) result))
+ (nreverse result)))
+
+(cl-defmethod seq-drop-while (pred (list list))
+ "Optimized implementation of `seq-drop-while' for lists."
+ (while (and list (funcall pred (car list)))
+ (setq list (cdr list)))
+ list)
+
+(cl-defmethod seq-empty-p ((list list))
+ "Optimized implementation of `seq-empty-p' for lists."
+ (null list))
+
+\f
+(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)))
+ (_
+ (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 (seqp elt)
+ (seq--make-pcase-patterns elt)
+ elt))
+ args)))
+
+;; TODO: make public?
+(defun seq--elt-safe (sequence n)
+ "Return element of SEQUENCE at the index N.
+If no element is found, return nil."
+ (ignore-errors (seq-elt sequence n))))
+
+(cl-defgeneric seq-random-elt (sequence)
+ "Return a random element from SEQUENCE.
+Signal an error if SEQUENCE is empty."
+ (if (seq-empty-p sequence)
+ (error "Sequence cannot be empty")
+ (seq-elt sequence (random (seq-length sequence)))))
+
+(provide 'seq-25)
+;;; seq-25.el ends here
--- /dev/null
+;;; seq-autoloads.el --- automatically extracted autoloads
+;;
+;;; Code:
+(add-to-list 'load-path (directory-file-name (or (file-name-directory #$) (car load-path))))
+\f
+;;;### (autoloads nil nil ("seq-24.el" "seq-25.el" "seq-pkg.el" "seq.el")
+;;;;;; (22692 30284 0 0))
+
+;;;***
+\f
+;; Local Variables:
+;; version-control: never
+;; no-byte-compile: t
+;; no-update-autoloads: t
+;; End:
+;;; seq-autoloads.el ends here
--- /dev/null
+;; Generated package description from seq.el
+(define-package "seq" "2.19" "Sequence manipulation functions" 'nil :url "http://elpa.gnu.org/packages/seq.html" :keywords '("sequences"))
--- /dev/null
+;;; seq.el --- Sequence manipulation functions -*- lexical-binding: t -*-
+
+;; Copyright (C) 2014-2016 Free Software Foundation, Inc.
+
+;; Author: Nicolas Petton <nicolasNOSPAMpetton.fr>
+;; Keywords: sequences
+;; Version: 2.19
+;; Package: seq
+
+;; Maintainer: emacs-develNOSPAMgnu.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.
+
+;;; Code:
+
+(if (version< emacs-version "25")
+ (require 'seq-24)
+ (require 'seq-25))
+
+(provide 'seq)
+;;; seq.el ends here
--- /dev/null
+;;; seq-tests.el --- Tests for sequences.el
+
+;; Copyright (C) 2014-2015 Free Software Foundation, Inc.
+
+;; Author: Nicolas Petton <nicolasNOSPAMpetton.fr>
+;; Maintainer: emacs-develNOSPAMgnu.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:
+
+;; Tests for seq.el
+
+;;; Code:
+
+(require 'ert)
+(require 'seq)
+
+(defmacro with-test-sequences (spec &rest body)
+ "Successively bind VAR to a list, vector, and string built from SEQ.
+Evaluate BODY for each created sequence.
+
+\(fn (var seq) body)"
+ (declare (indent 1) (debug ((symbolp form) body)))
+ (let ((initial-seq (make-symbol "initial-seq")))
+ `(let ((,initial-seq ,(cadr spec)))
+ ,@(mapcar (lambda (s)
+ `(let ((,(car spec) (apply (function ,s) ,initial-seq)))
+ ,@body))
+ '(list vector string)))))
+
+(defun same-contents-p (seq1 seq2)
+ "Return t if SEQ1 and SEQ2 have the same contents, nil otherwise."
+ (equal (append seq1 '()) (append seq2 '())))
+
+(defun test-sequences-evenp (integer)
+ "Return t if INTEGER is even."
+ (eq (logand integer 1) 0))
+
+(defun test-sequences-oddp (integer)
+ "Return t if INTEGER is odd."
+ (not (test-sequences-evenp integer)))
+
+(ert-deftest test-seq-drop ()
+ (with-test-sequences (seq '(1 2 3 4))
+ (should (equal (seq-drop seq 0) seq))
+ (should (equal (seq-drop seq 1) (seq-subseq seq 1)))
+ (should (equal (seq-drop seq 2) (seq-subseq seq 2)))
+ (should (seq-empty-p (seq-drop seq 4)))
+ (should (seq-empty-p (seq-drop seq 10))))
+ (with-test-sequences (seq '())
+ (should (seq-empty-p (seq-drop seq 0)))
+ (should (seq-empty-p (seq-drop seq 1)))))
+
+(ert-deftest test-seq-take ()
+ (with-test-sequences (seq '(2 3 4 5))
+ (should (seq-empty-p (seq-take seq 0)))
+ (should (= (seq-length (seq-take seq 1)) 1))
+ (should (= (seq-elt (seq-take seq 1) 0) 2))
+ (should (same-contents-p (seq-take seq 3) '(2 3 4)))
+ (should (equal (seq-take seq 10) seq))))
+
+(ert-deftest test-seq-drop-while ()
+ (with-test-sequences (seq '(1 3 2 4))
+ (should (equal (seq-drop-while #'test-sequences-oddp seq)
+ (seq-drop seq 2)))
+ (should (equal (seq-drop-while #'test-sequences-evenp seq)
+ seq))
+ (should (seq-empty-p (seq-drop-while #'numberp seq))))
+ (with-test-sequences (seq '())
+ (should (seq-empty-p (seq-drop-while #'test-sequences-oddp seq)))))
+
+(ert-deftest test-seq-take-while ()
+ (with-test-sequences (seq '(1 3 2 4))
+ (should (equal (seq-take-while #'test-sequences-oddp seq)
+ (seq-take seq 2)))
+ (should (seq-empty-p (seq-take-while #'test-sequences-evenp seq)))
+ (should (equal (seq-take-while #'numberp seq) seq)))
+ (with-test-sequences (seq '())
+ (should (seq-empty-p (seq-take-while #'test-sequences-oddp seq)))))
+
+(ert-deftest test-seq-map-indexed ()
+ (should (equal (seq-map-indexed (lambda (elt i)
+ (list elt i))
+ nil)
+ nil))
+ (should (equal (seq-map-indexed (lambda (elt i)
+ (list elt i))
+ '(a b c d))
+ '((a 0) (b 1) (c 2) (d 3)))))
+
+(ert-deftest test-seq-filter ()
+ (with-test-sequences (seq '(6 7 8 9 10))
+ (should (equal (seq-filter #'test-sequences-evenp seq) '(6 8 10)))
+ (should (equal (seq-filter #'test-sequences-oddp seq) '(7 9)))
+ (should (equal (seq-filter (lambda (elt) nil) seq) '())))
+ (with-test-sequences (seq '())
+ (should (equal (seq-filter #'test-sequences-evenp seq) '()))))
+
+(ert-deftest test-seq-remove ()
+ (with-test-sequences (seq '(6 7 8 9 10))
+ (should (equal (seq-remove #'test-sequences-evenp seq) '(7 9)))
+ (should (equal (seq-remove #'test-sequences-oddp seq) '(6 8 10)))
+ (should (same-contents-p (seq-remove (lambda (elt) nil) seq) seq)))
+ (with-test-sequences (seq '())
+ (should (equal (seq-remove #'test-sequences-evenp seq) '()))))
+
+(ert-deftest test-seq-count ()
+ (with-test-sequences (seq '(6 7 8 9 10))
+ (should (equal (seq-count #'test-sequences-evenp seq) 3))
+ (should (equal (seq-count #'test-sequences-oddp seq) 2))
+ (should (equal (seq-count (lambda (elt) nil) seq) 0)))
+ (with-test-sequences (seq '())
+ (should (equal (seq-count #'test-sequences-evenp seq) 0))))
+
+(ert-deftest test-seq-reduce ()
+ (with-test-sequences (seq '(1 2 3 4))
+ (should (= (seq-reduce #'+ seq 0) 10))
+ (should (= (seq-reduce #'+ seq 5) 15)))
+ (with-test-sequences (seq '())
+ (should (eq (seq-reduce #'+ seq 0) 0))
+ (should (eq (seq-reduce #'+ seq 7) 7))))
+
+(ert-deftest test-seq-some ()
+ (with-test-sequences (seq '(4 3 2 1))
+ (should (seq-some #'test-sequences-evenp seq))
+ (should (seq-some #'test-sequences-oddp seq))
+ (should-not (seq-some (lambda (elt) (> elt 10)) seq)))
+ (with-test-sequences (seq '())
+ (should-not (seq-some #'test-sequences-oddp seq)))
+ (should (seq-some #'null '(1 nil 2))))
+
+(ert-deftest test-seq-find ()
+ (with-test-sequences (seq '(4 3 2 1))
+ (should (= 4 (seq-find #'test-sequences-evenp seq)))
+ (should (= 3 (seq-find #'test-sequences-oddp seq)))
+ (should-not (seq-find (lambda (elt) (> elt 10)) seq)))
+ (should-not (seq-find #'null '(1 nil 2)))
+ (should-not (seq-find #'null '(1 nil 2) t))
+ (should-not (seq-find #'null '(1 2 3)))
+ (should (seq-find #'null '(1 2 3) 'sentinel)))
+
+(ert-deftest test-seq-contains ()
+ (with-test-sequences (seq '(3 4 5 6))
+ (should (seq-contains seq 3))
+ (should-not (seq-contains seq 7)))
+ (with-test-sequences (seq '())
+ (should-not (seq-contains seq 3))
+ (should-not (seq-contains seq nil))))
+
+(ert-deftest test-seq-every-p ()
+ (with-test-sequences (seq '(43 54 22 1))
+ (should (seq-every-p (lambda (elt) t) seq))
+ (should-not (seq-every-p #'test-sequences-oddp seq))
+ (should-not (seq-every-p #'test-sequences-evenp seq)))
+ (with-test-sequences (seq '(42 54 22 2))
+ (should (seq-every-p #'test-sequences-evenp seq))
+ (should-not (seq-every-p #'test-sequences-oddp seq)))
+ (with-test-sequences (seq '())
+ (should (seq-every-p #'identity seq))
+ (should (seq-every-p #'test-sequences-evenp seq))))
+
+(ert-deftest test-seq-empty-p ()
+ (with-test-sequences (seq '(0))
+ (should-not (seq-empty-p seq)))
+ (with-test-sequences (seq '(0 1 2))
+ (should-not (seq-empty-p seq)))
+ (with-test-sequences (seq '())
+ (should (seq-empty-p seq))))
+
+(ert-deftest test-seq-sort ()
+ (should (equal (seq-sort #'< "cbaf") "abcf"))
+ (should (equal (seq-sort #'< '(2 1 9 4)) '(1 2 4 9)))
+ (should (equal (seq-sort #'< [2 1 9 4]) [1 2 4 9]))
+ (should (equal (seq-sort #'< "") "")))
+
+(ert-deftest test-seq-uniq ()
+ (with-test-sequences (seq '(2 4 6 8 6 4 3))
+ (should (equal (seq-uniq seq) '(2 4 6 8 3))))
+ (with-test-sequences (seq '(3 3 3 3 3))
+ (should (equal (seq-uniq seq) '(3))))
+ (with-test-sequences (seq '())
+ (should (equal (seq-uniq seq) '()))))
+
+(ert-deftest test-seq-subseq ()
+ (with-test-sequences (seq '(2 3 4 5))
+ (should (equal (seq-subseq seq 0 4) seq))
+ (should (same-contents-p (seq-subseq seq 2 4) '(4 5)))
+ (should (same-contents-p (seq-subseq seq 1 3) '(3 4)))
+ (should (same-contents-p (seq-subseq seq 1 -1) '(3 4))))
+ (should (vectorp (seq-subseq [2 3 4 5] 2)))
+ (should (stringp (seq-subseq "foo" 2 3)))
+ (should (listp (seq-subseq '(2 3 4 4) 2 3)))
+ (should-error (seq-subseq '(1 2 3) 4))
+ (should-not (seq-subseq '(1 2 3) 3))
+ (should (seq-subseq '(1 2 3) -3))
+ (should-error (seq-subseq '(1 2 3) 1 4))
+ (should (seq-subseq '(1 2 3) 1 3)))
+
+(ert-deftest test-seq-concatenate ()
+ (with-test-sequences (seq '(2 4 6))
+ (should (equal (seq-concatenate 'string seq [8]) (string 2 4 6 8)))
+ (should (equal (seq-concatenate 'list seq '(8 10)) '(2 4 6 8 10)))
+ (should (equal (seq-concatenate 'vector seq '(8 10)) [2 4 6 8 10]))
+ (should (equal (seq-concatenate 'vector nil '(8 10)) [8 10]))
+ (should (equal (seq-concatenate 'vector seq nil) [2 4 6]))))
+
+(ert-deftest test-seq-mapcat ()
+ (should (equal (seq-mapcat #'seq-reverse '((3 2 1) (6 5 4)))
+ '(1 2 3 4 5 6)))
+ (should (equal (seq-mapcat #'seq-reverse '[(3 2 1) (6 5 4)])
+ '(1 2 3 4 5 6)))
+ (should (equal (seq-mapcat #'seq-reverse '((3 2 1) (6 5 4)) 'vector)
+ '[1 2 3 4 5 6])))
+
+(ert-deftest test-seq-partition ()
+ (should (same-contents-p (seq-partition '(0 1 2 3 4 5 6 7) 3)
+ '((0 1 2) (3 4 5) (6 7))))
+ (should (same-contents-p (seq-partition '[0 1 2 3 4 5 6 7] 3)
+ '([0 1 2] [3 4 5] [6 7])))
+ (should (same-contents-p (seq-partition "Hello world" 2)
+ '("He" "ll" "o " "wo" "rl" "d")))
+ (should (equal (seq-partition '() 2) '()))
+ (should (equal (seq-partition '(1 2 3) -1) '())))
+
+(ert-deftest test-seq-group-by ()
+ (with-test-sequences (seq '(1 2 3 4))
+ (should (equal (seq-group-by #'test-sequences-oddp seq)
+ '((t 1 3) (nil 2 4)))))
+ (should (equal (seq-group-by #'car '((a 1) (b 3) (c 4) (a 2)))
+ '((b (b 3)) (c (c 4)) (a (a 1) (a 2))))))
+
+(ert-deftest test-seq-reverse ()
+ (with-test-sequences (seq '(1 2 3 4))
+ (should (same-contents-p (seq-reverse seq) '(4 3 2 1)))
+ (should (equal (type-of (seq-reverse seq))
+ (type-of seq)))))
+
+(ert-deftest test-seq-into ()
+ (let* ((vector [1 2 3])
+ (list (seq-into vector 'list)))
+ (should (same-contents-p vector list))
+ (should (listp list)))
+ (let* ((list '(hello world))
+ (vector (seq-into list 'vector)))
+ (should (same-contents-p vector list))
+ (should (vectorp vector)))
+ (let* ((string "hello")
+ (list (seq-into string 'list)))
+ (should (same-contents-p string list))
+ (should (stringp string)))
+ (let* ((string "hello")
+ (vector (seq-into string 'vector)))
+ (should (same-contents-p string vector))
+ (should (stringp string)))
+ (let* ((list nil)
+ (vector (seq-into list 'vector)))
+ (should (same-contents-p list vector))
+ (should (vectorp vector))))
+
+(ert-deftest test-seq-intersection ()
+ (let ((v1 [2 3 4 5])
+ (v2 [1 3 5 6 7]))
+ (should (same-contents-p (seq-intersection v1 v2)
+ '(3 5))))
+ (let ((l1 '(2 3 4 5))
+ (l2 '(1 3 5 6 7)))
+ (should (same-contents-p (seq-intersection l1 l2)
+ '(3 5))))
+ (let ((v1 [2 4 6])
+ (v2 [1 3 5]))
+ (should (seq-empty-p (seq-intersection v1 v2)))))
+
+(ert-deftest test-seq-difference ()
+ (let ((v1 [2 3 4 5])
+ (v2 [1 3 5 6 7]))
+ (should (same-contents-p (seq-difference v1 v2)
+ '(2 4))))
+ (let ((l1 '(2 3 4 5))
+ (l2 '(1 3 5 6 7)))
+ (should (same-contents-p (seq-difference l1 l2)
+ '(2 4))))
+ (let ((v1 [2 4 6])
+ (v2 [2 4 6]))
+ (should (seq-empty-p (seq-difference v1 v2)))))
+
+(ert-deftest test-seq-let ()
+ (with-test-sequences (seq '(1 2 3 4))
+ (seq-let (a b c d e) seq
+ (should (= a 1))
+ (should (= b 2))
+ (should (= c 3))
+ (should (= d 4))
+ (should (null e)))
+ (seq-let (a b &rest others) seq
+ (should (= a 1))
+ (should (= b 2))
+ (should (same-contents-p others (seq-drop seq 2)))))
+ (let ((seq '(1 (2 (3 (4))))))
+ (seq-let (_ (_ (_ (a)))) seq
+ (should (= a 4))))
+ (let (seq)
+ (seq-let (a b c) seq
+ (should (null a))
+ (should (null b))
+ (should (null c)))))
+
+(ert-deftest test-seq-min-max ()
+ (with-test-sequences (seq '(4 5 3 2 0 4))
+ (should (= (seq-min seq) 0))
+ (should (= (seq-max seq) 5))))
+
+(ert-deftest test-seq-position ()
+ (with-test-sequences (seq '(2 4 6))
+ (should (null (seq-position seq 1)))
+ (should (= (seq-position seq 4) 1)))
+ (let ((seq '(a b c)))
+ (should (null (seq-position seq 'd #'eq)))
+ (should (= (seq-position seq 'a #'eq) 0))
+ (should (null (seq-position seq (make-symbol "a") #'eq)))))
+
+(ert-deftest test-seq-mapn ()
+ (should-error (seq-mapn #'identity))
+ (with-test-sequences (seq '(1 2 3 4 5 6 7))
+ (should (equal (append seq nil)
+ (seq-mapn #'identity seq)))
+ (should (equal (seq-mapn #'1+ seq)
+ (seq-map #'1+ seq)))
+
+ (with-test-sequences (seq-2 '(10 20 30 40 50))
+ (should (equal (seq-mapn #'+ seq seq-2)
+ '(11 22 33 44 55)))
+ (should (equal (seq-mapn #'+ seq seq-2 nil) nil)))))
+
+(ert-deftest test-seq-sort-by ()
+ (let ((seq ["x" "xx" "xxx"]))
+ (should (equal (seq-sort-by #'seq-length #'> seq)
+ ["xxx" "xx" "x"]))))
+
+(ert-deftest test-seq-random-elt-take-all ()
+ (let ((seq '(a b c d e))
+ (count '()))
+ (should (= 0 (map-length count)))
+ (dotimes (_ 1000)
+ (let ((random-elt (seq-random-elt seq)))
+ (map-put count
+ random-elt
+ (map-elt count random-elt 0))))
+ (should (= 5 (map-length count)))))
+
+(ert-deftest test-seq-random-elt-signal-on-empty ()
+ (should-error (seq-random-elt nil))
+ (should-error (seq-random-elt []))
+ (should-error (seq-random-elt "")))
+
+(provide 'seq-tests)
+;;; seq-tests.el ends here
--- /dev/null
+;;; terraform-mode-autoloads.el --- automatically extracted autoloads
+;;
+;;; Code:
+(add-to-list 'load-path (or (file-name-directory #$) (car load-path)))
+\f
+;;;### (autoloads nil "terraform-mode" "terraform-mode.el" (22473
+;;;;;; 28701 0 0))
+;;; Generated autoloads from terraform-mode.el
+
+(autoload 'terraform-mode "terraform-mode" "\
+Major mode for editing terraform configuration file
+
+\(fn)" t nil)
+
+(add-to-list 'auto-mode-alist '("\\.tf\\(vars\\)?\\'" . terraform-mode))
+
+;;;***
+\f
+;; Local Variables:
+;; version-control: never
+;; no-byte-compile: t
+;; no-update-autoloads: t
+;; End:
+;;; terraform-mode-autoloads.el ends here
--- /dev/null
+(define-package "terraform-mode" "20160823.31" "Major mode for terraform configuration file" '((hcl-mode "0.2") (cl-lib "0.5")) :url "https://github.com/syohex/emacs-terraform-mode")
--- /dev/null
+;;; terraform-mode.el --- Major mode for terraform configuration file
+
+;; Copyright (C) 2016 by Syohei YOSHIDA
+
+;; Author: Syohei YOSHIDA <syohexNOSPAMgmail.com>
+;; URL: https://github.com/syohex/emacs-terraform-mode
+;; Package-Version: 20160823.31
+;; Version: 0.05
+;; Package-Requires: ((hcl-mode "0.02") (cl-lib "0.5"))
+
+;; 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:
+
+;; Major mode of terraform configuration file. terraform-mode provides
+;; syntax highlighting, indentation function and formatting.
+
+;; Format the current buffer with terraform-format-buffer. To always
+;; format terraform buffers when saving, use:
+;; (add-hook 'terraform-mode-hook #'terraform-format-on-save-mode)
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'rx)
+(require 'hcl-mode)
+
+(defgroup terraform nil
+ "Major mode of Terraform configuration file."
+ :group 'languages)
+
+(defcustom terraform-indent-level 2
+ "The tab width to use when indenting."
+ :type 'integer)
+
+(defconst terraform--block-regexp
+ "^\\s-*\\(provider\\|resource\\|data\\|module\\|variable\\|output\\)\\s-+\"")
+
+(defconst terraform--atlas-regexp
+ "^\\s-*\\(atlas\\)\\s-*")
+
+(defconst terraform--provisioner-regexp
+ "^\\s-+\\(provisioner\\)\\s-+\"")
+
+(defvar terraform-font-lock-keywords
+ `((,terraform--block-regexp 1 font-lock-function-name-face)
+ (,terraform--atlas-regexp 1 font-lock-function-name-face)
+ (,terraform--provisioner-regexp 1 font-lock-function-name-face)
+ ,@hcl-font-lock-keywords))
+
+(defun terraform-format-buffer ()
+ "Rewrite current buffer in a canonical format using terraform fmt."
+ (interactive)
+ (let ((buf (get-buffer-create "*terraform-fmt*")))
+ (if (zerop (call-process-region (point-min) (point-max)
+ "terraform" nil buf nil "fmt" "-"))
+ (let ((point (point))
+ (window-start (window-start)))
+ (erase-buffer)
+ (insert-buffer-substring buf)
+ (goto-char point)
+ (set-window-start nil window-start))
+ (message "terraform fmt: %s" (with-current-buffer buf (buffer-string))))
+ (kill-buffer buf)))
+
+(define-minor-mode terraform-format-on-save-mode
+ "Run terraform-format-buffer before saving current buffer."
+ :lighter ""
+ (if terraform-format-on-save-mode
+ (add-hook 'before-save-hook #'terraform-format-buffer nil t)
+ (remove-hook 'before-save-hook #'terraform-format-buffer t)))
+
+;;;###autoload
+(define-derived-mode terraform-mode hcl-mode "Terraform"
+ "Major mode for editing terraform configuration file"
+
+ (setq font-lock-defaults '((terraform-font-lock-keywords)))
+
+ ;; indentation
+ (make-local-variable 'terraform-indent-level)
+ (setq hcl-indent-level terraform-indent-level)
+
+ ;; imenu
+ (setq imenu-generic-expression
+ '(("resource" "^resource\\s-+\"[^\"]+\"\\s-+\"\\([^\"]+\\)\"" 1)
+ ("data" "^data\\s-+\"[^\"]+\"\\s-+\"\\([^\"]+\\)\"" 1)
+ ("provider" "^provider\\s-+\"\\([^\"]+\\)\"" 1)
+ ("module" "^module\\s-+\"\\([^\"]+\\)\"" 1)
+ ("variable" "^variable\\s-+\"\\([^\"]+\\)\"" 1)
+ ("output" "^output\\s-+\"\\([^\"]+\\)\"" 1)))
+ (imenu-add-to-menubar "Index"))
+
+;;;###autoload
+(add-to-list 'auto-mode-alist '("\\.tf\\(vars\\)?\\'" . terraform-mode))
+
+(provide 'terraform-mode)
+
+;;; terraform-mode.el ends here
--- /dev/null
+Major mode of terraform configuration file. terraform-mode provides
+syntax highlighting, indentation function and formatting.
+
+Format the current buffer with terraform-format-buffer. To always
+format terraform buffers when saving, use:
+ (add-hook 'terraform-mode-hook #'terraform-format-on-save-mode)
--- /dev/null
+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.
+\1f
+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
+* With-Editor: (with-editor). Using the Emacsclient as $EDITOR.
--- /dev/null
+;;; with-editor-autoloads.el --- automatically extracted autoloads
+;;
+;;; Code:
+(add-to-list 'load-path (directory-file-name (or (file-name-directory #$) (car load-path))))
+\f
+;;;### (autoloads nil nil ("with-editor-pkg.el" "with-editor.el")
+;;;;;; (22975 34390 0 0))
+
+;;;***
+\f
+;; Local Variables:
+;; version-control: never
+;; no-byte-compile: t
+;; no-update-autoloads: t
+;; End:
+;;; with-editor-autoloads.el ends here
--- /dev/null
+(define-package "with-editor" "20170817.1240" "Use the Emacsclient as $EDITOR"
+ '((emacs "24.4")
+ (async "1.9"))
+ :url "https://github.com/magit/with-editor" :keywords
+ '("tools"))
+;; Local Variables:
+;; no-byte-compile: t
+;; End:
--- /dev/null
+;;; with-editor.el --- Use the Emacsclient as $EDITOR -*- lexical-binding: t -*-
+
+;; Copyright (C) 2014-2017 The Magit Project Contributors
+;;
+;; You should have received a copy of the AUTHORS.md file. If not,
+;; see https://github.com/magit/with-editor/blob/master/AUTHORS.md.
+
+;; Author: Jonas Bernoulli <jonasNOSPAMbernoul.li>
+;; Maintainer: Jonas Bernoulli <jonasNOSPAMbernoul.li>
+
+;; Package-Requires: ((emacs "24.4") (async "1.9"))
+;; Keywords: tools
+;; Homepage: https://github.com/magit/with-editor
+
+;; This file is not part of GNU Emacs.
+
+;; This file is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+
+;; This file is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with Magit. If not, see http://www.gnu.org/licenses.
+
+;;; Commentary:
+
+;; This library makes it possible to reliably use the Emacsclient as
+;; the `$EDITOR' of child processes. It makes sure that they know how
+;; to call home. For remote processes a substitute is provided, which
+;; communicates with Emacs on standard output/input instead of using a
+;; socket as the Emacsclient does.
+
+;; It provides the commands `with-editor-async-shell-command' and
+;; `with-editor-shell-command', which are intended as replacements
+;; for `async-shell-command' and `shell-command'. They automatically
+;; export `$EDITOR' making sure the executed command uses the current
+;; Emacs instance as "the editor". With a prefix argument these
+;; commands prompt for an alternative environment variable such as
+;; `$GIT_EDITOR'. To always use these variants add this to your init
+;; file:
+;;
+;; (define-key (current-global-map)
+;; [remap async-shell-command] 'with-editor-async-shell-command)
+;; (define-key (current-global-map)
+;; [remap shell-command] 'with-editor-shell-command)
+
+;; Alternatively use the global `shell-command-with-editor-mode',
+;; which always sets `$EDITOR' for all Emacs commands which ultimately
+;; use `shell-command' to asynchronously run some shell command.
+
+;; The command `with-editor-export-editor' exports `$EDITOR' or
+;; another such environment variable in `shell-mode', `term-mode' and
+;; `eshell-mode' buffers. Use this Emacs command before executing a
+;; shell command which needs the editor set, or always arrange for the
+;; current Emacs instance to be used as editor by adding it to the
+;; appropriate mode hooks:
+;;
+;; (add-hook 'shell-mode-hook 'with-editor-export-editor)
+;; (add-hook 'term-exec-hook 'with-editor-export-editor)
+;; (add-hook 'eshell-mode-hook 'with-editor-export-editor)
+
+;; Some variants of this function exist, these two forms are
+;; equivalent:
+;;
+;; (add-hook 'shell-mode-hook
+;; (apply-partially 'with-editor-export-editor "GIT_EDITOR"))
+;; (add-hook 'shell-mode-hook 'with-editor-export-git-editor)
+
+;; This library can also be used by other packages which need to use
+;; the current Emacs instance as editor. In fact this library was
+;; written for Magit and its `git-commit-mode' and `git-rebase-mode'.
+;; Consult `git-rebase.el' and the related code in `magit-sequence.el'
+;; for a simple example.
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'server)
+(require 'shell)
+
+(and (require 'async-bytecomp nil t)
+ (memq 'magit (bound-and-true-p async-bytecomp-allowed-packages))
+ (fboundp 'async-bytecomp-package-mode)
+ (async-bytecomp-package-mode 1))
+
+(eval-when-compile
+ (progn (require 'dired nil t)
+ (require 'eshell nil t)
+ (require 'term nil t)
+ (require 'warnings nil t)))
+(declare-function dired-get-filename 'dired)
+(declare-function term-emulate-terminal 'term)
+(defvar eshell-preoutput-filter-functions)
+
+;;; Options
+
+(defgroup with-editor nil
+ "Use the Emacsclient as $EDITOR."
+ :group 'external
+ :group 'server)
+
+(defun with-editor-locate-emacsclient ()
+ "Search for a suitable Emacsclient executable."
+ (or (with-editor-locate-emacsclient-1
+ (with-editor-emacsclient-path)
+ (length (split-string emacs-version "\\.")))
+ (prog1 nil (display-warning 'with-editor "\
+Cannot determine a suitable Emacsclient
+
+Determining an Emacsclient executable suitable for the
+current Emacs instance failed. For more information
+please see https://github.com/magit/magit/wiki/Emacsclient."))))
+
+(defun with-editor-locate-emacsclient-1 (path depth)
+ (let* ((version-lst (cl-subseq (split-string emacs-version "\\.") 0 depth))
+ (version-reg (concat "^" (mapconcat #'identity version-lst "\\."))))
+ (or (locate-file-internal
+ (if (equal invocation-name "remacs") "remacsclient" "emacsclient")
+ path
+ (cl-mapcan
+ (lambda (v) (cl-mapcar (lambda (e) (concat v e)) exec-suffixes))
+ (nconc (and (boundp 'debian-emacs-flavor)
+ (list (format ".%s" debian-emacs-flavor)))
+ (cl-mapcon (lambda (v)
+ (setq v (mapconcat #'identity (reverse v) "."))
+ (list v (concat "-" v) (concat ".emacs" v)))
+ (reverse version-lst))
+ (list "" "-snapshot" ".emacs-snapshot")))
+ (lambda (exec)
+ (ignore-errors
+ (string-match-p version-reg
+ (with-editor-emacsclient-version exec)))))
+ (and (> depth 1)
+ (with-editor-locate-emacsclient-1 path (1- depth))))))
+
+(defun with-editor-emacsclient-version (exec)
+ (let ((default-directory (file-name-directory exec)))
+ (ignore-errors
+ (cadr (split-string (car (process-lines exec "--version")))))))
+
+(defun with-editor-emacsclient-path ()
+ (let ((path exec-path))
+ (when invocation-directory
+ (push (directory-file-name invocation-directory) path)
+ (let* ((linkname (expand-file-name invocation-name invocation-directory))
+ (truename (file-chase-links linkname)))
+ (unless (equal truename linkname)
+ (push (directory-file-name (file-name-directory truename)) path)))
+ (when (eq system-type 'darwin)
+ (let ((dir (expand-file-name "bin" invocation-directory)))
+ (when (file-directory-p dir)
+ (push dir path)))
+ (when (string-match-p "Cellar" invocation-directory)
+ (let ((dir (expand-file-name "../../../bin" invocation-directory)))
+ (when (file-directory-p dir)
+ (push dir path))))))
+ (cl-remove-duplicates path :test 'equal)))
+
+(defcustom with-editor-emacsclient-executable (with-editor-locate-emacsclient)
+ "The Emacsclient executable used by the `with-editor' macro."
+ :group 'with-editor
+ :type '(choice (string :tag "Executable")
+ (const :tag "Don't use Emacsclient" nil)))
+
+(defcustom with-editor-sleeping-editor "\
+sh -c '\
+echo \"WITH-EDITOR: $$ OPEN $0\"; \
+sleep 604800 & sleep=$!; \
+trap \"kill $sleep; exit 0\" USR1; \
+trap \"kill $sleep; exit 1\" USR2; \
+wait $sleep'"
+ "The sleeping editor, used when the Emacsclient cannot be used.
+
+This fallback is used for asynchronous processes started inside
+the macro `with-editor', when the process runs on a remote machine
+or for local processes when `with-editor-emacsclient-executable'
+is nil (i.e. when no suitable Emacsclient was found, or the user
+decided not to use it).
+
+Where the latter uses a socket to communicate with Emacs' server,
+this substitute prints edit requests to its standard output on
+which a process filter listens for such requests. As such it is
+not a complete substitute for a proper Emacsclient, it can only
+be used as $EDITOR of child process of the current Emacs instance.
+
+Some shells do not execute traps immediately when waiting for a
+child process, but by default we do use such a blocking child
+process.
+
+If you use such a shell (e.g. `csh' on FreeBSD, but not Debian),
+then you have to edit this option. You can either replace \"sh\"
+with \"bash\" (and install that), or you can use the older, less
+performant implementation:
+
+ \"sh -c '\\
+ echo \\\"WITH-EDITOR: $$ OPEN $0\\\"; \\
+ trap \\\"exit 0\\\" USR1; \\
+ trap \\\"exit 1\" USR2; \\
+ while true; do sleep 1; done'\"
+
+Note that this leads to a delay of up to a second. The delay can
+be shortened by replacing \"sleep 1\" with \"sleep 0.01\", or if your
+implementation does not support floats, then by using `nanosleep'
+instead."
+ :group 'with-editor
+ :type 'string)
+
+(defcustom with-editor-finish-query-functions nil
+ "List of functions called to query before finishing session.
+
+The buffer in question is current while the functions are called.
+If any of them returns nil, then the session is not finished and
+the buffer is not killed. The user should then fix the issue and
+try again. The functions are called with one argument. If it is
+non-nil then that indicates that the user used a prefix argument
+to force finishing the session despite issues. Functions should
+usually honor that and return non-nil."
+ :group 'with-editor
+ :type 'hook)
+(put 'with-editor-finish-query-functions 'permanent-local t)
+
+(defcustom with-editor-cancel-query-functions nil
+ "List of functions called to query before canceling session.
+
+The buffer in question is current while the functions are called.
+If any of them returns nil, then the session is not canceled and
+the buffer is not killed. The user should then fix the issue and
+try again. The functions are called with one argument. If it is
+non-nil then that indicates that the user used a prefix argument
+to force canceling the session despite issues. Functions should
+usually honor that and return non-nil."
+ :group 'with-editor
+ :type 'hook)
+(put 'with-editor-cancel-query-functions 'permanent-local t)
+
+(defcustom with-editor-mode-lighter " WE"
+ "The mode-line lighter of the With-Editor mode."
+ :group 'with-editor
+ :type '(choice (const :tag "No lighter" "") string))
+
+(defvar with-editor-server-window-alist nil
+ "Alist of filename patterns vs corresponding `server-window'.
+
+Each element looks like (REGEXP . FUNCTION). Files matching
+REGEXP are selected using FUNCTION instead of the default in
+`server-window'.
+
+Note that when a package adds an entry here then it probably
+has a reason to disrespect `server-window' and it likely is
+not a good idea to change such entries.")
+
+(defvar with-editor-file-name-history-exclude nil
+ "List of regexps for filenames `server-visit' should not remember.
+When a filename matches any of the regexps, then `server-visit'
+does not add it to the variable `file-name-history', which is
+used when reading a filename in the minibuffer.")
+
+;;; Mode Commands
+
+(defvar with-editor-pre-finish-hook nil)
+(defvar with-editor-pre-cancel-hook nil)
+(defvar with-editor-post-finish-hook nil)
+(defvar with-editor-post-finish-hook-1 nil)
+(defvar with-editor-post-cancel-hook nil)
+(defvar with-editor-post-cancel-hook-1 nil)
+(defvar with-editor-cancel-alist nil)
+(put 'with-editor-pre-finish-hook 'permanent-local t)
+(put 'with-editor-pre-cancel-hook 'permanent-local t)
+(put 'with-editor-post-finish-hook 'permanent-local t)
+(put 'with-editor-post-cancel-hook 'permanent-local t)
+
+(defvar with-editor-show-usage t)
+(defvar with-editor-cancel-message nil)
+(defvar with-editor-previous-winconf nil)
+(make-variable-buffer-local 'with-editor-show-usage)
+(make-variable-buffer-local 'with-editor-cancel-message)
+(make-variable-buffer-local 'with-editor-previous-winconf)
+(put 'with-editor-cancel-message 'permanent-local t)
+(put 'with-editor-previous-winconf 'permanent-local t)
+
+(defvar-local with-editor--pid nil "For internal use.")
+(put 'with-editor--pid 'permanent-local t)
+
+(defun with-editor-finish (force)
+ "Finish the current edit session."
+ (interactive "P")
+ (when (run-hook-with-args-until-failure
+ 'with-editor-finish-query-functions force)
+ (let ((with-editor-post-finish-hook-1
+ (ignore-errors (delq t with-editor-post-finish-hook))))
+ (run-hooks 'with-editor-pre-finish-hook)
+ (with-editor-return nil)
+ (accept-process-output nil 0.1)
+ (run-hooks 'with-editor-post-finish-hook-1))))
+
+(defun with-editor-cancel (force)
+ "Cancel the current edit session."
+ (interactive "P")
+ (when (run-hook-with-args-until-failure
+ 'with-editor-cancel-query-functions force)
+ (let ((message with-editor-cancel-message))
+ (when (functionp message)
+ (setq message (funcall message)))
+ (let ((with-editor-post-cancel-hook-1
+ (ignore-errors (delq t with-editor-post-cancel-hook)))
+ (with-editor-cancel-alist nil))
+ (run-hooks 'with-editor-pre-cancel-hook)
+ (with-editor-return t)
+ (accept-process-output nil 0.1)
+ (run-hooks 'with-editor-post-cancel-hook-1))
+ (message (or message "Canceled by user")))))
+
+(defun with-editor-return (cancel)
+ (let ((winconf with-editor-previous-winconf)
+ (clients server-buffer-clients)
+ (dir default-directory)
+ (pid with-editor--pid))
+ (remove-hook 'kill-buffer-query-functions
+ 'with-editor-kill-buffer-noop t)
+ (cond (cancel
+ (save-buffer)
+ (if clients
+ (dolist (client clients)
+ (ignore-errors
+ (server-send-string client "-error Canceled by user"))
+ (delete-process client))
+ ;; Fallback for when emacs was used as $EDITOR
+ ;; instead of emacsclient or the sleeping editor.
+ ;; See https://github.com/magit/magit/issues/2258.
+ (ignore-errors (delete-file buffer-file-name))
+ (kill-buffer)))
+ (t
+ (save-buffer)
+ (if clients
+ ;; Don't use `server-edit' because we do not want to
+ ;; show another buffer belonging to another client.
+ ;; See https://github.com/magit/magit/issues/2197.
+ (server-done)
+ (kill-buffer))))
+ (when pid
+ (let ((default-directory dir))
+ (process-file "kill" nil nil nil
+ "-s" (if cancel "USR2" "USR1") pid)))
+ (when (and winconf (eq (window-configuration-frame winconf)
+ (selected-frame)))
+ (set-window-configuration winconf))))
+
+;;; Mode
+
+(defvar with-editor-mode-map
+ (let ((map (make-sparse-keymap)))
+ (define-key map "\C-c\C-c" 'with-editor-finish)
+ (define-key map [remap server-edit] 'with-editor-finish)
+ (define-key map [remap evil-save-and-close] 'with-editor-finish)
+ (define-key map [remap evil-save-modified-and-close] 'with-editor-finish)
+ (define-key map "\C-c\C-k" 'with-editor-cancel)
+ (define-key map [remap kill-buffer] 'with-editor-cancel)
+ (define-key map [remap ido-kill-buffer] 'with-editor-cancel)
+ (define-key map [remap iswitchb-kill-buffer] 'with-editor-cancel)
+ (define-key map [remap evil-quit] 'with-editor-cancel)
+ map))
+
+(define-minor-mode with-editor-mode
+ "Edit a file as the $EDITOR of an external process."
+ :lighter with-editor-mode-lighter
+ ;; Protect the user from killing the buffer without using
+ ;; either `with-editor-finish' or `with-editor-cancel',
+ ;; and from removing the key bindings for these commands.
+ (unless with-editor-mode
+ (user-error "With-Editor mode cannot be turned off"))
+ (add-hook 'kill-buffer-query-functions
+ 'with-editor-kill-buffer-noop nil t)
+ ;; `server-execute' displays a message which is not
+ ;; correct when using this mode.
+ (when with-editor-show-usage
+ (with-editor-usage-message)))
+
+(put 'with-editor-mode 'permanent-local t)
+
+(defun with-editor-kill-buffer-noop ()
+ (user-error (substitute-command-keys "\
+Don't kill this buffer. Instead cancel using \\[with-editor-cancel]")))
+
+(defun with-editor-usage-message ()
+ ;; Run after `server-execute', which is run using
+ ;; a timer which starts immediately.
+ (run-with-timer
+ 0.01 nil `(lambda ()
+ (with-current-buffer ,(current-buffer)
+ (message (substitute-command-keys "\
+Type \\[with-editor-finish] to finish, \
+or \\[with-editor-cancel] to cancel"))))))
+
+;;; Wrappers
+
+(defvar with-editor--envvar nil "For internal use.")
+
+(defmacro with-editor (&rest body)
+ "Use the Emacsclient as $EDITOR while evaluating BODY.
+Modify the `process-environment' for processes started in BODY,
+instructing them to use the Emacsclient as $EDITOR. If optional
+ENVVAR is provided then bind that environment variable instead.
+\n(fn [ENVVAR] BODY...)"
+ (declare (indent defun) (debug (body)))
+ `(let ((with-editor--envvar ,(if (stringp (car body))
+ (pop body)
+ '(or with-editor--envvar "EDITOR")))
+ (process-environment process-environment))
+ (with-editor--setup)
+ ,@body))
+
+(defun with-editor--setup ()
+ (if (or (not with-editor-emacsclient-executable)
+ (file-remote-p default-directory))
+ (push (concat with-editor--envvar "=" with-editor-sleeping-editor)
+ process-environment)
+ ;; Make sure server-use-tcp's value is valid.
+ (unless (featurep 'make-network-process '(:family local))
+ (setq server-use-tcp t))
+ ;; Make sure the server is running.
+ (unless server-process
+ (when (server-running-p server-name)
+ (setq server-name (format "server%s" (emacs-pid)))
+ (when (server-running-p server-name)
+ (server-force-delete server-name)))
+ (server-start))
+ ;; Tell $EDITOR to use the Emacsclient.
+ (push (concat with-editor--envvar "="
+ (shell-quote-argument with-editor-emacsclient-executable)
+ ;; Tell the process where the server file is.
+ (and (not server-use-tcp)
+ (concat " --socket-name="
+ (shell-quote-argument
+ (expand-file-name server-name
+ server-socket-dir)))))
+ process-environment)
+ (when server-use-tcp
+ (push (concat "EMACS_SERVER_FILE="
+ (expand-file-name server-name server-auth-dir))
+ process-environment))
+ ;; As last resort fallback to the sleeping editor.
+ (push (concat "ALTERNATE_EDITOR=" with-editor-sleeping-editor)
+ process-environment)))
+
+(defun with-editor-server-window ()
+ (or (and buffer-file-name
+ (cdr (cl-find-if (lambda (cons)
+ (string-match-p (car cons) buffer-file-name))
+ with-editor-server-window-alist)))
+ server-window))
+
+(defun server-switch-buffer--with-editor-server-window-alist
+ (fn &optional next-buffer killed-one filepos)
+ "Honor `with-editor-server-window-alist' (which see)."
+ (let ((server-window (with-current-buffer
+ (or next-buffer (current-buffer))
+ (when with-editor-mode
+ (setq with-editor-previous-winconf
+ (current-window-configuration)))
+ (with-editor-server-window))))
+ (funcall fn next-buffer killed-one filepos)))
+
+(advice-add 'server-switch-buffer :around
+ 'server-switch-buffer--with-editor-server-window-alist)
+
+(defun start-file-process--with-editor-process-filter
+ (fn name buffer program &rest program-args)
+ "When called inside a `with-editor' form and the Emacsclient
+cannot be used, then give the process the filter function
+`with-editor-process-filter'. To avoid overriding the filter
+being added here you should use `with-editor-set-process-filter'
+instead of `set-process-filter' inside `with-editor' forms.
+
+When the `default-directory' is located on a remote machine,
+then also manipulate PROGRAM and PROGRAM-ARGS in order to set
+the appropriate editor environment variable."
+ (if (not with-editor--envvar)
+ (apply fn name buffer program program-args)
+ (when (file-remote-p default-directory)
+ (unless (equal program "env")
+ (push program program-args)
+ (setq program "env"))
+ (push (concat with-editor--envvar "=" with-editor-sleeping-editor)
+ program-args))
+ (let ((process (apply fn name buffer program program-args)))
+ (set-process-filter process 'with-editor-process-filter)
+ (process-put process 'default-dir default-directory)
+ process)))
+
+(advice-add 'start-file-process :around
+ 'start-file-process--with-editor-process-filter)
+
+(defun with-editor-set-process-filter (process filter)
+ "Like `set-process-filter' but keep `with-editor-process-filter'.
+Give PROCESS the new FILTER but keep `with-editor-process-filter'
+if that was added earlier by the adviced `start-file-process'.
+
+Do so by wrapping the two filter functions using a lambda, which
+becomes the actual filter. It calls `with-editor-process-filter'
+first, passing t as NO-STANDARD-FILTER. Then it calls FILTER,
+which may or may not insert the text into the PROCESS' buffer."
+ (set-process-filter
+ process
+ (if (eq (process-filter process) 'with-editor-process-filter)
+ `(lambda (proc str)
+ (,filter proc str)
+ (with-editor-process-filter proc str t))
+ filter)))
+
+(defvar with-editor-filter-visit-hook nil)
+
+(defun with-editor-output-filter (string)
+ (save-match-data
+ (if (string-match "^WITH-EDITOR: \\([0-9]+\\) OPEN \\(.+?\\)\r?$" string)
+ (let ((pid (match-string 1 string))
+ (file (match-string 2 string)))
+ (with-current-buffer
+ (find-file-noselect
+ (if (file-name-absolute-p file)
+ (concat (file-remote-p default-directory) file)
+ (expand-file-name file)))
+ (with-editor-mode 1)
+ (setq with-editor--pid pid)
+ (run-hooks 'with-editor-filter-visit-hook)
+ (funcall (or (with-editor-server-window) 'switch-to-buffer)
+ (current-buffer))
+ (kill-local-variable 'server-window))
+ nil)
+ string)))
+
+(defun with-editor-process-filter
+ (process string &optional no-default-filter)
+ "Listen for edit requests by child processes."
+ (let ((default-directory (process-get process 'default-dir)))
+ (with-editor-output-filter string))
+ (unless no-default-filter
+ (internal-default-process-filter process string)))
+
+(advice-add 'server-visit-files :after
+ 'server-visit-files--with-editor-file-name-history-exclude)
+
+(defun server-visit-files--with-editor-file-name-history-exclude
+ (files _proc &optional _nowait)
+ (dolist (file files)
+ (setq file (car file))
+ (when (cl-find-if (lambda (regexp)
+ (string-match-p regexp file))
+ with-editor-file-name-history-exclude)
+ (setq file-name-history (delete file file-name-history)))))
+
+;;; Augmentations
+
+(cl-defun with-editor-export-editor (&optional (envvar "EDITOR"))
+ "Teach subsequent commands to use current Emacs instance as editor.
+
+Set and export the environment variable ENVVAR, by default
+\"EDITOR\". The value is automatically generated to teach
+commands to use the current Emacs instance as \"the editor\".
+
+This works in `shell-mode', `term-mode' and `eshell-mode'."
+ (interactive (list (with-editor-read-envvar)))
+ (cond
+ ((derived-mode-p 'comint-mode 'term-mode)
+ (let* ((process (get-buffer-process (current-buffer)))
+ (filter (process-filter process)))
+ (goto-char (process-mark process))
+ (process-send-string
+ process (format " export %s=%s\n" envvar
+ (shell-quote-argument with-editor-sleeping-editor)))
+ (while (accept-process-output process 0.1))
+ (set-process-filter process filter)
+ (if (derived-mode-p 'term-mode)
+ (with-editor-set-process-filter process 'with-editor-emulate-terminal)
+ (add-hook 'comint-output-filter-functions 'with-editor-output-filter
+ nil t))))
+ ((derived-mode-p 'eshell-mode)
+ (add-to-list 'eshell-preoutput-filter-functions
+ 'with-editor-output-filter)
+ (setenv envvar with-editor-sleeping-editor))
+ (t
+ (error "Cannot export environment variables in this buffer")))
+ (message "Successfully exported %s" envvar))
+
+(defun with-editor-export-git-editor ()
+ "Like `with-editor-export-editor' but always set `$GIT_EDITOR'."
+ (interactive)
+ (with-editor-export-editor "GIT_EDITOR"))
+
+(defun with-editor-export-hg-editor ()
+ "Like `with-editor-export-editor' but always set `$HG_EDITOR'."
+ (interactive)
+ (with-editor-export-editor "HG_EDITOR"))
+
+(defun with-editor-emulate-terminal (process string)
+ "Like `term-emulate-terminal' but also handle edit requests."
+ (when (with-editor-output-filter string)
+ (term-emulate-terminal process string)))
+
+(defvar with-editor-envvars '("EDITOR" "GIT_EDITOR" "HG_EDITOR"))
+
+(cl-defun with-editor-read-envvar
+ (&optional (prompt "Set environment variable")
+ (default "EDITOR"))
+ (let ((reply (completing-read (if default
+ (format "%s (%s): " prompt default)
+ (concat prompt ": "))
+ with-editor-envvars nil nil nil nil default)))
+ (if (string= reply "") (user-error "Nothing selected") reply)))
+
+(define-minor-mode shell-command-with-editor-mode
+ "Teach `shell-command' to use current Emacs instance as editor.
+
+Teach `shell-command', and all commands that ultimately call that
+command, to use the current Emacs instance as editor by executing
+\"EDITOR=CLIENT COMMAND&\" instead of just \"COMMAND&\".
+
+CLIENT is automatically generated; EDITOR=CLIENT instructs
+COMMAND to use to the current Emacs instance as \"the editor\",
+assuming no other variable overrides the effect of \"$EDITOR\".
+CLIENT may be the path to an appropriate emacsclient executable
+with arguments, or a script which also works over Tramp.
+
+Alternatively you can use the `with-editor-async-shell-command',
+which also allows the use of another variable instead of
+\"EDITOR\"."
+ :global t)
+
+(defun with-editor-async-shell-command
+ (command &optional output-buffer error-buffer envvar)
+ "Like `async-shell-command' but with `$EDITOR' set.
+
+Execute string \"ENVVAR=CLIENT COMMAND\" in an inferior shell;
+display output, if any. With a prefix argument prompt for an
+environment variable, otherwise the default \"EDITOR\" variable
+is used. With a negative prefix argument additionally insert
+the COMMAND's output at point.
+
+CLIENT is automatically generated; ENVVAR=CLIENT instructs
+COMMAND to use to the current Emacs instance as \"the editor\",
+assuming it respects ENVVAR as an \"EDITOR\"-like variable.
+CLIENT maybe the path to an appropriate emacsclient executable
+with arguments, or a script which also works over Tramp.
+
+Also see `async-shell-command' and `shell-command'."
+ (interactive (with-editor-shell-command-read-args "Async shell command: " t))
+ (let ((with-editor--envvar envvar))
+ (with-editor
+ (async-shell-command command output-buffer error-buffer))))
+
+(defun with-editor-shell-command
+ (command &optional output-buffer error-buffer envvar)
+ "Like `shell-command' or `with-editor-async-shell-command'.
+If COMMAND ends with \"&\" behave like the latter,
+else like the former."
+ (interactive (with-editor-shell-command-read-args "Shell command: "))
+ (if (string-match "&[ \t]*\\'" command)
+ (with-editor-async-shell-command
+ command output-buffer error-buffer envvar)
+ (shell-command command output-buffer error-buffer)))
+
+(defun with-editor-shell-command-read-args (prompt &optional async)
+ (let ((command (read-shell-command
+ prompt nil nil
+ (let ((filename (or buffer-file-name
+ (and (eq major-mode 'dired-mode)
+ (dired-get-filename nil t)))))
+ (and filename (file-relative-name filename))))))
+ (list command
+ (if (or async (setq async (string-match-p "&[ \t]*\\'" command)))
+ (< (prefix-numeric-value current-prefix-arg) 0)
+ current-prefix-arg)
+ shell-command-default-error-buffer
+ (and async current-prefix-arg (with-editor-read-envvar)))))
+
+(defun shell-command--shell-command-with-editor-mode
+ (fn command &optional output-buffer error-buffer)
+ ;; `shell-mode' and its hook are intended for buffers in which an
+ ;; interactive shell is running, but `shell-command' also turns on
+ ;; that mode, even though it only runs the shell to run a single
+ ;; command. The `with-editor-export-editor' hook function is only
+ ;; intended to be used in buffers in which an interactive shell is
+ ;; running, so it has to be remove here.
+ (let ((shell-mode-hook (remove 'with-editor-export-editor shell-mode-hook)))
+ (cond ((or (not (or with-editor--envvar shell-command-with-editor-mode))
+ (not (string-match-p "&\\'" command)))
+ (funcall fn command output-buffer error-buffer))
+ ((and with-editor-emacsclient-executable
+ (not (file-remote-p default-directory)))
+ (with-editor (funcall fn command output-buffer error-buffer)))
+ (t
+ (apply fn (format "%s=%s %s"
+ (or with-editor--envvar "EDITOR")
+ (shell-quote-argument with-editor-sleeping-editor)
+ command)
+ output-buffer error-buffer)
+ (ignore-errors
+ (let ((process (get-buffer-process
+ (or output-buffer
+ (get-buffer "*Async Shell Command*")))))
+ (set-process-filter
+ process (lambda (proc str)
+ (comint-output-filter proc str)
+ (with-editor-process-filter proc str t)))
+ process))))))
+
+(advice-add 'shell-command :around
+ 'shell-command--shell-command-with-editor-mode)
+
+;;; with-editor.el ends soon
+
+(defun with-editor-debug ()
+ "Debug configuration issues.
+See info node `(with-editor)Debugging' for instructions."
+ (interactive)
+ (with-current-buffer (get-buffer-create "*with-editor-debug*")
+ (pop-to-buffer (current-buffer))
+ (erase-buffer)
+ (ignore-errors (with-editor))
+ (insert
+ (format "with-editor: %s\n" (locate-library "with-editor.el"))
+ (format "emacs: %s (%s)\n"
+ (expand-file-name invocation-name invocation-directory)
+ emacs-version)
+ "system:\n"
+ (format " system-type: %s\n" system-type)
+ (format " system-configuration: %s\n" system-configuration)
+ (format " system-configuration-options: %s\n" system-configuration-options)
+ "server:\n"
+ (format " server-running-p: %s\n" (server-running-p))
+ (format " server-process: %S\n" server-process)
+ (format " server-use-tcp: %s\n" server-use-tcp)
+ (format " server-name: %s\n" server-name)
+ (format " server-socket-dir: %s\n" server-socket-dir))
+ (if (and server-socket-dir (file-accessible-directory-p server-socket-dir))
+ (dolist (file (directory-files server-socket-dir nil "^[^.]"))
+ (insert (format " %s\n" file)))
+ (insert (format " %s: not an accessible directory\n"
+ (if server-use-tcp "WARNING" "ERROR"))))
+ (insert (format " server-auth-dir: %s\n" server-auth-dir))
+ (if (file-accessible-directory-p server-auth-dir)
+ (dolist (file (directory-files server-auth-dir nil "^[^.]"))
+ (insert (format " %s\n" file)))
+ (insert (format " %s: not an accessible directory\n"
+ (if server-use-tcp "ERROR" "WARNING"))))
+ (let ((val with-editor-emacsclient-executable)
+ (def (default-value 'with-editor-emacsclient-executable))
+ (fun (let ((warning-minimum-level :error)
+ (warning-minimum-log-level :error))
+ (with-editor-locate-emacsclient))))
+ (insert "with-editor-emacsclient-executable:\n"
+ (format " value: %s (%s)\n" val
+ (and val (with-editor-emacsclient-version val)))
+ (format " default: %s (%s)\n" def
+ (and def (with-editor-emacsclient-version def)))
+ (format " funcall: %s (%s)\n" fun
+ (and fun (with-editor-emacsclient-version fun)))))
+ (insert "path:\n"
+ (format " $PATH: %S\n" (getenv "PATH"))
+ (format " exec-path: %s\n" exec-path))
+ (insert (format " with-editor-emacsclient-path:\n"))
+ (dolist (dir (with-editor-emacsclient-path))
+ (insert (format " %s (%s)\n" dir (car (file-attributes dir))))
+ (when (file-directory-p dir)
+ ;; Don't match emacsclientw.exe, it makes popup windows.
+ (dolist (exec (directory-files dir t "emacsclient\\(?:[^w]\\|\\'\\)"))
+ (insert (format " %s (%s)\n" exec
+ (with-editor-emacsclient-version exec))))))))
+
+(defconst with-editor-font-lock-keywords
+ '(("(\\(with-\\(?:git-\\)?editor\\)\\_>" (1 'font-lock-keyword-face))))
+(font-lock-add-keywords 'emacs-lisp-mode with-editor-font-lock-keywords)
+
+(provide 'with-editor)
+;; Local Variables:
+;; indent-tabs-mode: nil
+;; End:
+;;; with-editor.el ends here
--- /dev/null
+This is with-editor.info, produced by makeinfo version 5.2 from
+with-editor.texi.
+
+ Copyright (C) 2015-2017 Jonas Bernoulli <jonasNOSPAMbernoul.li>
+
+ You can redistribute this document 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 document 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.
+INFO-DIR-SECTION Emacs
+START-INFO-DIR-ENTRY
+* With-Editor: (with-editor). Using the Emacsclient as $EDITOR.
+END-INFO-DIR-ENTRY
+
+\1f
+File: with-editor.info, Node: Top, Next: Using the With-Editor package, Up: (dir)
+
+With-Editor User Manual
+***********************
+
+The library ‘with-editor’ makes it easy to use the Emacsclient as the
+‘$EDITOR’ of child processes, making sure they know how to call home.
+For remote processes a substitute is provided, which communicates with
+Emacs on standard output instead of using a socket as the Emacsclient
+does.
+
+ This library was written because Magit has to be able to do the above
+to allow the user to edit commit messages gracefully and to edit rebase
+sequences, which wouldn’t be possible at all otherwise.
+
+ Because other packages can benefit from such functionality, this
+library is made available as a separate package. It also defines some
+additional functionality which makes it useful even for end-users, who
+don’t use Magit or another package which uses it internally.
+
+ Copyright (C) 2015-2017 Jonas Bernoulli <jonasNOSPAMbernoul.li>
+
+ You can redistribute this document 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 document 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.
+
+* Menu:
+
+* Using the With-Editor package::
+* Using With-Editor as a library::
+* Debugging::
+
+— The Detailed Node Listing —
+
+Using the With-Editor package
+
+* Configuring With-Editor::
+* Using With-Editor commands::
+
+\1f
+File: with-editor.info, Node: Using the With-Editor package, Next: Using With-Editor as a library, Prev: Top, Up: Top
+
+1 Using the With-Editor package
+*******************************
+
+The ‘With-Editor’ package is used internally by Magit when editing
+commit messages and rebase sequences. It also provides some commands
+and features which are useful by themselves, even if you don’t use
+Magit.
+
+ For information about using this library in you own package, see
+*note Using With-Editor as a library::.
+
+* Menu:
+
+* Configuring With-Editor::
+* Using With-Editor commands::
+
+\1f
+File: with-editor.info, Node: Configuring With-Editor, Next: Using With-Editor commands, Up: Using the With-Editor package
+
+1.1 Configuring With-Editor
+===========================
+
+With-Editor tries very hard to locate a suitable ‘emacsclient’
+executable, so ideally you should never have to customize the option
+‘with-editor-emacsclient-executable’. When it fails to do so, then the
+most likely reason is that someone found yet another way to package
+Emacs (most likely on macOS) without putting the executable on ‘$PATH’,
+and we have to add another kludge to find it anyway.
+
+ -- User Option: with-editor-emacsclient-executable
+
+ The ‘emacsclient’ executable used as the editor by child process of
+ this Emacs instance. By using this executable, child processes can
+ call home to their parent process.
+
+ This option is automatically set at startup by looking in
+ ‘exec-path’, and other places where the executable could be
+ installed, to find the ‘emacsclient’ executable most suitable for
+ the current Emacs instance.
+
+ You should *not* customize this option permanently. If you have to
+ do it, then you should consider that a temporary kludge and inform
+ the Magit maintainer as described in *note Debugging::.
+
+ If With-Editor fails to find a suitable ‘emacsclient’ on you
+ system, then this should be fixed for all users at once, by
+ teaching ‘with-editor-locate-emacsclient’ how to do so on your
+ system and system like yours. Doing it this way has the advantage,
+ that you won’t have do it again every time you update Emacs, and
+ that other users who have installed Emacs the same way as you have,
+ won’t have to go through the same trouble.
+
+ Note that there also is a nuclear option; setting this variable to
+ ‘nil’ causes the "sleeping editor" described below to be used even
+ for local child processes. Obviously we don’t recommend that you
+ use this except in "emergencies", i.e. before we had a change to
+ add a kludge appropriate for you setup.
+
+ -- Function: with-editor-locate-emacsclient
+
+ The function used to set the initial value of the option
+ ‘with-editor-emacsclient-executable’. There’s a lot of voodoo
+ here.
+
+ The ‘emacsclient’ cannot be used when using Tramp to run a process on
+a remote machine. (Theoretically it could, but that would be hard to
+setup, very fragile, and rather insecure).
+
+ With-Editor provides an alternative "editor" which can be used by
+remote processes in much the same way as local processes use an
+‘emacsclient’ executable. This alternative is known as the "sleeping
+editor" because it is implemented as a shell script which sleeps until
+it receives a signal.
+
+ -- User Option: with-editor-sleeping-editor
+
+ The sleeping editor is a shell script used as the editor of child
+ processes when the ‘emacsclient’ executable cannot be used.
+
+ This fallback is used for asynchronous process started inside the
+ macro ‘with-editor’, when the process runs on a remote machine or
+ for local processes when ‘with-editor-emacsclient-executable’ is
+ ‘nil’.
+
+ Where the latter uses a socket to communicate with Emacs’ server,
+ this substitute prints edit requests to its standard output on
+ which a process filter listens for such requests. As such it is
+ not a complete substitute for a proper ‘emacsclient’, it can only
+ be used as ‘$EDITOR’ of child process of the current Emacs
+ instance.
+
+ Some shells do not execute traps immediately when waiting for a
+ child process, but by default we do use such a blocking child
+ process.
+
+ If you use such a shell (e.g. ‘csh’ on FreeBSD, but not Debian),
+ then you have to edit this option. You can either replace ‘sh’
+ with ‘bash’ (and install that), or you can use the older, less
+ performant implementation:
+
+ "sh -c '\
+ echo \"WITH-EDITOR: $$ OPEN $0\"; \
+ trap \"exit 0\" USR1; \
+ trap \"exit 1\" USR2; \
+ while true; do sleep 1; done'"
+
+ This leads to a delay of up to a second. The delay can be
+ shortened by replacing ‘sleep 1’ with ‘sleep 0.01’, or if your
+ implementation does not support floats, then by using ‘nanosleep
+ 0.01’ instead.
+
+\1f
+File: with-editor.info, Node: Using With-Editor commands, Prev: Configuring With-Editor, Up: Using the With-Editor package
+
+1.2 Using With-Editor commands
+==============================
+
+This section describes how to use the ‘with-editor’ library _outside_ of
+Magit. You don’t need to know any of this just to create commits using
+Magit.
+
+ The commands ‘with-editor-async-shell-command’ and
+‘with-editor-shell-command’ are intended as drop in replacements for
+‘async-shell-command’ and ‘shell-command’. They automatically export
+‘$EDITOR’ making sure the executed command uses the current Emacs
+instance as "the editor". With a prefix argument these commands prompt
+for an alternative environment variable such as ‘$GIT_EDITOR’.
+
+ -- Command: with-editor-async-shell-command
+
+ This command is like ‘async-shell-command’, but it runs the shell
+ command with the current Emacs instance exported as ‘$EDITOR’.
+
+ -- Command: with-editor-shell-command
+
+ This command is like ‘async-shell-command’, but it runs the shell
+ command with the current Emacs instance exported as ‘$EDITOR’.
+ This only has an effect if the shell command is run asynchronously,
+ i.e. when the command ends with ‘&’.
+
+ To always use these variants add this to you init file:
+
+ (define-key (current-global-map)
+ [remap async-shell-command] 'with-editor-async-shell-command)
+ (define-key (current-global-map)
+ [remap shell-command] 'with-editor-shell-command)
+
+ Alternatively use the global ‘shell-command-with-editor-mode’.
+
+ -- Variable: shell-command-with-editor-mode
+
+ When this mode is active, then ‘$EDITOR’ is exported whenever
+ ultimately ‘shell-command’ is called to asynchronously run some
+ shell command. This affects most variants of that command, whether
+ they are defined in Emacs or in some third-party package.
+
+ The command ‘with-editor-export-editor’ exports ‘$EDITOR’ or another
+such environment variable in ‘shell-mode’, ‘term-mode’ and ‘eshell-mode’
+buffers. Use this Emacs command before executing a shell command which
+needs the editor set, or always arrange for the current Emacs instance
+to be used as editor by adding it to the appropriate mode hooks:
+
+ (add-hook 'shell-mode-hook 'with-editor-export-editor)
+ (add-hook 'term-exec-hook 'with-editor-export-editor)
+ (add-hook 'eshell-mode-hook 'with-editor-export-editor)
+
+ Some variants of this function exist; these two forms are equivalent:
+
+ (add-hook 'shell-mode-hook
+ (apply-partially 'with-editor-export-editor "GIT_EDITOR"))
+ (add-hook 'shell-mode-hook 'with-editor-export-git-editor)
+
+ -- Command: with-editor-export-editor
+
+ When invoked in a ‘shell-mode’, ‘term-mode’, or ‘eshell-mode’
+ buffer, this command teaches shell commands to use the current
+ Emacs instance as the editor, by exporting ‘$EDITOR’.
+
+ -- Command: with-editor-export-git-editor
+
+ This command is like ‘with-editor-export-editor’ but exports
+ ‘$GIT_EDITOR’.
+
+ -- Command: with-editor-export-hg-editor
+
+ This command is like ‘with-editor-export-editor’ but exports
+ ‘$HG_EDITOR’.
+
+\1f
+File: with-editor.info, Node: Using With-Editor as a library, Next: Debugging, Prev: Using the With-Editor package, Up: Top
+
+2 Using With-Editor as a library
+********************************
+
+This section describes how to use the ‘with-editor’ library _outside_ of
+Magit to teach another package how to have its child processes call
+home, just like Magit does. You don’t need to know any of this just to
+create commits using Magit. You can also ignore this if you use
+‘with-editor’ outside of Magit, but only as an end-user.
+
+ For information about interactive use and options that affect both
+interactive and non-interactive use, see *note Using the With-Editor
+package::.
+
+ -- Macro: with-editor &rest body
+
+ This macro arranges for the ‘emacsclient’ or the sleeping editor to
+ be used as the editor of child processes, effectively teaching them
+ to call home to the current Emacs instance when they require that
+ the user edits a file.
+
+ This is essentially done by establishing a local binding for
+ ‘process-environment’ and changing the value of the ‘$EDITOR’
+ environment variable in that scope. This affects all asynchronous
+ processes started by forms (dynamically) inside BODY.
+
+ -- Function: with-editor-set-process-filter process filter
+
+ This function is like ‘set-process-filter’ but ensures that adding
+ the new FILTER does not remove the ‘with-editor-process-filter’.
+ This is done by wrapping the two filter functions using a lambda,
+ which becomes the actual filter. It calls
+ ‘with-editor-process-filter’ first, passing ‘t’ as
+ NO-STANDARD-FILTER. Then it calls FILTER.
+
+\1f
+File: with-editor.info, Node: Debugging, Prev: Using With-Editor as a library, Up: Top
+
+3 Debugging
+***********
+
+With-Editor tries very hard to locate a suitable ‘emacsclient’
+executable, and then sets option ‘with-editor-emacsclient-executable’
+accordingly. In very rare cases this fails. When it does fail, then
+the most likely reason is that someone found yet another way to package
+Emacs (most likely on macOS) without putting the executable on ‘$PATH’,
+and we have to add another kludge to find it anyway.
+
+ If you are having problems using ‘with-editor’, e.g. you cannot
+commit in Magit, then please open a new issue at
+<https://github.com/magit/with-editor/issues> and provide information
+about your Emacs installation. Most importantly how did you install
+Emacs and what is the output of ‘M-x with-editor-debug RET’.
+
+
+\1f
+Tag Table:
+Node: Top\7f771
+Node: Using the With-Editor package\7f2462
+Node: Configuring With-Editor\7f3048
+Node: Using With-Editor commands\7f7445
+Node: Using With-Editor as a library\7f10708
+Node: Debugging\7f12403
+\1f
+End Tag Table
+
+\1f
+Local Variables:
+coding: utf-8
+End:
--- /dev/null
+;;; x-path-walker-autoloads.el --- automatically extracted autoloads
+;;
+;;; Code:
+(add-to-list 'load-path (or (file-name-directory #$) (car load-path)))
+\f
+;;;### (autoloads nil "x-path-walker" "x-path-walker.el" (22477 28061
+;;;;;; 0 0))
+;;; Generated autoloads from x-path-walker.el
+
+(autoload 'helm-x-path-walker "x-path-walker" "\
+
+
+\(fn)" t nil)
+
+;;;***
+\f
+;;;### (autoloads nil nil ("x-path-walker-pkg.el") (22477 28061 263065
+;;;;;; 0))
+
+;;;***
+\f
+;; Local Variables:
+;; version-control: never
+;; no-byte-compile: t
+;; no-update-autoloads: t
+;; End:
+;;; x-path-walker-autoloads.el ends here
--- /dev/null
+(define-package "x-path-walker" "20160822.1015" "Navigation feature for JSON/XML/HTML based on path (imenu like)"
+ '((helm-core "1.9.2"))
+ :keywords
+ '("convenience"))
+;; Local Variables:
+;; no-byte-compile: t
+;; End:
--- /dev/null
+;;; x-path-walker.el --- Navigation feature for JSON/XML/HTML based on path (imenu like) -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2015
+
+;; Author: <lompik@ArchOrion>
+;; Keywords: convenience
+;; Package-Requires: ((helm-core "1.9.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:
+
+;;
+
+;;; Code:
+
+(require 'helm)
+
+(defvar x-path-walker-source-dir (concat (if load-file-name
+ (file-name-directory load-file-name)
+ default-directory)))
+
+(defvar x-path-walker-objects-separators ".")
+
+(defun x-path-walker-command ()
+ (list (concat "PYTHONPATH=" x-path-walker-source-dir)
+ (executable-find "python3")
+ "-m xpathwalker"))
+
+(defvar x-path-walker-verbose nil)
+
+(defun x-path-build-cmd-path (args)
+ (let ((cmdpython (x-path-walker-command)))
+ (mapconcat #'identity
+ (append cmdpython
+ args)
+ " ")))
+
+(defun x-path-run-py-script (args)
+ (let ((cmd (x-path-build-cmd-path args)))
+ (shell-command-to-string cmd)))
+
+(defun x-path-get-mode ()
+ (let ((mm (pcase major-mode
+ (`json-mode "JSON")
+ (`xml-mode "XML")
+ (`nxml-mode "XML")
+ (`html-mode "HTML")
+ (`web-mode "XML")
+ (code nil))))
+ (unless (and (buffer-file-name) mm)
+ (keyboard-quit))
+ mm))
+
+(defun x-path-walker-ask ()
+ (interactive)
+ (if (and (buffer-modified-p)
+ (yes-or-no-p "Buffer will be linted. Do you want to save the current buffer (required)?"))
+ (save-current-buffer)
+ (if (buffer-modified-p)
+ (keyboard-quit))))
+
+(defun x-path-walker-jump-path (path)
+ (let* ((mode (x-path-get-mode))
+ (path (if (not (bound-and-true-p x-path-walker-verbose))
+ path
+ (if (or (string= mode "HTML")
+ (string= mode "XML"))
+ (car (split-string path " | "))
+ (if (and (string= mode "JSON") )
+ (car (cdr (split-string path " | ")))
+ ""))))
+ (line (replace-regexp-in-string
+ "\n$" ""
+ (x-path-run-py-script `("-x"
+ ,(shell-quote-argument path)
+ "-m"
+ ,mode
+ ,(buffer-file-name) )))))
+ (if (string= mode "JSON")
+ (progn (x-path-walker-ask)
+ (erase-buffer)
+ (shell-command-on-region (point-min) (point-max)
+ (concat "python3 -m json.tool "
+ (buffer-file-name))
+ (current-buffer))))
+ (unless (or (string= "" line))
+ (goto-char 0)
+ (forward-line (1- (string-to-number line)))
+ (recenter)
+ (back-to-indentation))))
+
+;;;###autoload
+(defun helm-x-path-walker()
+ (interactive)
+ (let* ((mode (x-path-get-mode))
+ (file (buffer-file-name))
+ (cmd-line `(,(if (bound-and-true-p x-path-walker-verbose)
+ "-a"
+ "")
+ "-m"
+ ,mode
+ ,file ))
+ (cands (split-string (x-path-run-py-script cmd-line)"\n")))
+ (helm
+ :sources (helm-build-sync-source "PATH-WALKER"
+ :keymap helm-map
+ :candidates cands
+ :candidate-number-limit 500
+ :action (helm-make-actions
+ "Jump to path" 'x-path-walker-jump-path))
+ :prompt "Select Path:"
+ :resume 'noresume
+ :keymap helm-map
+ :buffer "*helm path-walker*")))
+
+(provide 'x-path-walker)
+;;; x-path-walker.el ends here
--- /dev/null
+# xpathwalker
+
+has_legs = False
--- /dev/null
+import sys
+
+from xpathwalker.args import parse_args
+
+
+##########################################################################
+# Main #
+##########################################################################
+
+def main(argv):
+ parse_args(argv)
+
+
+if __name__ == "__main__":
+ main(sys.argv[1:])
+
+# Bench:
+# wc -l
+# 21302 /mnt/VM/home/lompik/Programmation/Web/d3_Map_GOM/Data/fldunit.json
+# with multiproc:
+# # string | .features[99].properties.UNIT_AGT_N
+# # string | .features[99].properties.VERSION_DA
+# # string | .features[99].type
+# # string | .features[9].geometry.type
+# # string | .features[9].properties.OUTLINE_TY
+# # string | .features[9].properties.SDE_TEXT_L
+# # string | .features[9].properties.UNIT_AGT_1
+# # string | .features[9].properties.UNIT_AGT_N
+# # string | .features[9].properties.VERSION_DA
+# # string | .features[9].type
+# # string | .type
+# # ./xmlxpath.py -a -M 374.99s user 29.73s system 569% cpu 1:11.05 total
+
+# without multiproc:
+# # array | .features[9].geometry.coordinates[1][0][7]
+# # number | .features[9].geometry.coordinates[1][0][7][0]
+# # number | .features[9].geometry.coordinates[1][0][7][1]
+# # array | .features[9].geometry.coordinates[1][0][8]
+# # number | .features[9].geometry.coordinates[1][0][8][0]
+# # number | .features[9].geometry.coordinates[1][0][8][1]
+# # array | .features[9].geometry.coordinates[1][0][9]
+# # number | .features[9].geometry.coordinates[1][0][9][0]
+# # number | .features[9].geometry.coordinates[1][0][9][1]
+# # string | .features[9].geometry.type
+# # object | .features[9].properties
+# # string | .features[9].properties.OUTLINE_TY
+# # string | .features[9].properties.SDE_TEXT_L
+# # number | .features[9].properties.SEQUENCE_N
+# # number | .features[9].properties.SHAPE_Area
+# # number | .features[9].properties.SHAPE_Leng
+# # number | .features[9].properties.SN_UNIT_AL
+# # number | .features[9].properties.SN_UNIT_OU
+# # string | .features[9].properties.UNIT_AGT_1
+# # string | .features[9].properties.UNIT_AGT_N
+# # string | .features[9].properties.VERSION_DA
+# # string | .features[9].type
+# # string | .type
+# # ./xmlxpath.py -a 241.04s user 13.05s system 93% cpu 4:31.48 total
--- /dev/null
+from argparse import ArgumentParser
+import os
+import sys
+
+exts_mode = {'.html': "HTML", '.html': 'HTML', '.xml': 'XML', '.json': 'JSON', '.yaml': 'YAML'}
+
+def parse_args(argv):
+ """parse command line arguments
+
+ :param argv:
+ :returns: Processor class
+ :rtype:
+
+ """
+ default_separator = "."
+
+ parser = ArgumentParser(description="Xpath helper")
+ parser.add_argument("inputfile",
+ help="Input FILE", type=str)
+ parser.add_argument("-x", "--xpath", dest='xpath',
+ help="Returns line number corresponding to xpath from FILE", type=str)
+ parser.add_argument("-m", "--mode", dest='mode',
+ help="Language type", type=str, choices=('XML', 'HTML', 'JSON'))
+ parser.add_argument("-a", dest='verbosity', action="store_true", default=False,
+ help="Increase verbosity")
+ parser.add_argument("-M", dest='multiproc', action="store_true", default=False,
+ help="Use multiple process when possible")
+ parser.add_argument("-j", dest='use_jq', action="store_true", default=False,
+ help="JSON: Use jq for processing")
+ parser.add_argument("-F", dest='separator', default=default_separator, type=str,
+ help="Path elements separator")
+ args = parser.parse_args(argv)
+
+ inputfile = args.inputfile
+ proc = False
+ if(not os.path.isfile(inputfile)):
+ sys.exit(1)
+
+ ext = os.path.splitext(inputfile)[1].lower()
+
+ if(args.mode is None):
+ if ext not in exts_mode.keys():
+ print("Unrecognized file format.")
+ sys.exit(1)
+ else:
+ args.mode = exts_mode[ext]
+
+ if(args.mode == 'HTML'):
+ from xpathwalker.lxml_Processor import HTML_Processor
+ proc = HTML_Processor()
+ if args.xpath:
+ args.xpath = "/"+args.xpath
+ elif(args.mode == 'XML'):
+ from xpathwalker.lxml_Processor import XML_Processor
+ proc = XML_Processor()
+ if args.xpath:
+ args.xpath = "/"+args.xpath
+ elif(args.mode == 'JSON'):
+ if(args.use_jq):
+ from xpathwalker.json_jq_Processor import JSON_jq_Processor
+ proc = JSON_jq_Processor()
+ else:
+ from xpathwalker.json_Processor import JSON_Processor
+ proc = JSON_Processor()
+ else:
+ print("Error in arg parsing")
+ sys.exit(2)
+
+ proc.separator = args.separator
+ proc.parse_file(inputfile)
+
+ if(args.xpath is not None):
+ print(proc.get_path_line_number(args.xpath, args.verbosity))
+ else:
+ print("\n".join(proc.list_paths(args.verbosity)))
--- /dev/null
+from xpathwalker.utils import list_compare_idx
+from xpathwalker.processor import Processor
+from xpathwalker.utils import traverse_and_remove_path,\
+ get_dict_from_path, get_class
+import json
+from collections import MutableSequence, MutableMapping
+from collections import OrderedDict
+
+##########################################################################
+# JSON / Python #
+##########################################################################
+
+
+class JSON_Processor(Processor):
+ file_line_number = 0
+
+ def isValidJsonShorthandPropertyName(self, key):
+ if not key[0].isalpha() or not key.isalnum():
+ return('["' + key + '"]')
+ else:
+ return(self.separator + key)
+
+
+ def paths(self, obj, dirs=True, leaves=True, path='', skip=False, allow_empty_string_keys=False):
+ """Yield all paths of the object.
+ Arguments:
+ obj -- An object to get paths from.
+ Keyword Arguments:
+ dirs -- Yield intermediate paths.
+ leaves -- Yield the paths with leaf objects.
+ path -- A list of keys representing the path.
+ skip -- Skip special keys beginning with '+'.
+ """
+ if isinstance(obj, MutableMapping):
+ # Python 3 support
+ # if PY3:
+ iteritems = obj.items()
+
+ for (k, v) in iteritems:
+ if issubclass(k.__class__, (str)):
+ if (not k) and (not allow_empty_string_keys):
+ print("Empty string keys not allowed without "
+ "dpath.options.ALLOW_EMPTY_STRING_KEYS=True")
+ elif (skip and k[0] == '+'):
+ continue
+ newpath = path + self.isValidJsonShorthandPropertyName(str(k))
+ # validate(newpath)
+ if dirs:
+ yield {newpath: {"class": v.__class__}}
+ for child in self.paths(v, dirs, leaves, newpath, skip):
+ yield child
+
+ elif isinstance(obj, MutableSequence):
+ for (i, v) in enumerate(obj):
+ newpath = path + "[%s]" % i
+ if issubclass(i.__class__, int):
+ newpath = path + "[%d]" % i
+ if dirs:
+ yield {newpath: {"class": v.__class__}}
+ for child in self.paths(obj[i], dirs, leaves, newpath, skip):
+ yield child
+ elif leaves:
+ yield path + [[obj, obj.__class__]]
+ elif not dirs:
+ yield path
+
+ def serialize_json(self):
+ res = OrderedDict()
+ for x in self.paths(self.parsed, leaves=False):
+ res.update(x)
+ return(res)
+
+ def list_paths(self, with_attrs=True):
+ json_paths = self.serialize_json()
+ if(with_attrs):
+ return(["%6s | %s" % (get_class(json_paths[x]["class"]), x) for x in json_paths.keys()])
+ else:
+ return([x for x in json_paths.keys()])
+
+ def get_path_line_number(self, path, with_attrs=False):
+ path = path.split("| ")[1] if (with_attrs is True) else path
+
+ orig = self.parsed
+ path = get_dict_from_path(path, self.separator)
+ res = traverse_and_remove_path(orig, path)
+ orig = json.dumps(orig, indent=4).split("\n")
+
+ if(len(orig) != self.file_line_number):
+ raise ValueError("This json file formatting is not compatible. Please run `python -m json.tool file`")
+
+ with_del = json.dumps(res, indent=4).split("\n")
+ return(list_compare_idx(orig, with_del) + 1)
+
+ def parse_file(self, file):
+ with open(file) as f:
+ self.file_line_number = len(f.readlines())
+ f.seek(0)
+ self.parsed = json.load(f, object_pairs_hook=OrderedDict)
--- /dev/null
+import subprocess
+import sys
+import os
+from tempfile import NamedTemporaryFile
+from xpathwalker.utils import list_compare_idx
+from xpathwalker.processor import Processor
+
+##########################################################################
+# JSON #
+##########################################################################
+
+jq_command = """def safeLookupValue:
+ if type != "string" then
+ tostring
+ else
+ .
+ end;
+\
+def arrayToLookup:
+ map(safeLookupValue)
+ | reduce .[] as $exists (
+ {};
+ . + {
+ ($exists): null
+ }
+ );
+\
+def lookup(value):
+ (value | safeLookupValue) as $value
+ | has($value);
+\
+def isWhitelisted(whitelist):
+ whitelist as $whitelist
+ | explode
+ | map(
+ . as $charCode
+ | $whitelist
+ | lookup($charCode)
+ )
+ | all;
+\
+def isNumeric:
+ ("0123456789" | explode | arrayToLookup) as $digits
+ | isWhitelisted($digits);
+\
+def isAlpha:
+ ("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" | explode | arrayToLookup) as $letters
+ | isWhitelisted($letters);
+\
+def isAlphanumeric:
+ ("0123456789" | explode | arrayToLookup) as $digits
+ | ("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" | explode | arrayToLookup) as $letters
+ | ("_" | explode | arrayToLookup) as $special
+ | ($digits + $letters + $special) as $alphanumeric
+ | isWhitelisted($alphanumeric);
+\
+def isValidJsonShorthandPropertyName:
+ (.[0:1] | isAlpha | not) or (isAlphanumeric | not);
+\
+[
+ path(..)
+ | map(
+ if type == "number" then
+ ["[",(.|tostring),"]"]|join("")
+ else
+ tostring
+ | if isValidJsonShorthandPropertyName then
+ "[\\"\\(.)\\"]"
+ else
+ .
+ end
+ end
+ )
+ | join(".")
+ | split("." + "[")
+ | join("[")
+]
+| unique
+| map("." + .)
+| .[]"""
+
+jq_exec = ["jq", "--raw-output"]
+
+def jq_proc(args):
+ with NamedTemporaryFile() as f:
+ try:
+ proc = subprocess.check_call(args,
+ stdout=f,
+ stderr=subprocess.STDOUT)
+ except subprocess.CalledProcessError:
+ print(proc.stderr.fseek(0).read().decode('utf-8'))
+ sys.exit(1)
+ f.seek(0)
+ return f.read().decode('utf-8').split('\n')
+
+
+class JSON_jq_Processor(Processor):
+ file = ""
+
+ def list_paths(self, with_attrs=True, multiproc=False):
+ if(not os.path.isfile(self.file)):
+ sys.exit(1)
+ proc = jq_proc(args=jq_exec + [jq_command,
+ self.file])
+ paths = [x for x in proc if x != '']
+ res = []
+ if(with_attrs is False):
+ res = paths
+ elif with_attrs is True:
+ if multiproc is False:
+ for x in paths:
+ proc = jq_proc(args=jq_exec + ["%s|type" % x,
+ self.file])
+ type = proc[0]
+ res.append("%6s | %s" % (type[0:6], x))
+ else:
+ def get_types(q, x, file):
+ proc = jq_proc(args=jq_exec + ["%s|type" % x,
+ self.file])
+ type = proc[0]
+ q.put("%6s | %s" % (type[0:6], x))
+ import queue
+ import threading
+ q = queue.PriorityQueue()
+ for x in paths:
+ t = threading.Thread(target=get_types, args=(q, x, self.file))
+ t. start()
+ while(q.qsize() > 0):
+ res.append(q.get())
+ return(res)
+
+ def get_path_line_number(self, path, with_attrs=False):
+ path = path.split("| ")[1] if (with_attrs is True) else path
+ proc = jq_proc(args=jq_exec + ['.',
+ self.file])
+ orig = proc
+ proc = jq_proc(args=jq_exec + ['del(%s)' % path,
+ self.file])
+ with_del = proc
+ return(list_compare_idx(orig, with_del) + 1)
+
+ def parse_file(self, file):
+ if(not os.path.isfile(file)):
+ print("File %s: Not Found" % (file))
+ sys.exit(1)
+ self.file = file
--- /dev/null
+from xpathwalker.processor import Processor
+import os
+import sys
+import lxml.etree
+import lxml.html
+
+
+class lxmlProcessor(Processor):
+ """ [X/HT]ML processor
+ """
+ def list_paths(self, with_attrs=False):
+ if(not self.parsed):
+ raise ValueError("No data in parsed")
+ parsed = self.parsed
+ res = []
+ for el in parsed.xpath("//*"):
+ if(with_attrs):
+ if el.keys() is None:
+ res.append("/%s | %s | %s" % (parsed.getelementpath(el), ",".join(el.keys())))
+ else:
+ res.append("/%s | %s" % (parsed.getelementpath(el),
+ ",".join(["%s: %s" % (attr, el.get(key=attr)) for attr in el.keys()])))
+ else:
+ res.append("/%s" % (parsed.getelementpath(el)))
+ return(res)
+
+ def handle_namespace_in_xpath(self, xpath):
+ closinp = len(xpath.split("}"))
+ if(closinp > 1 and closinp != len(xpath.split("}"))):
+ return xpath
+ import re
+ import string
+ insidep = r"(?<={)[^}]*"
+ namesspaces = re.findall(insidep, xpath)
+ nsdict = {}
+
+ def get_letters(matchobj):
+ get_letters.counter += 1
+ id = string.ascii_letters[get_letters.counter]
+ nsdict.update({id: namesspaces[get_letters.counter]})
+ return id + ":"
+ get_letters.counter = -1
+ par = re.compile(r"{"+insidep+r"}")
+ xpath = par.sub(get_letters, xpath)
+ return (xpath, {"namespaces": nsdict})
+
+ def get_path_line_number(self, xpath, with_attrs=False):
+ if(not self.parsed):
+ raise ValueError("No data in parsed")
+
+ parsed = self.parsed
+ xpath = xpath.split(" | ")[0] if (with_attrs is True or xpath.find(" | ") > -1) else xpath
+ res = 0
+ matchs = []
+
+ if(xpath.find("{") > -1): # Handle namespace cases
+ xpath, args = self.handle_namespace_in_xpath(xpath)
+ matchs = parsed.xpath(xpath, **args)
+ else:
+ matchs = parsed.xpath(xpath)
+ if(len(matchs) > 0):
+ res = matchs[0].sourceline
+ return(res)
+
+class HTML_Processor(lxmlProcessor):
+ def parse_file(self, file):
+ """HTML file parse from lxml
+
+ :param file: file path (string)
+ :returns: null
+ :rtype:
+
+ """
+ self.parsed = lxml.html.parse(file)
+
+class XML_Processor(lxmlProcessor):
+ def parse_file(self, file):
+ """HTML file parse from lxml
+
+ :param file: file path (string)
+ :returns: null
+ :rtype:
+
+ """
+ self.parsed = lxml.etree.parse(file)
--- /dev/null
+
+
+class Processor:
+ """An abstract object class to handle the parsing/procesing of files
+
+ """
+ separator = "."
+
+ def __init__(self):
+ super(Processor, self).__init__()
+
+ def list_paths(self, parsed, with_attrs=False):
+ """Return array of path separated by the separator
+
+ :param parsed: A python type object
+ :param with_attrs: List additional attributes
+ :returns: array of paths
+ :rtype: array
+
+ """
+ pass
+
+ def get_path_line_number(self, path, with_attrs=False):
+ """Returns the line number from the file corresponding `path`
+
+ :param path: Path seeked
+ :param with_attrs: `True` if `path` is formatted with additional attributes
+ :returns: line numer corresponding to path
+ :rtype: int
+
+ """
+ pass
+
+ def parse_file(self, file):
+ """Translate the `file` into python object
+
+ :param file: File path
+ :returns: Nothing. insternal variable updated.
+ :rtype:
+
+ """
+ pass
--- /dev/null
+from collections import OrderedDict
+
+##########################################################################
+# Utils #
+##########################################################################
+
+def get_class(obj):
+ name = obj.__name__
+ if(name == "OrderedDict"):
+ return("object")
+ elif(name == "NoneType"):
+ return("null")
+ return(name)
+
+def list_compare_idx(list1, list2):
+ index = 0
+ for idx, origline in enumerate(list1):
+ if(list2[idx] != origline):
+ if((list2[idx]+",") != origline):
+ index = idx
+ break
+ return(index)
+
+def split_path(path, separator, inside_special=False):
+ first_match = '"]' if inside_special else '["'
+ i = path.find(first_match)
+ if i != -1 and inside_special is False:
+ if(path[0:i] != ''):
+ return (split_path(path[0:i],
+ separator=separator,
+ inside_special=False) +
+ split_path(path[i+len('["'):],
+ separator=separator,
+ inside_special=True))
+ else:
+ return (split_path(path[i+len('["'):],
+ separator=separator,
+ inside_special=True))
+ if i != -1 and inside_special is True:
+ if(path[i+len('["'):] != ''):
+ return ([path[:i], "special"],) + split_path(path[i+len('["'):],
+ separator=separator,
+ inside_special=False)
+ else:
+ return ([path[:i], "special"],)
+ else:
+ i = path.find(separator)
+ if i == -1:
+ return (path,)
+ else:
+ if(i != 0):
+ return (path[:i],) + split_path(path[i+1:], separator)
+ else:
+ return split_path(path[i+1:], separator)
+
+
+def get_dict_from_path(path, separator):
+ path = split_path(path, separator)
+
+ res = []
+ for x in path:
+ if not isinstance(x, list):
+ pos = x.find("[")
+ while pos != -1:
+ if pos == 0:
+ i1 = x.find("]")
+ x1 = int(x[0:i1].replace("[", "", 1).replace("]", "", 1))
+ x = x[i1+1:]
+ res.append(x1)
+ else:
+ res.append(x[0:pos])
+ x = x[pos:]
+ pos = x.find("[")
+ else:
+ res.append(x[0])
+ return(res)
+
+def traverse_and_remove_path(obj, path=None, match="First"):
+ if path is None:
+ path = []
+ if isinstance(obj, dict):
+ res = OrderedDict()
+ for k, v in obj.items():
+ cmatch = False
+ if(match and len(path) > 0 and path[0] == k):
+ cmatch = True
+ res.update({k: traverse_and_remove_path(v, path=path[1:], match=cmatch)})
+ if(len(path) == 1 and path[0] in res.keys() and match):
+ del res[path[0]]
+ return res
+ elif isinstance(obj, list):
+ res = []
+ for i, elem in enumerate(obj):
+ cmatch = False
+ if(match and len(path) >= 1 and isinstance(path[0], int) and path[0] < len(obj) and i == path[0]):
+ cmatch = True
+ res.append(traverse_and_remove_path(elem, path=path[1:], match=cmatch))
+ if(len(path) == 1 and isinstance(path[0], int) and path[0] < len(res) and match):
+ res.pop(path[0])
+ return res
+ else:
+ return obj # no container, just values (str, int, float)
--- /dev/null
+##########################################################################
+# YAML #
+##########################################################################
+import yaml
+from xpathwalker.utils import list_compare_idx
+from xpathwalker.utils import traverse_and_remove_path, get_dict_from_path, get_class, paths
+from collections import OrderedDict
+import os
+
+def parse_yaml(file):
+ with open(file) as f:
+ yaml_data = yaml.load(f)
+ res = OrderedDict()
+ for x in paths(yaml_data, leaves=False):
+ res.update(x)
+ return(res)
+
+def get_yaml_paths(file, include_type=True): # XXX: ordering is lost
+ yaml_paths = parse_yaml(file)
+ if(include_type is True):
+ return(["%s | %s" % (get_class(yaml_paths[x]['class']), x) for x in yaml_paths.keys()])
+ else:
+ return(yaml_paths.keys())
+
+def get_yaml_path_line_python(file, path, include_type=False):
+ if(not os.path.isfile(file)):
+ sys.exit(1)
+ path = path.split("| ")[1] if (include_type is True) else path
+ orig = ""
+ with open(file) as f:
+ orig = yaml.load(f)
+ path = get_dict_from_path(path)
+ res = traverse_and_remove_path(orig, path)
+ yaml_dump_options = {"indent": 4, "default_flow_style": False, "explicit_start": False}
+ orig = yaml.dump(orig, **yaml_dump_options).split("\n")
+ with_del = yaml.dump(dict(res), **yaml_dump_options).split("\n")
+ return(list_compare_idx(orig, with_del) + 1)
--- /dev/null
+**/.yas-compiled-snippets.el
--- /dev/null
+Please add here your name in alphabetical order (first name) if you contributed with
+
+- Andrea Crotti
+- James Ferguson
--- /dev/null
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 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.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ 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, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public 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.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
--- /dev/null
+# Yasnippet official snippet collections
+
+[](https://gitter.im/AndreaCrotti/yasnippet-snippets?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
+This repository contains the official snippets for [yasnippet](http://github.com/capitaomorte/yasnippet), as you can see from the git submodules link.
+
+# How to install
+
+There are two options, if you have checked out *yasnippet* already, the only thing you need to do is to run `git submodule update --init`
+and it will checkout automatically this repository, at the last version it was synchronized too.
+
+Otherwise if you want the latest and greatest snippets collection proceed as follows:
+
+1. clone this repository
+2. add to your .emacs the following
+ - `(add-to-list 'yas-snippet-dirs "$$DIRECTORY_WHERE_YOU_CLONED")`
+ - and in case you want to enable yasnippet globally: `(yas-global-mode t)`
+
+3. `M-x yas-reload-all` to activate them
+
+# Contributing
+
+This repository has now become the default snippets repository (as a submodule) in yasnippet.
+So if you have any useful snippets for any language or framework please feel free to contribute.
+
+To study the current snippets I suggest to use `M-x yas-describe-tables`
+which will gave a table representation of all the snippets available in the current mode.
+
+
+# Guidelines
+
+Snippets need to be generic enough to be useful for everyone, and not contain anything specific to your own system.
+
+# Various notes
+
+## HTML snippets
+
+Until September 1st 2014 there were a lot of HTML snippets in the repository, which were sometimes useful but I came to the conclusion that yasnippet was not the right fool for them, so they were removed in this pull request:
+https://github.com/AndreaCrotti/yasnippet-snippets/pull/49
+
+To everyone writing a lot of HTML I suggest using [emmet mode](https://github.com/smihica/emmet-mode) instead, which is a much more powerful mode for writing HTML tags.
--- /dev/null
+# -*- mode: snippet -*-
+# name: project
+# key: proj
+# --
+<project name="${1:test}" default="${2:compile}" basedir="${3:.}">
+
+$0
+</project>
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: property
+# key: prop
+# --
+<property name="${1:name}" value="${2:value}" />
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: target
+# key: target
+# --
+<target name="${1:compile}" ${2:other}>
+ $0
+</target>
\ No newline at end of file
--- /dev/null
+prog-mode
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: comment
+# --
+(*
+$0
+*)
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: considering
+# --
+considering $1
+$0
+end considering
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: considering-application-responses
+# --
+considering application responses
+$0
+end considering
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: display-dialog
+# --
+display dialog "$0"
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: if
+# --
+if $1 then
+$2
+else
+$0
+end if
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: ignoring
+# --
+ignoring $1
+$0
+end ignoring
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: ignoring-application-responses
+# --
+ignoring application responses
+$0
+end ignoring
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: on
+# --
+on $1
+$0
+end $1
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: repeat
+# --
+repeat $1
+$0
+end repeat
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: repeat-until
+# --
+repeat until $1
+$0
+end repeat
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: repeat-while
+# --
+repeat while $1
+$0
+end repeat
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: repeat-with
+# --
+repeat with $1
+$0
+end repeat
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: tell-application
+# --
+tell application "$1"
+$0
+end tell
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: tell-application-to-activate
+# --
+tell application "$1" to activate
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: try
+# --
+try
+$1
+on error $2
+$0
+end try
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: using-terms-from-application
+# --
+using terms from application "$1"
+$0
+end using terms from
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: with-timeout-of-seconds
+# --
+with timeout of $1 seconds
+$0
+end timeout
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: with-transaction
+# --
+with transaction
+$0
+end transaction
\ No newline at end of file
--- /dev/null
+prog-mode
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: comment
+# --
+(*
+$0
+*)
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: considering
+# --
+considering $1
+$0
+end considering
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: considering-application-responses
+# --
+considering application responses
+$0
+end considering
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: display-dialog
+# --
+display dialog "$0"
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: if
+# --
+if $1 then
+$2
+else
+$0
+end if
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: ignoring
+# --
+ignoring $1
+$0
+end ignoring
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: ignoring-application-responses
+# --
+ignoring application responses
+$0
+end ignoring
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: on
+# --
+on $1
+$0
+end $1
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: repeat
+# --
+repeat $1
+$0
+end repeat
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: repeat-until
+# --
+repeat until $1
+$0
+end repeat
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: repeat-while
+# --
+repeat while $1
+$0
+end repeat
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: repeat-with
+# --
+repeat with $1
+$0
+end repeat
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: tell-application
+# --
+tell application "$1"
+$0
+end tell
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: tell-application-to-activate
+# --
+tell application "$1" to activate
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: try
+# --
+try
+$1
+on error $2
+$0
+end try
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: using-terms-from-application
+# --
+using terms from application "$1"
+$0
+end using terms from
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: with-timeout-of-seconds
+# --
+with timeout of $1 seconds
+$0
+end timeout
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: with-transaction
+# --
+with transaction
+$0
+end transaction
\ No newline at end of file
--- /dev/null
+(require 'yasnippet)
+
+(defun yas-c++-class-name (str)
+ "Search for a class name like `DerivedClass' in STR
+(which may look like `DerivedClass : ParentClass1, ParentClass2, ...')
+
+If found, the class name is returned, otherwise STR is returned"
+ (yas-substr str "[^: ]*"))
+
+(defun yas-c++-class-method-declare-choice ()
+ "Choose and return the end of a C++11 class method declaration"
+ (yas-choose-value '(";" " = default;" " = delete;")))
--- /dev/null
+# -*- mode: snippet -*-
+# name: accumulate
+# key: acl
+# --
+auto sum = std::accumulate(std::begin(${1:container}), std::end($1), 0, [](int total, $2) {
+ $3
+});
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: accumulate
+# key: acm
+# --
+auto sum = std::accumulate(std::begin(${1:container}), std::end($1), 0);
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: adjacent_find
+# key: ajf
+# --
+auto pos = std::adjacent_find(std::begin(${1:container}), std::end($1));
+if (pos != std::end($1)) {
+ $2
+}
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: all_of
+# key: alo
+# --
+if (std::all_of(std::begin(${1:container}), std::end($1), []($2) {
+ $3
+})) {
+ $4
+}
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: any_of
+# key: ano
+# --
+if (std::any_of(std::begin(${1:container}), std::end($1), []($2) {
+ $3
+})) {
+ $4
+}
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: assert
+# key: ass
+# --
+assert($0);
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name : v.begin(), v.end()
+# key: beginend
+# --
+${1:v}.begin(), $1.end
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: boost_require
+# key: req
+# group: boost
+# --
+BOOST_REQUIRE( ${1:condition} );
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: cerr
+# key: err
+# --
+cerr << $0;
--- /dev/null
+# -*- mode: snippet -*-
+# name: cin
+# key: cin
+# --
+cin >> $0;
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: class
+# key: cls
+# --
+class ${1:Name}
+{
+public:
+ ${1:$(yas/substr yas-text "[^: ]*")}();
+ ${2:virtual ~${1:$(yas/substr yas-text "[^: ]*")}();}
+};
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: class11
+# key: cls11
+# group: c++11
+# uuid: d7c41f87-9b8a-479d-bb12-89f4cbdd46a7
+# contributor: Ved Vyas
+# desc: Snippet for C++11 classes based on c++-mode/class. Allows for Rule of
+# [0, All]. A choice between ";", " = default;", and " = delete;" is presented
+# for each method. The methods and some of the optional keywords/specifiers are
+# exposed as fields that users can easily skip-and-clear.
+# Hackish query-replace-regexp to renumber non-mirror fields in the region
+# between public and protected (can use N as a field number in the snippet):
+# \${[0-9N]*:\([^\$]\) -> ${\,(+ 2 \#):\1
+# References:
+# 1. http://en.cppreference.com/w/cpp/language/rule_of_three#Rule_of_five
+# 2. https://en.wikipedia.org/wiki/Rule_of_three_%28C%2B%2B_programming%29#Example_in_C.2B.2B
+# 3. http://stackoverflow.com/a/4782927
+# --
+class ${1:Name}
+{
+public:
+${2: ${3://! Default constructor
+ }${1:$(yas-c++-class-name yas-text)}()${4:;$(yas-c++-class-method-declare-choice)}
+
+}${5: ${6://! Copy constructor
+ }${1:$(yas-c++-class-name yas-text)}(const ${1:$(yas-c++-class-name yas-text)} &other)${7:;$(yas-c++-class-method-declare-choice)}
+
+}${8: ${9://! Move constructor
+ }${1:$(yas-c++-class-name yas-text)}(${1:$(yas-c++-class-name yas-text)} &&other)${10: noexcept}${11:;$(yas-c++-class-method-declare-choice)}
+
+}${12: ${13://! Destructor
+ }${14:virtual }~${1:$(yas-c++-class-name yas-text)}()${15: noexcept}${16:;$(yas-c++-class-method-declare-choice)}
+
+}${17: ${18://! Copy assignment operator
+ }${1:$(yas-c++-class-name yas-text)}& operator=(const ${1:$(yas-c++-class-name yas-text)} &other)${19:;$(yas-c++-class-method-declare-choice)}
+
+}${20: ${21://! Move assignment operator
+ }${1:$(yas-c++-class-name yas-text)}& operator=(${1:$(yas-c++-class-name yas-text)} &&other)${22: noexcept}${23:;$(yas-c++-class-method-declare-choice)}
+
+}$0
+
+protected:
+private:
+};
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: count_if
+# key: cni
+# --
+auto n = std::count_if(std::begin(${1:container}), std::end($1), []($2) {
+ $3
+});
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: count
+# key: cnt
+# --
+auto n = std::count(std::begin(${1:container}), std::end($1), $2);
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: const_[]
+# key: c[
+# --
+const ${1:Type}& operator[](${2:int index}) const
+{
+ $0
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: constructor
+# key: ct
+# --
+${1:Class}::$1(${2:args}) ${3: : ${4:init}}
+{
+ $0
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# contributor: York Zhao <gtdplatformNOSPAMgmail.com>
+# name: cout
+# key: cout
+# --
+`(progn (goto-char (point-min)) (unless (re-search-forward
+"^using\\s-+namespace std;" nil 'no-errer) "std::"))
+`cout << $0${1: << "${2:\n}"};
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: copy_backward
+# key: cpb
+# --
+std::copy_backward(std::begin(${1:container}), std::end($1), std::end($1));
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: copy_if
+# key: cpi
+# --
+std::copy_if(std::begin(${1:container}), std::end($1), std::begin($2),
+[]($3) {
+ $4
+});
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: copy_n
+# key: cpn
+# --
+std::copy_n(std::begin(${1:container}), $2, std::end($1));
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: cpp
+# key: cpp
+# --
+#include "`(file-name-nondirectory (file-name-sans-extension (buffer-file-name)))`.h"
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: copy
+# key: cpy
+# --
+std::copy(std::begin(${1:container}), std::end($1), std::begin($2));
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: cstd
+# key: cstd
+# --
+#include <cstdlib>
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: d+=
+# key: d+=
+# --
+${1:MyClass}& operator+=(${2:const $1 &});
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: d_operator<<
+# key: <<
+# --
+friend std::ostream& operator<<(std::ostream&, const ${1:Class}&);
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: d_operator[]
+# key: [
+# --
+${1:Type}& operator[](${2:int index});
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: d_operator[]_const
+# key: c[
+# --
+const ${1:Type}& operator[](${2:int index}) const;
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: d_operator>>
+# key: >>
+# --
+friend std::istream& operator>>(std::istream&, const ${1:Class}&);
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: d_operator<<
+# key: <<
+# --
+friend std::ostream& operator<<(std::ostream&, const ${1:Class}&);
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: delete
+# key: dl
+# --
+delete ${1:pointer};
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: delete[]
+# key: dla
+# --
+delete[] ${1:arr};
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: doc
+# key: doc
+# --
+/**
+ * $0
+ */
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: dynamic_casting
+# key: cast
+# --
+check_and_cast<${1:Type} *>(${2:msg});
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: enum
+# key: enum
+# --
+enum ${1:NAME}{
+$0
+};
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: equal
+# key: eql
+# --
+if (std::equal(std::begin(${1:container}), std::end($1), std::begin($2))) {
+ $3
+}
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: remove
+# key: erm
+# --
+${1:container}.erase(std::remove(std::begin($1), std::end($1), $2), std::end($1));
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: find_first_of
+# key: ffo
+# --
+auto pos = std::find_first_of(std::begin(${1:container}), std::end($1),
+ std::begin($2), std::end($3));
+if (pos != std::end($1)) {
+ $4
+}
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: fill
+# key: fil
+# --
+std::fill(std::begin(${1:container}), std::end($1), $2);
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: find_if_not
+# key: fin
+# --
+auto pos = std::find_if_not(std::begin(${1:container}), std::end($1),[]($2) {
+ $3
+});
+if (pos != std::end($1)) {
+ $4
+}
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: fixture
+# key: fixt
+# --
+BOOST_FIXTURE_TEST_SUITE( ${1:name}, ${2:Fixture} )
+
+$0
+
+BOOST_AUTO_TEST_SUITE_END()
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: fill_n
+# key: fln
+# --
+std::fill_n(std::begin(${1:container}), $2, $3);
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: find
+# key: fnd
+# --
+auto pos = std::find(std::begin(${1:container}), std::end($1), $2);
+if (pos != std::end($1)) {
+ $3
+}
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: find_end
+# key: fne
+# --
+auto pos = std::find_std::end(std::begin(${1:container}), std::end($1),
+ std::begin($2), std::end($3));
+if (pos != std::end($1)) {
+ $4
+}
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: find_if
+# key: fni
+# --
+auto pos = std::find_if(std::begin(${1:container}), std::end($1), []($2) {
+ $3
+});
+if (pos != std::end($1)) {
+ $4
+}
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: fori
+# key: fori
+# --
+for (${1:auto }${2:it} = ${3:var}.begin(); $2 != $3.end(); ++$2) {
+ $0
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: for_each
+# key: fre
+# --
+std::for_each(std::begin(${1:container}), std::end($1), []($2) {
+ $3
+});
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: friend
+# key: fr
+# --
+friend $0;
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: fun_declaration
+# key: f
+# --
+${1:type} ${2:name}(${3:args})${4: const};
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: generate_n
+# key: gnn
+# --
+std::generate_n(std::begin(${1:container}), $2, []($3) {
+ $4
+});
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: generate
+# key: gnr
+# --
+std::generate(std::begin(${1:container}), std::end($1), []($2) {
+ $3
+});
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: gtest
+# key: gtest
+# group: testing
+# --
+#include <gtest/gtest.h>
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: ignore
+# key: ignore
+# --
+${1:std::}cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: is_heap
+# key: ihp
+# --
+if (std::is_heap(std::begin(${1:container}), std::end($1))) {
+ $2
+}
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: is_heap_until
+# key: ihu
+# --
+auto pos = std::is_heap_until(std::begin(${1:container}), std::end($1));
+if (pos != std::end($1)) {
+ $2
+}
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: inline
+# key: il
+# --
+inline $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: io
+# key: io
+# --
+#include <iostream>
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: is_permutation
+# key: ipr
+# --
+if (std::is_permutation(std::begin(${1:container}), std::end($1), std::begin($2))) {
+ $3
+}
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: is_partitioned
+# key: ipt
+# --
+if (std::is_partitioned(std::begin(${1:container}), std::end($1), []($2) {
+ $3
+})) {
+ $4
+}
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: is_sorted
+# key: iss
+# --
+if (std::is_sorted(std::begin(${1:container}), std::end($1))) {
+ $2
+}
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: is_sorted_until
+# key: isu
+# --
+auto pos = std::is_sorted_until(std::begin(${1:container}), std::end($1));
+if (pos != std::end($1)) {
+ $2
+}
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: iota
+# key: ita
+# --
+std::iota(std::begin(${1:container}), std::end($1), $2);
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: iterator
+# key: iter
+# --
+${1:std::}${2:vector<int>}::iterator ${3:iter};
--- /dev/null
+# -*- mode: snippet -*-
+# name: transform
+# key: ltr
+# --
+${1:container}.erase(0, $1.find_first_not_of(" \t\n\r"));
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: transform
+# key: lwr
+# --
+std::transform(std::begin(${1:container}), std::end($1), std::begin($1), [](char c) {
+return std::tolower(c);});
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: lexigraphical_compare
+# key: lxc
+# --
+if (std::lexigraphical_compare(std::begin(${1:container}), std::end($1),
+ std::begin($2), std::end($3)) {
+ $4
+}
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: map
+# key: map
+# --
+std::map<${1:type1}$0> ${2:var};
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: member_function
+# key: mf
+# --
+${1:type} ${2:Class}::${3:name}(${4:args})${5: const}
+{
+ $0
+}
--- /dev/null
+# -*- mode: snippet -*-
+# name: make_heap
+# key: mkh
+# --
+std::make_heap(std::begin(${1:container}), std::end($1));
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: minmax_element
+# key: mme
+# --
+auto minmax = std::minmax_element(std::begin(${1:container}), std::end($1));
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: min_element
+# key: mne
+# --
+auto pos = std::min_element(std::begin(${1:container}), std::end($1));
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: module
+# key: mod
+# --
+class ${1:Class} : public cSimpleModule
+{
+ $0
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: move_backward
+# key: mpb
+# --
+std::move_backward(std::begin(${1:container}), std::end($1), std::end($1));
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: merge
+# key: mrg
+# --
+std::merge(std::begin(${1:container}), std::end($1),
+std::begin($2), std::end($3), std::begin($4));
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: mismatch
+# key: msm
+# --
+auto values = std::mismatch(std::begin(${1:container}), std::end($1), std::begin($1));
+if (values.first == std::end($1)) {
+ $2
+} else {
+ $3
+}
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: max_element
+# key: mxe
+# --
+auto pos = std::max_element(std::begin(${1:container}), std::end($1));
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: namespace
+# key: ns
+# --
+namespace ${1:Namespace} {
+
+ `yas/selected-text`
+
+} // $1
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: none_of
+# key: nno
+# --
+if (std::none_of(std::begin(${1:container}), std::end($1), []($2) {
+ $3
+})) {
+ $4
+}
+$0
--- /dev/null
+#name : namespace ...
+# key: ns
+# --
+namespace
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: nth_element
+# key: nth
+# --
+std::nth_element(std::begin(${1:container}), std::end($1), std::end($1));
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: next_permutation
+# key: nxp
+# --
+if (std::next_permutation(std::begin(${1:container}), std::end($1))) {
+ $2
+}
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: copy
+# key: oit
+# --
+std::copy(std::begin(${1:container}), std::end($1), std::ostream_iterator<$2>{
+%\istd::cout, "$3"
+});
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: operator!=
+# key: !=
+# group: operator overloading
+# --
+bool ${1:MyClass}::operator!=(const $1 &other) const
+{
+ return !(*this == other);
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: operator+
+# key: +
+# group: operator overloading
+# --
+${1:MyClass} $1::operator+(const $1 &other)
+{
+ $1 result = *this;
+ result += other;
+ return result;
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: operator+=
+# key: +=
+# group: operator overloading
+# --
+${1:MyClass}& $1::operator+=(${2:const $1 &rhs})
+{
+ $0
+ return *this;
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: operator=
+# key: =
+# where this is a reference to myself
+# group: operator overloading
+# --
+${1:MyClass}& $1::operator=(const $1 &rhs)
+{
+ // Check for self-assignment!
+ if (this == &rhs)
+ return *this;
+ $0
+ return *this;
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: operator==
+# key: ==
+# group: operator overloading
+# --
+bool ${1:MyClass}::operator==(const $1 &other) const
+{
+ $0
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: operator[]
+# key: []
+# group: operator overloading
+# --
+${1:Type}& operator[](${2:int index})
+{
+ $0
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: operator>>
+# key: >>
+# group: operator overloading
+# --
+std::istream& operator>>(std::istream& is, const ${1:Class}& ${2:c})
+{
+ $0
+ return is;
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: operator<<
+# key: <<
+# group: operator overloading
+# --
+std::ostream& operator<<(std::ostream& os, const ${1:Class}& ${2:c})
+{
+ $0
+ return os;
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: ostream
+# key: os
+# --
+#include <ostream>
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: pack
+# key: pack
+# --
+void cNetCommBuffer::pack(${1:type})
+{
+
+}
+
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: push_heap
+# key: phh
+# --
+std::push_heap(std::begin(${1:container}), std::end($1));
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: partition_point
+# key: ppt
+# --
+auto pos = std::partition_point(std::begin(${1:container}), std::end($1), []($2) {
+ $3
+});
+if (pos != std::end($1)) {
+ $4
+}
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: private
+# key: pr
+# expand-env: ((yas-also-auto-indent-first-line t))
+# --
+private:
+ $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: protected
+# key: pt
+# expand-env: ((yas-also-auto-indent-first-line t))
+# --
+protected:
+ $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: prev_permutation
+# key: prp
+# --
+if (std::prev_permutation(std::begin(${1:container}), std::end($1))) {
+ $2
+}
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: partial_sort_copy
+# key: psc
+# --
+std::partial_sort_copy(std::begin(${1:container}), std::end($1),
+ std::begin($2), std::end($3));
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: partial_sort
+# key: pst
+# --
+std::partial_sort(std::begin(${1:container}), std::end($1), std::end($1));
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: partition_copy
+# key: ptc
+# --
+std::partition_copy(std::begin(${1:container}), std::end($1),
+ std::begin($2), std::end($3));
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: partition
+# key: ptn
+# --
+auto pos = std::partition(std::begin(${1:container}), std::end($1), []($2) {
+ $3
+});
+if (pos != std::end($1)) {
+ $4
+}
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: public
+# key: pb
+# expand-env: ((yas-also-auto-indent-first-line t))
+# --
+public:
+ $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: replace_copy_if
+# key: rci
+# --
+std::replace_copy_if(std::begin(${1:container}), std::end($1),
+ std::begin($1), []($2) {
+ $3
+}, $4);
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: remove_copy
+# key: rmc
+# --
+std::remove_copy(std::begin(${1:container}), std::end($1),
+ std::begin($1), $2);
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: remove_copy_if
+# key: rmf
+# --
+std::remove_copy_if(std::begin(${1:container}), std::end($1),
+ std::begin($1), []($2) {
+ $3
+});
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: remove_if
+# key: rmi
+# --
+auto pos = std::remove_if(std::begin(${1:container}), std::end($1), []($2) {
+ $3
+});
+if (pos != std::end($1)) {
+ $4
+}
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: remove
+# key: rmv
+# --
+auto pos = std::remove(std::begin(${1:container}), std::end($1), $2);
+if (pos != std::end($1)) {
+ $3
+}
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: replace_copy
+# key: rpc
+# --
+std::replace_copy(std::begin(${1:container}), std::end($1), std::begin($1), $2, $3);
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: replace_if
+# key: rpi
+# --
+std::replace_if(std::begin(${1:container}), std::end($1), []($2) {
+$3
+}, $4);
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: replace
+# key: rpl
+# --
+std::replace(std::begin(${1:container}), std::end($1), $2, $3);
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: rotate_copy
+# key: rtc
+# --
+std::rotate_copy(std::begin(${1:container}), std::begin($2), std::end($1),
+ std::begin($3));
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: rotate
+# key: rte
+# --
+std::rotate(std::begin(${1:container}), std::begin($2), std::end($1));
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: reverse_copy
+# key: rvc
+# --
+std::reverse_copy(std::begin(${1:container}), std::end($1), std::begin($2));
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: reverse
+# key: rvr
+# --
+std::reverse(std::begin(${1:container}), std::end($1));
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: random_shuffle
+# key: shf
+# --
+std::random_shuffle(std::begin(${1:container}), std::end($1));
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: stable_partition
+# key: spt
+# --
+auto pos = std::stable_partition(std::begin(${1:container}), std::end($1), []($2) {
+ $3});
+if (pos != std::end($1)) {
+ $4
+}
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: search
+# key: srh
+# --
+auto pos = std::search(std::begin(${1:container}), std::end($1),
+ std::begin($2), std::end($3));
+if (pos != std::end($1)) {
+ $4
+}
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: search_n
+# key: srn
+# --
+auto pos = std::search_n(std::begin(${1:container}), std::end($1),$2,$3);
+if (pos != std::end($1)) {
+ $4
+}
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: sort
+# key: srt
+# --
+std::sort(std::begin(${1:container}), std::end($1));
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: <sstream>
+# key: ss
+# --
+#include <sstream>
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: std
+# key: std
+# --
+using namespace std;
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: std::
+# key: st
+# --
+std::$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: sort_heap
+# key: sth
+# --
+std::sort_heap(std::begin(${1:container}), std::end($1));
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: cin
+# key: sti
+# --
+std::cin >>
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: cout
+# key: sto
+# --
+std::cout <<
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: str
+# key: str
+# --
+#include <string>
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: stable_sort
+# key: sts
+# --
+std::stable_sort(std::begin(${1:container}), std::end($1));
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: vector
+# key: stv
+# --
+std::vector<$2> $3
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: swap_ranges
+# key: swr
+# --
+std::swap_ranges(std::begin(${1:container}), std::end($1), std::begin($2));
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: template
+# key: temp
+# --
+template<${1:$$(yas/choose-value '("typename" "class"))} ${2:T}>
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: test case
+# key: tc
+# group: testing
+# --
+BOOST_AUTO_TEST_CASE( ${1:test_case} )
+{
+ $0
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: test_main
+# key: test_main
+# group: testing
+# --
+int main(int argc, char **argv)
+{
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: test_suite
+# key: ts
+# group: testing
+# --
+BOOST_AUTO_TEST_SUITE( ${1:test_suite1} )
+
+$0
+
+BOOST_AUTO_TEST_SUITE_END()
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: transform
+# key: tfm
+# --
+std::transform(std::begin(${1:container}), std::end($1),
+ std::begin($1), []($2) {
+$3%
+});
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: this
+# key: th
+# --
+this
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: throw
+# key: throw
+# --
+throw ${1:MyError}($0);
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: generate_n
+# key: trm
+# --
+${1:container}.erase($1.find_last_not_of(" \t\n\r") + 1);
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: try
+# key: try
+# a bit too intrusive now still, not always I want to do this
+# --
+try {
+ $0
+} catch (${1:type}) {
+
+}
--- /dev/null
+# -*- mode: snippet -*-
+# name: tryw
+# key: tryw
+# --
+try {
+ `(or yas/selected-text (car kill-ring))`
+} catch ${1:Exception} {
+
+}
--- /dev/null
+# -*- mode: snippet -*-
+# name: unique_copy
+# key: ucp
+# --
+std::unique_copy(std::begin(${1:container}), std::end($1),
+ std::ostream_iterator<string>(std::cout, "\n"));
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: transform
+# key: upr
+# --
+std::transform(std::begin(${1:container}), std::end($1), std::begin($1), [](char c) {
+return std::toupper(c);
+});
+$2
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: unique
+# key: uqe
+# --
+auto pos = std::unique(std::begin(${1:container}), std::end($1));
+$0
--- /dev/null
+#name : using namespace ...
+# key: using
+# --
+using namespace ${std};
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: vector
+# key: vec
+# --
+std::vector<${1:Class}> ${2:var}${3:(${4:10}, $1($5))};
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: assert
+# key: ass
+# --
+#include <assert.h>
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: compile
+# key: compile
+# --
+// -*- compile-command: "${1:gcc -Wall -o ${2:dest} ${3:file}}" -*-
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: define
+# key: d
+# --
+#define $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: malloc
+# key: malloc
+# --
+malloc(sizeof($1)${2: * ${3:3}});
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: packed
+# key: packed
+# --
+__attribute__((__packed__))$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: printf
+# key: pr
+# --
+printf("${1:format string}"${2: ,a0,a1});
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: stdio
+# key: io
+# --
+#include <stdio.h>
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: stdlib
+# key: std
+# --
+#include <stdlib.h>
--- /dev/null
+# -*- mode: snippet -*-
+# name: string
+# key: str
+# --
+#include <string.h>
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: union
+# key: union
+# --
+typedef union {
+ $0
+} ${1:name};
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: unistd
+# key: uni
+# --
+#include <unistd.h>
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name : case : {...}
+# key: case
+# expand-env: ((yas-also-auto-indent-first-line t))
+# --
+case ${2:constexpr}:${3: \{}
+ $0
+ break;
+${3:$(if (string-match "\{" yas-text) "\}" "")}
\ No newline at end of file
--- /dev/null
+#name : do { ... } while (...)
+# key: do
+# --
+do
+{
+ $0
+} while (${1:condition});
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name : else { ... }
+# key: else
+# --
+else${1: {
+ $0
+}}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+#cotributor: Henrique Jung <henriquenjNOSPAMgmail.com>
+#name: File description
+#key: \file
+#group: doxygen
+# --
+/**
+ * \file ${1:`(file-name-nondirectory(buffer-file-name))`}
+ * \brief ${2:A Documented file.}
+ ${3:*
+ * ${4:Detailed description}
+ *
+}*/
--- /dev/null
+# -*- mode: snippet -*-
+# name: FILE *fp = fopen(..., ...);
+# key: fopen
+# --
+FILE *${fp} = fopen(${"file"}, "${r}");
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: for
+# key: for
+# --
+for (${1:i = 0}; ${2:i < N}; ${3:++i}) {
+ $0
+}
--- /dev/null
+# -*- mode: snippet -*-
+# contributor: York Zhao
+# name: for_n
+# key: forn
+# --
+for (${1:auto }${2:i} = ${3:0}; $2 < ${4:MAXIMUM}; ++$2) {
+ $0
+}
--- /dev/null
+# -*- mode: snippet -*-
+#cotributor: Henrique Jung <henriquenjNOSPAMgmail.com>
+#name: Function description
+#key: \brief
+#group: doxygen
+# --
+/**
+ * \brief ${1:function description}
+ ${2:*
+ * ${3:Detailed description}
+ *
+ }* \param ${4:param}
+ * \return ${5:return type}
+ */
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name : if (...) { ... }
+# key: if
+# --
+if (${1:condition}) ${2:{
+ $0
+}}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: ifdef
+# key: ifdef
+# --
+#ifdef ${1:MACRO}
+
+$0
+
+#endif // $1
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name : #include <...>
+# key : incs
+# --
+#include <$1>
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name : #include "..."
+# key : incl
+# --
+#include "$1"
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: main
+# key: main
+# --
+int main(${1:int argc, char *argv[argc]})
+{
+ $0
+ return 0;
+}
--- /dev/null
+# -*- mode: snippet -*-
+# name: math
+# key: math
+# --
+#include <math.h>
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+#cotributor: Henrique Jung <henriquenjNOSPAMgmail.com>
+#name: Member description
+#key: !<
+#group: doxygen
+# --
+/*!< ${1:Detailed description after the member} */
\ No newline at end of file
--- /dev/null
+#name : #ifndef XXX; #define XXX; #endif
+# key: once
+# --
+#ifndef ${1:`(upcase (file-name-nondirectory (file-name-sans-extension (or (buffer-file-name) ""))))`_H}
+#define $1
+
+$0
+
+#endif /* $1 */
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: printf
+# key: printf
+# --
+printf("${1:%s}\\n"${1:$(if (string-match "%" yas-text) ", " "\);")
+}$2${1:$(if (string-match "%" yas-text) "\);" "")}
\ No newline at end of file
--- /dev/null
+#name : struct ... { ... }
+# key: struct
+# --
+struct ${1:name}
+{
+ $0
+};
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name : switch (...) { case : ... default: ...}
+# key: switch
+# --
+switch (${1:expr}) {
+case ${2:constexpr}:${3: \{}
+ $0
+ break;
+${3:$(if (string-match "\{" yas-text) "\}\n" "")}default:
+ break;
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: ternary
+# key: ?
+# --
+(${1:cond}) ? ${2:then} : ${3:else};
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: typedef
+# key: typedef
+# --
+typedef ${1:type} ${2:alias};
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: while
+# key: while
+# --
+while (${1:condition}) {
+ $0
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: action
+# key: action
+# --
+action: ${0:nothing}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: bash
+# key: bash
+# --
+bash "${1:install something}" do
+ user "${2:root}"
+ cwd "${3:/tmp}"
+ creates "${4:maybe}"
+ code <<-EOH
+ STATUS=0
+ $0 || STATUS=1
+ exit $STATUS
+ EOH
+end
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: cookbook_file
+# key: cookbook_file
+# --
+cookbook_file "${1:/tmp/file}" do
+ owner "${2:root}"
+ group "${3:root}"
+ mode "${4:0644}"
+ source "${5:my-filename}"
+end
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: cron
+# key: cron
+# --
+cron "${1:name}" do
+ hour "${2:5}"
+ minute "${3:0}"
+
+ command "${4:/bin/true}"
+end
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: cronf
+# key: cronf
+# --
+cron "${1:name}" do
+ hour "${2:*}"
+ minute "${3:*}"
+ day "${4:*}"
+ weekday "${6:*}"
+ command "${7:/bin/true}"
+ user "${8:root}"
+ mailto "${9:rootNOSPAMexample.com}"
+ path "${10:/bin:/usr/bin}"
+ home "${11:/tmp}"
+ shell "${12:/bin/bash}"
+end
--- /dev/null
+# -*- mode: snippet -*-
+# name: deploy
+# key: deploy
+# --
+deploy "/my/deploy/dir" do
+ repo "gitNOSPAMgithub.com/whoami/provideroject"
+ revision "abc123" # or "HEAD" or "TAG_for_1.0" or (subversion) "1234"
+ user "deploy_ninja"
+ enable_submodules true
+ migrate true
+ migration_command "rake db:migrate"
+ environment "RAILS_ENV" => "production", "OTHER_ENV" => "foo"
+ shallow_clone true
+ action :deploy # or :rollback
+ restart_command "touch tmp/restart.txt"
+ git_ssh_wrapper "wrap-ssh4git.sh"
+ scm_provider Chef::Provider::Git # is the default, for svn: Chefhef::Provider::Subversion
+end
--- /dev/null
+# -*- mode: snippet -*-
+# name: directory
+# key: directory
+# --
+directory "${1:name}" do
+ owner "root"
+ group "root"
+ mode "0755"
+
+ action :create
+end
--- /dev/null
+# -*- mode: snippet -*-
+# name: directoryf
+# key: directoryf
+# --
+directory "${1:name}" do
+ owner "$create{2:root}"
+ group "${3:root}"
+ mode "${4:0755}"
+ path "${5:name}"
+ recursive ${6:false}
+
+ action :${7:create}
+end
--- /dev/null
+# -*- mode: snippet -*-
+# name: env
+# key: env
+# --
+env "${1:RAILS_ENV}" do
+ value "${2:production}"
+end
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: execute
+# key: execute
+# --
+execute "${1:name}" do
+ command "${2:ls -la}"
+ creates "${3:/tmp/something}"
+
+ action :${4:run}
+end
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: executef
+# key: executef
+# --
+execute "${1:name}" do
+ command "${2:ls -la}"
+ creates "$ls{3:/tmp/something}"
+ cwd "${4:/tmp}"
+ environment ({${5:'HOME' => '/home/myhome'}})
+ user "${6:root}"
+ group "${7:root}"
+ path "${8:['/opt/bin','/opt/sbin']}"
+ timeout ${9:3600}
+ returns ${10:0}
+ umask "${11:022}umask"
+
+ action :${12:run}
+end
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: file
+# key: file
+# --
+file "${1:name}" do
+ owner "root"
+ group "root"
+ mode "0644"
+
+ action :create
+end
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: filef
+# key: filef
+# --
+file "${1:name}" do
+ path "${3:path}"
+ backup ${4:5}
+ owner "${5:root}"
+ group "${6:root}"
+ mode "${7:0644}"
+ content "${8:content here}"
+
+ action :${2:create}
+end
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: git
+# key: git
+# --
+git "${1:/home/user/deployment}" do
+ repository "${2:gitNOSPAMgithub.com:gitsite/deploymentployment.git}"
+ reference "${3:master}"
+ user "${4:user}"
+ group "${5:templateest}"
+ action :sync
+end
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: group
+# key: group
+# --
+group "${1:name}" do
+ gid ${2:999}
+ members [${3:'paco','vicente'}]
+
+ action :create
+end
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: http_request
+# key: http_request
+# --
+http_request "${1:some message}" do
+ url "${2:http://example.com/check_in}"
+end
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: http_requestp
+# key: http_requestp
+# --
+http_request "${1:posting data}" do
+ action :post
+ url "${2:http://example.com/check_in}"
+ message ${3::some => "data"}
+ headers (${4:\{"AUTHORIZATION" => authorization\}})
+end
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: ignore_failure
+# key: ignore_failure
+# --
+ignore_failure ${0:true}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: inc
+# key: inc
+# --
+include_recipe "${1:example::recipe}"
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: link
+# key: link
+# --
+link "${1:/tmp/passwd}" do
+ to "${2:/etc/passwd}"
+end
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: linkf
+# key: linkf
+# --
+link "${1:/tmp/passwd}" do
+ to "${2:/etc/passwd}"
+ link_type :${3:symbolic}
+ owner "${4:root}"
+ group "${5:root}"
+end
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: log
+# key: log
+# --
+log ("${1:your string to log}") { level :${2:debug} }
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: machine
+# key: machine
+# --
+machine "${1:name}" do
+ role '${2:web}'
+ recipe '${3:web}'
+ chef_environment '${4:_default}'
+ converge true
+end
--- /dev/null
+# -*- mode: snippet -*-
+# name: meta
+# key: meta
+# --
+maintainer "${1:YOUR_COMPANY_NAME}"
+maintainer_email "${2:YOUR_EMAIL}"
+license "${3:All rights reserved}"
+description "${4:Installs/Configures example}"
+long_description IO.read(File.join(File.dirname(__FILE__), 'README.rdoc'))
+version "${5:0.0.1}"
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: not_if
+# key: not_if
+# --
+not_if "${1}"
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: notifies
+# key: notifies
+# --
+notifies :${1:restart}, "${2:service}[${3:name}]"
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: only_if
+# key: only_if
+# --
+only_if "${1}"
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: pac
+# key: pac
+# --
+package "${1:name}" do
+ action :${2:install}
+ version "${3:1.0-1}"
+end
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: pak
+# key: pak
+# --
+package "${1:name}" do
+ action :${2:install}
+ version "${3:1.0-1}"
+end
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: provider
+# key: provider
+# --
+provider Chef::Provider::${0:Package::Rubygems}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: python
+# key: python
+# --
+python "${1:install something}" do
+ user "${2:root}"
+ cwd "${3:/tmp}"
+ code <<-EOH
+ $0
+ EOH
+end
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: remote_file
+# key: remote_file
+# --
+remote_file "${1:/tmp/remote_file}" do
+ owner "${2:root}"
+ group "${3:root}"
+ mode "${4:0644}"
+ source "${5:http://www.example.com/remote_file}"
+ checksum "${6:sha256checksum}"
+end
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: retries
+# key: retries
+# --
+retries ${1:1}
+retry_delay ${2:2}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: role
+# key: role
+# --
+name "${1:role name}"
+ description "${2:Description for the role}"
+ env_run_lists "${3:role name}" => [
+ ]
+ run_list ""
+ default_attributes(
+ ${4::attribute => "example"}
+ )
--- /dev/null
+# -*- mode: snippet -*-
+# name: ruby
+# key: ruby
+# --
+ruby_block "${1:reload client config}" do
+ block do
+ ${0:Chef::Config.from_file("/Chefetc/chef/client.rb")}
+ end
+end
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: script
+# key: script
+# --
+script "${1:do something}" do
+ interpreter "bash"
+ user "${2:root}"
+ cwd "${3:/tmp}"
+ creates "${4:maybe}"
+ code <<-EOH
+ STATUS=0
+ $0 || STATUS=1
+ exit $STATUS
+ EOH
+end
--- /dev/null
+# -*- mode: snippet -*-
+# name: service
+# key: service
+# --
+service "${1:name}" do
+ supports :status => ${2:true}, :restart => ${3:true}, :truereload => ${4:true}
+ action ${5:[ :enable, :start ]}
+end
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: servicep
+# key: servicep
+# --
+service "${1:name}" do
+ pattern "${2:pattern}"
+ supports :status => ${3:true}, :restart => ${4:true}, :reload => ${5:true}
+ action ${6:[ :enable, :start ]}
+end
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: subscribes
+# key: subscribes
+# --
+subscribes :${1:restart}, "${2:template}[${3:name}]"
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: supports
+# key: supports
+# --
+supports :status => :${1:true}, :restart => :${2:true}, :reload => :${3:true}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: template
+# key: template
+# --
+template "${1:name}" do
+ source "${2:source}.erb"
+ owner "root"
+ group "root"
+ mode "0644"
+end
--- /dev/null
+# -*- mode: snippet -*-
+# name: templatev
+# key: templatev
+# --
+template "${1:name}" do
+ source "${2:source}.erb"
+ owner "root"
+ group "root"
+ node "0644"
+ variables( ${3::config_var => node[:configs][:config_var]} )
+end
--- /dev/null
+# -*- mode: snippet -*-
+# name: user
+# key: user
+# --
+user "${1:random}" do
+ action :create
+ comment "${2:Random User}"
+ uid ${3:1000}
+ gid "${4:users}"
+ home "${5:/home/random}"
+ shell "${6:/bin/zsh}"
+ password "${7:\$1\$JJsvHslV\$szsCjVEroftprNn4JHtDi.}"
+ supports :manage_home =>manage_home true
+end
--- /dev/null
+clojure-mode
--- /dev/null
+# name: bench
+# key: bench
+# --
+(dotimes [_ 5 ]$>
+ (time (dotimes [i 1000000]$>
+ $0$>
+ )))$>
\ No newline at end of file
--- /dev/null
+# name: bp
+# key: bp
+# --
+(swank.core/break)
--- /dev/null
+# name: def
+# key: def
+# --
+(def $0)
--- /dev/null
+# name: defmacro
+# key: defm
+# --
+(defmacro $1
+ "$2"$>
+ [$3]$>
+ $0)$>
--- /dev/null
+# name: defn
+# key: defn
+# --
+(defn $1
+ "$2"$>
+ [$3]$>
+ $0)$>
--- /dev/null
+# name: defrecord
+# key: defr
+# --
+(defrecord
+ ^{"$1"}$>
+ $2$>
+ [$3]$>
+ $0)$>
--- /dev/null
+# name: deftype
+# key: deft
+# --
+(deftype
+ ^{"$1"}$>
+ $2$>
+ [$3]$>
+ $0)$>
\ No newline at end of file
--- /dev/null
+# name: doseq
+# key: doseq
+# --
+(doseq [$1 $2]
+ $3)$>
+$0
\ No newline at end of file
--- /dev/null
+# name: fn
+# key: fn
+# --
+(fn [$1]
+ $0)$>
--- /dev/null
+# name: for
+# key: for
+# --
+(for [$1 $2]
+ $3)$>
--- /dev/null
+# -*- coding: utf-8 -*-
+# name: if
+# key: if
+# --
+(if $1
+ $2$>
+ $3)$>
+$0
--- /dev/null
+# -*- coding: utf-8 -*-
+# name: ifl
+# key: ifl
+# --
+(if-let [$1 $2]
+ $3)$>
+$0
\ No newline at end of file
--- /dev/null
+# name: import
+# key: import
+# expand-env: ((yas-triggers-in-field nil))
+# --
+(:import ($1))$>
\ No newline at end of file
--- /dev/null
+# -*- coding: utf-8 -*-
+# name: is
+# key: is
+# --
+(is (= $1 $2))
--- /dev/null
+# -*- coding: utf-8 -*-
+# name: let
+# key: let
+# --
+(let [$1 $2]$>
+ $3)$>
+$0
--- /dev/null
+# -*- coding: utf-8 -*-
+# name: map
+# key: map
+# --
+(map $1 $2)
\ No newline at end of file
--- /dev/null
+# -*- coding: utf-8 -*-
+# name: map lambda
+# key: map
+# --
+(map #($1) $2)$>
\ No newline at end of file
--- /dev/null
+# -*- coding: utf-8 -*-
+# name: mdoc
+# key: mdoc
+# --
+^{:doc "$1"}
\ No newline at end of file
--- /dev/null
+# -*- coding: utf-8 -*-
+# name: ns
+# key: ns
+# --
+(ns `(cl-flet ((try-src-prefix
+ (path src-pfx)
+ (let ((parts (split-string path src-pfx)))
+ (if (= 2 (length parts))
+ (cl-second parts)
+ nil))))
+ (let* ((p (buffer-file-name))
+ (p2 (cl-first
+ (cl-remove-if-not '(lambda (x) x)
+ (mapcar
+ '(lambda (pfx)
+ (try-src-prefix p pfx))
+ '("/src/cljs/" "/src/clj/" "/src/" "/test/")))))
+ (p3 (file-name-sans-extension p2))
+ (p4 (mapconcat '(lambda (x) x)
+ (split-string p3 "/")
+ ".")))
+ (replace-regexp-in-string "_" "-" p4)))`)
--- /dev/null
+# key: opts
+# name: opts
+# --
+{:keys [$1]$>
+ :or {$2}$>
+ :as $3}$>
\ No newline at end of file
--- /dev/null
+# -*- coding: utf-8 -*-
+# name: pr
+# key: pr
+# --
+(prn $1)
+$0
\ No newline at end of file
--- /dev/null
+# -*- coding: utf-8 -*-
+# name: print
+# key: print
+# --
+(println $1)
+$0
\ No newline at end of file
--- /dev/null
+# -*- coding: utf-8 -*-
+# name: reduce
+# key: reduce
+# --
+(reduce ${1:(fn [p n] $0)} $2)
--- /dev/null
+# name: require
+# key: require
+# expand-env: ((yas-triggers-in-field nil))
+# --
+(:require [$1 :as $2])$>
--- /dev/null
+# name: test
+# key: test
+# --
+(deftest $1
+ (is (= $2))$>
+ $0)$>
--- /dev/null
+# name: try
+# key: try
+# --
+(try
+$1$>
+(catch ${2:Exception} e$>
+$3$>))$>
\ No newline at end of file
--- /dev/null
+# name: use
+# key: use
+# expand-env: ((yas-triggers-in-field nil))
+# --
+(:use [$1 :refer [$2]])$>
\ No newline at end of file
--- /dev/null
+# -*- coding: utf-8 -*-
+# name: when
+# key: when
+# --
+(when $1
+ $2)$>
+$0$>
--- /dev/null
+# -*- coding: utf-8 -*-
+# name: whenl
+# key: whenl
+# --
+(when-let [$1 $2]
+ $3)$>
+ $0$>
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: add_executable
+# key: exe
+# --
+add_executable($1 ${2:main.cpp})
+target_link_libraries($1 $3)
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: add_library
+# key: lib
+# --
+add_library($1 ${2:class.cpp})
+target_link_libraries($1 $3)
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: cmake_minimum_required
+# key: min
+# --
+cmake_minimum_required(VERSION ${1:2.6})
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: foreach
+# key: for
+# --
+foreach(${1:var} \${${2:array}})
+ $3
+endforeach($1)$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: function
+# key: fun
+# --
+function(${1:name})
+ $2
+endfunction($1)$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: if
+# key: if
+# --
+if(${1:cond})
+ $2
+endif($1)$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: ifelse
+# key: if
+# --
+if(${1:cond})
+ $2
+else(${3:cond})
+ $0
+endif($1)$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: include
+# key: inc
+# --
+include($0)
--- /dev/null
+# -*- mode: snippet -*-
+# name: macro
+# key: macro
+# --
+macro(${1:name}${2: args})
+ $2
+endmacro($1)$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: message
+# key: msg
+# --
+message(${1:STATUS }"$0")
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: option
+# key: opt
+# --
+option(${1:OPT} "${2:docstring}" ${3:value})
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: project
+# key: proj
+# --
+project($0)
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: set
+# key: set
+# --
+set(${1:var} ${2:value})
\ No newline at end of file
--- /dev/null
+text-mode
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: section
+# key: sec
+# section for xorg.conf
+# --
+Section "${1:Device}"
+ $0
+EndSection
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: EV
+# key: ev
+# --
+EV << "${1:string}"$0;
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: emit_signal
+# key: emit
+# --
+emit(${1:signal_id}, ${2:long});
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: intuniform
+# key: intuni
+# --
+intuniform(${1:0}, ${2:1})
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: math
+# key: math
+# --
+#include <cmath>
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: nan
+# key: nan
+# --
+isnan(${1:x})
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: omnet
+# key: omnet
+# --
+#include <omnetpp.h>
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: parameter_omnetpp
+# key: par
+# --
+${1:var} = par("${2:par}");
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: scheduleAt
+# key: sched
+# --
+scheduleAt(simTime()+${1:1.0}, ${2:event});
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: uniform
+# key: uni
+# uniform distribution
+# --
+uniform(${1:0}, ${2:1})
\ No newline at end of file
--- /dev/null
+#contributor : Alejandro Espinoza Esparza <aespinozaNOSPAMstructum.com.mx>
+#name : private attribute ....;
+# key: attrib
+# --
+/// <summary>
+/// $3
+/// </summary>
+private $1 $2;
\ No newline at end of file
--- /dev/null
+#contributor : Alejandro Espinoza Esparza <aespinozaNOSPAMstructum.com.mx>
+#name : private attribute ....; public property ... ... { ... }
+# key: attrib
+# --
+/// <summary>
+/// $3
+/// </summary>
+private $1 $2;
+
+/// <summary>
+/// $4
+/// </summary>
+/// <value>$5</value>
+public $1 $2
+{
+ get {
+ return this.$2;
+ }
+ set {
+ this.$2 = value;
+ }
+}
\ No newline at end of file
--- /dev/null
+#contributor : Alejandro Espinoza Esparza <aespinozaNOSPAMstructum.com.mx>
+#name : private _attribute ....; public Property ... ... { ... }
+# key: attrib
+# --
+/// <summary>
+/// $3
+/// </summary>
+private $1 ${2:$(if (> (length yas-text) 0) (format "_%s%s" (downcase (substring yas-text 0 1)) (substring yas-text 1 (length yas-text))) "")};
+
+/// <summary>
+/// ${3:Description}
+/// </summary>
+/// <value><c>$1</c></value>
+public ${1:Type} ${2:Name}
+{
+ get {
+ return this.${2:$(if (> (length yas-text) 0) (format "_%s%s" (downcase (substring yas-text 0 1)) (substring yas-text 1 (length yas-text))) "")};
+ }
+ set {
+ this.${2:$(if (> (length yas-text) 0) (format "_%s%s" (downcase (substring yas-text 0 1)) (substring yas-text 1 (length yas-text))) "")} = value;
+ }
+}
\ No newline at end of file
--- /dev/null
+#contributor : Alejandro Espinoza Esparza <aespinozaNOSPAMstructum.com.mx>
+#name : class ... { ... }
+# key: class
+# --
+${5:public} class ${1:Name}
+{
+ #region Ctor & Destructor
+ /// <summary>
+ /// ${3:Standard Constructor}
+ /// </summary>
+ public $1($2)
+ {
+ }
+
+ /// <summary>
+ /// ${4:Default Destructor}
+ /// </summary>
+ public ~$1()
+ {
+ }
+ #endregion
+}
\ No newline at end of file
--- /dev/null
+#contributor : Alejandro Espinoza Esparza <aespinozaNOSPAMstructum.com.mx>
+#name : /// <summary> ... </summary>
+# key: comment
+# --
+/// <summary>
+/// $1
+/// </summary>
\ No newline at end of file
--- /dev/null
+#contributor : Alejandro Espinoza Esparza <aespinozaNOSPAMstructum.com.mx>
+#name : /// <param name="..."> ... </param>
+# key: comment
+# --
+/// <param name="$1">$2</param>
\ No newline at end of file
--- /dev/null
+#contributor : Alejandro Espinoza Esparza <aespinozaNOSPAMstructum.com.mx>
+#name : /// <param name="..."> ... </param>
+# key: comment
+# --
+/// <returns>$1</returns>
\ No newline at end of file
--- /dev/null
+#contributor : Alejandro Espinoza Esparza <aespinozaNOSPAMstructum.com.mx>
+#name : /// <exception cref="..."> ... </exception>
+# key: comment
+# --
+/// <exception cref="$1">$2</exception>
\ No newline at end of file
--- /dev/null
+#contributor : Jostein Kjønigsen <josteinNOSPAMkjonigsen.net>
+#name : foreach { ... }
+# key: fore
+# --
+foreach (${1:var} ${2:item} in ${3:list})
+{
+ $0
+}
\ No newline at end of file
--- /dev/null
+#contributor : Alejandro Espinoza Esparza <aespinozaNOSPAMstructum.com.mx>
+#name : public void Method { ... }
+# key: method
+# --
+/// <summary>
+/// ${5:Description}
+/// </summary>${2:$(if (string= (upcase yas-text) "VOID") "" (format "%s%s%s" "\n/// <returns><c>" yas-text "</c></returns>"))}
+${1:public} ${2:void} ${3:MethodName}($4)
+{
+$0
+}
\ No newline at end of file
--- /dev/null
+#contributor : Alejandro Espinoza Esparza <aespinozaNOSPAMstructum.com.mx>
+#name : namespace .. { ... }
+# key: namespace
+# --
+namespace $1
+{
+$0
+}
\ No newline at end of file
--- /dev/null
+#contributor : Alejandro Espinoza Esparza <aespinozaNOSPAMstructum.com.mx>
+#name : property ... ... { ... }
+# key: prop
+# --
+/// <summary>
+/// $5
+/// </summary>
+/// <value>$6</value>
+$1 $2 $3
+{
+ get {
+ return this.$4;
+ }
+ set {
+ this.$4 = value;
+ }
+}
\ No newline at end of file
--- /dev/null
+#contributor : Alejandro Espinoza Esparza <aespinozaNOSPAMstructum.com.mx>
+#name : #region ... #endregion
+# key: region
+# --
+#region $1
+$0
+#endregion
\ No newline at end of file
--- /dev/null
+#contributor : Alejandro Espinoza Esparza <aespinozaNOSPAMstructum.com.mx>
+#name : using ...;
+# key: using
+# --
+using $1;
\ No newline at end of file
--- /dev/null
+#contributor : Alejandro Espinoza Esparza <aespinozaNOSPAMstructum.com.mx>
+#name : using System;
+# key: using
+# --
+using System;
\ No newline at end of file
--- /dev/null
+#contributor : Alejandro Espinoza Esparza <aespinozaNOSPAMstructum.com.mx>
+#name : using System....;
+# key: using
+# --
+using System.$1;
\ No newline at end of file
--- /dev/null
+#name : background-color: ...
+# --
+background-color: #${1:DDD};
\ No newline at end of file
--- /dev/null
+#name : background-image: ...
+# --
+background-image: url($1);
\ No newline at end of file
--- /dev/null
+#name : border size style color
+# --
+border: ${1:1px} ${2:solid} #${3:999};
\ No newline at end of file
--- /dev/null
+#contributor : rejeep <johan.rejeepNOSPAMgmail.com>
+#name : clear: ...
+# --
+clear: $1;
--- /dev/null
+#contributor : rejeep <johan.rejeepNOSPAMgmail.com>
+#name : display: block
+# --
+display: block;
--- /dev/null
+#contributor : rejeep <johan.rejeepNOSPAMgmail.com>
+#name : display: inline
+# --
+display: inline;
--- /dev/null
+#contributor : rejeep <johan.rejeepNOSPAMgmail.com>
+#name : display: none
+# --
+display: none;
--- /dev/null
+#contributor : rejeep <johan.rejeepNOSPAMgmail.com>
+#name : font-family: ...
+# --
+font-family: $1;
--- /dev/null
+#contributor : rejeep <johan.rejeepNOSPAMgmail.com>
+#name : font-size: ...
+# --
+font-size: ${12px};
--- /dev/null
+#contributor : rejeep <johan.rejeepNOSPAMgmail.com>
+#name : margin-bottom: ...
+# --
+margin-bottom: $1;
--- /dev/null
+#contributor : rejeep <johan.rejeepNOSPAMgmail.com>
+#name : margin-left: ...
+# --
+margin-left: $1;
--- /dev/null
+#contributor : rejeep <johan.rejeepNOSPAMgmail.com>
+#name : margin: ...
+# --
+margin: $1;
--- /dev/null
+#contributor : rejeep <johan.rejeepNOSPAMgmail.com>
+#name : margin top right bottom left
+# --
+margin: ${top} ${right} ${bottom} ${left};
--- /dev/null
+#contributor : rejeep <johan.rejeepNOSPAMgmail.com>
+#name : margin-right: ...
+# --
+margin-right: $1;
--- /dev/null
+#contributor : rejeep <johan.rejeepNOSPAMgmail.com>
+#name : margin-top: ...
+# --
+margin-top: $1;
--- /dev/null
+#contributor : rejeep <johan.rejeepNOSPAMgmail.com>
+#name : padding-bottom: ...
+# --
+padding-bottom: $1;
--- /dev/null
+#contributor : rejeep <johan.rejeepNOSPAMgmail.com>
+#name : padding-left: ...
+# --
+padding-left: $1;
--- /dev/null
+#contributor : rejeep <johan.rejeepNOSPAMgmail.com>
+#name : padding: ...
+# --
+padding: $1;
--- /dev/null
+#contributor : rejeep <johan.rejeepNOSPAMgmail.com>
+#name : padding: top right bottom left
+# --
+padding: ${top} ${right} ${bottom} ${left};
--- /dev/null
+#contributor : rejeep <johan.rejeepNOSPAMgmail.com>
+#name : padding-right: ...
+# --
+padding-right: $1;
--- /dev/null
+#contributor : rejeep <johan.rejeepNOSPAMgmail.com>
+#name : padding-top: ...
+# --
+padding-top: $1;
--- /dev/null
+# -*- mode: snippet -*-
+# name: -vendor-prefix
+# contributor: Prateek Saxena
+# key: -v
+# --
+$1: $2;
+-webkit-$1: $2;
+-moz-$1: $2;
+-ms-$1: $2;
+-o-$1: $2;
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet; require-final-newline: nil -*-
+# name: <call-macro>
+# key: m
+# condition: (progn (backward-char 1) (dix-transfer-enclosing-allows "call-macro"))
+# binding: direct-keybinding
+# --
+<call-macro n="$1"><with-param pos="$2"/>$0</call-macro>
--- /dev/null
+# -*- mode: snippet; require-final-newline: nil -*-
+# name: <choose><when><test> elements
+# key: c
+# condition: (progn (backward-char 1) (dix-transfer-enclosing-allows "choose"))
+# binding: direct-keybinding
+# --
+<choose><when>
+ <test><equal>$0</equal></test>
+
+</when></choose>
--- /dev/null
+# -*- mode: snippet; require-final-newline: nil -*-
+# name: <clip> elements
+# key: c
+# condition: (progn (backward-char 1) (dix-transfer-enclosing-allows "clip"))
+# binding: direct-keybinding
+# --
+<clip pos="$1" ${2:side="tl"} part="$3"/>$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet; require-final-newline: nil -*-
+# name: <e> in monodix section
+# key: <e
+# condition: (dix-enclosing-is-mono-section)
+# binding: direct-keybinding
+#TODO: remove suffix from <i> after leaving <par>
+# --
+<e lm="${1:`(dix-yas-prev-lemma)`}"> <i>${1:$(dix-yas-lm-to-i)}</i> <par n="${3:$$(dix-yas-choose-pdname)}"/></e>
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet; require-final-newline: nil -*-
+# name: <e> in pardefs
+# key: <e
+# condition: (not (dix-enclosing-is-mono-section))
+# binding: direct-keybinding
+# --
+<e> <p><l>$1</l> <r>$1$0</r></p> </e>
--- /dev/null
+# -*- mode: snippet; require-final-newline: nil -*-
+# name: <let> elements
+# key: l
+# condition: (progn (backward-char 1) (dix-transfer-enclosing-allows "let"))
+# binding: direct-keybinding
+# --
+<let>$0</let>
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet; require-final-newline: nil -*-
+# name: <lit> elements
+# key: l
+# condition: (progn (backward-char 1) (dix-transfer-enclosing-allows "lit"))
+# binding: direct-keybinding
+# --
+<lit v="$1"/>$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet; require-final-newline: nil -*-
+# name: <lit-tag> elements
+# key: lt
+# condition: (progn (backward-char 1) (dix-transfer-enclosing-allows "lit-tag"))
+# binding: direct-keybinding
+# --
+<lit-tag v="$1"/>$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet; require-final-newline: nil -*-
+# name: <otherwise> elements
+# key: o
+# condition: (progn (backward-char 1) (dix-transfer-enclosing-allows "otherwise"))
+# binding: direct-keybinding
+# --
+<otherwise>$0</otherwise>
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet; require-final-newline: nil -*-
+# name: <p> element
+# key: p
+# condition: (progn (backward-char 1) (equal (dix-enclosing-elt 'noerror) "e"))
+# binding: direct-keybinding
+# --
+<p><l>$1</l> <r>$1$0</r></p>
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet; require-final-newline: nil -*-
+# name: <par> element
+# key: <p
+# condition: (progn (backward-char 2) (equal (dix-enclosing-elt 'noerror) "e"))
+# binding: direct-keybinding
+# --
+<par n="${1::$$(dix-yas-message-pardef (yas-choose-value (dix-pardef-suggest-for (dix-lemma-at-point))))`}"/>$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet; require-final-newline: nil -*-
+# name: <pardef> element
+# key: <p
+# condition: (progn (backward-char 2) (not (equal (dix-enclosing-elt 'noerror) "e")))
+# binding: direct-keybinding
+# --
+<pardef n="${1:corp/us__n}">
+ <e> <p><l>${1:$(dix-yas-pdname-to-suffix yas-text)}</l> <r>${1:$(dix-yas-pdname-to-suffix yas-text)}${1:$(dix-yas-pdname-to-pos yas-text)}$2</r></p></e>
+ <e> <p><l>${1:$(dix-yas-pdname-to-suffix yas-text)}$0</l> <r>${1:$(dix-yas-pdname-to-suffix yas-text)}${1:$(dix-yas-pdname-to-pos yas-text)}$2</r></p></e>
+ <e> <p><l>${1:$(dix-yas-pdname-to-suffix yas-text)}</l> <r>${1:$(dix-yas-pdname-to-suffix yas-text)}${1:$(dix-yas-pdname-to-pos yas-text)}$2</r></p></e>
+ <e> <p><l>${1:$(dix-yas-pdname-to-suffix yas-text)}</l> <r>${1:$(dix-yas-pdname-to-suffix yas-text)}${1:$(dix-yas-pdname-to-pos yas-text)}$2</r></p></e>
+</pardef>
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet; require-final-newline: nil -*-
+# name: <s> element
+# key: <s
+# binding: direct-keybinding
+# condition: (progn (backward-char 2) (member (dix-enclosing-elt 'noerror) '("l" "r" "i" "g")))
+#Note: requires (eval-after-load 'yasnippet '(add-to-list 'yas-key-syntaxes 'dix-yas-skip-backwards-to-key))
+#so that you can expand it after regular letter chars
+# --
+<s n="$1"/>$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet; require-final-newline: nil -*-
+# name: <sdef> element
+# key: <s
+# condition: (progn (backward-char 2) (equal (dix-enclosing-elt 'noerror) "sdefs"))
+# binding: direct-keybinding
+# --
+<sdef n="$1" c="$2"/>
--- /dev/null
+# -*- mode: snippet; require-final-newline: nil -*-
+# name: <section> element
+# key: <s
+# condition: (progn (backward-char 2) (and (not (dix-enclosing-is-mono-section)) (not (member (dix-enclosing-elt 'noerror) '("l" "r" "i" "g" "sdefs")))))
+# binding: direct-keybinding
+# --
+<section id="${1:main}" type="${2:$$(yas-choose-value '("standard" "inconditional" "postblank" "preblank"))}">
+$0
+</section>
--- /dev/null
+# -*- mode: snippet; require-final-newline: nil -*-
+# name: <var> elements
+# key: v
+# condition: (progn (backward-char 1) (dix-transfer-enclosing-allows "var"))
+# binding: direct-keybinding
+# --
+<var n="$1"/>$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet; require-final-newline: nil -*-
+# name: <when> elements
+# key: w
+# condition: (progn (backward-char 1) (dix-transfer-enclosing-allows "when"))
+# binding: direct-keybinding
+# --
+<when>$0</when>
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet; require-final-newline: nil -*-
+# name: <with-param>
+# key: w
+# condition: (progn (backward-char 1) (dix-transfer-enclosing-allows "with-param"))
+# binding: direct-keybinding
+# --
+<with-param pos="$1"/>$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: call
+# key: call
+# --
+GenServer.call(${1:__MODULE__}, $0)
--- /dev/null
+# -*- mode: snippet -*-
+# name: case
+# key: case
+# --
+case $1 do
+ $0
+end
--- /dev/null
+# -*- mode: snippet -*-
+# name: cast
+# key: cast
+# --
+GenServer.cast(${1:__MODULE__}, $0)
--- /dev/null
+# -*- mode: snippet -*-
+# name: cond
+# key: cond
+# --
+cond do
+ $0
+end
--- /dev/null
+# -*- mode: snippet -*-
+# name: def
+# key: def
+# --
+def ${1:function}${2:(${3:args})} do
+ $0
+end
--- /dev/null
+# -*- mode: snippet -*-
+# name: defmacro
+# key: defmacro
+# --
+defmacro $1 do
+ $0
+end
--- /dev/null
+# -*- mode: snippet -*-
+# name: defmacrop
+# key: defmacrop
+# --
+defmacrop $1 do
+ $0
+end
--- /dev/null
+# -*- mode: snippet -*-
+# name: defmodule
+# key: defmodule
+# --
+defmodule $1 do
+ $0
+end
--- /dev/null
+# -*- mode: snippet -*-
+# name: defp
+# key: defp
+# --
+defp $1 do
+ $0
+end
--- /dev/null
+# -*- mode: snippet -*-
+# name: do
+# key: do
+# --
+do
+ $0
+end
--- /dev/null
+# -*- mode: snippet -*-
+# name: doc
+# key: doc
+# --
+@doc """
+$0
+"""
--- /dev/null
+# -*- mode: snippet -*-
+# name: fn
+# key: fn
+# --
+fn ${1:x} -> $1$0 end
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: for
+# key: for
+# --
+for ${2:x} <- ${1:enum} do
+ $2$0
+end
--- /dev/null
+# -*- mode: snippet -*-
+# name: hcall
+# key: hcall
+# --
+def handle_call($1, _from, state) do
+ reply = $0
+ {:reply, reply, state}
+end
--- /dev/null
+# -*- mode: snippet -*-
+# name: hcast
+# key: hcast
+# --
+def handle_cast($1, state) do
+ $0
+ {:noreply, state}
+end
--- /dev/null
+# -*- mode: snippet -*-
+# name: hinfo
+# key: hinfo
+# --
+def handle_info($1, state) do
+ $0
+ {:noreply, state}
+end
--- /dev/null
+# -*- mode: snippet -*-
+# name: if
+# key: if
+# --
+if ${1:condition} do
+ $0
+end
--- /dev/null
+# -*- mode: snippet -*-
+# name: if-else
+# key: ife
+# --
+if ${1:condition} do
+ $2
+else
+ $3
+end
--- /dev/null
+# -*- mode: snippet -*-
+# name: io
+# key: io
+# --
+IO.puts("$1")$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: iop
+# key: iop
+# --
+IO.puts("$1 #{inspect $1}")$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: moduledoc
+# key: mdoc
+# --
+@moduledoc """
+$0
+"""
--- /dev/null
+# -*- mode: snippet -*-
+# name: pry
+# key: pry
+# group: debug
+# --
+require IEx; IEx.pry
--- /dev/null
+# -*- mode: snippet -*-
+# name: test
+# key: test
+# --
+test "$1" do
+ $0
+end
--- /dev/null
+# -*- mode: snippet -*-
+# name: unless
+# key: unless
+# --
+unless ${1:condition} do
+ $0
+end
--- /dev/null
+-*- coding: utf-8 -*-
+Originally started by Xah Lee (xahlee.org) on 2009-02-22
+Released under GPL 3.
+
+Feel free to add missing ones or modify existing ones to improve.
+
+Those starting with “x-” are supposed to be idiom templates. Not sure it's very useful. They might start with “i-” or "id-" in the future.
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet; -*-
+#contributor: Xah Lee (XahLee.org)
+#name: add-hook
+#key: add-hook
+#key: ah
+# --
+(add-hook '${1:name}-hook ${2:'${3:function}})$0
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: and
+#key: and
+#key: a
+# --
+(and $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: append
+#key: append
+# --
+(append $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: apply
+#key: apply
+# --
+(apply $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: aref
+#key: aref
+# --
+(aref ${1:array} {2:index})
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: aset
+#key: aset
+# --
+(aset ${1:array} ${2:index} ${3:element})
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: assq
+#key: assq
+# --
+(assq ${1:key} ${2:list})
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: autoload
+#key: autoload
+# --
+(autoload ${1:function} "${2:filename}"${3: "docstring"}${4: interactive}${5: type})
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: backward-char
+#key: backward-char
+#key: bc
+# --
+(backward-char $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: beginning-of-line
+#key: beginning-of-line
+#key: bol
+# --
+(beginning-of-line)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: bounds-of-thing-at-point
+#key: bounds-of-thing-at-point
+#key: botap
+# --
+(bounds-of-thing-at-point $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: buffer-file-name
+#key: buffer-file-name
+#key: bfn
+# --
+(buffer-file-name)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: buffer-modified-p
+#key: buffer-modified-p
+#key: bmp
+# --
+(buffer-modified-p $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: buffer-substring
+#key: buffer-substring
+#key: bs
+# --
+(buffer-substring ${1:start} ${2:end})
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: buffer-substring-no-properties
+#key: buffer-substring-no-properties
+#key: bsnp
+# --
+(buffer-substring-no-properties ${1:start} ${2:end})
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: car
+#key: car
+# --
+(car $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: cdr
+#key: cdr
+# --
+(cdr $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: concat
+#key: concat
+# --
+(concat $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: cond
+#key: cond
+# --
+(cond
+ (${1:condition} ${2:body})$0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: condition-case
+#key: condition-case
+#key: cc
+# --
+(condition-case $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: cons
+#key: cons
+# --
+(cons $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: consp
+#key: consp
+# --
+(consp $0)
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: defconst
+# key: const
+# --
+(defconst ${1:name} ${2:value}${3: "${4:docstring}"})$0
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: copy-directory
+#key: copy-directory
+#key: cd
+# --
+(copy-directory ${1:directory} {2:target}${3: keep-time}${4: parents})
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: copy-file
+#key: copy-file
+#key: cf
+# --
+(copy-file ${1:filename} ${2:newname}${3: ok-if-already-exists}${4: keep-time}{5: preserve-uid-gid})
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: current-buffer
+#key: current-buffer
+#key: cb
+# --
+(current-buffer)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: custom-autoload
+#key: custom-autoload
+#key: ca
+# --
+(custom-autoload ${1:symbol} ${2:load}${3: noset})
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: defalias
+#key: defalias
+# --
+(defalias '${1:symbol} '${2:alias}${3: "docstring"})
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: defcustom
+#key: defcustom
+# --
+(defcustom ${1:symbol} ${2:standard} "${3:docstring}"${4: args})
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: define-key
+#key: define-key
+#key: dk
+# --
+(define-key ${1:mode}-map (kbd "${2:key}") $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: defsubst
+#key: defsubst
+# --
+(defsubst $0)
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: defun
+# key: def
+# --
+(defun ${1:fun} (${2:args})
+ "${3:docstring}"
+ ${4:(interactive${5: "${6:P}"})}
+ $0)
\ No newline at end of file
--- /dev/null
+#name: defvar
+#key: defvar
+# --
+(defvar ${1:symbol}${2: initvalue}${3: "docstring"})
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: delete-char
+#key: delete-char
+#key: dc
+# --
+(delete-char $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: delete-directory
+#key: delete-directory
+#key: dd
+# --
+(delete-directory ${1:dicretory}${2: recursive})
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: delete-file
+#key: delete-file
+#key: df
+# --
+(delete-file $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: delete-region
+#key: delete-region
+#key: dr
+# --
+(delete-region $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: directory-files
+#key: directory-files
+#key: df
+# --
+(directory-files ${1:directory}${2: full}${3: match}${4: nosort})
\ No newline at end of file
--- /dev/null
+#name : process marked files in dired
+#contributor : Xah Lee
+# --
+;; idiom for processing a list of files in dired's marked files
+
+;; suppose myProcessFile is your function that takes a file path
+;; and do some processing on the file
+
+(defun dired-myProcessFile ()
+ "apply myProcessFile function to marked files in dired."
+ (interactive)
+ (require 'dired)
+ (mapc 'myProcessFile (dired-get-marked-files))
+)
+
+;; to use it, type M-x dired-myProcessFile
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: dolist
+#key: dolist
+# --
+(dolist $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: end-of-line
+#key: end-of-line
+#key: eol
+# --
+(end-of-line)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: eq
+#key: eq
+# --
+(eq $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: equal
+#key: equal
+# --
+(equal $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: error
+#key: error
+# --
+(error "${1:message}"${2: format-args})
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+#contributor: Raghav Kumar Gautam
+#name: ert-deftest
+#key: edt
+# --
+(ert-deftest ${1:test-name} ()
+ $0)
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: expand-file-name
+#key: expand-file-name
+#key: efn
+# --
+(expand-file-name $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: fboundp
+#key: fboundp
+# --
+(fboundp '$0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: file-name-directory
+#key: file-name-directory
+#key: fnd
+# --
+(file-name-directory $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: file-name-extension
+#key: file-name-extension
+#key: fne
+# --
+(file-name-extension ${1:filename}${2: period})
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: file-name-nondirectory
+#key: file-name-nondirectory
+#key: fnn
+# --
+(file-name-nondirectory $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: file-name-sans-extension
+#key: file-name-sans-extension
+#key: fnse
+# --
+(file-name-sans-extension $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: file-relative-name
+#key: file-relative-name
+#key: frn
+# --
+(file-relative-name $0)
\ No newline at end of file
--- /dev/null
+#name : a function that process a file
+#contributor : Xah Lee
+# --
+(defun doThisFile (fpath)
+ "Process the file at path FPATH ..."
+ (let ()
+ ;; create temp buffer without undo record or font lock. (more efficient)
+ ;; first space in temp buff name is necessary
+ (set-buffer (get-buffer-create " myTemp"))
+ (insert-file-contents fpath nil nil nil t)
+
+ ;; process it ...
+ ;; (goto-char 0) ; move to begining of file's content (in case it was open)
+ ;; ... do something here
+ ;; (write-file fpath) ;; write back to the file
+
+ (kill-buffer " myTemp")))
--- /dev/null
+#name : read lines of a file
+#contributor : Xah Lee
+# --
+(defun read-lines (filePath)
+ "Return a list of lines in FILEPATH."
+ (with-temp-buffer
+ (insert-file-contents filePath)
+ (split-string
+ (buffer-string) "\n" t)))
+
+;; process all lines
+(mapc
+ (lambda (aLine)
+ (message aLine) ; do your stuff here
+ )
+ (read-lines "inputFilePath")
+)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: find-file
+#key: find-file
+#key: ff
+# --
+(find-file $0)
\ No newline at end of file
--- /dev/null
+#name : find and replace on region
+#contributor : Xah Lee
+# --
+(defun replace-html-chars-region (start end)
+ "Replace “<” to “<” and other chars in HTML.
+This works on the current region."
+ (interactive "r")
+ (save-restriction
+ (narrow-to-region start end)
+ (goto-char (point-min))
+ (while (search-forward "&" nil t) (replace-match "&" nil t))
+ (goto-char (point-min))
+ (while (search-forward "<" nil t) (replace-match "<" nil t))
+ (goto-char (point-min))
+ (while (search-forward ">" nil t) (replace-match ">" nil t))
+ )
+ )
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: format
+#key: f
+# --
+(format "${1:message}" ${2:format-args})
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: forward-char
+#key: forward-char
+#key: fc
+# --
+(forward-char $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: forward-line
+#key: forward-line
+#key: fl
+# --
+(forward-line $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: funcall
+#key: funcall
+# --
+(funcall $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: function
+#key: function
+# --
+(function $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: get
+#key: get
+# --
+(get ${1:symbol} {2:propname})
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: global-set-key
+#key: global-set-key
+#key: gsk
+# --
+(global-set-key (kbd "${1:key}") $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: goto-char
+#key: goto-char
+#key: gc
+# --
+(goto-char $0)
\ No newline at end of file
--- /dev/null
+#name : grab buffer substring
+#contributor : Xah Lee
+# --
+(setq $0 (buffer-substring-no-properties myStartPos myEndPos))
--- /dev/null
+#name : grab word under cursor
+#contributor : Xah Lee
+# --
+(setq $0 (thing-at-point 'symbol))
--- /dev/null
+# -*- mode: snippet -*-
+# name: hash
+# key: hash
+# --
+(make-hash-table $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: if
+#key: if
+# --
+(if $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: insert
+#key: insert
+#key: i
+# --
+(insert $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: insert-file-contents
+#key: insert-file-contents
+#key: ifc
+# --
+(insert-file-contents ${1:filename}${2: visit}${3: beg}${4: end}${5: replace})
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: interactive
+#key: interactive
+# --
+(interactive${1: "${2:P}"})
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: kbd
+#key: kbd
+# --
+(kbd "$0")
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: kill-buffer
+#key: kill-buffer
+#key: kb
+# --
+(kill-buffer $0)
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet; -*-
+#contributor: Xah Lee (XahLee.org)
+#name: lambda
+#key: lam
+# --
+(lambda ($1) ${2:(interactive${3: "$4"}) }$0)
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: length
+#key: length
+# --
+(length $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: let
+#key: let
+#key: l
+# --
+(let${1:*} (${2:args})
+ $0)
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: line-beginning-position
+#key: line-beginning-position
+#key: lbp
+# --
+(line-beginning-position)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: line-end-position
+#key: line-end-position
+#key: lep
+# --
+(line-end-position)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: list
+#key: list
+# --
+(list $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: looking-at
+#key: looking-at
+#key: la
+# --
+(looking-at $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: make-directory
+#key: make-directory
+#key: md
+# --
+(make-directory ${1:directory}${2: parents})
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: make-local-variable
+#key: make-local-variable
+#key: mlv
+# --
+(make-local-variable $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: mapc
+#key: mapc
+# --
+(mapc ${1:function} $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: mapcar
+#key: mapcar
+# --
+(mapcar $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: match-beginning
+#key: match-beginning
+#key: mb
+# --
+(match-beginning $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: match-end
+#key: match-end
+#key: me
+# --
+(match-end $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: match-string
+#key: match-string
+#key: ms
+# --
+(match-string $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: memq
+#key: memq
+# --
+(memq ${1:element} ${2:list})
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: message
+#key: message
+#key: m
+# --
+(message "${1:message}"${2: format-args})
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: minor_mode
+# key: minor
+# --
+(defvar ${1:mode}-modeline-indicator " ${2:indicator}"
+ "call ($1-install-mode) again if this is changed")
+
+(defvar $1-mode nil)
+(make-variable-buffer-local '$1-mode)
+(put '$1-mode 'permanent-local t)
+
+(defun $1-mode (&optional arg)
+ "$0"
+ (interactive "P")
+ (setq $1-mode
+ (if (null arg) (not $1-mode)
+ (> (prefix-numeric-value arg) 0)))
+ (force-mode-line-update))
+
+(provide '$1-mode)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: not
+#key: not
+#key: n
+# --
+(not $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: nth
+#key: nth
+# --
+(nth ${1:index} ${2:list})
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: null
+#key: null
+# --
+(null $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: number-to-string
+#key: number-to-string
+#key: nts
+# --
+(number-to-string $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: or
+#key: or
+#key: o
+# --
+(or $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: point
+#key: point
+#key: p
+# --
+(point)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: point-max
+#key: point-max
+# --
+(point-max)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: point-min
+#key: point-min
+#key: pm
+# --
+(point-min)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: princ
+#key: princ
+# --
+(princ $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: print
+#key: print
+# --
+(print $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: progn
+#key: progn
+# --
+(progn $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: push
+#key: push
+# --
+(push $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: put
+#key: put
+# --
+(put ${1:symbol} ${2:propname} ${3:value})
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: re-search-backward
+#key: re-search-backward
+#key: rsb
+# --
+(re-search-backward ${1:regexp}${2: bound}${3: noerror}${4: count})
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: re-search-forward
+#key: re-search-forward
+#key: rsf
+# --
+(re-search-forward ${1:regexp}${2: bound}${3: noerror}${4: count})
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: region-active-p
+#key: region-active-p
+#key: rap
+# --
+(region-active-p)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: region-beginning
+#key: region-beginning
+#key: rb
+# --
+(region-beginning)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: region-end
+#key: region-end
+#key: re
+# --
+(region-end)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: rename-file
+#key: rename-file
+#key: rf
+# --
+(rename-file ${1:file} ${2:newname}${3: ok-if-already-exists})
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: repeat
+#key: repeat
+# --
+(repeat $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: replace-regexp
+#key: replace-regexp
+#key: rr
+# --
+(replace-regexp ${1:regexp}${2: delimited}${3: start}${4: end})
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: replace-regexp-in-string
+#key: replace-regexp-in-string
+#key: rris
+# --
+(replace-regexp-in-string ${1:regexp} ${2:rep} ${3:string}${4: fixedcase}${5: literal}${6: subexp}${7: start})
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: require
+#key: require
+# --
+(require $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: save-buffer
+#key: save-buffer
+#key: sb
+# --
+(save-buffer $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: save-excursion
+#key: save-excursion
+#key: se
+# --
+(save-excursion $0)
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet; -*-
+#contributor: Xah Lee (XahLee.org)
+#name: search-backward
+#key: search-backward
+#key: sb
+# --
+(search-backward "$1"${2: ${3:bound}${4: ${5:noerror}${6: count}}})$0
--- /dev/null
+# -*- mode: snippet; -*-
+#contributor: Xah Lee (XahLee.org)
+#name: search-backward-regexp
+#key: search-backward-regexp
+#key: sbr
+# --
+(search-backward-regexp "$1"${2: ${3:bound}${4: ${5:noerror}${6: count}}})$0
--- /dev/null
+# -*- mode: snippet; -*-
+#contributor: Xah Lee (XahLee.org)
+#name: search-forward
+#key: search-forward
+#key: sf
+# --
+(search-forward "$1"${2: ${3:bound}${4: ${5:noerror}${6: count}}})$0
--- /dev/null
+# -*- mode: snippet; -*-
+#contributor: Xah Lee (XahLee.org)
+#name: search-forward-regexp
+#key: search-forward-regexp
+#key: sfr
+# --
+(search-forward-regexp "$1"${2: ${3:bound}${4: ${5:noerror}${6: count}}})$0
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: set
+#key: set
+# --
+(set $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: set-buffer
+#key: set-buffer
+#key: sb
+# --
+(set-buffer $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: set-file-modes
+#key: set-file-modes
+#key: sfm
+# --
+(set-file-modes ${1:filename} $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: set-mark
+#key: set-mark
+#key: sm
+# --
+(set-mark $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: setq
+#key: setq
+#key: s
+# --
+(setq $0)
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+#contributor: Raghav Kumar Gautam
+#name: should
+#key: sh
+# --
+(should $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: skip-chars-backward
+#key: skip-chars-backward
+#key: scb
+# --
+(skip-chars-backward "${1:string}"${2: lim})
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: skip-chars-forward
+#key: skip-chars-forward
+#key: scf
+# --
+(skip-chars-forward "${1:string}"${2: lim})
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: split-string
+#key: split-string
+#key: ss
+# --
+(split-string ${1:string}${2: separators}${3: omit-nulls})
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: string
+#key: string
+# --
+(string $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: string-match
+#key: string-match
+#key: sm
+# --
+(string-match "${1:regexp}" "${2:string}"${3: start})
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: string-to-number
+#key: string-to-number
+#key: stn
+# --
+(string-to-number $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: string=
+#key: string=
+# --
+(string= $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: stringp
+#key: stringp
+# --
+(stringp $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: substring
+#key: substring
+# --
+(substring ${1:string} ${2:from}${3: to})
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: thing-at-point
+#key: thing-at-point
+#key: tap
+# --
+(thing-at-point ${1:thing}${2: no-properties})
\ No newline at end of file
--- /dev/null
+#name : traversing a directory
+#contributor : Xah Lee
+# --
+;; apply a function to all files in a dir
+(require 'find-lisp)
+(mapc 'my-process-file (find-lisp-find-files "~/myweb/" "\\.html$"))
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: unless
+#key: unless
+# --
+(unless $0)
\ No newline at end of file
--- /dev/null
+#contributor: Daniel Hitzel
+#name: use-package
+#key: up
+# --
+(use-package ${1:package-name}
+:ensure t$0)
\ No newline at end of file
--- /dev/null
+#contributor: Daniel Hitzel
+#name: use-package binding
+#key: upb
+# --
+:bind ("${1:binding}" . ${2:function-name})
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: vector
+#key: vector
+#key: v
+# --
+(vector $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: when
+#key: w
+# --
+(when $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: while
+#key: while
+# --
+(while $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: widget-get
+#key: widget-get
+#key: wg
+# --
+(widget-get $0)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: with-current-buffer
+#key: with-current-buffer
+#key: wcb
+# --
+(with-current-buffer $0)
\ No newline at end of file
--- /dev/null
+#name : Command that works on region or word
+#contributor : Xah Lee
+# --
+;; example of a command that works on current word or text selection
+(defun down-case-word-or-region ()
+ "Lower case the current word or text selection."
+(interactive)
+(let (pos1 pos2 meat)
+ (if (and transient-mark-mode mark-active)
+ (setq pos1 (region-beginning)
+ pos2 (region-end))
+ (setq pos1 (car (bounds-of-thing-at-point 'symbol))
+ pos2 (cdr (bounds-of-thing-at-point 'symbol))))
+
+ ; now, pos1 and pos2 are the starting and ending positions
+ ; of the current word, or current text selection if exists
+
+ ;; put your code here.
+ $0
+ ;; Some example of things you might want to do
+ (downcase-region pos1 pos2) ; example of a func that takes region as args
+ (setq meat (buffer-substring-no-properties pos1 pos2)) ; grab the text.
+ (delete-region pos1 pos2) ; get rid of it
+ (insert "newText") ; insert your new text
+
+ )
+)
--- /dev/null
+# -*- mode: snippet -*-
+# name: word_regexp
+# key: <
+# --
+"\\_<${1:word}\\_>"
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: process marked files in dired
+# key: x-dired
+# --
+;; idiom for processing a list of files in dired's marked files
+
+;; suppose myProcessFile is your function that takes a file path
+;; and do some processing on the file
+
+(defun dired-myProcessFile ()
+ "apply myProcessFile function to marked files in dired."
+ (interactive)
+ (require 'dired)
+ (mapc 'myProcessFile (dired-get-marked-files))
+)
+
+;; to use it, type M-x dired-myProcessFile
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: a function that process a file
+# key: x-file
+# --
+(defun doThisFile (fpath)
+ "Process the file at path FPATH ..."
+ (let ()
+ ;; create temp buffer without undo record or font lock. (more efficient)
+ ;; first space in temp buff name is necessary
+ (set-buffer (get-buffer-create " myTemp"))
+ (insert-file-contents fpath nil nil nil t)
+
+ ;; process it ...
+ ;; (goto-char 0) ; move to begining of file's content (in case it was open)
+ ;; ... do something here
+ ;; (write-file fpath) ;; write back to the file
+
+ (kill-buffer " myTemp")))
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: read lines of a file
+# key: x-file
+# --
+(defun read-lines (filePath)
+ "Return a list of lines in FILEPATH."
+ (with-temp-buffer
+ (insert-file-contents filePath)
+ (split-string
+ (buffer-string) "\n" t)))
+
+;; process all lines
+(mapc
+ (lambda (aLine)
+ (message aLine) ; do your stuff here
+ )
+ (read-lines "inputFilePath")
+)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: find and replace on region
+# key: x-find-replace
+# --
+(defun replace-html-chars-region (start end)
+ "Replace “<” to “<” and other chars in HTML.
+This works on the current region."
+ (interactive "r")
+ (save-restriction
+ (narrow-to-region start end)
+ (goto-char (point-min))
+ (while (search-forward "&" nil t) (replace-match "&" nil t))
+ (goto-char (point-min))
+ (while (search-forward "<" nil t) (replace-match "<" nil t))
+ (goto-char (point-min))
+ (while (search-forward ">" nil t) (replace-match ">" nil t))
+ )
+ )
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: grab buffer substring
+# key: x-grabstring
+# --
+(setq $0 (buffer-substring-no-properties myStartPos myEndPos))
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: grab word under cursor
+# key: x-grabthing
+# --
+(setq $0 (thing-at-point 'symbol))
\ No newline at end of file
--- /dev/null
+#name: traversing a directory
+#contributor: Xah Lee (XahLee.org)
+# key: x-traverse_dir
+# --
+;; apply a function to all files in a dir
+(require 'find-lisp)
+(mapc 'my-process-file (find-lisp-find-files "~/myweb/" "\\.html$"))
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: Command that works on region or word
+# key: x-word-or-region
+# --
+;; example of a command that works on current word or text selection
+(defun down-case-word-or-region ()
+ "Lower case the current word or text selection."
+(interactive)
+(let (pos1 pos2 meat)
+ (if (and transient-mark-mode mark-active)
+ (setq pos1 (region-beginning)
+ pos2 (region-end))
+ (setq pos1 (car (bounds-of-thing-at-point 'symbol))
+ pos2 (cdr (bounds-of-thing-at-point 'symbol))))
+
+ ; now, pos1 and pos2 are the starting and ending positions
+ ; of the current word, or current text selection if exists
+
+ ;; put your code here.
+ $0
+ ;; Some example of things you might want to do
+ (downcase-region pos1 pos2) ; example of a func that takes region as args
+ (setq meat (buffer-substring-no-properties pos1 pos2)) ; grab the text.
+ (delete-region pos1 pos2) ; get rid of it
+ (insert "newText") ; insert your new text
+
+ )
+)
\ No newline at end of file
--- /dev/null
+#contributor: Xah Lee (XahLee.org)
+#name: yes-or-no-p
+#key: yonp
+# --
+(yes-or-no-p "${1:prompt} ")
\ No newline at end of file
--- /dev/null
+scala-mode
--- /dev/null
+# -*- mode: snippet -*-
+# name: blist
+# key: b
+# --
+blist
--- /dev/null
+# -*- mode: snippet -*-
+# name: help
+# key: h
+# --
+help $0
\ No newline at end of file
--- /dev/null
+#name : after ... ->
+# --
+after
+ $1 -> $0
--- /dev/null
+#name : begin ... end
+# --
+begin
+ $0
+end
--- /dev/null
+#name : -behaviour(...).
+# --
+-behaviour(${1:gen_server}).
+$0
--- /dev/null
+#name : case ... of ... end
+# --
+case $1 of
+ $0
+end
--- /dev/null
+#name : -compile(...).
+# --
+-compile([${1:export_all}]).
+$0
--- /dev/null
+#name : -define(...,...).
+# --
+-define($1,$2).
+$0
--- /dev/null
+#name : -export([]).
+#contributor : hitesh <hitesh.jasaniNOSPAMgmail.com>
+# --
+-export([${1:start/0}]).
+$0
--- /dev/null
+#name : fun (...) -> ... end
+# --
+fun ($1) -> $0 end
--- /dev/null
+#name : if ... -> ... ; true -> ... end
+# --
+if
+ $1 -> $2;
+ true -> $0
+end
--- /dev/null
+#name : -ifdef(...). ... -endif.
+# --
+-ifdef($1).
+$0
+-endif.
--- /dev/null
+#name : -ifndef(...). ... -endif.
+# --
+-ifndef($1).
+$0
+-endif.
--- /dev/null
+#name : -import([]).
+#contributor : hitesh <hitesh.jasaniNOSPAMgmail.com>
+# --
+-import(${1:lists}, [${2:map/2, sum/1}]).
+$0
--- /dev/null
+#name : -include("...").
+# --
+-include("$1").
+$0
--- /dev/null
+#name : -include_lib("...").
+# --
+-include_lib("$1").
+$0
--- /dev/null
+#name : loop(...) -> receive _ -> loop(...) end.
+# --
+${1:loop}($2) ->
+ receive
+ ${3:_} ->
+ $1($2)
+ end.
+$0
--- /dev/null
+#name : -module().
+#contributor : hitesh <hitesh.jasaniNOSPAMgmail.com>
+# --
+-module(${1:`(file-name-nondirectory
+ (file-name-sans-extension (or (buffer-file-name) (buffer-name))))`}).
+$0
--- /dev/null
+#name : receive ... -> ... end
+# --
+receive
+ $1 -> $0
+end
--- /dev/null
+#name : receive after ... -> ... end
+# --
+receive
+after
+ $1 -> $0
+end
--- /dev/null
+#name : -record(...,{...}).
+# --
+-record($1,{$2}).
+$0
--- /dev/null
+#name : try ... of ... catch after end
+# --
+try $1 of
+ $0
+catch
+after
+end
--- /dev/null
+#name : -undef(...).
+# --
+-undef($1).
+$0
--- /dev/null
+#contributor: Li Zhu <http://www.zhuli.name>
+#name : block data
+# --
+block data $0
--- /dev/null
+#contributor: Li Zhu <http://www.zhuli.name>
+#name : continue
+# --
+continue $0
--- /dev/null
+#contributor: Li Zhu <http://www.zhuli.name>
+#name : character
+# --
+character $0
--- /dev/null
+#contributor: Li Zhu <http://www.zhuli.name>
+#name : complex
+# --
+complex $0
--- /dev/null
+#contributor: Li Zhu <http://www.zhuli.name>
+#name : double complex
+# --
+double complex $0
--- /dev/null
+# -*- mode: snippet -*-
+# contributor: Jonas Kalderstam <jonasNOSPAMkalderstam.se>
+# name: do ... end do ...
+# key: do
+# --
+do $1
+ $0
+end do
--- /dev/null
+#contributor: Li Zhu <http://www.zhuli.name>
+#name : double precision
+# --
+double precision $0
--- /dev/null
+# -*- mode: snippet -*-
+# contributor: Jonas Kalderstam <jonasNOSPAMkalderstam.se>
+# name: forall ... end forall ...
+# key: forall
+# --
+forall ($1)
+ $0
+end forall
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# contributor: Jonas Kalderstam <jonasNOSPAMkalderstam.se>
+# name: function ... end function ...
+# key: function
+# --
+function ${1:name} (${2:arg})
+ ${3:real} :: $1
+ ${4:real, intent(in)} :: $2
+
+ $0
+
+end function $1
--- /dev/null
+#contributor: Li Zhu <http://www.zhuli.name>
+#name : if then end if
+# --
+if ( ${1:condition} ) then
+ $0
+end if
--- /dev/null
+#contributor: Li Zhu <http://www.zhuli.name>
+#name : implicit none
+# --
+implicit none
--- /dev/null
+#contributor: Li Zhu <http://www.zhuli.name>
+#name : include
+# --
+include $0
--- /dev/null
+#contributor: Li Zhu <http://www.zhuli.name>
+#name : intrinsic
+# --
+intrinsic $0
--- /dev/null
+#contributor: Li Zhu <http://www.zhuli.name>
+#name : logical
+# --
+logical $0
--- /dev/null
+# -*- mode: snippet -*-
+# contributor: Jonas Kalderstam <jonasNOSPAMkalderstam.se>
+# name: module ... end module ...
+# key: module
+# --
+module ${1:name}
+
+contains
+
+ $0
+
+end module $1
--- /dev/null
+#contributor: Li Zhu <http://www.zhuli.name>
+#name : parameter
+# --
+parameter $0
--- /dev/null
+# -*- mode: snippet -*-
+# contributor: Jonas Kalderstam <jonasNOSPAMkalderstam.se>
+# name: program .. end program
+# key: program
+# --
+program ${1:name}
+ ${2:implicit none}
+
+ $0
+
+end program $1
--- /dev/null
+# -*- mode: snippet -*-
+# contributor: Jonas Kalderstam <jonasNOSPAMkalderstam.se>
+# name: pure function ... end function ...
+# key: pure func
+# --
+pure function ${1:name} (${2:arg})
+ ${3:real} :: $1
+ ${4:real, intent(in)} :: $2
+
+ $0
+
+end function $1
--- /dev/null
+# -*- mode: snippet -*-
+# contributor: Jonas Kalderstam <jonasNOSPAMkalderstam.se>
+# name: pure subroutine .. end subroutine
+# key: pure subroutine
+# --
+pure subroutine ${1:name} (${2:arg})
+ ${3:real, intent(in) :: $2}
+
+ $0
+end subroutine $1
--- /dev/null
+#contributor: Li Zhu <http://www.zhuli.name>
+#name : read (*,*)
+# --
+read (${1:*},${2:*}) $0
--- /dev/null
+# -*- mode: snippet -*-
+# contributor: Jonas Kalderstam <jonasNOSPAMkalderstam.se>
+# name: subroutine .. end subroutine
+# key: subroutine
+# --
+subroutine ${1:name} (${2:arg})
+ ${3:real, intent(in) :: $2}
+
+ $0
+end subroutine $1
--- /dev/null
+# -*- mode: snippet -*-
+# contributor: Jonas Kalderstam <jonasNOSPAMkalderstam.se>
+# name: until ... end until ...
+# key: until
+# --
+do
+ $0
+ if (${1:condition}) exit
+end do
--- /dev/null
+# -*- mode: snippet -*-
+# contributor: Jonas Kalderstam <jonasNOSPAMkalderstam.se>
+# name: where ... end where ...
+# key: where
+# --
+
+where (${1:condition})
+ $0
+end where
--- /dev/null
+# -*- mode: snippet -*-
+# contributor: Jonas Kalderstam <jonasNOSPAMkalderstam.se>
+# name: while ... end while ...
+# key: while
+# --
+do while (${1:condition})
+ $0
+end do
--- /dev/null
+#contributor: Li Zhu <http://www.zhuli.name>
+#name : write (*,*)
+# --
+write (${1:*},${2:*}) $0
--- /dev/null
+# -*- mode: snippet -*-
+# name: button
+# key: bu
+# --
+button("$1")$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: case
+# key: ca
+# --
+case {
+ $1
+ };
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: checkbox
+# key: ch
+# --
+checkbox("$1")$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: component
+# key: co
+# --
+component("$1.dsp")$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: declare
+# key: de
+# --
+declare ${1:key} "${2:value}";
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: declare author
+# key: da
+# --
+declare author "$1";
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: declare license
+# key: dl
+# --
+declare license "${1:$$
+ (yas-choose-value '(
+ "AGPLv3"
+ "Apache"
+ "BSD 2-clause"
+ "BSD 3-clause"
+ "GPLv2"
+ "GPLv3"
+ "LGPLv3"
+ "MIT"
+ ))}";
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: declare name
+# key: dn
+# --
+declare name "$1";
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: declare version
+# key: dv
+# --
+declare version "${1:0.1}";
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: hbargraph
+# key: hb
+# --
+hbargraph("${1:name}", ${2:min}, ${3:max})$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: header
+# key: he
+# --
+declare name "$1";
+declare version "${2:0.1}";
+declare author "$3";
+declare license "${4:$$
+ (yas-choose-value '(
+ "AGPLv3"
+ "Apache"
+ "BSD 2-clause"
+ "BSD 3-clause"
+ "GPLv2"
+ "GPLv3"
+ "LGPLv3"
+ "MIT"
+ ))}";
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: hgroup
+# key: hg
+# --
+hgroup("${1:name}", ${2:expression})$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: hslider
+# key: hs
+# --
+hslider("${1:name}", ${2:default}, ${3:min}, ${4:max}, ${5:step})$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: import
+# key: im
+# --
+import("$1.lib");$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: nentry
+# key: ne
+# --
+nentry("${1:name}", ${2:default}, ${3:min}, ${4:max}, ${5:step})$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: par
+# key: pa
+# --
+par(${1:i}, ${2:Nr}, ${3:expression})$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: process
+# key: pr
+# --
+process = $1;
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: processx
+# key: px
+# --
+process(${1:x}) = ${2:expression}($1);
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: prod
+# key: mu
+# --
+prod(${1:i}, ${2:Nr}, ${3:expression})$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: rule
+# key: ru
+# --
+ (${1:pattern}) => ${2:expression};
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: seq
+# key: se
+# --
+seq(${1:i}, ${2:Nr}, ${3:expression})$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: sum
+# key: su
+# --
+sum(${1:i}, ${2:Nr}, ${3:expression})$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: tgroup
+# key: tg
+# --
+tgroup("${1:name}", ${2:expression})$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: vbargraph
+# key: vb
+# --
+vbargraph("${1:name}", ${2:min}, ${3:max})$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: vgroup
+# key: vg
+# --
+vgroup("${1:name}", ${2:expression})$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: vslider
+# key: vs
+# --
+vslider("${1:name}", ${2:default}, ${3:min}, ${4:max}, ${5:step})$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: with
+# key: wi
+# --
+with {
+ ${1:expression}
+};
+$0
\ No newline at end of file
--- /dev/null
+text-mode
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: fixes
+# key: fix
+# --
+fixes #${1:100}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: references
+# key: ref
+# --
+references #${1:100}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: benchmark
+# key: bench
+# contributor : @atotto
+# --
+func Benchmark$1(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ $0
+ }
+}
--- /dev/null
+# -*- mode:snippet -*-
+# name: const
+# key: const
+# --
+const ${1:name type} = ${2:val}
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode:snippet -*-
+# name: const (...)
+# key: const
+# --
+const (
+ ${1:name type} = ${2:val}
+)
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: debug fmt.Printf
+# key: dd
+# --
+fmt.Printf("%+v\n", $1) // output for debug
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: default
+# key: def
+# --
+default:
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: else
+# key: el
+# --
+ else {
+ $0
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: error
+# key: err
+# contributor : @atotto
+# --
+if err != nil {
+ $0
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: example
+# key: example
+# contributor : @atotto
+# --
+func Example$1() {
+ $0
+}
--- /dev/null
+# -*- mode:snippet -*-
+# name: for
+# key: for
+# --
+for $1 {
+ $0
+}
--- /dev/null
+# -*- mode: snippet -*-
+# name: for range
+# key: range
+# contributor : @atotto
+# --
+for ${3:key}, ${2:value} := range ${1:target} {
+ $0
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: func
+# key: func
+# --
+// $1 ${4:...}
+func ${1:name}(${2:args}) $3 {
+ $0
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: if
+# key: if
+# --
+if $1 {
+ $0
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: if error
+# key: iferr
+# --
+if err != $1 {
+ $0
+}
--- /dev/null
+# -*- mode:snippet -*-
+# name: import
+# key: imp
+# --
+import "$1"
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode:snippet -*-
+# name: import (...)
+# key: imp
+# --
+import (
+ "$0"
+)
--- /dev/null
+# -*- mode: snippet -*-
+# name: lambda func
+# key: lambda
+# --
+func(${1:args}) $2 {
+ $0
+}()
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: func main()
+# key: main
+# --
+func main() {
+ $0
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: map
+# key: map
+# --
+map[${1:type}]${2:type}
--- /dev/null
+# -*- mode: snippet -*-
+# name: parallel_benchmark
+# key: parbench
+# contributor : @kostya-sh
+# --
+func Benchmark$1(b *testing.B) {
+ b.RunParallel(func(pb *testing.PB) {
+ for pb.Next() {
+ $0
+ }
+ })
+}
--- /dev/null
+# -*- mode: snippet -*-
+# name: fmt.Printf(...)
+# key: pr
+# --
+fmt.Printf("${1:%s}\n", ${2:args})
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: select
+# key: sel
+# --
+select {
+case $1:
+ $0
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: switch
+# key: sw
+# --
+switch $1 {
+case $2:
+ $0
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: test
+# key: at
+# contributor : @atotto
+# --
+func Test$1(t *testing.T) {
+ $0
+}
--- /dev/null
+# -*- mode: snippet -*-
+# name: testmain
+# key: testmain
+# contributor : @atotto
+# --
+func TestMain(m *testing.M) {
+ setup()
+ ret := m.Run()
+ if ret == 0 {
+ teardown()
+ }
+ os.Exit(ret)
+}
+
+func setup() {
+ $1
+}
+
+func teardown() {
+ $2
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: type
+# key: type
+# --
+type $1 $2 {
+ $0
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: var
+# key: var
+# --
+var ${1:name} ${2:type}
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: var (...)
+# key: var
+# --
+var (
+ ${1:name} ${2:type}
+)
\ No newline at end of file
--- /dev/null
+java-mode
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: class
+# key: class
+# --
+class ${1:Class} {
+ $0
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: def
+# key: def
+# --
+def ${1:method}(${2:args}) {
+ $0
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: dict
+# key: dict
+# --
+${1:dict} = [${2:key} : ${3:value}$0]
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: for
+# key: for
+# --
+for (${1:var} in ${2:iter}) {
+ $0
+}
--- /dev/null
+# -*- mode: snippet -*-
+# name: println
+# key: pr
+# --
+println ${1:"string"}
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: times
+# key: times
+# --
+${1:10}.times {
+ $0
+} .
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: case
+# key: case
+# expand-env: ((yas-indent-line 'fixed))
+# --
+case ${1:var} of
+ ${2:cond} -> ${3:value}
+ $0
+ otherwise -> ${4:other}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: data
+# key: da
+# --
+data ${1:Type} = $2
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: doc
+# key: d
+# --
+{-
+ $0
+-}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: fixme dummy
+# key: efix
+# expand-env: ((yas-indent-line 'fixed))
+# --
+(error "FIXME: $0")
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: fun
+# key: fun
+# --
+${1:function-name} :: ${2:type}
+$1 ${3:arguments} $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: fune
+# key: fune
+# --
+${1:function-name} :: ${2:type}
+$1 = $0error "Not implemented: $1"
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: import
+# key: import
+# --
+import${1: qualified} ${2:Module${3:(symbols)}}${4: as ${5:alias}}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: instance
+# key: ins
+# --
+instance ${1:${2:(Show a)} => }${3:Ord} ${4:DataType} where
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: main function
+# key: main
+# expand-env: ((yas-indent-line 'fixed))
+# --
+main :: IO ()
+main = do $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: module
+# key: mod
+# --
+module ${1:Module} where
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: new class
+# key: class
+# expand-env: ((yas-indent-line 'fixed))
+# --
+class ${1:Name} where
+ $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: pragma
+# key: prag
+# --
+{-# ${1:PRAGMA} #-}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: print
+# key: pr
+# --
+print $0
\ No newline at end of file
--- /dev/null
+#contributor : Rodrigo Setti <rodrigosettiNOSPAMgmail.com>
+#name : <dd> ... </dd>
+#group : list
+# --
+<dd>$1</dd>
\ No newline at end of file
--- /dev/null
+#contributor : Rodrigo Setti <rodrigosettiNOSPAMgmail.com>
+#name : <dl> ... </dl>
+#group : list
+# --
+<dl>
+ $0
+</dl>
--- /dev/null
+#name : Doctype HTML 4.01 Strict
+#group : meta
+# --
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
\ No newline at end of file
--- /dev/null
+#name : Doctype HTML 5
+#group : meta
+# --
+<!DOCTYPE html>
--- /dev/null
+#name : DocType XHTML 1.0 frameset
+#group : meta
+# --
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
\ No newline at end of file
--- /dev/null
+#name : DocType XHTML 1.1
+#group : meta
+# --
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
\ No newline at end of file
--- /dev/null
+#name : DocType XHTML 1.0 Strict
+#group : meta
+# --
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
\ No newline at end of file
--- /dev/null
+#name : DocType XHTML 1.0 Transitional
+#group : meta
+# --
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
\ No newline at end of file
--- /dev/null
+#contributor : Rodrigo Setti <rodrigosettiNOSPAMgmail.com>
+#name : <dt> ... </dt>
+#group : list
+# --
+<dt>$1</dt>
\ No newline at end of file
--- /dev/null
+#contributor : Jimmy Wu <frozenthrone88NOSPAMgmail.com>\r
+#name :<form method="..." id="..." action="..."></form>\r
+# --\r
+<form method="$1" id="$2" action="$3">\r
+ $0\r
+</form>
\ No newline at end of file
--- /dev/null
+#contributor : Jimmy Wu <frozenthrone88NOSPAMgmail.com>\r
+#name : <html>...</html>\r
+# --\r
+<html>\r
+ $0\r
+</html>\r
--- /dev/null
+#contributor : Jimmy Wu <frozenthrone88NOSPAMgmail.com>\r
+#name : <html xmlns="...">...</html>\r
+# --\r
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="${1:en}" lang="${2:en}">\r
+ $0\r
+</html>\r
--- /dev/null
+#contributor : Vikrant Rathore <vikrantNOSPAMvyomtech.com>
+#name : <link rel="import" />
+# --
+<link rel="import" href="${1:url}" />
--- /dev/null
+#contributor : Jimmy Wu <frozenthrone88NOSPAMgmail.com>\r
+#name : <link stylesheet="..." />\r
+# --\r
+<link rel="${1:stylesheet}" href="${2:url}" type="${3:text/css}" media="${4:screen}" />
\ No newline at end of file
--- /dev/null
+#contributor : Jimmy Wu <frozenthrone88NOSPAMgmail.com>\r
+#name : <!--[if IE]><link stylesheet="..." /><![endif]-->\r
+# --\r
+<!--[if IE]>\r
+<link rel="${1:stylesheet}" href="${2:url}" type="${3:text/css}" media="${4:screen}" />\r
+<![endif]-->
\ No newline at end of file
--- /dev/null
+#contributor : Jimmy Wu <frozenthrone88NOSPAMgmail.com>\r
+#name : <a href="mailto:...@...">...</a>\r
+# --\r
+<a href="mailto:$1@$2">$0</a>
\ No newline at end of file
--- /dev/null
+#contributor : Jimmy Wu <frozenthrone88NOSPAMgmail.com>\r
+#group : meta\r
+#name : <meta name="..." content="..." />\r
+# --\r
+<meta name="${1:generator}" content="${2:content}" />
\ No newline at end of file
--- /dev/null
+#contributor : Jimmy Wu <frozenthrone88NOSPAMgmail.com>\r
+#name : <meta http-equiv="..." content="..." />\r
+#group : meta\r
+# --\r
+<meta http-equiv="${1:Content-Type}" content="${2:text/html; charset=UTF-8}" />\r
--- /dev/null
+#contributor : Jimmy Wu <frozenthrone88NOSPAMgmail.com>\r
+#name :<script type="text/javascript">...</script> \r
+# --\r
+<script type="text/javascript">\r
+ $0\r
+</script>
\ No newline at end of file
--- /dev/null
+#contributor : Jimmy Wu <frozenthrone88NOSPAMgmail.com>\r
+#name :<script type="text/javascript" src="..."></script> \r
+# --\r
+<script type="text/javascript" src="$1"></script>
\ No newline at end of file
--- /dev/null
+#contributor : Jimmy Wu <frozenthrone88NOSPAMgmail.com>\r
+#name : <textarea ...></textarea>\r
+# --\r
+<textarea name="$1" id="$2" rows="$3" cols="$4" tabindex="$5"></textarea>
\ No newline at end of file
--- /dev/null
+#contributor : Jimmy Wu <frozenthrone88NOSPAMgmail.com>\r
+#name : <th>...</th>\r
+#group : table\r
+# --\r
+<th$1>$2</th>
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: apr_assert
+# key: apr_assert
+# --
+if (Globals.useAssertions) {
+ ${1:assert ..};
+}
--- /dev/null
+# -*- mode: snippet; require-final-newline: nil -*-
+# name: assert
+# key: as
+# --
+assert ${1:expression};
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet; require-final-newline: nil -*-
+# name: assertEquals
+# key: ae
+# group: test
+# --
+Assert.assertEquals($1, $2);
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: cls
+# key: cls
+# --
+class ${1:Class} {
+ $0
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet; require-final-newline: nil -*-
+# name: constructor
+# key: c
+# --
+public ${1:Class} (${2:args}) {
+ $0
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet; require-final-newline: nil -*-
+# name: define test method
+# key: dt
+# --
+@Test
+public void test${1:Name}() throws Exception {
+ $0
+}
--- /dev/null
+# -*- mode: snippet -*-
+# name: doc
+# key: /*
+# --
+/**
+ * ${1:documentation}
+ */
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: equals
+# key: eq
+# --
+public boolean equals(${1:Class} other) {
+ $0
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: file_class
+# key: file
+# --
+public class ${1:`(file-name-base
+ (or (buffer-file-name)
+ (buffer-name)))`} {
+ $0
+}
--- /dev/null
+# -*- mode: snippet -*-
+# name: for
+# key: for
+# --
+for (${1:int i = 0}; ${2:i < N}; ${3:i++}) {
+ $0
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: fori
+# key: fori
+# --
+for (${1:Object el} : ${2:iterator}) {
+ $0
+}
--- /dev/null
+# -*- mode: snippet; require-final-newline: nil -*-
+# name: getter
+# key: g
+# --
+public ${1:int} get${2:Field}() {
+ return ${3:field};
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: if
+# key: if
+# --
+if (${1:condition}) {
+ $0
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: ife
+# key: ife
+# --
+if (${1:cond}) {
+ $2
+}
+else {
+ $3
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: import
+# key: imp
+# --
+import ${1:System.};
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: iterator
+# key: iterator
+# --
+public Iterator<${1:type}> iterator() {
+ $0
+}
--- /dev/null
+# -*- mode: snippet -*-
+# name: javadoc
+# key: doc
+# --
+/**
+ * $0
+ *
+ */
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet; require-final-newline: nil -*-
+# name: lambda
+# key: \
+# --
+(${1:args}) -> ${2:expression};
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: main
+# key: main
+# --
+public static void main(String[] args) {
+ $0
+}
\ No newline at end of file
--- /dev/null
+# contributor: L. Guruprasad <lgp171188NOSPAMgmail.com>
+# name: main_class
+# key: main_class
+# --
+class `(file-name-nondirectory (file-name-sans-extension (buffer-file-name)))`
+{
+public static void main(String args[])
+{
+$0
+}
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet; require-final-newline: nil -*-
+# name: method
+# key: m
+# --
+${1:public} ${2:void} ${3:name}(${4:args}) {
+ $0
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: new
+# key: new
+# --
+${1:Type} ${2:obj} = new ${3:Constr}(${4:args});
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet; require-final-newline: nil -*-
+# name: override
+# key: o
+# --
+@Override
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: param
+# key: param
+# --
+@param ${1:paramater} $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: printf
+# key: printf
+# --
+System.out.printf("$0%n");
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: println
+# key: pr
+# --
+System.out.println("${1:text}");
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet; require-final-newline: nil -*-
+# name: return
+# key: r
+# --
+return $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: test
+# key: test
+# --
+@Test
+public void test_${1:Case}() {
+ $0
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: testClass
+# key: tc
+# --
+import junit.framework.*;
+import junit.textui.*;
+
+public class Test${1:Class} extends TestCase {
+ protected void setUp() {
+ $0
+ }
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet; require-final-newline: nil -*-
+# name: this
+# key: .
+# --
+this.$1 = $1;
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: toString
+# key: toStr
+# --
+public String toString() {
+ $0
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: try
+# key: try
+# --
+try {
+ $0
+}
+catch (${1:Throwable e}) {
+ ${2:System.out.println("Error " + e.getMessage());
+ e.printStackTrace();}
+}
--- /dev/null
+# -*- mode: snippet; require-final-newline: nil -*-
+# name: value
+# key: val
+# --
+final ${1:int} ${2:n} = $0;
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+#name : alert
+# --
+alert($0);
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+#name : Class
+# --
+var ${1:name} = new Class({
+ initialize: function($2) {
+ $0
+ }
+});
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+#name : comment (/* ... */)
+# --
+/*
+ * $0
+ */
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet; require-final-newline: nil -*-
+# name: debugger
+# key: dbg
+# --
+debugger;
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+#name : each
+# --
+${1:collection}.each(function($2) {
+ $0
+});
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+#name : else
+# --
+else {
+ $0
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+#name : addEvent
+# --
+addEvent('${1:event}', function($2) {
+ $0
+});
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+#name : fireEvent
+# --
+fireEvent('$0')
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+#name : for
+# --
+for(var ${1:i} = ${2:0}; $1 < ${3:collection}.length; $1++) {
+ $0
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet; require-final-newline: nil -*-
+# name: function
+# key: f
+# --
+function ${1:name}(${2:arg}) {
+ $0
+}
--- /dev/null
+# -*- mode: snippet -*-
+#name : if
+# --
+if (${1:condition}) {
+ $0
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+#name : Constructor
+# --
+initialize: function($1) {
+ $0
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+#name : console.log
+# --
+console.log($0);
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+#name : multiline-comment
+#key: /**
+# --
+/**
+ * $0
+ */
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+#name: param-comment
+#key: *@p
+#condition: (= (js2-node-type (js2-node-at-point)) js2-COMMENT)
+# --
+* @param {${type}} ${comment}.
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+#name : html
+# --
+new Request.HTML({
+ onSuccess: function(responseTree, responseElements, responseHTML, responseJavaScript) {
+ $0
+ }
+}).${1:get}(${2:url});
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+#name : json
+# --
+new Request.JSON({
+ onSuccess: function(responseJSON, responseText) {
+ $0
+ }
+}).${1:send}(${2:url});
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+#name: return-comment
+#key: *@r
+#condition: (= (js2-node-type (js2-node-at-point)) js2-COMMENT)
+# --
+* @return {${type}}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+#name: type-inline-comment
+#key: @ty
+#condition: (not (= (js2-node-type (js2-node-at-point)) js2-COMMENT))
+# --
+/** @type {${type}} */
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+#name: type-inline-comment
+#key: *ty
+#condition: (= (js2-node-type (js2-node-at-point)) js2-COMMENT)
+# --
+* @type {${type}}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: acronym
+# key: ac
+# --
+\newacronym{${1:label}}{${1:$(upcase yas-text)}}{${2:Name}}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: alertblock
+# key: al
+# --
+\begin{alertblock}{$2}
+ $0
+\end{alertblock}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: alg
+# key: alg
+# --
+\begin{algorithmic}
+$0
+\end{algorithmic}
--- /dev/null
+# -*- mode: snippet -*-
+# name: full template of article class
+# key: article
+# --
+\documentclass[${1:options}]{article}
+
+\author{$3}
+
+\begin{document}
+$0
+\end{document}
--- /dev/null
+# -*- mode: snippet -*-
+# name: begin
+# key: begin
+# --
+\begin{${1:environment}}
+$0
+\end{$1}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: block
+# key: bl
+# --
+\begin{block}{$1}
+ $0
+\end{block}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: Gls
+# key: G
+# --
+\Gls{${1:label}}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: caption
+# key: ca
+# --
+\caption{$0}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: cite
+# key: c
+# --
+\cite{$1} $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: code
+# key: code
+# --
+\begin{lstlisting}
+$0
+\end{lstlisting}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: columns
+# key: cols
+# --
+\begin{columns}
+ \begin{column}{.${1:5}\textwidth}
+ $0
+ \end{column}
+
+ \begin{column}{.${2:5}\textwidth}
+
+ \end{column}
+\end{columns}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: documentclass
+# key: doc
+# --
+\documentclass[${1:options}]{$2}
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: emph
+# key: e
+# --
+\emph{$1}$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: enumerate
+# key: enum
+# --
+\begin{enumerate}
+\item $0
+\end{enumerate}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: figure
+# key: fig
+# --
+\begin{figure}[ht]
+ \centering
+ \includegraphics[${1:options}]{figures/${2:path.pdf}}
+ \caption{\label{fig:${3:label}} $0}
+\end{figure}
--- /dev/null
+# -*- mode: snippet -*-
+# name: frac
+# key: frac
+# --
+\frac{${1:numerator}}{${2:denominator}}$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: frame
+# key: fr
+# --
+\begin{frame}${1:[$2]}
+ ${3:\frametitle{$4}}
+ $0
+\end{frame}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: gls
+# key: g
+# --
+\gls{${1:label}}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: glspl
+# key: gp
+# --
+\glspl{${1:label}}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: if
+# key: if
+# --
+\IF {$${1:cond}$}
+ $0
+\ELSE
+\ENDIF
--- /dev/null
+# -*- mode: snippet -*-
+# name: includegraphics
+# key: ig
+# --
+\includegraphics${1:[$2]}{$0}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: item
+# key: -
+# --
+\item $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: itemize
+# key: it
+# --
+\begin{itemize}
+\item $0
+\end{itemize}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: label
+# key: lab
+# --
+\label{$0}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: listing
+# key: lst
+# --
+\begin{lstlisting}[float,label=lst:${1:label},caption=nextHopInfo: ${2:caption}]
+$0
+\end{lstlisting}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: full template of moderncv class
+# key: moderncv
+# --
+\documentclass[${1:options}]{moderncv}
+
+\firstname{$3}
+\familyname{$4}
+
+\moderncvstyle{${5:casual}}
+\moderncvcolor{${6:blue}}
+
+\begin{document}
+$0
+\end{document}
--- /dev/null
+# -*- mode: snippet -*-
+# name: moderncv-cvcomputer
+# key: cvcomp
+# --
+\cvcomputer{${1:category}}{${2:programs}}{${3:category}}{${3:programs}}
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: moderncv-cventry
+# key: cventry
+# --
+\cventry{${1:year}}{${2:job}}{${3:employer}}{${4:city}}{${5:description}}
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: moderncv-cvlanguage
+# key: cvlang
+# --
+\cvlanguage{${1:language}}{${2:skill-level}}{${3:comment}}
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: moderncv-cvline
+# key: cvline
+# --
+\cvline{${1:hobby}}{${2:Description}}
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: moderncv-cvlistdoubleitem
+# key: cvditem
+# --
+\cvlistdoubleitem{${1:item}}{${2:item}}
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: moderncv-cvlistitem
+# key: cvitem
+# --
+\cvlistitem{${1:item}}
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: movie
+# key: movie
+# --
+\begin{center}
+\includemovie[
+ label=test,
+ controls=false,
+ text={\includegraphics[width=4in]{${1:image.pdf}}}
+]{4in}{4in}{${2:video file}}
+
+\movieref[rate=3]{test}{Play Fast}
+\movieref[rate=1]{test}{Play Normal Speed}
+\movieref[rate=0.2]{test}{Play Slow}
+\movieref[resume]{test}{Pause/Resume}
--- /dev/null
+# -*- mode: snippet -*-
+# name: newcommand
+# key: cmd
+# --
+\newcommand{\\${1:name}}${2:[${3:0}]}{$0}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: newglossaryentry
+# key: gl
+# --
+\newglossaryentry{${1:AC}}{name=${2:Andrea Crotti}${3:, description=${4:description}}}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: note
+# key: no
+# --
+\note{$0}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: python
+# key: py
+# --
+\lstset{language=python}
+\begin[language=python]{lstlisting}
+$0
+\end{lstlisting}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: question
+# key: q
+# --
+\question{$0}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: section
+# key: sec
+# --
+\section{${1:name}}
+\label{sec:${2:label}}
+
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: subf
+# key: sf
+# --
+\subfigure[${1:caption}]{
+ \label{fig:${2:label}}
+ \includegraphics[width=.${3:3}\textwidth]{${4:path}}}
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: subfigure
+# key: subfig
+# --
+\begin{figure}[ht]
+ \centering
+ \subfigure[$1]
+ {\label{fig:${2:label}}
+ \includegraphics[width=.${3:5}\textwidth]{${4:path}}}
+
+ \caption{${5:caption}}
+\label{fig:${6:label}}
+\end{figure}
--- /dev/null
+# -*- mode: snippet -*-
+# name: subsec
+# key: sub
+# --
+\subsection{${1:name}}
+\label{subsec:${2:label}}
+
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: textbf
+# key: b
+# --
+\textbf{$1}$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: usepackage
+# key: pkg
+# --
+\usepackage{$0}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: defun
+# key: defun
+# --
+(defun ${1:fun} (${2:args})
+ $0
+)
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: class
+# key: cls
+# --
+(defclass ${1:name} (${2:inherits})
+ (${4:slot})
+ (:documentation "${3:doc}"))
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: comment
+# key: /*
+# --
+#|${1:type the comment here}|#
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: defpackage
+# key: defp
+# --
+(defpackage #:${1:name}
+ (:nicknames #:${2:nick})
+ (:use #:cl #:closer-mop #:${3:package})
+ (:shadow :${4.symbol})
+ (:shadowing-import-from #:${5:package} #:${6:symbol})
+ (:export :$0))
--- /dev/null
+# -*- mode: snippet -*-
+# name: do
+# key: do
+# --
+(do ((${1:var1} ${2:init-form} ${3:step-form})
+ (${4:var2} ${5:init-form} ${6:step-form}))
+ (${7:condition} ${8:return-value})
+ (${9:body}))
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: do
+# key: for
+# --
+(dotimes (${1:var} ${2:count-form})
+ ${3:body})
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: do
+# key: foreach
+# --
+(dolist (${1:var} ${2:list-form})
+ ${3:body})
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: format
+# key: print
+# --
+(format t "~& $0 ~%")
--- /dev/null
+# -*- mode: snippet -*-
+# name: if
+# key: if
+# --
+(when (${1:condition})
+ (${2:then-do-this}))
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: ifelse (...) (...) (...) ...
+# key: ifelse
+# --
+
+(if (${1:condition})
+ (${2:then})
+ (${3:else}))
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: ifnot (...) (...) ...
+# key: ifnot
+# --
+
+(unless (${1:condition})
+ (${2:then-do-this}))
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: slot
+# key: slot
+# --
+(${1:name} :initarg :${1:$(yas/substr yas-text "[^: ]*")}
+ :initform (error ":${1:$(yas/substr yas-text "[^: ]*")} must be specified")
+ ;; :accessor ${1:$(yas/substr yas-text "[^: ]*")}
+ :reader ${1:$(yas/substr yas-text "[^: ]*")}-changed
+ :writer set-${1:$(yas/substr yas-text "[^: ]*")}
+ :type
+ :allocation ${3::class :instance}
+ :documentation "${2:about-slot}")
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: switch
+# key: switch
+# --
+
+(cond (${1:case1} (${2:do-this}))
+ (${3:case2} (${4:do-this}))
+ (t ${5:default}))
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: typecast
+# name: cast
+# --
+(coerce ${1:object} ${2:type})
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: do
+# key: do
+# --
+do
+ $0
+end
--- /dev/null
+# -*- mode: snippet -*-
+# name: if elseif
+# key: eif
+# --
+if $1 then
+ $2
+elseif $3 then
+ $0
+end
--- /dev/null
+# -*- mode: snippet -*-
+# name: if elseif else
+# key: eife
+# --
+if $1 then
+ $2
+elseif $3 then
+ $4
+else
+ $0
+end
--- /dev/null
+# -*- mode: snippet -*-
+# name: fun
+# key: fun
+# --
+function ($1)
+ $0
+end
--- /dev/null
+# -*- mode: snippet -*-
+# name: if
+# key: if
+# --
+if $1 then
+ $0
+end
--- /dev/null
+# -*- mode: snippet -*-
+# name: if else
+# key: ife
+# --
+if $1 then
+ $2
+else
+ $0
+end
--- /dev/null
+# -*- mode: snippet -*-
+# name: for in ipairs
+# key: ipairs
+# --
+for ${1:idx}, ${2:val} in ipairs(${3:table_name}) do
+ $0
+end
--- /dev/null
+# -*- mode: snippet -*-
+# name: for in pairs
+# key: pairs
+# --
+for ${1:name}, ${2:val} in pairs(${3:table_name}) do
+ $0
+end
--- /dev/null
+# -*- mode: snippet -*-
+# name: repeat util
+# key: repeat
+# --
+repeat
+ $0
+until $1
--- /dev/null
+# -*- mode: snippet -*-
+# name: require
+# key: require
+# --
+local $1 = require "$2"
--- /dev/null
+# -*- mode: snippet -*-
+# name: while
+# key: while
+# --
+while $1 do
+ $0
+end
--- /dev/null
+# -*- mode: snippet -*-
+# name: def
+# key: def
+# --
+define(\`${1:macro}',\`${2:subst}').
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: noinst_HEADERS
+# key: noinst
+# --
+noinst_HEADERS = $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: PHONY
+# key: phony
+# --
+.PHONY: $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: echo
+# key: echo
+# --
+@echo ${1:"message to output"}
--- /dev/null
+# -*- mode: snippet -*-
+# name: gen
+# key: gen
+# possibly add some smart control over the list
+# --
+all: ${1:targets}
+
+$0
+
+clean:
+ ${2:clean actions}
--- /dev/null
+# -*- mode: snippet -*-
+# name: if
+# key: if
+# --
+@if [ ${1:cond} ]
+ then $0
+fi
--- /dev/null
+# -*- mode: snippet -*-
+# name: var
+# key: $
+# --
+$(${1:VAR})$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet; require-final-newline: nil -*-
+# name: abspath
+# contributor: gbalats
+# key: abs
+# --
+\$(abspath ${1:\$(${2:paths})})$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet; require-final-newline: nil -*-
+# name: addprefix
+# contributor: gbalats
+# key: ap
+# --
+\$(addprefix ${1:\$(${2:dir})/},${3:\$(${4:items})})$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet; require-final-newline: nil -*-
+# name: addsuffix
+# contributor: gbalats
+# key: as
+# --
+\$(addsuffix ${1:.suffix},${2:\$(${3:items})})$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet; require-final-newline: nil -*-
+# name: dir
+# contributor: gbalats
+# key: d
+# --
+\$(dir ${1:\$(${2:paths})})$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: make
+# contributor: gbalats
+# key: make
+# --
+\$(MAKE) --directory=${1:\$@}
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet; require-final-newline: nil -*-
+# name: notdir
+# contributor: gbalats
+# key: nd
+# --
+\$(notdir ${1:\$(${2:paths})})$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: patsubst
+# key: ps
+# --
+$(patsubst ${1:from},${2:to},${3:src})
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: phony
+# key: ph
+# --
+.PHONY = $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet; require-final-newline: nil -*-
+# name: shell
+# key: sh
+# --
+\$(shell ${1:command})$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet; require-final-newline: nil -*-
+# name: special targets
+# contributor: gbalats
+# key: .
+# --
+.${1:PHONY$(upcase yas-text)}: $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: template
+# contributor: gbalats
+# binding: C-c C-t
+# --
+define ${1:PROGRAM$(upcase yas-text)}_template
+$0
+endef
+
+\$(foreach ${2:${1:$(downcase yas-text)}},\$(${3:$1S}),\$(eval \$(call $1_template,\$($2))))
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: wildcard
+# key: wl
+# --
+$(wildcard $0)
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: all
+# key: all
+# --
+all:
+ $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: clean
+# contributor: gbalats
+# expand-env: ((yas-indent-line 'fixed))
+# key: cl
+# --
+clean:
+ ${1:rm -r ${2:\$(${3:OUTDIR})}}
+$0
--- /dev/null
+# -*- mode: snippet; require-final-newline: nil -*-
+# name: variable
+# key: var
+# --
+${1:int} ${2:n} = $0;
\ No newline at end of file
--- /dev/null
+#name : Unordered List
+#contributor: Peng Deng <dengpengNOSPAMgmail.com>
+# --
++ ${1:Text}
++$0
--- /dev/null
+#name : Unordered List
+#contributor: Peng Deng <dengpengNOSPAMgmail.com>
+# --
+- ${1:Text}
+-$0
--- /dev/null
+#name : Emphasis
+#contributor: Peng Deng <dengpengNOSPAMgmail.com>
+# --
+_${1:Text}_ $0
--- /dev/null
+#name : Strong
+#contributor: Peng Deng <dengpengNOSPAMgmail.com>
+# --
+**${1:Text}** $0
--- /dev/null
+#name : Inline Code
+#contributor: Peng Deng <dengpengNOSPAMgmail.com>
+# --
+\`${1:Code}\` $0
--- /dev/null
+#name : Header 1 (#)
+#contributor: Peng Deng <dengpengNOSPAMgmail.com>
+# --
+# ${1:Header 1} #
+
+$0
--- /dev/null
+#name : Header 1 (=)
+#contributor: Peng Deng <dengpengNOSPAMgmail.com>
+# --
+${1:Header 1}
+${1:$(make-string (string-width yas-text) ?\=)}
+
+$0
--- /dev/null
+#name : Header 2 (##)
+#contributor: Peng Deng <dengpengNOSPAMgmail.com>
+# --
+## ${1:Header 1} ##
+
+$0
--- /dev/null
+#name : Header 2 (-)
+#contributor: Peng Deng <dengpengNOSPAMgmail.com>
+# --
+${1:Header 2}
+${1:$(make-string (string-width yas-text) ?\-)}
+
+$0
--- /dev/null
+#name : Header 3
+#contributor: Peng Deng <dengpengNOSPAMgmail.com>
+# --
+### ${1:Header 3} ###
+
+$0
--- /dev/null
+#name : Header 4
+#contributor: Peng Deng <dengpengNOSPAMgmail.com>
+# --
+#### ${1:Header 4} ####
+
+$0
--- /dev/null
+#name : Header 5
+#contributor: Peng Deng <dengpengNOSPAMgmail.com>
+# --
+##### ${1:Header 5} #####
+
+$0
--- /dev/null
+#name : Header 6
+#contributor: Peng Deng <dengpengNOSPAMgmail.com>
+# --
+###### ${1:Header 6} ######
+
+$0
--- /dev/null
+#name : Highlight
+#contributor: nguyenvinhlinh <nguyenvinhlinh93NOSPAMgmail.com>
+# --
+{% highlight ${1:language} %}
+${0:content}
+{% endhighlight %}
\ No newline at end of file
--- /dev/null
+#name : Horizontal Rule (-)
+#contributor: Peng Deng <dengpengNOSPAMgmail.com>
+# --
+
+----------
+
+$0
--- /dev/null
+#name : Horizontal Rule (*)
+#contributor: Peng Deng <dengpengNOSPAMgmail.com>
+# --
+
+*******
+
+$0
--- /dev/null
+#name : Image
+#contributor: Peng Deng <dengpengNOSPAMgmail.com>
+# --
+ $0
--- /dev/null
+#name : Link
+#contributor: Peng Deng <dengpengNOSPAMgmail.com>
+# --
+[${1:Link Text}](${2:URL} $3) $0
--- /dev/null
+#name : Ordered List
+#contributor: Peng Deng <dengpengNOSPAMgmail.com>
+# --
+${1:1}. ${2:Text}
+${1:$(number-to-string (1+ (string-to-number yas-text)))}. $0
--- /dev/null
+#name : Referenced Image
+#contributor: Peng Deng <dengpengNOSPAMgmail.com>
+# --
+![${1:Alt Text}][$2] $0
--- /dev/null
+#name : Reference Label
+#contributor: Peng Deng <dengpengNOSPAMgmail.com>
+# --
+[${1:Reference}]: ${2:URL} $3
+$0
--- /dev/null
+#name : Reference Link
+#contributor: Peng Deng <dengpengNOSPAMgmail.com>
+# --
+[${1:Link Text}][$2] $0
--- /dev/null
+# name: utf-8 encoding
+# key: utf8
+# contributor: Thiago Perrotta
+# --
+<meta http-equiv='Content-Type' content='text/html; charset=utf-8' />
+$0
--- /dev/null
+prog-mode
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: chan
+# key: chan
+# --
+channel Channel extends ${1:ned.DelayChannel} {
+ $0
+}
--- /dev/null
+# -*- mode: snippet -*-
+# name: connections
+# key: conn
+# --
+connections${1: allowunconnected}:
+ $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: for
+# key: for
+# --
+for ${1:i}=${2:0}..${3:sizeof(port)-1} {
+ $0
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: import
+# key: imp
+# --
+import ned.${1:Package};
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: network
+# key: net
+# --
+network ${1:Name}
+{
+ submodules:
+ $2
+ connections:
+ $3
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: simple
+# key: simple
+# --
+simple ${1:Component}${2: extends ${3:Component}}
+{
+ $0
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: submodules
+# key: sub
+# --
+submodules:
+ $0
\ No newline at end of file
--- /dev/null
+text-mode cc-mode
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: TOSSIM
+# key: tossim
+# --
+#ifndef TOSSIM
+ $0
+#endif
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: command
+# key: command
+# --
+command ${1:void} ${2:naMe}($3) {
+
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: dbg
+# key: dbg
+# --
+dbg("${1:Module}", "${2:message}"${3:, ${4:var list}});
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: event
+# key: event
+# --
+event ${1:void} ${2:On.Event}($3) {
+ $0
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: ifdef
+# key: ifdef
+# --
+#ifdef ${1:Macro}
+ $2
+${3:#else}
+ $4
+#endif
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: interface
+# key: int
+# --
+interface ${1:Interface} {
+ $0
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: module
+# key: mod
+# --
+module ${1:Module} {
+ ${2:uses interface ${3:Packet}};
+ $0
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: nx
+# key: nx
+# --
+nx_uint${1:8}_t ${2:var};
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: provides
+# key: provides
+# --
+provides interface ${1:Interface};
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: sim
+# key: sim
+# --
+#ifdef TOSSIM
+ $0
+#endif
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: uint8_t
+# key: u8
+# --
+uint8_t ${1:var};
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: uses
+# key: uses
+# --
+uses interface ${1:Interface}${2: as ${3:alias}};
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: buildPhase
+# key: bp
+# --
+buildPhase= ''
+$1
+'';
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: checkPhase
+# key: ch
+# --
+checkPhase= ''
+$1
+'';
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: configurePhase
+# key: cp
+# --
+configurePhase= ''
+$1
+'';
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: distPhase
+# key: dp
+# --
+distPhase= ''
+$1
+'';
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: fixPhase
+# key: fp
+# --
+fixPhase= ''
+$1
+'';
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: installCheckPhase
+# key: ic
+# --
+installCheckPhase= ''
+$1
+'';
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: installPhase
+# key: ip
+# --
+installPhase= ''
+${1: mkdir -p \$out/bin
+ for f in \$(find . -executable -type f);
+ do
+ cp \$f \$out/bin/
+ done}
+'';
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: package github
+# key: pg
+# --
+{ stdenv, fetchFromGitHub$1 }:
+stdenv.mkDerivation rec {
+ name = "$2-\$\{version\}";
+ version = "$3";
+
+ src = fetchFromGitHub {
+ owner = "$4";
+ repo = "$2";
+ rev = "${5:v\$\{version\}}";
+ sha256 = "$6";
+ };
+
+ buildInputs = [ $1];
+
+ meta = {
+ description = "$7";
+ homepage = https://${8:github.com/$4/$2};
+
+ license = stdenv.lib.licenses.${9:$$
+ (yas-choose-value '(
+ "agpl3"
+ "asl20"
+ "bsd2"
+ "bsd3"
+ "gpl2"
+ "gpl3"
+ "lgpl3"
+ "mit"
+ ))};
+ maintainers = [ stdenv.lib.maintainers.$10 ];
+ platforms = stdenv.lib.platforms.${11:$$
+ (yas-choose-value '(
+ "gnu"
+ "linux"
+ "darwin"
+ "freebsd"
+ "openbsd"
+ "netbsd"
+ "cygwin"
+ "illumos"
+ "unix"
+ "all"
+ "none"
+ "allBut"
+ "mesaPlatforms"
+ "x86"
+ "i686"
+ "arm"
+ "mips"
+ ))};
+ };
+}
--- /dev/null
+# -*- mode: snippet -*-
+# name: package url
+# key: pu
+# --
+{ stdenv, fetchurl$1}:
+
+stdenv.mkDerivation rec {
+ version = "$2";
+ name = "$3-\$\{version\}";
+
+ src = fetchurl {
+ url = "$4";
+ sha256 = "$5";
+ };
+
+ buildInputs = [ $1 ];
+
+ meta = {
+ description = "$6";
+ homepage = https://$7;
+ license = stdenv.lib.licenses.${8:$$
+ (yas-choose-value '(
+ "agpl3"
+ "asl20"
+ "bsd2"
+ "bsd3"
+ "gpl2"
+ "gpl3"
+ "lgpl3"
+ "mit"
+ ))};
+ maintainers = [ stdenv.lib.maintainers.$9 ];
+ platforms = stdenv.lib.platforms.${10:$$
+ (yas-choose-value '(
+ "gnu"
+ "linux"
+ "darwin"
+ "freebsd"
+ "openbsd"
+ "netbsd"
+ "cygwin"
+ "illumos"
+ "unix"
+ "all"
+ "none"
+ "allBut"
+ "mesaPlatforms"
+ "x86"
+ "i686"
+ "arm"
+ "mips"
+ ))};
+ };
+}
--- /dev/null
+# -*- mode: snippet -*-
+# name: patchPhase
+# key: pp
+# --
+patchPhase = ''
+ $1
+'';
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: phases
+# key: ph
+# --
+ phases="${1:\$prePhases unpackPhase patchPhase \$preConfigurePhases configurePhase \$preBuildPhases buildPhase checkPhase \$preInstallPhases installPhase fixupPhase installCheckPhase \$preDistPhases distPhase \$postPhases}";
--- /dev/null
+# -*- mode: snippet -*-
+# name: unpackPhase
+# key: up
+# --
+unpackPhase = ''
+ $1
+'';
+$0
--- /dev/null
+prog-mode
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: define
+# key: def
+# --
+!define ${1:CONSTANT} ${2:value}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: function
+# key: fun
+# --
+Function ${1:Name}
+ $0
+FunctionEnd
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: if
+# key: if
+# --
+${IF} ${1:cond}
+ $0
+${ElseIf} ${2:else_cond}
+
+${EndIf}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: include
+# key: inc
+# --
+!include "${Library.nsh}"
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: insert_macro
+# key: im
+# --
+!insermacro ${1:Name} ${2:"args"}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: instdir
+# key: $
+# --
+$INSTDIR
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: macro
+# key: macro
+# --
+!macro ${1:Name} UN
+$0
+
+!macroend
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: message
+# key: msg
+# --
+MessageBox MB_OK "${1:hello}"
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: outdir
+# key: $
+# --
+$OUTDIR
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: outfile
+# key: out
+# --
+outFile "${1:setup}.exe"
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: section
+# key: sec
+# --
+Section "${1:Program}"
+ $0
+SectionEnd
\ No newline at end of file
--- /dev/null
+#contributor : Anders Bach Nielsen <abachnNOSPAMabachn.net>\r
+#name : <body>...</body>\r
+# --\r
+<body$1>\r
+ $0\r
+</body>
\ No newline at end of file
--- /dev/null
+#contributor : Anders Bach Nielsen <abachnNOSPAMabachn.net>\r
+#name : <br />\r
+# --\r
+<br />
\ No newline at end of file
--- /dev/null
+#contributor : Anders Bach Nielsen <abachnNOSPAMabachn.net>
+#name : DocType XHTML 1.1
+#group : meta
+# --
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
\ No newline at end of file
--- /dev/null
+#contributor : Anders Bach Nielsen <abachnNOSPAMabachn.net>
+#name : DocType XHTML 1.0 Strict
+#group : meta
+# --
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
\ No newline at end of file
--- /dev/null
+#contributor : Anders Bach Nielsen <abachnNOSPAMabachn.net>
+#name : DocType XHTML 1.0 Transitional
+#group : meta
+# --
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
\ No newline at end of file
--- /dev/null
+#contributor : Anders Bach Nielsen <abachnNOSPAMabachn.net>\r
+#name :<form method="..." action="..."></form>\r
+# --\r
+<form method="$1" action="$2">\r
+ $0\r
+</form>
\ No newline at end of file
--- /dev/null
+#contributor : Anders Bach Nielsen <abachnNOSPAMabachn.net>\r
+#name : <a href="...">...</a>\r
+#key: a\r
+# --\r
+<a href="$1">$2</a>
\ No newline at end of file
--- /dev/null
+#contributor : Anders Bach Nielsen <abachnNOSPAMabachn.net>\r
+#name : <html xmlns="...">...</html>\r
+# --\r
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="${1:en}" lang="${2:en}">\r
+ $0\r
+</html>\r
--- /dev/null
+#contributor : Anders Bach Nielsen <abachnNOSPAMabachn.net>\r
+#name : <img src="..." alt="..." />\r
+# --\r
+<img src="$1" alt="$2" />
\ No newline at end of file
--- /dev/null
+#contributor : Anders Bach Nielsen <abachnNOSPAMabachn.net>\r
+#name : <input ... />\r
+# --\r
+<input type="$1" name="$2" value="$3" />
\ No newline at end of file
--- /dev/null
+#contributor : Anders Bach Nielsen <abachnNOSPAMabachn.net>\r
+#name : <link stylesheet="..." />\r
+# --\r
+<link rel="${1:stylesheet}" href="${2:url}" type="${3:text/css}" media="${4:screen}" />
\ No newline at end of file
--- /dev/null
+#contributor : Anders Bach Nielsen <abachnNOSPAMabachn.net>\r
+#name : <meta name="..." content="..." />\r
+#group : meta\r
+# --\r
+<meta name="${1:generator}" content="${2:content}" />
\ No newline at end of file
--- /dev/null
+#contributor : Anders Bach Nielsen <abachnNOSPAMabachn.net>\r
+#name : <a name="..."></a>\r
+# --\r
+<a name="$1"></a>
\ No newline at end of file
--- /dev/null
+#contributor : Anders Bach Nielsen <abachnNOSPAMabachn.net>\r
+#name : <blockquote>...</blockquote>\r
+# --\r
+<blockquote>\r
+ $1\r
+</blockquote>
\ No newline at end of file
--- /dev/null
+#contributor : Anders Bach Nielsen <abachnNOSPAMabachn.net>\r
+#name : <style type="text/css" media="...">...</style>\r
+# --\r
+<style type="text/css" media="${1:screen}">\r
+ $0\r
+</style>
\ No newline at end of file
--- /dev/null
+#contributor : Anders Bach Nielsen <abachnNOSPAMabachn.net>
+#name : <tag>...</tag>
+#key: t
+# --
+<${1:tag}>$2</$1>$0
\ No newline at end of file
--- /dev/null
+#contributor : Anders Bach Nielsen <abachnNOSPAMabachn.net>
+#name : <tag.../>
+#key: t
+# --
+<$1 $2 />$0
\ No newline at end of file
--- /dev/null
+#contributor : Anders Bach Nielsen <abachn@abachn.net>
+#name : <tag> \n...\n</tag>
+#key: tn
+# --
+<${1:tag}>
+ $2
+</$1>$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: for
+# key: for
+# --
+for ${1:var} = ${2:expr}
+ $0
+endfor
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: function
+# key: fun
+# --
+function ${1:return_val} = ${2:fname}(${3:args})
+ $0
+endfunction
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: if
+# key: if
+# --
+if ${1:cond}
+ $0
+${2:else
+ ${3:other}}
+endif
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: dot
+# key: dot_
+# --
+#+begin_src dot :file ${1:file} :cmdline -T${2:pdf} :exports none :results silent
+ $0
+#+end_src
+
+[[file:$1]]
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: elisp
+# key: elisp_
+# --
+#+begin_src emacs-lisp :tangle yes
+$0
+#+end_src
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: embedded
+# key: emb_
+# --
+src_${1:lang}${2:[${3:where}]}{${4:code}}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: entry
+# key: entry_
+# --
+#+begin_html
+---
+layout: ${1:default}
+title: ${2:title}
+---
+#+end_html
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: figure
+# key: fig_
+# --
+#+CAPTION: ${1:caption}
+#+ATTR_LaTeX: ${2:scale=0.75}
+#+LABEL: fig:${3:label}
--- /dev/null
+# -*- mode: snippet -*-
+# name: img
+# key: img_
+# --
+<img src="$1"
+ alt="$2" align="${3:left}"
+ title="${4:image title}"
+ class="img"
+</img>
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: latex
+# key: latex_
+# --
+#+BEGIN_LaTeX
+$0
+#+END_LaTeX
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: matrix
+# key: matrix_
+# possible improvement, compute the number of lines from the argument to array
+# --
+\left \(
+\begin{array}{${1:ccc}}
+${2:v1 & v2} \\
+$0
+\end{array}
+\right \)
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+#name : uml
+#key : uml
+#contributor : Robert O'Connor
+# --
+#+BEGIN_UML
+$1
+#+END_UML
--- /dev/null
+# -*- mode: snippet -*-
+# name: verse
+# key: verse_
+# --
+#+begin_verse
+ $0
+#+end_verse
\ No newline at end of file
--- /dev/null
+# name: eval { ... } if ($@) { ... }
+# key: eval
+# --
+eval {
+ ${1:# do something risky...}
+};
+if (\$@) {
+ ${2:# handle failure...}
+}
\ No newline at end of file
--- /dev/null
+# name: for (...) { ... }
+# key: for
+# --
+for (my \$${1:var} = 0; \$$1 < ${2:expression}; \$$1++) {
+ ${3:# body...}
+}
\ No newline at end of file
--- /dev/null
+# name: foreach ... { ... }
+# key: fore
+# --
+foreach my \$${1:x} (@${2:array}) {
+ ${3:# body...}
+}
\ No newline at end of file
--- /dev/null
+# name: if (...) { ... }
+# key: if
+# --
+if ($1) {
+ $0
+}
\ No newline at end of file
--- /dev/null
+# name: if (...) { ... } else { ... }
+# key: ife
+# --
+if ($1) {
+ $2
+} else {
+ $3
+}
\ No newline at end of file
--- /dev/null
+# name: if, elsif, else ...
+# key: ifee
+# --
+if ($1) {
+ ${2:# body...}
+} elsif ($3) {
+ ${4:# elsif...}
+} else {
+ ${5:# else...}
+}
\ No newline at end of file
--- /dev/null
+# name: sub ... { ... }
+# key: sub
+# --
+sub ${1:function_name} {
+ $0
+}
\ No newline at end of file
--- /dev/null
+# name: unless (...) { ... }
+# key: unless
+# --
+unless ($1) {
+ $0
+}
\ No newline at end of file
--- /dev/null
+# name: while (...) { ... }
+# key: while
+# --
+while ($1) {
+ $0
+}
\ No newline at end of file
--- /dev/null
+# name: ... foreach ...
+# key: xfore
+# --
+${1:expression} foreach @${2:array};
\ No newline at end of file
--- /dev/null
+# name: ... if ...
+# key: xif
+# --
+${1:expression} if ${2:condition}
\ No newline at end of file
--- /dev/null
+# name: ... unless ...
+# key: xunless
+# --
+${1:expression} unless ${2:condition}
\ No newline at end of file
--- /dev/null
+# name: ... while ...
+# key: xwhile
+# --
+${1:expression} while ${2:condition};
\ No newline at end of file
--- /dev/null
+(require 'yasnippet)
+
+(defun yas-with-comment (str)
+ (format "%s%s%s" comment-start str comment-end))
+
+;; whitespace removing functions from Magnar Sveen ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+(defun yas-s-trim-left (s)
+ "Remove whitespace at the beginning of S."
+ (if (string-match "\\`[ \t\n\r]+" s)
+ (replace-match "" t t s)
+ s))
+
+(defun yas-s-trim-right (s)
+ "Remove whitespace at the end of S."
+ (if (string-match "[ \t\n\r]+\\'" s)
+ (replace-match "" t t s)
+ s))
+
+(defun yas-s-trim (s)
+ "Remove whitespace at the beginning and end of S."
+ (yas-s-trim-left (yas-s-trim-right s)))
+
+
+(defun yas-string-reverse (str)
+ "Reverse a string STR manually to be compatible with emacs versions < 25."
+ (apply #'string
+ (reverse
+ (string-to-list str))))
+
+(defun yas-trimmed-comment-start ()
+ "This function returns `comment-start' trimmed by whitespaces."
+ (yas-s-trim comment-start))
+
+(defun yas-trimmed-comment-end ()
+ "This function returns `comment-end' trimmed by whitespaces if `comment-end' is not empty.
+Otherwise the reversed output of function `yas-trimmed-comment-start' is returned."
+ (if (eq (length comment-end) 0)
+ (yas-string-reverse (yas-trimmed-comment-start))
+ (yas-s-trim comment-end)))
--- /dev/null
+# -*- mode: snippet -*-
+# contributor: sh-ow <sh-owNOSPAMusers.noreply.github.com>
+# name: comment
+# key: co
+# --
+`(yas-trimmed-comment-start)` ${1:comment}`(unless (eq (length comment-end) 0) (concat " " (yas-trimmed-comment-end)))`$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# contributor: sh-ow <sh-owNOSPAMusers.noreply.github.com>
+# name: commentblock
+# key: cob
+# --
+${1:$(let* ((col (current-column))
+ (str "")
+ (lastcom (substring (yas-trimmed-comment-start) -1))
+ (start (yas-trimmed-comment-start))
+ (end (yas-trimmed-comment-end))
+ (over (- (+ (string-width yas-text) (length start) (length end) col) 77)))
+ (while (< (length str) (+ (- 79 (length start) (length end) col) (if (> over 0) over 0)))
+ (setq str (concat str lastcom)))
+ (concat start str end))}
+${1:$(let* ((col (current-column))
+ (str "")
+ (start (yas-trimmed-comment-start))
+ (end (yas-trimmed-comment-end)))
+ (while (< (length str) (ffloor (/ (- 78.0 (+ col (length start) (string-width yas-text) (length end))) 2.0)))
+ (setq str (concat str " ")))
+ (concat start str))} ${1:comment} ${1:$(let* ((col (current-column))
+ (str "")
+ (start (yas-trimmed-comment-start))
+ (end (yas-trimmed-comment-end)))
+ (while (< (length str) (- 79.0 (if (eq (mod (string-width yas-text) 2) 1) (- col 1) col) (length end)))
+ (setq str (concat str " ")))
+ (concat str end))}
+${1:$(let* ((col (current-column))
+ (str "")
+ (lastcom (substring (yas-trimmed-comment-start) -1))
+ (start (yas-trimmed-comment-start))
+ (end (yas-trimmed-comment-end))
+ (over (- (+ (string-width yas-text) (length start) (length end) col) 77)))
+ (while (< (length str) (+ (- 79 (length start) (length end) col) (if (> over 0) over 0)))
+ (setq str (concat str lastcom)))
+ (concat start str end))}$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# contributor: sh-ow <sh-owNOSPAMusers.noreply.github.com>
+# name: commentline
+# key: col
+# --
+`(yas-trimmed-comment-start)` ${1:comment} ${1:$(let* ((start (yas-trimmed-comment-start))
+ (lastcom (aref start (1- (length start))))
+ (end (yas-trimmed-comment-end))
+ (endpadlen (- 79 (+ (current-column) (length end)))))
+ (concat (make-string (max endpadlen 0) lastcom)
+ end))}$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: fixme
+# key: fi
+# condition: (not (eq major-mode 'sh-mode))
+# --
+`(yas-with-comment "FIXME: ")`
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: todo
+# key: t
+# --
+`(yas-with-comment "TODO: ")`
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: xxx
+# key: x
+# --
+`(yas-with-comment "XXX: ")`
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: message
+# key: msg
+# --
+message ${1:Name} {
+ $0
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: syntax
+# key: syn
+# --
+syntax = "${1:proto3}";
--- /dev/null
+(require 'yasnippet)
+(defvar yas-text)
+
+(defun python-split-args (arg-string)
+ "Split a python argument string into ((name, default)..) tuples"
+ (mapcar (lambda (x)
+ (split-string x "[[:blank:]]*=[[:blank:]]*" t))
+ (split-string arg-string "[[:blank:]]*,[[:blank:]]*" t)))
+
+(defun python-args-to-docstring ()
+ "return docstring format for the python arguments in yas-text"
+ (let* ((indent (concat "\n" (make-string (current-column) 32)))
+ (args (python-split-args yas-text))
+ (max-len (if args (apply 'max (mapcar (lambda (x) (length (nth 0 x))) args)) 0))
+ (formatted-args (mapconcat
+ (lambda (x)
+ (concat (nth 0 x) (make-string (- max-len (length (nth 0 x))) ? ) " -- "
+ (if (nth 1 x) (concat "\(default " (nth 1 x) "\)"))))
+ args
+ indent)))
+ (unless (string= formatted-args "")
+ (mapconcat 'identity (list "Keyword Arguments:" formatted-args) indent))))
+
+(defun python-args-to-docstring-numpy ()
+ "return docstring format for the python arguments in yas-text"
+ (let* ((args (python-split-args yas-text))
+ (format-arg (lambda(arg)
+ (concat (nth 0 arg) " : " (if (nth 1 arg) ", optional") "\n")))
+ (formatted-params (mapconcat format-arg args "\n"))
+ (formatted-ret (mapconcat format-arg (list (list "out")) "\n")))
+ (unless (string= formatted-params "")
+ (mapconcat 'identity
+ (list "\nParameters\n----------" formatted-params
+ "\nReturns\n-------" formatted-ret)
+ "\n"))))
+
+
+(add-hook 'python-mode-hook
+ '(lambda () (set (make-local-variable 'yas-indent-line) 'fixed)))
--- /dev/null
+# -*- mode: snippet -*-
+# name: __contains__
+# key: cont
+# group: dunder methods
+# --
+def __contains__(self, el):
+ $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: __enter__
+# key: ent
+# group: dunder methods
+# --
+def __enter__(self):
+ $0
+
+ return self
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: __exit__
+# key: ex
+# group: dunder methods
+# --
+def __exit__(self, type, value, traceback):
+ $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: __getitem__
+# key: getit
+# group: dunder methods
+# --
+def __getitem__(self, ${1:key}):
+ $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: __len__
+# key: len
+# group: dunder methods
+# --
+def __len__(self):
+ $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: __new__
+# key: new
+# group: dunder methods
+# --
+def __new__(mcs, name, bases, dct):
+ $0
+ return type.__new__(mcs, name, bases, dct)
--- /dev/null
+# -*- mode: snippet -*-
+# name: __setitem__
+# key: setit
+# group: dunder methods
+# --
+def __setitem__(self, ${1:key}, ${2:val}):
+ $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: all
+# key: all
+# --
+__all__ = [
+ $0
+]
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: arg
+# key: arg
+# group: argparser
+# --
+parser.add_argument('-$1', '--$2',
+ $0)
--- /dev/null
+# -*- mode: snippet -*-
+# name: arg_positional
+# key: arg
+# group: argparser
+# --
+parser.add_argument('${1:varname}', $0)
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: assert
+# key: ass
+# group: testing
+# --
+assert $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: assertEqual
+# key: ae
+# group: testing
+# --
+self.assertEqual($1, $2)
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: assertFalse
+# key: af
+# group: testing
+# --
+self.assertFalse($0)
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: assertIn
+# key: ai
+# group: testing
+# --
+self.assertIn(${1:member}, ${2:container})
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: assertNotEqual
+# key: ane
+# group: testing
+# --
+self.assertNotEqual($1, $2)
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: assetNotIn
+# key: an
+# group: testing
+# --
+self.assertNotIn(${1:member}, ${2:container})
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: assertRaises
+# key: ar
+# group: testing
+# --
+self.assertRaises(${1:Exception}, ${2:fun})
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: assertRaises
+# key: ar
+# --
+with self.assertRaises(${1:Exception}):
+ $0
--- /dev/null
+# -*- mode: snippet -*-
+# name: assertTrue
+# key: at
+# group: testing
+# --
+self.assertTrue($0)
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: celery pdb
+# key: cdb
+# group: debug
+# --
+from celery.contrib import rdb; rdb.set_trace()
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: classmethod
+# key: cm
+# group: object oriented
+# --
+@classmethod
+def ${1:meth}(cls, $2):
+ $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: class
+# key: cls
+# group: object oriented
+# --
+class ${1:class}:
+ $0
--- /dev/null
+# -*- mode: snippet -*-
+# name: dec
+# key: dec
+# group : definitions
+# --
+def ${1:decorator}(func):
+ $2
+ def _$1(*args, **kwargs):
+ $3
+ ret = func(*args, **kwargs)
+ $4
+ return ret
+
+ return _$1
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: deftest
+# key: dt
+# group: testing
+# --
+def test_${1:long_name}(self):
+ $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet; require-final-newline: nil -*-
+# name: django_test_class
+# key: tcs
+# group: testing
+# --
+class ${1:Model}Test(TestCase):
+ $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: doc
+# key: d
+# --
+"""$0
+"""
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: doctest
+# key: doc
+# group: testing
+# --
+>>> ${1:function calls}
+${2:desired output}
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: embed
+# key: embed
+# --
+from IPython import embed; embed()
--- /dev/null
+# -*- mode: snippet -*-
+# name: __eq__
+# key: eq
+# group: dunder methods
+# --
+def __eq__(self, other):
+ return self.$1 == other.$1
\ No newline at end of file
--- /dev/null
+# name: for ... in ... : ...
+# key: for
+# group : control structure
+# --
+for ${var} in ${collection}:
+ $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: from
+# key: from
+# group : general
+# --
+from ${1:lib} import ${2:funs}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: function
+# key: f
+# group: definitions
+# --
+def ${1:fun}(${2:args}):
+ $0
--- /dev/null
+# -*- mode: snippet -*-
+# name: function_docstring
+# key: fd
+# group: definitions
+# NOTE: Use minimum indentation, because Emacs 25+ doesn't dedent docstrings.
+# --
+def ${1:name}($2):
+ \"\"\"$3
+ ${2:$(python-args-to-docstring)}
+ \"\"\"
+ $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# contributor: Egor Panfilov <egor.v.panfilov[at]gmail[dot]com>
+# name: function_docstring_numpy
+# key: fdn
+# group: definitions
+# --
+def ${1:name}($2):
+ \"\"\"$3
+ ${2:$(python-args-to-docstring-numpy)}
+ \"\"\"
+ $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: if
+# key: if
+# group : control structure
+# --
+if ${1:cond}:
+ $0
--- /dev/null
+# -*- mode: snippet -*-
+# name: ife
+# key: ife
+# group : control structure
+# --
+if $1:
+ $2
+else:
+ $0
--- /dev/null
+# -*- mode: snippet -*-
+# name: ifmain
+# key: ifm
+# --
+if __name__ == '__main__':
+ ${1:main()}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: import
+# key: imp
+# group : general
+# --
+import ${1:lib}${2: as ${3:alias}}
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: init
+# key: init
+# group : definitions
+# --
+def __init__(self${1:, args}):
+ ${2:"${3:docstring}"
+ }$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: init_docstring
+# key: id
+# group : definitions
+# --
+def __init__(self$1):
+ \"\"\"$2
+ ${1:$(python-args-to-docstring)}
+ \"\"\"
+ $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: interact
+# key: int
+# --
+import code; code.interact(local=locals())
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet; require-final-newline: nil -*-
+# name: ipdb trace
+# key: itr
+# group: debug
+# --
+import ipdb; ipdb.set_trace()
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: __iter__
+# key: iter
+# group: dunder methods
+# --
+def __iter__(self):
+ return ${1:iter($2)}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: lambda
+# key: lam
+# --
+lambda ${1:x}: $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: list
+# key: li
+# group : definitions
+# --
+[${1:el} for $1 in ${2:list}]
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: logger_name
+# key: ln
+# --
+logger = logging.getLogger(${1:__name__})
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: logging
+# key: log
+# --
+logger = logging.getLogger("${1:name}")
+logger.setLevel(logging.${2:level})
--- /dev/null
+# -*- mode: snippet -*-
+# name: main
+# key: main
+# --
+def main():
+ $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: metaclass
+# key: mt
+# group: object oriented
+# --
+__metaclass__ = type
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: method
+# key: m
+# group: object oriented
+# --
+def ${1:method}(self${2:, $3}):
+ $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: method_docstring
+# key: md
+# group: object oriented
+# --
+def ${1:name}(self$2):
+ \"\"\"$3
+ ${2:$(python-args-to-docstring)}
+ \"\"\"
+ $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: not_impl
+# key: not_impl
+# --
+raise NotImplementedError
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: np
+# key: np
+# group : general
+# --
+import numpy as np
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: parse_args
+# key: pargs
+# group: argparser
+# --
+def parse_arguments():
+ parser = argparse.ArgumentParser(description='$1')
+ $0
+ return parser.parse_args()
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: parser
+# key: pars
+# group: argparser
+# --
+parser = argparse.ArgumentParser(description='$1')
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: pass
+# key: ps
+# --
+pass
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: Import pyplot
+# key: plt
+# group : general
+# --
+import matplotlib.pyplot as plt
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: print
+# key: p
+# --
+print($0)
\ No newline at end of file
--- /dev/null
+# contributor: Mads D. Kristensen <madsdkNOSPAMgmail.com>
+# name: prop
+# --
+def ${1:foo}():
+ doc = """${2:Doc string}"""
+ def fget(self):
+ return self._$1
+
+ def fset(self, value):
+ self._$1 = value
+
+ def fdel(self):
+ del self._$1
+ return locals()
+$1 = property(**$1())
+
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: reg
+# key: reg
+# group : general
+# --
+${1:regexp} = re.compile(r"${2:expr}")
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: __repr__
+# key: repr
+# group: dunder methods
+# --
+def __repr__(self):
+ $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: return
+# key: r
+# --
+return $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: subclass
+# key: scls
+# group: object oriented
+# --
+class ${1:class}(${2:super-class}):
+ $0
--- /dev/null
+# -*- mode: snippet -*-
+# name: script
+# key: script
+# --
+#!/usr/bin/env python
+
+def main():
+ pass
+
+if __name__ == '__main__':
+ main()
--- /dev/null
+# -*- mode: snippet -*-
+# name: self
+# key: .
+# group: object oriented
+# --
+self.$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: self_without_dot
+# key: s
+# group: object oriented
+# --
+self
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: selfassign
+# key: sn
+# group: object oriented
+# --
+self.$1 = $1
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: setdef
+# key: setdef
+# --
+${1:var}.setdefault(${2:key}, []).append(${3:value})
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: setup
+# key: setup
+# group: distribute
+# --
+from setuptools import setup
+
+package = '${1:name}'
+version = '${2:0.1}'
+
+setup(name=package,
+ version=version,
+ description="${3:description}",
+ url='${4:url}'$0)
--- /dev/null
+# -*- mode: snippet -*-
+# name: size
+# key: size
+# --
+sys.getsizeof($0)
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: static
+# key: sm
+# --
+@staticmethod
+def ${1:func}($0):
--- /dev/null
+# -*- mode: snippet -*-
+# name: __str__
+# key: str
+# group: dunder methods
+# --
+def __str__(self):
+ $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: super
+# key: super
+# group: object oriented
+# --
+super(`(replace-regexp-in-string "\\([.]\\)[^.]+$" ", self)." (python-info-current-defun) nil nil 1)`($1)
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: test_class
+# key: tcs
+# group : testing
+# --
+class Test${1:toTest}(${2:unittest.TestCase}):
+ $0
--- /dev/null
+# -*- mode: snippet -*-
+# name: test_file
+# key: tf
+# group : testing
+# --
+import unittest
+${1:from ${2:test_file} import *}
+
+$0
+
+if __name__ == '__main__':
+ unittest.main()
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: trace
+# key: tr
+# group: debug
+# --
+import pdb; pdb.set_trace()
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: try
+# key: try
+# --
+try:
+ $1
+except ${2:Exception}:
+ $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: tryelse
+# key: try
+# --
+try:
+ $1
+except $2:
+ $3
+else:
+ $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: __unicode__
+# key: un
+# group: dunder methods
+# --
+def __unicode__(self):
+ $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: unicode_literals
+# key: fu
+# group: future
+# --
+from __future__ import unicode_literals
--- /dev/null
+# -*- mode: snippet -*-
+# name: utf-8 encoding
+# key: utf8
+# --
+# -*- coding: utf-8 -*-
--- /dev/null
+# -*- mode: snippet -*-
+# name: while
+# key: wh
+# group: control structure
+# --
+while ${1:True}:
+ $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: with
+# key: with
+# group : control structure
+# --
+with ${1:expr}${2: as ${3:alias}}:
+ $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: with_statement
+# key: fw
+# group: future
+# --
+from __future__ import with_statement
\ No newline at end of file
--- /dev/null
+#!/usr/bin/env python
+import os
+import re
+from os.path import join
+from shutil import move
+
+
+def rename(root, f):
+ if f.endswith('.yasnippet'):
+ base, _ = f.split('.')
+ print("move %s to %s" % (join(root, f), join(root, base)))
+ move(join(root, f), join(root, base))
+
+
+CONT = "# contributor: Andrea crotti\n# --"
+END = "# --\n\n"
+
+orig = "# --\n\n"
+to = "# --\n"
+
+def insert(root, f, orig, to):
+ fname = join(root, f)
+ text = open(fname).read()
+ nex_text = re.sub(orig, to, text)
+ open(fname, 'w').write(nex_text)
+
+if __name__ == '__main__':
+ for root, dirs, files in os.walk('.'):
+ if "mode" in root:
+ # os.popen("git add *yasnippet")
+ for f in files:
+ rename(root, f)
+ # insert(root, f, orig, to)
+
+
+
--- /dev/null
+# -*- mode: snippet -*-
+# name: autoclass
+# key: auto
+# --
+.. autoclass:: $0
+ ${1::members: ${2:members}}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: autofunction
+# key: auto
+# --
+.. autofunction:: $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: automodule
+# key: auto
+# --
+.. automodule:: ${1:module_name}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name : Chapter title
+# key: chap
+# --
+${1:Chapter}
+${1:$(make-string (string-width yas-text) ?\=)}
+
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: class
+# key: cls
+# --
+:class:\`$0\`
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: code
+# key: code
+# --
+.. code:: ${1:python}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: digraph
+# key: graph
+# --
+.. digraph:: $1
+
+ $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: function
+# key: fun
+# --
+:function:\`$0\`
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: graph
+# key: graph
+# --
+.. graph:: $1
+
+ $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: graphviz
+# key: graph
+# --
+.. graphviz::
+
+ $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: image
+# key: img
+# --
+.. image:: ${1:path}
+ :height: ${2:100}
+ :width: ${3:200}
+ :alt: ${4:description}
+
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: inheritance
+# key: inh
+# --
+.. inheritance-diagram:: $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: literatal include
+# key: inc
+# --
+.. literalinclude:: ${1:path}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: meta
+# key: :
+# --
+:${1:var}: $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: module
+# key: mod
+# --
+:mod: \`$0\`
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: parsed_literal
+# key: src
+# --
+.. parsed-literal::
+ $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: pause
+# key: pause
+# group: hieroglyph
+# --
+.. rst-class:: build
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name : Section title
+# key: sec
+# --
+${1:Section}
+${1:$(make-string (string-width yas-text) ?\-)}
+
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: term
+# key: term
+# --
+:term:\`$0\`
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name : Document title
+# key: tit
+# --
+${1:$(make-string (string-width yas-text) ?\=)}
+${1:Title}
+${1:$(make-string (string-width yas-text) ?\=)}
+
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: url
+# key: url
+# --
+.. _${1:description}: $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: verbatim
+# key: |
+# --
+| $0
+|
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: warning
+# key: warn
+# --
+.. warning:
+ $0
\ No newline at end of file
--- /dev/null
+#name : # =>
+#group : general
+# --
+# =>
\ No newline at end of file
--- /dev/null
+#name : =begin rdoc ... =end
+#group : general
+# --
+=begin rdoc
+ $0
+=end
\ No newline at end of file
--- /dev/null
+#name : include Comparable; def <=> ... end
+#group : definitions
+# --
+include Comparable
+
+def <=> other
+ $0
+end
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: include Enumerable
+# key: Enum
+# group: collections
+# --
+include Enumerable
+
+def each${1:(&block)}
+ $0
+end
--- /dev/null
+# -*- mode: snippet -*-
+# name: GLOB
+# key: $
+# --
+$${1:GLOBAL} = $0
\ No newline at end of file
--- /dev/null
+#name : all? { |...| ... }
+#group : collections
+# --
+all? { |${e}| $0 }
\ No newline at end of file
--- /dev/null
+#name : alias_method new, old
+#group : definitions
+# --
+alias_method :${new_name}, :${old_name}
\ No newline at end of file
--- /dev/null
+#name : any? { |...| ... }
+#group : collections
+# --
+any? { |${e}| $0 }
\ No newline at end of file
--- /dev/null
+#name : if __FILE__ == $PROGRAM_NAME ... end
+#group : general
+# --
+if __FILE__ == $PROGRAM_NAME
+ $0
+end
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: attribute
+# key: @
+# --
+@${1:attr} = $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: bench
+# key: bench
+# --
+require "benchmark"
+
+TESTS = ${1:1_000}
+Benchmark.bmbm do |x|
+ x.report("${2:var}") {}
+end
--- /dev/null
+#name : Benchmark.bmbm(...) do ... end
+#group : general
+# --
+Benchmark.bmbm(${1:10}) do |x|
+ $0
+end
\ No newline at end of file
--- /dev/null
+#name : case ... end
+#group : general
+# --
+case ${1:object}
+when ${2:condition}
+ $0
+end
\ No newline at end of file
--- /dev/null
+#name : class << self ... end
+#group : definitions
+# --
+class << ${self}
+ $0
+end
\ No newline at end of file
--- /dev/null
+#name : class ... end
+#contributor : hitesh <hitesh.jasaniNOSPAMgmail.com>
+#group : definitions
+# --
+class ${1:`(let ((fn (capitalize (file-name-nondirectory
+ (file-name-sans-extension
+ (or (buffer-file-name)
+ (buffer-name (current-buffer))))))))
+ (replace-regexp-in-string "_" "" fn t t))`}
+ $0
+end
--- /dev/null
+#name : collect { |...| ... }
+#group : collections
+# --
+collect { |${e}| $0 }
\ No newline at end of file
--- /dev/null
+#name : deep_copy(...)
+#group : general
+# --
+Marshal.load(Marshal.dump($0))
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: def ... end
+# key: def
+# --
+def ${1:method}${2:(${3:args})}
+ $0
+end
\ No newline at end of file
--- /dev/null
+#name : delete_if { |...| ... }
+#group : collections
+# --
+delete_if { |${e}| $0 }
\ No newline at end of file
--- /dev/null
+#name : detect { |...| ... }
+#group : collections
+# --
+detect { |${e}| $0 }
\ No newline at end of file
--- /dev/null
+#name : downto(...) { |n| ... }
+#group : control structure
+# --
+downto(${0}) { |${n}|
+ $0
+}
\ No newline at end of file
--- /dev/null
+#name : each { |...| ... }
+#group : collections
+# --
+each { |${e}| $0 }
\ No newline at end of file
--- /dev/null
+#name : each_cons(...) { |...| ... }
+#group : collections
+# --
+each_cons(${1:2}) { |${group}| $0 }
\ No newline at end of file
--- /dev/null
+#name : each_index { |i| ... }
+#group : collections
+# --
+each_index { |${i}| $0 }
\ No newline at end of file
--- /dev/null
+#name : each_value { |val| ... }
+#group : collections
+# --
+each_value { |${val}| $0 }
\ No newline at end of file
--- /dev/null
+#name : each_with_index { |e, i| ... }
+#group : collections
+# --
+each_with_index { |${e}, ${i}| $0 }
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: for
+# key: for
+# --
+for ${1:el} in ${2:collection}
+ $0
+end
\ No newline at end of file
--- /dev/null
+#name : for ... in ...; ... end
+#group : control structure
+# --
+for ${1:element} in ${2:collection}
+ $0
+end
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: formula
+# key: form
+# --
+require 'formula'
+
+class ${1:Name} <Formula
+ url '${2:url}'
+ homepage '${3:home}'
+ md5 '${4:md5}'
+
+ def install
+ ${5:system "./configure"}
+ $0
+ end
+end
--- /dev/null
+#name : if ... end
+#group : control structure
+# --
+if ${1:condition}
+ $0
+end
\ No newline at end of file
--- /dev/null
+#name : if ... else ... end
+#group : control structure
+# --
+if ${1:condition}
+ $2
+else
+ $3
+end
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: include Module
+# key: inc
+# group: general
+# --
+include ${1:Module}
+$0
--- /dev/null
+# -*- mode: snippet -*-
+# name: init
+# key: init
+# --
+def initialize(${1:args})
+ $0
+end
\ No newline at end of file
--- /dev/null
+#name : inject(...) { |...| ... }
+#group : collections
+# --
+inject(${1:0}) { |${2:injection}, ${3:element}| $0 }
\ No newline at end of file
--- /dev/null
+#name : map { |...| ... }
+#group : collections
+# --
+map { |${e}| $0 }
\ No newline at end of file
--- /dev/null
+#name : def method_missing ... end
+#group : definitions
+# --
+def method_missing(method, *args)
+ $0
+end
\ No newline at end of file
--- /dev/null
+# name: module ... end
+# contributor: hitesh <hitesh.jasaniNOSPAMgmail.com>, jimeh <contactNOSPAMjimeh.me>
+# key: mod
+# --
+module ${1:`(let ((fn (capitalize (file-name-nondirectory
+ (file-name-sans-extension
+ (or (buffer-file-name)
+ (buffer-name (current-buffer))))))))
+ (while (string-match "_" fn)
+ (setq fn (replace-match "" nil nil fn)))
+ fn)`}
+ $0
+end
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: binding.pry
+# key: pry
+# --
+require 'pry'; binding.pry
--- /dev/null
+#name : attr_reader ...
+#group : definitions
+# --
+attr_reader :
\ No newline at end of file
--- /dev/null
+#name : /usr/bin/ruby -wU
+#group : general
+# --
+#!/usr/bin/ruby -wU
--- /dev/null
+#name : reduce(...) { |...| ... }
+#group : collections
+# --
+reduce(${1:0}) { |${2:accumulator}, ${3:element}| $0 }
--- /dev/null
+#name : reject { |...| ... }
+#group : collections
+# --
+reject { |${1:element}| $0 }
\ No newline at end of file
--- /dev/null
+#name : require_relative
+#group : general
+# --
+require_relative '$0'
\ No newline at end of file
--- /dev/null
+#name : require "..."
+#group : general
+# --
+require '$0'
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: binding.pry_remote
+# key: rpry
+# --
+require 'pry-remote'; binding.remote_pry
\ No newline at end of file
--- /dev/null
+#name : attr_accessor ...
+#group : definitions
+# --
+attr_accessor :
\ No newline at end of file
--- /dev/null
+#name : select { |...| ... }
+#group : collections
+# --
+select { |${1:element}| $0 }
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: str
+# key: s
+# --
+#{$0}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: test class
+# key: tc
+# --
+class TC_${1:Class} < Test::Unit::TestCase
+ $0
+end
\ No newline at end of file
--- /dev/null
+#name : times { |n| ... }
+#group : control structure
+# --
+times { |${n}| $0 }
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: to_
+# key: to_
+# --
+def to_s
+ "${1:string}"
+end
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: tu
+# key: tu
+# --
+require 'test/unit'
\ No newline at end of file
--- /dev/null
+#name : until ... end
+#group: control structure
+# --
+until ${condition}
+ $0
+end
\ No newline at end of file
--- /dev/null
+#name : upto(...) { |n| ... }
+#group : control structure
+# --
+upto(${n}) { |${i}|
+ $0
+}
\ No newline at end of file
--- /dev/null
+#name : attr_writer ...
+#group : definitions
+# --
+attr_writer :
\ No newline at end of file
--- /dev/null
+#name : when ... end
+#group : control structure
+# --
+when ${condition}
+ $0
+end
\ No newline at end of file
--- /dev/null
+#name : while ... end
+#group : control structure
+# --
+while ${condition}
+ $0
+end
\ No newline at end of file
--- /dev/null
+#name : :yields: arguments (rdoc)
+#group : general
+# --
+:yields: $0
\ No newline at end of file
--- /dev/null
+#name : zip(...) { |...| ... }
+#group : collections
+# --
+zip(${enums}) { |${row}| $0 }
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: #[allow(lint)]
+# key: allow
+# --
+#[allow(${1:lint})]
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: #![allow(lint)]
+# key: allow!
+# --
+#![allow(${1:lint})]
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: assert!(predicate);
+# key: ass
+# --
+assert!(${1:predicate});
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: assert_eq!(expected, actual);
+# key: asseq
+# --
+assert_eq!(${1:expected}, ${2:actual});
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: pattern => expression,
+# key: case
+# --
+${1:pattern} => ${2:expression},
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: #[cfg(option)]
+# key: cfg
+# --
+#[cfg(${1:option})]
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: #[cfg(option = "value")]
+# key: cfg=
+# --
+#[cfg(${1:option} = "${2:value}")]
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: closure
+# key: ||
+# --
+|${1:arguments}| {
+ $0
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: #[deny(lint)]
+# key: deny
+# --
+#[deny(${1:lint})]
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: #![deny(lint)]
+# key: deny!
+# --
+#![deny(${1:lint})]
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: #[derive(Trait)]
+# key: derive
+# --
+#[derive(${1:Trait})]
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: impl Drop for Type { fn drop(...) }
+# key: drop
+# --
+impl Drop for ${1:Type} {
+ fn drop(&mut self) {
+ $0
+ }
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: enum Type { ... }
+# key: enum
+# --
+enum ${1:Type} {
+ $0
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: fn name() { ... }
+# key: fn
+# --
+fn ${1:name}($2) {
+ $0
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: fn name() -> Type { ... }
+# key: fnr
+# --
+fn ${1:name}($2) -> ${3:Type} {
+ $0
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: fn name(&self) -> Type;
+# key: fns
+# --
+fn ${1:name}(${2:&self}) -> ${3:Type};
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: fn name<T>(x: T) where T: Clone { ... }
+# key: fnw
+# --
+fn ${1:name}<${2:T}>(${3:x: T}) where ${4:T: Clone} {
+ $0
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: for var in iterable { ... }
+# key: for
+# --
+for ${1:var} in ${2:iterable} {
+ $0
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: if expr { ... }
+# key: if
+# --
+if ${1:expression} {
+ $0
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: if expression { ... } else { .. }
+# key: ife
+# --
+if ${1:expression} {
+ $0
+} else {
+
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: if let pattern = expression { ... };
+# key: ifl
+# --
+if let ${1:pattern} = ${2:expression} { $0 };
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: impl Type { ... }
+# key: impl
+# --
+impl ${1:Type} {
+ $0
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: impl Trait for Type { ... }
+# key: implt
+# --
+impl ${1:Trait} for ${2:Type} {
+ $0
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: let pattern = expression;
+# key: let
+# --
+let ${1:pattern} = ${2:expression};
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: let mut pattern = expression;
+# key: letm
+# --
+let mut ${1:pattern} = ${2:expression};
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: let pattern: type = expression;
+# key: lett
+# --
+let ${1:pattern}: ${2:type} = ${3:expression};
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: let mut pattern: type = expression;
+# key: lettm
+# --
+let mut ${1:pattern}: ${2:type} = ${3:expression};
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: loop { ... }
+# key: loop
+# --
+loop {
+ $0
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: macro_rules! name { (..) => (..); }
+# key: macro
+# --
+macro_rules! ${1:name} {
+ ($2) => ($3);
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: fn main() { ... }
+# key: main
+# --
+fn main() {
+ $0
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: match expression { ... }
+# key: match
+# --
+match ${1:expression} {
+ $0
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: print!("{}", value);
+# key: print
+# --
+print!("${1:{}}", $2);
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: println!("{}", value);
+# key: println
+# --
+println!("${1:{}}", $2);
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: spawn(proc() { ... });
+# key: spawn
+# --
+spawn(proc() {
+ $0
+});
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: CONSTANT: Type = value;
+# key: static
+# --
+static ${1:CONSTANT}: ${2:Type} = ${3:value};
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: struct TypeName { .. }
+# key: struct
+# --
+struct ${1:TypeName} {
+ $0
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: #[test] fn test_name() { .. }
+# key: test
+# --
+#[test]
+fn ${1:test_name}() {
+ $0
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: test module
+# key: testmod
+# --
+#[cfg(test)]
+mod ${1:tests} {
+ use super::*;
+
+ #[test]
+ fn ${2:test_name}() {
+ $0
+ }
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: trait Type { ... }
+# key: trait
+# --
+trait ${1:Type} {
+ $0
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: type TypeName = TypeName;
+# key: type
+# --
+type ${1:TypeName} = ${2:TypeName};
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: union Type { ... }
+# key: union
+# --
+union ${1:Type} {
+ $0
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: #[warn(lint)]
+# key: warn
+# --
+#[warn(${1:lint})]
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: #![warn(lint)]
+# key: warn!
+# --
+#![warn(${1:lint})]
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: while expression { ... }
+# key: while
+# --
+while ${1:expression} {
+ $0
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: while let pattern = expression { ... }
+# key: whilel
+# --
+while let ${1:pattern} = ${2:expression} {
+ $0
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+#Author : Anders Bach Nielsen <andersbach.nielsenNOSPAMepfl.ch>
+#name : object name extends App
+# key: app
+# --
+object ${1:name} extends App {
+ $0
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+#Author : Jonas Bonèr <jonasNOSPAMjonasboner.com>
+#name : case pattern =>
+# key: case
+# --
+case ${1:_} => $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+#Author : Sam Halliday
+#name : case class T(arg: A)
+# key: cc
+# --
+case class ${1:Name}(
+ ${2:arg}: ${3:Type}
+)
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+#Author : Jonas Bonèr <jonasNOSPAMjonasboner.com>
+#name : case object T
+# key: co
+# --
+case object ${1:name} $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+#Author : Jonas Bonèr <jonasNOSPAMjonasboner.com>
+#name : element1 :: element2
+# key: cons
+# --
+${1:element1} :: ${2:element2} $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+#Author : Jonas Bonèr <jonasNOSPAMjonasboner.com>
+#name : def f(arg: T): R = {...}
+# key: def
+# --
+def ${1:name}(${2:args}): ${3:Unit} = {
+ $0
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+#Author : Anders Bach Nielsen <andersbach.nielsenNOSPAMepfl.ch>
+#name : /** ... */
+# key: doc
+# --
+/**
+ * ${1:description}
+ * $0
+ */
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+#Author : Sam Halliday
+#name : for { x <- xs } yield
+#key: for
+# --
+for {
+ ${1:x} <- ${2:xs}
+} yield ${3:x}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+#Author : Jonas Bonèr <jonasNOSPAMjonasboner.com>
+#name : if (cond) { .. }
+# key: if
+# --
+if (${1:condition}) {
+ $0
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+#Author : Jonas Bonèr <jonasNOSPAMjonasboner.com>
+#name : List(..)
+# key: ls
+# --
+List(${1:args}, ${2:args}) $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+#Author : Jonas Bonèr <jonasNOSPAMjonasboner.com>
+#name: def main(args: Array[String]) = { ... }
+# key: main
+# --
+def main(args: Array[String]) = {
+ $0
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+#Author : Jonas Bonèr <jonasNOSPAMjonasboner.com>
+#name : cc match { .. }
+# key: match
+# --
+${1:cc} match {
+ case ${2:pattern} => $0
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+#Author : Jonas Bonèr <jonasNOSPAMjonasboner.com>
+#name : object name extends T
+# key: ob
+# --
+object ${1:name} extends ${2:type} $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+#Author : Jonas Bonèr <jonasNOSPAMjonasboner.com>
+#name : throw new Exception
+# key: throw
+# --
+throw new ${1:Exception}(${2:msg}) $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+#Author : Sam Halliday
+#name : try { .. } catch { case e => ..}
+# key: try
+# --
+try {
+ $0
+} catch {
+ case e: ${1:Throwable} =>
+ ${2:// TODO: handle exception}
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# Author: Michael Pollmeier
+# name: value class
+# key: vc
+# --
+case class ${1:Name}(value: ${2:Type}) extends AnyVal
--- /dev/null
+# -*- mode: snippet -*-
+# name:args
+# key: args
+# --
+if [ $# -lt ${1:2} ]
+ then $0
+fi
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: bang
+# key: !
+# --
+#!/usr/bin/env bash
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: for loop
+# key: for
+# --
+for ${1:var} in ${2:stuff}; do
+ $0
+done
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: function
+# key: f
+# --
+function ${1:name} {
+ $0
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: if
+# key: if
+# --
+if ${1:[ -f file]}
+ then ${2:do}
+fi
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: ife
+# key: ife
+# --
+if ${1:cond}
+then ${2:stuff}
+else ${3:other}
+fi
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: safer bash settings for scripts
+# key: s!
+# --
+#!/usr/bin/env bash
+set -euo pipefail
+IFS=$'\n\t'
+
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: while loop
+# key: while
+# --
+while ${1:cond}; do
+ $0
+done
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: cont
+# key: cont
+# --
+# contributor: `user-full-name`
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: elisp
+# key: `
+# --
+\`$0\`
\ No newline at end of file
--- /dev/null
+# name : ${ ... } field
+# contributor : joaotavora
+# key : $f
+# key: field
+# --
+\${${1:${2:n}:}$3${4:\$(${5:lisp-fn})}\}$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: group
+# key: group
+# --
+# group : ${1:group}
\ No newline at end of file
--- /dev/null
+# name : ${n:$(...)} mirror
+# key : $m
+# contributor : joaotavora
+# key: mirror
+# --
+\${${2:n}:${4:\$(${5:reflection-fn})}\}$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name : Snippet header
+# contributor : joaotavora
+# key: vars
+# --
+# name : $1${2:
+# key : ${3:trigger-key}}${4:
+# keybinding : ${5:keybinding}}${6:
+# expand-env : (${7:})}
+# contributor : $6
+# key: vars
+# --
+$0
\ No newline at end of file
--- /dev/null
+#contributor : Alejandro Espinoza Esparza <aespinozaNOSPAMstructum.com.mx>
+#name : , ColumnName ColumnType NOT NULL...
+# --
+ , ${1:Name} ${2:Type} ${3:NOT NULL}
--- /dev/null
+#contributor : Alejandro Espinoza Esparza <aespinozaNOSPAMstructum.com.mx>
+#name : CONSTRAINT [..] PRIMARY KEY ...
+# --
+CONSTRAINT [${1:PK_Name}] PRIMARY KEY ${2:CLUSTERED} ([${3:ColumnName}])
--- /dev/null
+#contributor : Alejandro Espinoza Esparza <aespinozaNOSPAMstructum.com.mx>
+#name : CONSTRAINT [..] FOREIGN KEY ...
+# --
+CONSTRAINT [${1:FK_Name}] FOREIGN KEY ${2:CLUSTERED} ([${3:ColumnName}])
--- /dev/null
+#contributor : Alejandro Espinoza Esparza <aespinozaNOSPAMstructum.com.mx>
+#name : create table ...
+# --
+CREATE TABLE [${1:dbo}].[${2:TableName}]
+(
+ ${3:Id} ${4:INT IDENTITY(1,1)} ${5:NOT NULL}
+$0
+ CONSTRAINT [${6:PK_}] PRIMARY KEY ${7:CLUSTERED} ([$3])
+)
+GO
--- /dev/null
+#contributor : Alejandro Espinoza Esparza <aespinozaNOSPAMstructum.com.mx>
+#name : create procedure ...
+# --
+CREATE PROCEDURE [${1:dbo}].[${2:Name}]
+(
+ $3 $4 = ${5:NULL} ${6:OUTPUT}
+)
+AS
+BEGIN
+$0
+END
+GO
--- /dev/null
+# -*- mode: snippet; -*-
+# name: insert
+# key: ins
+# --
+INSERT INTO ${table-name} (${col1, col2}) VALUES (${'val1', 'val2'});$0
\ No newline at end of file
--- /dev/null
+#contributor : Alejandro Espinoza Esparza <aespinozaNOSPAMstructum.com.mx>
+#name : REFERENCES ...
+# --
+REFERENCES ${1:TableName}([${2:ColumnName}])
--- /dev/null
+# -*- mode: snippet -*-
+# name: resource
+# key: res
+# --
+resource "${1:name}" {
+ $0
+}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: variable
+# key: var
+# --
+variable "${1:name}" {
+ ${2:default = "$3"}
+}
\ No newline at end of file
--- /dev/null
+fundamental-mode
--- /dev/null
+# -*- mode: snippet -*-
+# name: assert
+# key: as
+# --
+assert $0;;
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: docstring
+# key: d
+# --
+(* $0 *)
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: for
+# key: for
+# --
+for ${1:cond} do
+ $0
+done
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: fun
+# key: fun
+# --
+fun ${1:args} -> $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: guard
+# key: |
+# --
+| ${1:match} -> $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: ifthen
+# key: if
+# --
+if ${1:cond} then
+ $0
--- /dev/null
+# -*- mode: snippet -*-
+# name: ifthenelse
+# key: if
+# --
+if ${1:cond} then
+ $2
+else
+ $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: let
+# key: let
+# --
+let ${1:var} $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: list_comprehension
+# key: l
+# --
+[? $1 | $0 ?]
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: main
+# key: m
+# --
+let main =
+ $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: match
+# key: match
+# --
+match ${1:to_match} with
+ | ${2:matching} -> $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: module
+# key: mod
+# --
+module ${1:A} =
+ struct
+ ${2:type t = { name : string; phone : string }}
+ $0
+end;;
--- /dev/null
+# -*- mode: snippet -*-
+# name: open
+# key: op
+# --
+open ${1:Module}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: printf
+# key: pr
+# --
+Printf.printf "${1:string}" ${2:vals};;
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: rec
+# key: rec
+# --
+let rec ${1:fun} ${2:args} =
+ $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: try
+# key: try
+# --
+try
+ $0
+with
+ $1
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: type_record
+# key: type
+# --
+type ${1:name} = {${2:var}: ${3:int}$0}
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: type_type
+# key: type
+# --
+type ${1:expr} =
+ | $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: val
+# key: val
+# --
+val ${1:fun} : $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: while
+# key: wh
+# --
+while ${1:cond} do
+ $0
+done
\ No newline at end of file
--- /dev/null
+tuareg-mode
--- /dev/null
+# -*- mode: snippet -*-
+# name: ENV
+# key: env
+# --
+ENV{$1}$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: GOTO
+# key: goto
+# --
+GOTO="$1"
+$0
+
+LABEL="$1"
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: KERNEL
+# key: ker
+# --
+KERNEL!="$0"
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: add
+# key: add
+# --
+ACTION=="add", $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: env$
+# key: $
+# --
+$env{$1} $0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: run
+# key: run
+# --
+RUN+="$0"
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: entry
+# key: entry
+# --
+${1:entry}: ${2:value}
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: list
+# key: list
+# --
+[$1]
+$0
\ No newline at end of file
--- /dev/null
+# -*- mode: snippet -*-
+# name: section
+# key: --
+# --
+--- # ${1:section}
+$0
\ No newline at end of file
--- /dev/null
+;;; yasnippet-autoloads.el --- automatically extracted autoloads
+;;
+;;; Code:
+(add-to-list 'load-path (directory-file-name (or (file-name-directory #$) (car load-path))))
+\f
+;;;### (autoloads nil "yasnippet" "yasnippet.el" (23123 18368 884536
+;;;;;; 797000))
+;;; Generated autoloads from yasnippet.el
+
+(autoload 'yas-minor-mode "yasnippet" "\
+Toggle YASnippet mode.
+
+When YASnippet mode is enabled, `yas-expand', normally bound to
+the TAB key, expands snippets of code depending on the major
+mode.
+
+With no argument, this command toggles the mode.
+positive prefix argument turns on the mode.
+Negative prefix argument turns off the mode.
+
+Key bindings:
+\\{yas-minor-mode-map}
+
+\(fn &optional ARG)" t nil)
+
+(defvar yas-global-mode nil "\
+Non-nil if Yas-Global mode is enabled.
+See the `yas-global-mode' command
+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 `yas-global-mode'.")
+
+(custom-autoload 'yas-global-mode "yasnippet" nil)
+
+(autoload 'yas-global-mode "yasnippet" "\
+Toggle Yas minor mode in all buffers.
+With prefix ARG, enable Yas-Global mode if ARG is positive;
+otherwise, disable it. If called from Lisp, enable the mode if
+ARG is omitted or nil.
+
+Yas minor mode is enabled in all buffers where
+`yas-minor-mode-on' would do it.
+See `yas-minor-mode' for more information on Yas minor mode.
+
+\(fn &optional ARG)" t nil)
+
+(autoload 'snippet-mode "yasnippet" "\
+A mode for editing yasnippets
+
+\(fn)" t nil)
+
+;;;***
+\f
+;;;### (autoloads nil nil ("yasnippet-pkg.el") (23123 18366 841773
+;;;;;; 375000))
+
+;;;***
+\f
+;; Local Variables:
+;; version-control: never
+;; no-byte-compile: t
+;; no-update-autoloads: t
+;; End:
+;;; yasnippet-autoloads.el ends here
--- /dev/null
+(define-package "yasnippet" "20180102.1824" "Yet another snippet extension for Emacs."
+ '((cl-lib "0.5"))
+ :url "http://github.com/joaotavora/yasnippet" :keywords
+ '("convenience" "emulation"))
+;; Local Variables:
+;; no-byte-compile: t
+;; End:
--- /dev/null
+;;; yasnippet.el --- Yet another snippet extension for Emacs.
+
+;; Copyright (C) 2008-2017 Free Software Foundation, Inc.
+;; Authors: pluskid <pluskid@gmail.com>,
+;; João Távora <joaotavoraNOSPAMgmail.com>,
+;; Noam Postavsky <npostavsNOSPAMgmail.com>
+;; Maintainer: Noam Postavsky <npostavsNOSPAMgmail.com>
+;; Version: 0.12.2
+;; X-URL: http://github.com/joaotavora/yasnippet
+;; Keywords: convenience, emulation
+;; URL: http://github.com/joaotavora/yasnippet
+;; Package-Requires: ((cl-lib "0.5"))
+;; EmacsWiki: YaSnippetMode
+
+;; 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:
+;;
+;; Basic steps to setup:
+;;
+;; (add-to-list 'load-path
+;; "~/path-to-yasnippet")
+;; (require 'yasnippet)
+;; (yas-global-mode 1)
+;;
+;;
+;; Interesting variables are:
+;;
+;; `yas-snippet-dirs'
+;;
+;; The directory where user-created snippets are to be
+;; stored. Can also be a list of directories. In that case,
+;; when used for bulk (re)loading of snippets (at startup or
+;; via `yas-reload-all'), directories appearing earlier in
+;; the list override other dir's snippets. Also, the first
+;; directory is taken as the default for storing the user's
+;; new snippets.
+;;
+;; The deprecated `yas/root-directory' aliases this variable
+;; for backward-compatibility.
+;;
+;;
+;; Major commands are:
+;;
+;; M-x yas-expand
+;;
+;; Try to expand snippets before point. In `yas-minor-mode',
+;; this is normally bound to TAB, but you can customize it in
+;; `yas-minor-mode-map'.
+;;
+;; M-x yas-load-directory
+;;
+;; Prompts you for a directory hierarchy of snippets to load.
+;;
+;; M-x yas-activate-extra-mode
+;;
+;; Prompts you for an extra mode to add snippets for in the
+;; current buffer.
+;;
+;; M-x yas-insert-snippet
+;;
+;; Prompts you for possible snippet expansion if that is
+;; possible according to buffer-local and snippet-local
+;; expansion conditions. With prefix argument, ignore these
+;; conditions.
+;;
+;; M-x yas-visit-snippet-file
+;;
+;; Prompts you for possible snippet expansions like
+;; `yas-insert-snippet', but instead of expanding it, takes
+;; you directly to the snippet definition's file, if it
+;; exists.
+;;
+;; M-x yas-new-snippet
+;;
+;; Lets you create a new snippet file in the correct
+;; subdirectory of `yas-snippet-dirs', according to the
+;; active major mode.
+;;
+;; M-x yas-load-snippet-buffer
+;;
+;; When editing a snippet, this loads the snippet. This is
+;; bound to "C-c C-c" while in the `snippet-mode' editing
+;; mode.
+;;
+;; M-x yas-tryout-snippet
+;;
+;; When editing a snippet, this opens a new empty buffer,
+;; sets it to the appropriate major mode and inserts the
+;; snippet there, so you can see what it looks like. This is
+;; bound to "C-c C-t" while in `snippet-mode'.
+;;
+;; M-x yas-describe-tables
+;;
+;; Lists known snippets in a separate buffer. User is
+;; prompted as to whether only the currently active tables
+;; are to be displayed, or all the tables for all major
+;; modes.
+;;
+;; If you have `dropdown-list' installed, you can optionally use it
+;; as the preferred "prompting method", putting in your .emacs file,
+;; for example:
+;;
+;; (require 'dropdown-list)
+;; (setq yas-prompt-functions '(yas-dropdown-prompt
+;; yas-ido-prompt
+;; yas-completing-prompt))
+;;
+;; Also check out the customization group
+;;
+;; M-x customize-group RET yasnippet RET
+;;
+;; If you use the customization group to set variables
+;; `yas-snippet-dirs' or `yas-global-mode', make sure the path to
+;; "yasnippet.el" is present in the `load-path' *before* the
+;; `custom-set-variables' is executed in your .emacs file.
+;;
+;; For more information and detailed usage, refer to the project page:
+;; http://github.com/joaotavora/yasnippet
+
+;;; Code:
+
+(require 'cl-lib)
+(declare-function cl-progv-after "cl-extra") ; Needed for 23.4.
+(require 'easymenu)
+(require 'help-mode)
+
+(defvar yas--editing-template)
+(defvar yas--guessed-modes)
+(defvar yas--indent-original-column)
+(defvar yas--scheduled-jit-loads)
+(defvar yas-keymap)
+(defvar yas-selected-text)
+(defvar yas-verbosity)
+(defvar yas--current-template)
+
+\f
+;;; User customizable variables
+
+(defgroup yasnippet nil
+ "Yet Another Snippet extension"
+ :prefix "yas-"
+ :group 'editing)
+
+(defconst yas--loaddir
+ (file-name-directory (or load-file-name buffer-file-name))
+ "Directory that yasnippet was loaded from.")
+
+(defconst yas-installed-snippets-dir (expand-file-name "snippets" yas--loaddir))
+(make-obsolete-variable 'yas-installed-snippets-dir "\
+Yasnippet no longer comes with installed snippets" "0.13")
+
+(defconst yas--default-user-snippets-dir
+ (expand-file-name "snippets" user-emacs-directory))
+
+(defcustom yas-snippet-dirs (list yas--default-user-snippets-dir)
+ "List of top-level snippet directories.
+
+Each element, a string or a symbol whose value is a string,
+designates a top-level directory where per-mode snippet
+directories can be found.
+
+Elements appearing earlier in the list override later elements'
+snippets.
+
+The first directory is taken as the default for storing snippet's
+created with `yas-new-snippet'. "
+ :type '(choice (directory :tag "Single directory")
+ (repeat :tag "List of directories"
+ (choice (directory) (variable))))
+ :set #'(lambda (symbol new)
+ (let ((old (and (boundp symbol)
+ (symbol-value symbol))))
+ (set-default symbol new)
+ (unless (or (not (fboundp 'yas-reload-all))
+ (equal old new))
+ (yas-reload-all)))))
+
+(defun yas-snippet-dirs ()
+ "Return variable `yas-snippet-dirs' as list of strings."
+ (cl-loop for e in (if (listp yas-snippet-dirs)
+ yas-snippet-dirs
+ (list yas-snippet-dirs))
+ collect
+ (cond ((stringp e) e)
+ ((and (symbolp e)
+ (boundp e)
+ (stringp (symbol-value e)))
+ (symbol-value e))
+ (t
+ (error "[yas] invalid element %s in `yas-snippet-dirs'" e)))))
+
+(defcustom yas-new-snippet-default "\
+# -*- mode: snippet -*-
+# name: $1
+# key: ${2:${1:$(yas--key-from-desc yas-text)}}
+# --
+$0`(yas-escape-text yas-selected-text)`"
+ "Default snippet to use when creating a new snippet.
+If nil, don't use any snippet."
+ :type 'string)
+
+(defcustom yas-prompt-functions '(yas-dropdown-prompt
+ yas-completing-prompt
+ yas-maybe-ido-prompt
+ yas-no-prompt)
+ "Functions to prompt for keys, templates, etc interactively.
+
+These functions are called with the following arguments:
+
+- PROMPT: A string to prompt the user
+
+- CHOICES: a list of strings or objects.
+
+- optional DISPLAY-FN : A function that, when applied to each of
+the objects in CHOICES will return a string.
+
+The return value of any function you put here should be one of
+the objects in CHOICES, properly formatted with DISPLAY-FN (if
+that is passed).
+
+- To signal that your particular style of prompting is
+unavailable at the moment, you can also have the function return
+nil.
+
+- To signal that the user quit the prompting process, you can
+signal `quit' with
+
+ (signal \\='quit \"user quit!\")."
+ :type '(repeat function))
+
+(defcustom yas-indent-line 'auto
+ "Controls indenting applied to a recent snippet expansion.
+
+The following values are possible:
+
+- `fixed' Indent the snippet to the current column;
+
+- `auto' Indent each line of the snippet with `indent-according-to-mode'
+
+Every other value means don't apply any snippet-side indentation
+after expansion (the manual per-line \"$>\" indentation still
+applies)."
+ :type '(choice (const :tag "Nothing" nothing)
+ (const :tag "Fixed" fixed)
+ (const :tag "Auto" auto)))
+
+(defcustom yas-also-auto-indent-first-line nil
+ "Non-nil means also auto indent first line according to mode.
+
+Naturally this is only valid when `yas-indent-line' is `auto'."
+ :type 'boolean)
+
+(defcustom yas-also-indent-empty-lines nil
+ "Non-nil means also indent empty lines according to mode."
+ :type 'boolean)
+
+(defcustom yas-snippet-revival t
+ "Non-nil means re-activate snippet fields after undo/redo."
+ :type 'boolean)
+
+(defcustom yas-triggers-in-field nil
+ "If non-nil, allow stacked expansions (snippets inside snippets).
+
+Otherwise `yas-next-field-or-maybe-expand' just moves on to the
+next field"
+ :type 'boolean)
+
+(defcustom yas-fallback-behavior 'return-nil
+ "This option is obsolete.
+Now that the conditional keybinding `yas-maybe-expand' is
+available, there's no more need for it."
+ :type '(choice (const :tag "Call previous command" call-other-command)
+ (const :tag "Do nothing" return-nil)))
+
+(make-obsolete-variable
+ 'yas-fallback-behavior
+ "For `call-other-command' behavior bind to the conditional
+command value `yas-maybe-expand', for `return-nil' behavior bind
+directly to `yas-expand'."
+ "0.12")
+
+(defcustom yas-choose-keys-first nil
+ "If non-nil, prompt for snippet key first, then for template.
+
+Otherwise prompts for all possible snippet names.
+
+This affects `yas-insert-snippet' and `yas-visit-snippet-file'."
+ :type 'boolean)
+
+(defcustom yas-choose-tables-first nil
+ "If non-nil, and multiple eligible snippet tables, prompts user for tables first.
+
+Otherwise, user chooses between the merging together of all
+eligible tables.
+
+This affects `yas-insert-snippet', `yas-visit-snippet-file'"
+ :type 'boolean)
+
+(defcustom yas-use-menu 'abbreviate
+ "Display a YASnippet menu in the menu bar.
+
+When non-nil, submenus for each snippet table will be listed
+under the menu \"Yasnippet\".
+
+- If set to `abbreviate', only the current major-mode
+menu and the modes set in `yas--extra-modes' are listed.
+
+- If set to `full', every submenu is listed
+
+- If set to nil, hide the menu.
+
+Any other non-nil value, every submenu is listed."
+ :type '(choice (const :tag "Full" full)
+ (const :tag "Abbreviate" abbreviate)
+ (const :tag "No menu" nil)))
+
+(defcustom yas-trigger-symbol (or (and (eq window-system 'mac)
+ (ignore-errors
+ (char-to-string ?\x21E5))) ;; little ->| sign
+ " =>")
+ "The text that will be used in menu to represent the trigger."
+ :type 'string)
+
+(defcustom yas-wrap-around-region nil
+ "What to insert for snippet's $0 field.
+
+If set to a character, insert contents of corresponding register.
+If non-nil insert region contents. This can be overridden on a
+per-snippet basis. A value of `cua' is considered equivalent to
+`?0' for backwards compatibility."
+ :type '(choice (character :tag "Insert from register")
+ (const t :tag "Insert region contents")
+ (const nil :tag "Don't insert anything")
+ (const cua))) ; backwards compat
+
+(defcustom yas-good-grace t
+ "If non-nil, don't raise errors in elisp evaluation.
+
+This affects both the inline elisp in snippets and the hook
+variables such as `yas-after-exit-snippet-hook'.
+
+If this variable's value is `inline', an error string \"[yas]
+error\" is returned instead of raising the error. If this
+variable's value is `hooks', a message is output to according to
+`yas-verbosity-level'. If this variable's value is t, both are
+active."
+ :type 'boolean)
+
+(defcustom yas-visit-from-menu nil
+ "If non-nil visit snippets's files from menu, instead of expanding them.
+
+This can only work when snippets are loaded from files."
+ :type 'boolean)
+
+(defcustom yas-expand-only-for-last-commands nil
+ "List of `last-command' values to restrict tab-triggering to, or nil.
+
+Leave this set at nil (the default) to be able to trigger an
+expansion simply by placing the cursor after a valid tab trigger,
+using whichever commands.
+
+Optionally, set this to something like (self-insert-command) if
+you to wish restrict expansion to only happen when the last
+letter of the snippet tab trigger was typed immediately before
+the trigger key itself."
+ :type '(repeat function))
+
+(defcustom yas-alias-to-yas/prefix-p t
+ "If non-nil make aliases for the old style yas/ prefixed symbols.
+It must be set to nil before loading yasnippet to take effect."
+ :type 'boolean
+ :group 'yasnippet)
+
+;; Only two faces, and one of them shouldn't even be used...
+;;
+(defface yas-field-highlight-face
+ '((t (:inherit 'region)))
+ "The face used to highlight the currently active field of a snippet")
+
+(defface yas--field-debug-face
+ '()
+ "The face used for debugging some overlays normally hidden")
+
+\f
+;;; User-visible variables
+
+(defvar yas-keymap (let ((map (make-sparse-keymap)))
+ (define-key map [(tab)] 'yas-next-field-or-maybe-expand)
+ (define-key map (kbd "TAB") 'yas-next-field-or-maybe-expand)
+ (define-key map [(shift tab)] 'yas-prev-field)
+ (define-key map [backtab] 'yas-prev-field)
+ (define-key map (kbd "C-g") 'yas-abort-snippet)
+ (define-key map (kbd "C-d") 'yas-skip-and-clear-or-delete-char)
+ map)
+ "The active keymap while a snippet expansion is in progress.")
+
+(defvar yas-key-syntaxes (list "w" "w_" "w_." "w_.()"
+ #'yas-try-key-from-whitespace)
+ "Syntaxes and functions to help look for trigger keys before point.
+
+Each element in this list specifies how to skip buffer positions
+backwards and look for the start of a trigger key.
+
+Each element can be either a string or a function receiving the
+original point as an argument. A string element is simply passed
+to `skip-syntax-backward' whereas a function element is called
+with no arguments and should also place point before the original
+position.
+
+The string between the resulting buffer position and the original
+point is matched against the trigger keys in the active snippet
+tables.
+
+If no expandable snippets are found, the next element is the list
+is tried, unless a function element returned the symbol `again',
+in which case it is called again from the previous position and
+may once more reposition point.
+
+For example, if `yas-key-syntaxes' has the value (\"w\" \"w_\"),
+trigger keys composed exclusively of \"word\"-syntax characters
+are looked for first. Failing that, longer keys composed of
+\"word\" or \"symbol\" syntax are looked for. Therefore,
+triggering after
+
+foo-bar
+
+will, according to the \"w\" element first try \"barbaz\". If
+that isn't a trigger key, \"foo-barbaz\" is tried, respecting the
+second \"w_\" element. Notice that even if \"baz\" is a trigger
+key for an active snippet, it won't be expanded, unless a
+function is added to `yas-key-syntaxes' that eventually places
+point between \"bar\" and \"baz\".
+
+See also Info node `(elisp) Syntax Descriptors'.")
+
+(defvar yas-after-exit-snippet-hook
+ '()
+ "Hooks to run after a snippet exited.
+
+The hooks will be run in an environment where some variables bound to
+proper values:
+
+`yas-snippet-beg' : The beginning of the region of the snippet.
+
+`yas-snippet-end' : Similar to beg.
+
+Attention: These hooks are not run when exiting nested/stacked snippet expansion!")
+
+(defvar yas-before-expand-snippet-hook
+ '()
+ "Hooks to run just before expanding a snippet.")
+
+(defconst yas-not-string-or-comment-condition
+ '(if (and (let ((ppss (syntax-ppss)))
+ (or (nth 3 ppss) (nth 4 ppss)))
+ (memq this-command '(yas-expand yas-expand-from-trigger-key
+ yas-expand-from-keymap)))
+ '(require-snippet-condition . force-in-comment)
+ t)
+ "Disables snippet expansion in strings and comments.
+To use, set `yas-buffer-local-condition' to this value.")
+
+(defcustom yas-buffer-local-condition t
+ "Snippet expanding condition.
+
+This variable is a Lisp form which is evaluated every time a
+snippet expansion is attempted:
+
+ * If it evaluates to nil, no snippets can be expanded.
+
+ * If it evaluates to the a cons (require-snippet-condition
+ . REQUIREMENT)
+
+ * Snippets bearing no \"# condition:\" directive are not
+ considered
+
+ * Snippets bearing conditions that evaluate to nil (or
+ produce an error) won't be considered.
+
+ * If the snippet has a condition that evaluates to non-nil
+ RESULT:
+
+ * If REQUIREMENT is t, the snippet is considered
+
+ * If REQUIREMENT is `eq' RESULT, the snippet is
+ considered
+
+ * Otherwise, the snippet is not considered.
+
+ * If it evaluates to the symbol `always', all snippets are
+ considered for expansion, regardless of any conditions.
+
+ * If it evaluates to t or some other non-nil value
+
+ * Snippet bearing no conditions, or conditions that
+ evaluate to non-nil, are considered for expansion.
+
+ * Otherwise, the snippet is not considered.
+
+Here's an example preventing snippets from being expanded from
+inside comments, in `python-mode' only, with the exception of
+snippets returning the symbol `force-in-comment' in their
+conditions.
+
+ (add-hook \\='python-mode-hook
+ (lambda ()
+ (setq yas-buffer-local-condition
+ \\='(if (python-syntax-comment-or-string-p)
+ \\='(require-snippet-condition . force-in-comment)
+ t))))"
+ :type
+ `(choice
+ (const :tag "Disable snippet expansion inside strings and comments"
+ ,yas-not-string-or-comment-condition)
+ (const :tag "Expand all snippets regardless of conditions" always)
+ (const :tag "Expand snippets unless their condition is nil" t)
+ (const :tag "Disable all snippet expansion" nil)
+ sexp))
+
+(defcustom yas-overlay-priority 100
+ "Priority to use for yasnippets overlays.
+This is useful to control whether snippet navigation bindings
+override bindings from other packages (e.g., `company-mode')."
+ :type 'integer)
+
+\f
+;;; Internal variables
+
+(defconst yas--version "0.12.2")
+
+(defvar yas--menu-table (make-hash-table)
+ "A hash table of MAJOR-MODE symbols to menu keymaps.")
+
+(defvar yas--escaped-characters
+ '(?\\ ?` ?\" ?' ?$ ?} ?{ ?\( ?\))
+ "List of characters which *might* need to be escaped.")
+
+(defconst yas--field-regexp
+ "${\\([0-9]+:\\)?\\([^}]*\\)}"
+ "A regexp to *almost* recognize a field.")
+
+(defconst yas--multi-dollar-lisp-expression-regexp
+ "$+[ \t\n]*\\(([^)]*)\\)"
+ "A regexp to *almost* recognize a \"$(...)\" expression.")
+
+(defconst yas--backquote-lisp-expression-regexp
+ "`\\([^`]*\\)`"
+ "A regexp to recognize a \"\\=`lisp-expression\\=`\" expression." )
+
+(defconst yas--transform-mirror-regexp
+ "${\\(?:\\([0-9]+\\):\\)?$\\([ \t\n]*([^}]*\\)"
+ "A regexp to *almost* recognize a mirror with a transform.")
+
+(defconst yas--simple-mirror-regexp
+ "$\\([0-9]+\\)"
+ "A regexp to recognize a simple mirror.")
+
+(defvar yas--snippet-id-seed 0
+ "Contains the next id for a snippet.")
+
+(defvar yas--original-auto-fill-function nil
+ "The original value of `auto-fill-function'.")
+(make-variable-buffer-local 'yas--original-auto-fill-function)
+
+(defun yas--snippet-next-id ()
+ (let ((id yas--snippet-id-seed))
+ (cl-incf yas--snippet-id-seed)
+ id))
+
+\f
+;;; Minor mode stuff
+
+;; XXX: `last-buffer-undo-list' is somehow needed in Carbon Emacs for MacOSX
+(defvar last-buffer-undo-list nil)
+
+(defvar yas--minor-mode-menu nil
+ "Holds the YASnippet menu.")
+
+(defvar yas--condition-cache-timestamp nil)
+
+(defun yas--maybe-expand-key-filter (cmd)
+ (when (let ((yas--condition-cache-timestamp (current-time)))
+ (yas--templates-for-key-at-point))
+ cmd))
+
+(defconst yas-maybe-expand
+ '(menu-item "" yas-expand :filter yas--maybe-expand-key-filter)
+ "A conditional key definition.
+This can be used as a key definition in keymaps to bind a key to
+`yas-expand' only when there is a snippet available to be
+expanded.")
+
+(defvar yas-minor-mode-map
+ (let ((map (make-sparse-keymap)))
+ (define-key map [(tab)] yas-maybe-expand)
+ (define-key map (kbd "TAB") yas-maybe-expand)
+ (define-key map "\C-c&\C-s" 'yas-insert-snippet)
+ (define-key map "\C-c&\C-n" 'yas-new-snippet)
+ (define-key map "\C-c&\C-v" 'yas-visit-snippet-file)
+ map)
+ "The keymap used when `yas-minor-mode' is active.")
+
+(easy-menu-define yas--minor-mode-menu
+ yas-minor-mode-map
+ "Menu used when `yas-minor-mode' is active."
+ '("YASnippet" :visible yas-use-menu
+ "----"
+ ["Expand trigger" yas-expand
+ :help "Possibly expand tab trigger before point"]
+ ["Insert at point..." yas-insert-snippet
+ :help "Prompt for an expandable snippet and expand it at point"]
+ ["New snippet..." yas-new-snippet
+ :help "Create a new snippet in an appropriate directory"]
+ ["Visit snippet file..." yas-visit-snippet-file
+ :help "Prompt for an expandable snippet and find its file"]
+ "----"
+ ("Snippet menu behaviour"
+ ["Visit snippets" (setq yas-visit-from-menu t)
+ :help "Visit snippets from the menu"
+ :active t :style radio :selected yas-visit-from-menu]
+ ["Expand snippets" (setq yas-visit-from-menu nil)
+ :help "Expand snippets from the menu"
+ :active t :style radio :selected (not yas-visit-from-menu)]
+ "----"
+ ["Show all known modes" (setq yas-use-menu 'full)
+ :help "Show one snippet submenu for each loaded table"
+ :active t :style radio :selected (eq yas-use-menu 'full)]
+ ["Abbreviate according to current mode" (setq yas-use-menu 'abbreviate)
+ :help "Show only snippet submenus for the current active modes"
+ :active t :style radio :selected (eq yas-use-menu 'abbreviate)])
+ ("Indenting"
+ ["Auto" (setq yas-indent-line 'auto)
+ :help "Indent each line of the snippet with `indent-according-to-mode'"
+ :active t :style radio :selected (eq yas-indent-line 'auto)]
+ ["Fixed" (setq yas-indent-line 'fixed)
+ :help "Indent the snippet to the current column"
+ :active t :style radio :selected (eq yas-indent-line 'fixed)]
+ ["None" (setq yas-indent-line 'none)
+ :help "Don't apply any particular snippet indentation after expansion"
+ :active t :style radio :selected (not (member yas-indent-line '(fixed auto)))]
+ "----"
+ ["Also auto indent first line" (setq yas-also-auto-indent-first-line
+ (not yas-also-auto-indent-first-line))
+ :help "When auto-indenting also, auto indent the first line menu"
+ :active (eq yas-indent-line 'auto)
+ :style toggle :selected yas-also-auto-indent-first-line]
+ )
+ ("Prompting method"
+ ["System X-widget" (setq yas-prompt-functions
+ (cons #'yas-x-prompt
+ (remove #'yas-x-prompt
+ yas-prompt-functions)))
+ :help "Use your windowing system's (gtk, mac, windows, etc...) default menu"
+ :active t :style radio :selected (eq (car yas-prompt-functions)
+ #'yas-x-prompt)]
+ ["Dropdown-list" (setq yas-prompt-functions
+ (cons #'yas-dropdown-prompt
+ (remove #'yas-dropdown-prompt
+ yas-prompt-functions)))
+ :help "Use a special dropdown list"
+ :active t :style radio :selected (eq (car yas-prompt-functions)
+ #'yas-dropdown-prompt)]
+ ["Ido" (setq yas-prompt-functions
+ (cons #'yas-ido-prompt
+ (remove #'yas-ido-prompt
+ yas-prompt-functions)))
+ :help "Use an ido-style minibuffer prompt"
+ :active t :style radio :selected (eq (car yas-prompt-functions)
+ #'yas-ido-prompt)]
+ ["Completing read" (setq yas-prompt-functions
+ (cons #'yas-completing-prompt
+ (remove #'yas-completing-prompt
+ yas-prompt-functions)))
+ :help "Use a normal minibuffer prompt"
+ :active t :style radio :selected (eq (car yas-prompt-functions)
+ #'yas-completing-prompt)]
+ )
+ ("Misc"
+ ["Wrap region in exit marker"
+ (setq yas-wrap-around-region
+ (not yas-wrap-around-region))
+ :help "If non-nil automatically wrap the selected text in the $0 snippet exit"
+ :style toggle :selected yas-wrap-around-region]
+ ["Allow stacked expansions "
+ (setq yas-triggers-in-field
+ (not yas-triggers-in-field))
+ :help "If non-nil allow snippets to be triggered inside other snippet fields"
+ :style toggle :selected yas-triggers-in-field]
+ ["Revive snippets on undo "
+ (setq yas-snippet-revival
+ (not yas-snippet-revival))
+ :help "If non-nil allow snippets to become active again after undo"
+ :style toggle :selected yas-snippet-revival]
+ ["Good grace "
+ (setq yas-good-grace
+ (not yas-good-grace))
+ :help "If non-nil don't raise errors in bad embedded elisp in snippets"
+ :style toggle :selected yas-good-grace]
+ )
+ "----"
+ ["Load snippets..." yas-load-directory
+ :help "Load snippets from a specific directory"]
+ ["Reload everything" yas-reload-all
+ :help "Cleanup stuff, reload snippets, rebuild menus"]
+ ["About" yas-about
+ :help "Display some information about YASnippet"]))
+
+(defvar yas--extra-modes nil
+ "An internal list of modes for which to also lookup snippets.
+
+This variable probably makes more sense as buffer-local, so
+ensure your use `make-local-variable' when you set it.")
+(define-obsolete-variable-alias 'yas-extra-modes 'yas--extra-modes "0.9.1")
+
+(defvar yas--tables (make-hash-table)
+ "A hash table of mode symbols to `yas--table' objects.")
+
+(defvar yas--parents (make-hash-table)
+ "A hash table of mode symbols do lists of direct parent mode symbols.
+
+This list is populated when reading the \".yas-parents\" files
+found when traversing snippet directories with
+`yas-load-directory'.
+
+There might be additional parenting information stored in the
+`derived-mode-parent' property of some mode symbols, but that is
+not recorded here.")
+
+(defvar yas--direct-keymaps (list)
+ "Keymap alist supporting direct snippet keybindings.
+
+This variable is placed in `emulation-mode-map-alists'.
+
+Its elements looks like (TABLE-NAME . KEYMAP). They're
+instantiated on `yas-reload-all' but KEYMAP is added to only when
+loading snippets. `yas--direct-TABLE-NAME' is then a variable
+set buffer-locally when entering `yas-minor-mode'. KEYMAP binds
+all defined direct keybindings to `yas-maybe-expand-from-keymap'
+which decides on the snippet to expand.")
+
+(defun yas-direct-keymaps-reload ()
+ "Force reload the direct keybinding for active snippet tables."
+ (interactive)
+ (setq yas--direct-keymaps nil)
+ (maphash #'(lambda (name table)
+ (push (cons (intern (format "yas--direct-%s" name))
+ (yas--table-direct-keymap table))
+ yas--direct-keymaps))
+ yas--tables))
+
+(defun yas--modes-to-activate (&optional mode)
+ "Compute list of mode symbols that are active for `yas-expand' and friends."
+ (defvar yas--dfs) ;We rely on dynbind. We could use `letrec' instead!
+ (let* ((explored (if mode (list mode) ; Building up list in reverse.
+ (cons major-mode (reverse yas--extra-modes))))
+ (yas--dfs
+ (lambda (mode)
+ (cl-loop for neighbour
+ in (cl-list* (get mode 'derived-mode-parent)
+ ;; NOTE: `fboundp' check is redundant
+ ;; since Emacs 24.4.
+ (and (fboundp mode) (symbol-function mode))
+ (gethash mode yas--parents))
+ when (and neighbour
+ (not (memq neighbour explored))
+ (symbolp neighbour))
+ do (push neighbour explored)
+ (funcall yas--dfs neighbour)))))
+ (mapc yas--dfs explored)
+ (nreverse explored)))
+
+(defvar yas-minor-mode-hook nil
+ "Hook run when `yas-minor-mode' is turned on.")
+
+(defun yas--auto-fill-wrapper ()
+ (when (and auto-fill-function
+ (not (eq auto-fill-function #'yas--auto-fill)))
+ (setq yas--original-auto-fill-function auto-fill-function)
+ (setq auto-fill-function #'yas--auto-fill)))
+
+;;;###autoload
+(define-minor-mode yas-minor-mode
+ "Toggle YASnippet mode.
+
+When YASnippet mode is enabled, `yas-expand', normally bound to
+the TAB key, expands snippets of code depending on the major
+mode.
+
+With no argument, this command toggles the mode.
+positive prefix argument turns on the mode.
+Negative prefix argument turns off the mode.
+
+Key bindings:
+\\{yas-minor-mode-map}"
+ :lighter " yas" ;; The indicator for the mode line.
+ (cond ((and yas-minor-mode (featurep 'yasnippet))
+ ;; Install the direct keymaps in `emulation-mode-map-alists'
+ ;; (we use `add-hook' even though it's not technically a hook,
+ ;; but it works). Then define variables named after modes to
+ ;; index `yas--direct-keymaps'.
+ ;;
+ ;; Also install the post-command-hook.
+ ;;
+ (cl-pushnew 'yas--direct-keymaps emulation-mode-map-alists)
+ (add-hook 'post-command-hook #'yas--post-command-handler nil t)
+ ;; Set the `yas--direct-%s' vars for direct keymap expansion
+ ;;
+ (dolist (mode (yas--modes-to-activate))
+ (let ((name (intern (format "yas--direct-%s" mode))))
+ (set-default name nil)
+ (set (make-local-variable name) t)))
+ ;; Perform JIT loads
+ (yas--load-pending-jits)
+ ;; Install auto-fill handler.
+ (yas--auto-fill-wrapper) ; Now...
+ (add-hook 'auto-fill-mode-hook #'yas--auto-fill-wrapper)) ; or later.
+ (t
+ ;; Uninstall the direct keymaps, post-command hook, and
+ ;; auto-fill handler.
+ (remove-hook 'post-command-hook #'yas--post-command-handler t)
+ (remove-hook 'auto-fill-mode-hook #'yas--auto-fill-wrapper)
+ (when (local-variable-p 'yas--original-auto-fill-function)
+ (setq auto-fill-function yas--original-auto-fill-function))
+ (setq emulation-mode-map-alists
+ (remove 'yas--direct-keymaps emulation-mode-map-alists)))))
+
+(defun yas-activate-extra-mode (mode)
+ "Activates the snippets for the given `mode' in the buffer.
+
+The function can be called in the hook of a minor mode to
+activate snippets associated with that mode."
+ (interactive
+ (let (modes
+ symbol)
+ (maphash (lambda (k _)
+ (setq modes (cons (list k) modes)))
+ yas--parents)
+ (setq symbol (completing-read
+ "Activate mode: " modes nil t))
+ (list
+ (when (not (string= "" symbol))
+ (intern symbol)))))
+ (when mode
+ (add-to-list (make-local-variable 'yas--extra-modes) mode)
+ (yas--load-pending-jits)))
+
+(defun yas-deactivate-extra-mode (mode)
+ "Deactivates the snippets for the given `mode' in the buffer."
+ (interactive
+ (list (intern
+ (completing-read
+ "Deactivate mode: " (mapcar #'list yas--extra-modes) nil t))))
+ (set (make-local-variable 'yas--extra-modes)
+ (remove mode
+ yas--extra-modes)))
+
+(define-obsolete-variable-alias 'yas-dont-activate
+ 'yas-dont-activate-functions "0.9.2")
+(defvar yas-dont-activate-functions (list #'minibufferp)
+ "Special hook to control which buffers `yas-global-mode' affects.
+Functions are called with no argument, and should return non-nil to prevent
+`yas-global-mode' from enabling yasnippet in this buffer.
+
+In Emacsen < 24, this variable is buffer-local. Because
+`yas-minor-mode-on' is called by `yas-global-mode' after
+executing the buffer's major mode hook, setting this variable
+there is an effective way to define exceptions to the \"global\"
+activation behaviour.
+
+In Emacsen >= 24, only the global value is used. To define
+per-mode exceptions to the \"global\" activation behaviour, call
+`yas-minor-mode' with a negative argument directily in the major
+mode's hook.")
+(unless (> emacs-major-version 23)
+ (with-no-warnings
+ (make-variable-buffer-local 'yas-dont-activate)))
+
+
+(defun yas-minor-mode-on ()
+ "Turn on YASnippet minor mode.
+
+Honour `yas-dont-activate-functions', which see."
+ (interactive)
+ (unless (or
+ ;; The old behavior used for Emacs<24 was to set
+ ;; `yas-dont-activate-functions' to t buffer-locally.
+ (not (or (listp yas-dont-activate-functions)
+ (functionp yas-dont-activate-functions)))
+ (run-hook-with-args-until-success 'yas-dont-activate-functions))
+ (yas-minor-mode 1)))
+
+;;;###autoload
+(define-globalized-minor-mode yas-global-mode yas-minor-mode yas-minor-mode-on)
+
+(defun yas--global-mode-reload-with-jit-maybe ()
+ "Run `yas-reload-all' when `yas-global-mode' is on."
+ (when yas-global-mode (yas-reload-all)))
+
+(add-hook 'yas-global-mode-hook #'yas--global-mode-reload-with-jit-maybe)
+
+\f
+;;; Major mode stuff
+
+(defvar yas--font-lock-keywords
+ (append '(("^#.*$" . font-lock-comment-face))
+ (with-temp-buffer
+ (let ((prog-mode-hook nil)
+ (emacs-lisp-mode-hook nil))
+ (ignore-errors (emacs-lisp-mode)))
+ (font-lock-set-defaults)
+ (if (eq t (car-safe font-lock-keywords))
+ ;; They're "compiled", so extract the source.
+ (cadr font-lock-keywords)
+ font-lock-keywords))
+ '(("\\$\\([0-9]+\\)"
+ (0 font-lock-keyword-face)
+ (1 font-lock-string-face t))
+ ("\\${\\([0-9]+\\):?"
+ (0 font-lock-keyword-face)
+ (1 font-lock-warning-face t))
+ ("\\(\\$(\\)" 1 font-lock-preprocessor-face)
+ ("}"
+ (0 font-lock-keyword-face)))))
+
+(defvar snippet-mode-map
+ (let ((map (make-sparse-keymap)))
+ (easy-menu-define nil
+ map
+ "Menu used when snippet-mode is active."
+ (cons "Snippet"
+ (mapcar #'(lambda (ent)
+ (when (nth 2 ent)
+ (define-key map (nth 2 ent) (nth 1 ent)))
+ (vector (nth 0 ent) (nth 1 ent) t))
+ '(("Load this snippet" yas-load-snippet-buffer "\C-c\C-l")
+ ("Load and quit window" yas-load-snippet-buffer-and-close "\C-c\C-c")
+ ("Try out this snippet" yas-tryout-snippet "\C-c\C-t")))))
+ map)
+ "The keymap used when `snippet-mode' is active.")
+
+
+;;;###autoload
+(define-derived-mode snippet-mode text-mode "Snippet"
+ "A mode for editing yasnippets"
+ (setq font-lock-defaults '(yas--font-lock-keywords))
+ (set (make-local-variable 'require-final-newline) nil)
+ (set (make-local-variable 'comment-start) "#")
+ (set (make-local-variable 'comment-start-skip) "#+[\t ]*")
+ (add-hook 'after-save-hook #'yas-maybe-load-snippet-buffer nil t))
+
+(defun yas-snippet-mode-buffer-p ()
+ "Return non-nil if current buffer should be in `snippet-mode'.
+Meaning it's visiting a file under one of the mode directories in
+`yas-snippet-dirs'."
+ (when buffer-file-name
+ (member
+ (expand-file-name
+ ".."
+ (file-name-directory buffer-file-name))
+ (yas-snippet-dirs))))
+
+;; We're abusing `magic-fallback-mode-alist' here because
+;; `auto-mode-alist' doesn't support function matchers.
+(add-to-list 'magic-fallback-mode-alist
+ `(yas-snippet-mode-buffer-p . snippet-mode))
+
+\f
+;;; Internal structs for template management
+
+(cl-defstruct (yas--template
+ (:constructor yas--make-template)
+ ;; Handles `yas-define-snippets' format, plus the
+ ;; initial TABLE argument.
+ (:constructor
+ yas--define-snippets-2
+ (table
+ key content
+ &optional xname condition group
+ expand-env load-file xkeybinding xuuid save-file
+ &aux
+ (name (or xname
+ ;; A little redundant: we always get a name
+ ;; from `yas--parse-template' except when
+ ;; there isn't a file.
+ (and load-file (file-name-nondirectory load-file))
+ (and save-file (file-name-nondirectory save-file))
+ key))
+ (keybinding (yas--read-keybinding xkeybinding))
+ (uuid (or xuuid name))
+ (old (gethash uuid (yas--table-uuidhash table)))
+ (menu-binding-pair
+ (and old (yas--template-menu-binding-pair old)))
+ (perm-group
+ (and old (yas--template-perm-group old))))))
+ "A template for a snippet."
+ key
+ content
+ name
+ condition
+ expand-env
+ load-file
+ save-file
+ keybinding
+ uuid
+ menu-binding-pair
+ group ;; as dictated by the #group: directive or .yas-make-groups
+ perm-group ;; as dictated by `yas-define-menu'
+ table
+ )
+
+(cl-defstruct (yas--table (:constructor yas--make-snippet-table (name)))
+ "A table to store snippets for a particular mode.
+
+Has the following fields:
+
+`yas--table-name'
+
+ A symbol name normally corresponding to a major mode, but can
+ also be a pseudo major-mode to be used in
+ `yas-activate-extra-mode', for example.
+
+`yas--table-hash'
+
+ A hash table (KEY . NAMEHASH), known as the \"keyhash\". KEY is
+ a string or a vector, where the former is the snippet's trigger
+ and the latter means it's a direct keybinding. NAMEHASH is yet
+ another hash of (NAME . TEMPLATE) where NAME is the snippet's
+ name and TEMPLATE is a `yas--template' object.
+
+`yas--table-direct-keymap'
+
+ A keymap for the snippets in this table that have direct
+ keybindings. This is kept in sync with the keyhash, i.e., all
+ the elements of the keyhash that are vectors appear here as
+ bindings to `yas-maybe-expand-from-keymap'.
+
+`yas--table-uuidhash'
+
+ A hash table mapping snippets uuid's to the same `yas--template'
+ objects. A snippet uuid defaults to the snippet's name."
+ name
+ (hash (make-hash-table :test 'equal))
+ (uuidhash (make-hash-table :test 'equal))
+ (parents nil)
+ (direct-keymap (make-sparse-keymap)))
+
+(defun yas--get-template-by-uuid (mode uuid)
+ "Find the snippet template in MODE by its UUID."
+ (let* ((table (gethash mode yas--tables mode)))
+ (when table
+ (gethash uuid (yas--table-uuidhash table)))))
+
+;; Apropos storing/updating in TABLE, this works in two steps:
+;;
+;; 1. `yas--remove-template-by-uuid' removes any
+;; keyhash-namehash-template mappings from TABLE, grabbing the
+;; snippet by its uuid. Also removes mappings from TABLE's
+;; `yas--table-direct-keymap' (FIXME: and should probably take care
+;; of potentially stale menu bindings right?.)
+;;
+;; 2. `yas--add-template' adds this all over again.
+;;
+;; Create a new or add to an existing keyhash-namehash mapping.
+;;
+;; For reference on understanding this, consider three snippet
+;; definitions:
+;;
+;; A: # name: The Foo
+;; # key: foo
+;; # binding: C-c M-l
+;;
+;; B: # name: Mrs Foo
+;; # key: foo
+;;
+;; C: # name: The Bar
+;; # binding: C-c M-l
+;;
+;; D: # name: Baz
+;; # key: baz
+;;
+;; keyhash namehashes(3) yas--template structs(4)
+;; -----------------------------------------------------
+;; __________
+;; / \
+;; "foo" ---> "The Foo" ---> [yas--template A] |
+;; "Mrs Foo" ---> [yas--template B] |
+;; |
+;; [C-c M-l] ---> "The Foo" -------------------------/
+;; "The Bar" ---> [yas--template C]
+;;
+;; "baz" ---> "Baz" ---> [yas--template D]
+;;
+;; Additionally, since uuid defaults to the name, we have a
+;; `yas--table-uuidhash' for TABLE
+;;
+;; uuidhash yas--template structs
+;; -------------------------------
+;; "The Foo" ---> [yas--template A]
+;; "Mrs Foo" ---> [yas--template B]
+;; "The Bar" ---> [yas--template C]
+;; "Baz" ---> [yas--template D]
+;;
+;; FIXME: the more I look at this data-structure the more I think I'm
+;; stupid. There has to be an easier way (but beware lots of code
+;; depends on this).
+;;
+(defun yas--remove-template-by-uuid (table uuid)
+ "Remove from TABLE a template identified by UUID."
+ (let ((template (gethash uuid (yas--table-uuidhash table))))
+ (when template
+ (let* ((name (yas--template-name template))
+ (empty-keys nil))
+ ;; Remove the name from each of the targeted namehashes
+ ;;
+ (maphash #'(lambda (k v)
+ (let ((template (gethash name v)))
+ (when (and template
+ (equal uuid (yas--template-uuid template)))
+ (remhash name v)
+ (when (zerop (hash-table-count v))
+ (push k empty-keys)))))
+ (yas--table-hash table))
+ ;; Remove the namehash themselves if they've become empty
+ ;;
+ (dolist (key empty-keys)
+ (when (vectorp key)
+ (define-key (yas--table-direct-keymap table) key nil))
+ (remhash key (yas--table-hash table)))
+
+ ;; Finally, remove the uuid from the uuidhash
+ ;;
+ (remhash uuid (yas--table-uuidhash table))))))
+
+(defconst yas-maybe-expand-from-keymap
+ '(menu-item "" yas-expand-from-keymap
+ :filter yas--maybe-expand-from-keymap-filter))
+
+(defun yas--add-template (table template)
+ "Store in TABLE the snippet template TEMPLATE.
+
+KEY can be a string (trigger key) of a vector (direct
+keybinding)."
+ (let ((name (yas--template-name template))
+ (key (yas--template-key template))
+ (keybinding (yas--template-keybinding template))
+ (_menu-binding-pair (yas--template-menu-binding-pair-get-create template)))
+ (dolist (k (remove nil (list key keybinding)))
+ (puthash name
+ template
+ (or (gethash k
+ (yas--table-hash table))
+ (puthash k
+ (make-hash-table :test 'equal)
+ (yas--table-hash table))))
+ (when (vectorp k)
+ (define-key (yas--table-direct-keymap table) k yas-maybe-expand-from-keymap)))
+
+ ;; Update TABLE's `yas--table-uuidhash'
+ (puthash (yas--template-uuid template)
+ template
+ (yas--table-uuidhash table))))
+
+(defun yas--update-template (table template)
+ "Add or update TEMPLATE in TABLE.
+
+Also takes care of adding and updating to the associated menu.
+Return TEMPLATE."
+ ;; Remove from table by uuid
+ ;;
+ (yas--remove-template-by-uuid table (yas--template-uuid template))
+ ;; Add to table again
+ ;;
+ (yas--add-template table template)
+ ;; Take care of the menu
+ ;;
+ (yas--update-template-menu table template)
+ template)
+
+(defun yas--update-template-menu (table template)
+ "Update every menu-related for TEMPLATE."
+ (let ((menu-binding-pair (yas--template-menu-binding-pair-get-create template))
+ (key (yas--template-key template))
+ (keybinding (yas--template-keybinding template)))
+ ;; The snippet might have changed name or keys, so update
+ ;; user-visible strings
+ ;;
+ (unless (eq (cdr menu-binding-pair) :none)
+ ;; the menu item name
+ ;;
+ (setf (cl-cadar menu-binding-pair) (yas--template-name template))
+ ;; the :keys information (also visible to the user)
+ (setf (cl-getf (cdr (car menu-binding-pair)) :keys)
+ (or (and keybinding (key-description keybinding))
+ (and key (concat key yas-trigger-symbol))))))
+ (unless (yas--template-menu-managed-by-yas-define-menu template)
+ (let ((menu-keymap
+ (yas--menu-keymap-get-create (yas--table-mode table)
+ (mapcar #'yas--table-mode
+ (yas--table-parents table))))
+ (group (yas--template-group template)))
+ ;; Remove from menu keymap
+ ;;
+ (cl-assert menu-keymap)
+ (yas--delete-from-keymap menu-keymap (yas--template-uuid template))
+
+ ;; Add necessary subgroups as necessary.
+ ;;
+ (dolist (subgroup group)
+ (let ((subgroup-keymap (lookup-key menu-keymap (vector (make-symbol subgroup)))))
+ (unless (and subgroup-keymap
+ (keymapp subgroup-keymap))
+ (setq subgroup-keymap (make-sparse-keymap))
+ (define-key menu-keymap (vector (make-symbol subgroup))
+ `(menu-item ,subgroup ,subgroup-keymap)))
+ (setq menu-keymap subgroup-keymap)))
+
+ ;; Add this entry to the keymap
+ ;;
+ (define-key menu-keymap
+ (vector (make-symbol (yas--template-uuid template)))
+ (car (yas--template-menu-binding-pair template))))))
+
+(defun yas--namehash-templates-alist (namehash)
+ "Return NAMEHASH as an alist."
+ (let (alist)
+ (maphash #'(lambda (k v)
+ (push (cons k v) alist))
+ namehash)
+ alist))
+
+(defun yas--fetch (table key)
+ "Fetch templates in TABLE by KEY.
+
+Return a list of cons (NAME . TEMPLATE) where NAME is a
+string and TEMPLATE is a `yas--template' structure."
+ (let* ((keyhash (yas--table-hash table))
+ (namehash (and keyhash (gethash key keyhash))))
+ (when namehash
+ (yas--filter-templates-by-condition (yas--namehash-templates-alist namehash)))))
+
+\f
+;;; Filtering/condition logic
+
+(defun yas--eval-condition (condition)
+ (condition-case err
+ (save-excursion
+ (save-restriction
+ (save-match-data
+ (eval condition))))
+ (error (progn
+ (yas--message 1 "Error in condition evaluation: %s" (error-message-string err))
+ nil))))
+
+
+(defun yas--filter-templates-by-condition (templates)
+ "Filter the templates using the applicable condition.
+
+TEMPLATES is a list of cons (NAME . TEMPLATE) where NAME is a
+string and TEMPLATE is a `yas--template' structure.
+
+This function implements the rules described in
+`yas-buffer-local-condition'. See that variables documentation."
+ (let ((requirement (yas--require-template-specific-condition-p)))
+ (if (eq requirement 'always)
+ templates
+ (cl-remove-if-not (lambda (pair)
+ (yas--template-can-expand-p
+ (yas--template-condition (cdr pair)) requirement))
+ templates))))
+
+(defun yas--require-template-specific-condition-p ()
+ "Decide if this buffer requests/requires snippet-specific
+conditions to filter out potential expansions."
+ (if (eq 'always yas-buffer-local-condition)
+ 'always
+ (let ((local-condition (or (and (consp yas-buffer-local-condition)
+ (yas--eval-condition yas-buffer-local-condition))
+ yas-buffer-local-condition)))
+ (when local-condition
+ (if (eq local-condition t)
+ t
+ (and (consp local-condition)
+ (eq 'require-snippet-condition (car local-condition))
+ (symbolp (cdr local-condition))
+ (cdr local-condition)))))))
+
+(defun yas--template-can-expand-p (condition requirement)
+ "Evaluate CONDITION and REQUIREMENT and return a boolean."
+ (let* ((result (or (null condition)
+ (yas--eval-condition condition))))
+ (cond ((eq requirement t)
+ result)
+ (t
+ (eq requirement result)))))
+
+(defun yas--table-templates (table)
+ (when table
+ (let ((acc (list)))
+ (maphash #'(lambda (_key namehash)
+ (maphash #'(lambda (name template)
+ (push (cons name template) acc))
+ namehash))
+ (yas--table-hash table))
+ (yas--filter-templates-by-condition acc))))
+
+(defun yas--templates-for-key-at-point ()
+ "Find `yas--template' objects for any trigger keys preceding point.
+Returns (TEMPLATES START END). This function respects
+`yas-key-syntaxes', which see."
+ (save-excursion
+ (let ((original (point))
+ (methods yas-key-syntaxes)
+ (templates)
+ (method))
+ (while (and methods
+ (not templates))
+ (unless (eq method (car methods))
+ ;; TRICKY: `eq'-ness test means we can only be here if
+ ;; `method' is a function that returned `again', and hence
+ ;; don't revert back to original position as per
+ ;; `yas-key-syntaxes'.
+ (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 ((possible-key (buffer-substring-no-properties (point) original)))
+ (save-excursion
+ (goto-char original)
+ (setq templates
+ (cl-mapcan (lambda (table)
+ (yas--fetch table possible-key))
+ (yas--get-snippet-tables))))))
+ (when templates
+ (list templates (point) original)))))
+
+(defun yas--table-all-keys (table)
+ "Get trigger keys of all active snippets in TABLE."
+ (let ((acc))
+ (maphash #'(lambda (key namehash)
+ (when (yas--filter-templates-by-condition (yas--namehash-templates-alist namehash))
+ (push key acc)))
+ (yas--table-hash table))
+ acc))
+
+(defun yas--table-mode (table)
+ (intern (yas--table-name table)))
+
+\f
+;;; Internal functions and macros:
+
+(defun yas--eval-for-string (form)
+ "Evaluate FORM and convert the result to string."
+ (let ((debug-on-error (and (not (memq yas-good-grace '(t inline)))
+ debug-on-error)))
+ (condition-case oops
+ (save-excursion
+ (save-restriction
+ (save-match-data
+ (widen)
+ (let ((result (eval form)))
+ (when result
+ (format "%s" result))))))
+ ((debug error) (cdr oops)))))
+
+(defun yas--eval-for-effect (form)
+ (yas--safely-call-fun (apply-partially #'eval form)))
+
+(defun yas--read-lisp (string &optional nil-on-error)
+ "Read STRING as a elisp expression and return it.
+
+In case STRING in an invalid expression and NIL-ON-ERROR is nil,
+return an expression that when evaluated will issue an error."
+ (condition-case err
+ (read string)
+ (error (and (not nil-on-error)
+ `(error (error-message-string ,err))))))
+
+(defun yas--read-keybinding (keybinding)
+ "Read KEYBINDING as a snippet keybinding, return a vector."
+ (when (and keybinding
+ (not (string-match "keybinding" keybinding)))
+ (condition-case err
+ (let ((res (or (and (string-match "^\\[.*\\]$" keybinding)
+ (read keybinding))
+ (read-kbd-macro keybinding 'need-vector))))
+ res)
+ (error
+ (yas--message 2 "warning: keybinding \"%s\" invalid since %s."
+ keybinding (error-message-string err))
+ nil))))
+
+(defun yas--table-get-create (mode)
+ "Get or create the snippet table corresponding to MODE."
+ (let ((table (gethash mode
+ yas--tables)))
+ (unless table
+ (setq table (yas--make-snippet-table (symbol-name mode)))
+ (puthash mode table yas--tables)
+ (push (cons (intern (format "yas--direct-%s" mode))
+ (yas--table-direct-keymap table))
+ yas--direct-keymaps))
+ table))
+
+(defun yas--get-snippet-tables (&optional mode)
+ "Get snippet tables for MODE.
+
+MODE defaults to the current buffer's `major-mode'.
+
+Return a list of `yas--table' objects. The list of modes to
+consider is returned by `yas--modes-to-activate'"
+ (remove nil
+ (mapcar #'(lambda (name)
+ (gethash name yas--tables))
+ (yas--modes-to-activate mode))))
+
+(defun yas--menu-keymap-get-create (mode &optional parents)
+ "Get or create the menu keymap for MODE and its PARENTS.
+
+This may very well create a plethora of menu keymaps and arrange
+them all in `yas--menu-table'"
+ (let* ((menu-keymap (or (gethash mode yas--menu-table)
+ (puthash mode (make-sparse-keymap) yas--menu-table))))
+ (mapc #'yas--menu-keymap-get-create parents)
+ (define-key yas--minor-mode-menu (vector mode)
+ `(menu-item ,(symbol-name mode) ,menu-keymap
+ :visible (yas--show-menu-p ',mode)))
+ menu-keymap))
+
+\f
+;;; Template-related and snippet loading functions
+
+(defun yas--parse-template (&optional file)
+ "Parse the template in the current buffer.
+
+Optional FILE is the absolute file name of the file being
+parsed.
+
+Optional GROUP is the group where the template is to go,
+otherwise we attempt to calculate it from FILE.
+
+Return a snippet-definition, i.e. a list
+
+ (KEY TEMPLATE NAME CONDITION GROUP VARS LOAD-FILE KEYBINDING UUID)
+
+If the buffer contains a line of \"# --\" then the contents above
+this line are ignored. Directives can set most of these with the syntax:
+
+# directive-name : directive-value
+
+Here's a list of currently recognized directives:
+
+ * type
+ * name
+ * contributor
+ * condition
+ * group
+ * key
+ * expand-env
+ * binding
+ * uuid"
+ (goto-char (point-min))
+ (let* ((type 'snippet)
+ (name (and file
+ (file-name-nondirectory file)))
+ (key nil)
+ template
+ bound
+ condition
+ (group (and file
+ (yas--calculate-group file)))
+ expand-env
+ binding
+ uuid)
+ (if (re-search-forward "^# --\\s-*\n" nil t)
+ (progn (setq template
+ (buffer-substring-no-properties (point)
+ (point-max)))
+ (setq bound (point))
+ (goto-char (point-min))
+ (while (re-search-forward "^# *\\([^ ]+?\\) *: *\\(.*?\\)[[:space:]]*$" bound t)
+ (when (string= "uuid" (match-string-no-properties 1))
+ (setq uuid (match-string-no-properties 2)))
+ (when (string= "type" (match-string-no-properties 1))
+ (setq type (if (string= "command" (match-string-no-properties 2))
+ 'command
+ 'snippet)))
+ (when (string= "key" (match-string-no-properties 1))
+ (setq key (match-string-no-properties 2)))
+ (when (string= "name" (match-string-no-properties 1))
+ (setq name (match-string-no-properties 2)))
+ (when (string= "condition" (match-string-no-properties 1))
+ (setq condition (yas--read-lisp (match-string-no-properties 2))))
+ (when (string= "group" (match-string-no-properties 1))
+ (setq group (match-string-no-properties 2)))
+ (when (string= "expand-env" (match-string-no-properties 1))
+ (setq expand-env (yas--read-lisp (match-string-no-properties 2)
+ 'nil-on-error)))
+ (when (string= "binding" (match-string-no-properties 1))
+ (setq binding (match-string-no-properties 2)))))
+ (setq template
+ (buffer-substring-no-properties (point-min) (point-max))))
+ (unless (or key binding)
+ (setq key (and file (file-name-nondirectory file))))
+ (when (eq type 'command)
+ (setq template (yas--read-lisp (concat "(progn" template ")"))))
+ (when group
+ (setq group (split-string group "\\.")))
+ (list key template name condition group expand-env file binding uuid)))
+
+(defun yas--calculate-group (file)
+ "Calculate the group for snippet file path FILE."
+ (let* ((dominating-dir (locate-dominating-file file
+ ".yas-make-groups"))
+ (extra-path (and dominating-dir
+ (file-relative-name file dominating-dir)))
+ (extra-dir (and extra-path
+ (file-name-directory extra-path)))
+ (group (and extra-dir
+ (replace-regexp-in-string "/"
+ "."
+ (directory-file-name extra-dir)))))
+ group))
+
+(defun yas--subdirs (directory &optional filep)
+ "Return subdirs or files of DIRECTORY according to FILEP."
+ (cl-remove-if (lambda (file)
+ (or (string-match "\\`\\."
+ (file-name-nondirectory file))
+ (string-match "\\`#.*#\\'"
+ (file-name-nondirectory file))
+ (string-match "~\\'"
+ (file-name-nondirectory file))
+ (if filep
+ (file-directory-p file)
+ (not (file-directory-p file)))))
+ (directory-files directory t)))
+
+(defun yas--make-menu-binding (template)
+ (let ((mode (yas--table-mode (yas--template-table template))))
+ `(lambda () (interactive) (yas--expand-or-visit-from-menu ',mode ,(yas--template-uuid template)))))
+
+(defun yas--expand-or-visit-from-menu (mode uuid)
+ (let* ((table (yas--table-get-create mode))
+ (yas--current-template (and table
+ (gethash uuid (yas--table-uuidhash table)))))
+ (when yas--current-template
+ (if yas-visit-from-menu
+ (yas--visit-snippet-file-1 yas--current-template)
+ (let ((where (if (region-active-p)
+ (cons (region-beginning) (region-end))
+ (cons (point) (point)))))
+ (yas-expand-snippet (yas--template-content yas--current-template)
+ (car where)
+ (cdr where)
+ (yas--template-expand-env yas--current-template)))))))
+
+(defun yas--key-from-desc (text)
+ "Return a yasnippet key from a description string TEXT."
+ (replace-regexp-in-string "\\(\\w+\\).*" "\\1" text))
+
+\f
+;;; Popping up for keys and templates
+
+(defun yas--prompt-for-template (templates &optional prompt)
+ "Interactively choose a template from the list TEMPLATES.
+
+TEMPLATES is a list of `yas--template'.
+
+Optional PROMPT sets the prompt to use."
+ (when templates
+ (setq templates
+ (sort templates #'(lambda (t1 t2)
+ (< (length (yas--template-name t1))
+ (length (yas--template-name t2))))))
+ (cl-some (lambda (fn)
+ (funcall fn (or prompt "Choose a snippet: ")
+ templates
+ #'yas--template-name))
+ yas-prompt-functions)))
+
+(defun yas--prompt-for-keys (keys &optional prompt)
+ "Interactively choose a template key from the list KEYS.
+
+Optional PROMPT sets the prompt to use."
+ (when keys
+ (cl-some (lambda (fn)
+ (funcall fn (or prompt "Choose a snippet key: ") keys))
+ yas-prompt-functions)))
+
+(defun yas--prompt-for-table (tables &optional prompt)
+ "Interactively choose a table from the list TABLES.
+
+Optional PROMPT sets the prompt to use."
+ (when tables
+ (cl-some (lambda (fn)
+ (funcall fn (or prompt "Choose a snippet table: ")
+ tables
+ #'yas--table-name))
+ yas-prompt-functions)))
+
+(defun yas-x-prompt (prompt choices &optional display-fn)
+ "Display choices in a x-window prompt."
+ (when (and window-system choices)
+ ;; Let window position be recalculated to ensure that
+ ;; `posn-at-point' returns non-nil.
+ (redisplay)
+ (or
+ (x-popup-menu
+ (if (fboundp 'posn-at-point)
+ (let ((x-y (posn-x-y (posn-at-point (point)))))
+ (list (list (+ (car x-y) 10)
+ (+ (cdr x-y) 20))
+ (selected-window)))
+ t)
+ `(,prompt ("title"
+ ,@(cl-mapcar (lambda (c d) `(,(concat " " d) . ,c))
+ choices
+ (if display-fn (mapcar display-fn choices)
+ choices)))))
+ (keyboard-quit))))
+
+(defun yas-maybe-ido-prompt (prompt choices &optional display-fn)
+ (when (bound-and-true-p ido-mode)
+ (yas-ido-prompt prompt choices display-fn)))
+
+(defun yas-ido-prompt (prompt choices &optional display-fn)
+ (require 'ido)
+ (yas-completing-prompt prompt choices display-fn #'ido-completing-read))
+
+(defun yas-dropdown-prompt (_prompt choices &optional display-fn)
+ (when (fboundp 'dropdown-list)
+ (let* ((formatted-choices
+ (if display-fn (mapcar display-fn choices) choices))
+ (n (dropdown-list formatted-choices)))
+ (if n (nth n choices)
+ (keyboard-quit)))))
+
+(defun yas-completing-prompt (prompt choices &optional display-fn completion-fn)
+ (let* ((formatted-choices
+ (if display-fn (mapcar display-fn choices) choices))
+ (chosen (funcall (or completion-fn #'completing-read)
+ prompt formatted-choices
+ nil 'require-match nil nil)))
+ (if (eq choices formatted-choices)
+ chosen
+ (nth (or (cl-position chosen formatted-choices :test #'string=) 0)
+ choices))))
+
+(defun yas-no-prompt (_prompt choices &optional _display-fn)
+ (cl-first choices))
+
+\f
+;;; Defining snippets
+;; This consists of creating and registering `yas--template' objects in the
+;; correct tables.
+;;
+
+(defvar yas--creating-compiled-snippets nil)
+
+(defun yas--define-snippets-1 (snippet snippet-table)
+ "Helper for `yas-define-snippets'."
+ ;; Update the appropriate table. Also takes care of adding the
+ ;; key indicators in the templates menu entry, if any.
+ (yas--update-template
+ snippet-table (apply #'yas--define-snippets-2 snippet-table snippet)))
+
+(defun yas-define-snippets (mode snippets)
+ "Define SNIPPETS for MODE.
+
+SNIPPETS is a list of snippet definitions, each taking the
+following form
+
+ (KEY TEMPLATE NAME CONDITION GROUP EXPAND-ENV LOAD-FILE KEYBINDING UUID SAVE-FILE)
+
+Within these, only KEY and TEMPLATE are actually mandatory.
+
+TEMPLATE might be a Lisp form or a string, depending on whether
+this is a snippet or a snippet-command.
+
+CONDITION, EXPAND-ENV and KEYBINDING are Lisp forms, they have
+been `yas--read-lisp'-ed and will eventually be
+`yas--eval-for-string'-ed.
+
+The remaining elements are strings.
+
+FILE is probably of very little use if you're programatically
+defining snippets.
+
+UUID is the snippet's \"unique-id\". Loading a second snippet
+file with the same uuid would replace the previous snippet.
+
+You can use `yas--parse-template' to return such lists based on
+the current buffers contents."
+ (if yas--creating-compiled-snippets
+ (let ((print-length nil))
+ (insert ";;; Snippet definitions:\n;;;\n")
+ (dolist (snippet snippets)
+ ;; Fill in missing elements with nil.
+ (setq snippet (append snippet (make-list (- 10 (length snippet)) nil)))
+ ;; Move LOAD-FILE to SAVE-FILE because we will load from the
+ ;; compiled file, not LOAD-FILE.
+ (let ((load-file (nth 6 snippet)))
+ (setcar (nthcdr 6 snippet) nil)
+ (setcar (nthcdr 9 snippet) load-file)))
+ (insert (pp-to-string
+ `(yas-define-snippets ',mode ',snippets)))
+ (insert "\n\n"))
+ ;; Normal case.
+ (let ((snippet-table (yas--table-get-create mode))
+ (template nil))
+ (dolist (snippet snippets)
+ (setq template (yas--define-snippets-1 snippet
+ snippet-table)))
+ template)))
+
+\f
+;;; Loading snippets from files
+
+(defun yas--template-get-file (template)
+ "Return TEMPLATE's LOAD-FILE or SAVE-FILE."
+ (or (yas--template-load-file template)
+ (let ((file (yas--template-save-file template)))
+ (when file
+ (yas--message 3 "%s has no load file, using save file, %s, instead."
+ (yas--template-name template) file))
+ file)))
+
+(defun yas--load-yas-setup-file (file)
+ (if (not yas--creating-compiled-snippets)
+ ;; Normal case.
+ (load file 'noerror (<= yas-verbosity 4))
+ (let ((elfile (concat file ".el")))
+ (when (file-exists-p elfile)
+ (insert ";;; contents of the .yas-setup.el support file:\n;;;\n")
+ (insert-file-contents elfile)
+ (goto-char (point-max))))))
+
+(defun yas--define-parents (mode parents)
+ "Add PARENTS to the list of MODE's parents."
+ (puthash mode (cl-remove-duplicates
+ (append parents
+ (gethash mode yas--parents)))
+ yas--parents))
+
+(defun yas-load-directory (top-level-dir &optional use-jit interactive)
+ "Load snippets in directory hierarchy TOP-LEVEL-DIR.
+
+Below TOP-LEVEL-DIR each directory should be a mode name.
+
+With prefix argument USE-JIT do jit-loading of snippets."
+ (interactive
+ (list (read-directory-name "Select the root directory: " nil nil t)
+ current-prefix-arg t))
+ (unless yas-snippet-dirs
+ (setq yas-snippet-dirs top-level-dir))
+ (let ((impatient-buffers))
+ (dolist (dir (yas--subdirs top-level-dir))
+ (let* ((major-mode-and-parents (yas--compute-major-mode-and-parents
+ (concat dir "/dummy")))
+ (mode-sym (car major-mode-and-parents))
+ (parents (cdr major-mode-and-parents)))
+ ;; Attention: The parents and the menus are already defined
+ ;; here, even if the snippets are later jit-loaded.
+ ;;
+ ;; * We need to know the parents at this point since entering a
+ ;; given mode should jit load for its parents
+ ;; immediately. This could be reviewed, the parents could be
+ ;; discovered just-in-time-as well
+ ;;
+ ;; * We need to create the menus here to support the `full'
+ ;; option to `yas-use-menu' (all known snippet menus are shown to the user)
+ ;;
+ (yas--define-parents mode-sym parents)
+ (yas--menu-keymap-get-create mode-sym)
+ (let ((fun (apply-partially #'yas--load-directory-1 dir mode-sym)))
+ (if use-jit
+ (yas--schedule-jit mode-sym fun)
+ (funcall fun)))
+ ;; Look for buffers that are already in `mode-sym', and so
+ ;; need the new snippets immediately...
+ ;;
+ (when use-jit
+ (cl-loop for buffer in (buffer-list)
+ do (with-current-buffer buffer
+ (when (eq major-mode mode-sym)
+ (yas--message 4 "Discovered there was already %s in %s" buffer mode-sym)
+ (push buffer impatient-buffers)))))))
+ ;; ...after TOP-LEVEL-DIR has been completely loaded, call
+ ;; `yas--load-pending-jits' in these impatient buffers.
+ ;;
+ (cl-loop for buffer in impatient-buffers
+ do (with-current-buffer buffer (yas--load-pending-jits))))
+ (when interactive
+ (yas--message 3 "Loaded snippets from %s." top-level-dir)))
+
+(defun yas--load-directory-1 (directory mode-sym)
+ "Recursively load snippet templates from DIRECTORY."
+ (if yas--creating-compiled-snippets
+ (let ((output-file (expand-file-name ".yas-compiled-snippets.el"
+ directory)))
+ (with-temp-file output-file
+ (insert (format ";;; Compiled snippets and support files for `%s'\n"
+ mode-sym))
+ (yas--load-directory-2 directory mode-sym)
+ (insert (format ";;; Do not edit! File generated at %s\n"
+ (current-time-string)))))
+ ;; Normal case.
+ (unless (file-exists-p (expand-file-name ".yas-skip" directory))
+ (unless (and (load (expand-file-name ".yas-compiled-snippets" directory) 'noerror (<= yas-verbosity 3))
+ (progn (yas--message 4 "Loaded compiled snippets from %s" directory) t))
+ (yas--message 4 "Loading snippet files from %s" directory)
+ (yas--load-directory-2 directory mode-sym)))))
+
+(defun yas--load-directory-2 (directory mode-sym)
+ ;; Load .yas-setup.el files wherever we find them
+ ;;
+ (yas--load-yas-setup-file (expand-file-name ".yas-setup" directory))
+ (let* ((default-directory directory)
+ (snippet-defs nil))
+ ;; load the snippet files
+ ;;
+ (with-temp-buffer
+ (dolist (file (yas--subdirs directory 'no-subdirs-just-files))
+ (when (file-readable-p file)
+ ;; Erase the buffer instead of passing non-nil REPLACE to
+ ;; `insert-file-contents' (avoids Emacs bug #23659).
+ (erase-buffer)
+ (insert-file-contents file)
+ (push (yas--parse-template file)
+ snippet-defs))))
+ (when snippet-defs
+ (yas-define-snippets mode-sym
+ snippet-defs))
+ ;; now recurse to a lower level
+ ;;
+ (dolist (subdir (yas--subdirs directory))
+ (yas--load-directory-2 subdir
+ mode-sym))))
+
+(defun yas--load-snippet-dirs (&optional nojit)
+ "Reload the directories listed in `yas-snippet-dirs' or
+prompt the user to select one."
+ (let (errors)
+ (if (null yas-snippet-dirs)
+ (call-interactively 'yas-load-directory)
+ (when (member yas--default-user-snippets-dir yas-snippet-dirs)
+ (make-directory yas--default-user-snippets-dir t))
+ (dolist (directory (reverse (yas-snippet-dirs)))
+ (cond ((file-directory-p directory)
+ (yas-load-directory directory (not nojit))
+ (if nojit
+ (yas--message 4 "Loaded %s" directory)
+ (yas--message 4 "Prepared just-in-time loading for %s" directory)))
+ (t
+ (push (yas--message 1 "Check your `yas-snippet-dirs': %s is not a directory" directory) errors)))))
+ errors))
+
+(defun yas-reload-all (&optional no-jit interactive)
+ "Reload all snippets and rebuild the YASnippet menu.
+
+When NO-JIT is non-nil force immediate reload of all known
+snippets under `yas-snippet-dirs', otherwise use just-in-time
+loading.
+
+When called interactively, use just-in-time loading when given a
+prefix argument."
+ (interactive (list (not current-prefix-arg) t))
+ (catch 'abort
+ (let ((errors)
+ (snippet-editing-buffers
+ (cl-remove-if-not (lambda (buffer)
+ (with-current-buffer buffer
+ yas--editing-template))
+ (buffer-list))))
+ ;; Warn if there are buffers visiting snippets, since reloading will break
+ ;; any on-line editing of those buffers.
+ ;;
+ (when snippet-editing-buffers
+ (if interactive
+ (if (y-or-n-p "Some buffers editing live snippets, close them and proceed with reload? ")
+ (mapc #'kill-buffer snippet-editing-buffers)
+ (yas--message 1 "Aborted reload...")
+ (throw 'abort nil))
+ ;; in a non-interactive use, at least set
+ ;; `yas--editing-template' to nil, make it guess it next time around
+ (mapc #'(lambda (buffer)
+ (with-current-buffer buffer
+ (kill-local-variable 'yas--editing-template)))
+ (buffer-list))))
+
+ ;; Empty all snippet tables and parenting info
+ ;;
+ (setq yas--tables (make-hash-table))
+ (setq yas--parents (make-hash-table))
+
+ ;; Before killing `yas--menu-table' use its keys to cleanup the
+ ;; mode menu parts of `yas--minor-mode-menu' (thus also cleaning
+ ;; up `yas-minor-mode-map', which points to it)
+ ;;
+ (maphash #'(lambda (menu-symbol _keymap)
+ (define-key yas--minor-mode-menu (vector menu-symbol) nil))
+ yas--menu-table)
+ ;; Now empty `yas--menu-table' as well
+ (setq yas--menu-table (make-hash-table))
+
+ ;; Cancel all pending 'yas--scheduled-jit-loads'
+ ;;
+ (setq yas--scheduled-jit-loads (make-hash-table))
+
+ ;; Reload the directories listed in `yas-snippet-dirs' or prompt
+ ;; the user to select one.
+ ;;
+ (setq errors (yas--load-snippet-dirs no-jit))
+ ;; Reload the direct keybindings
+ ;;
+ (yas-direct-keymaps-reload)
+
+ (run-hooks 'yas-after-reload-hook)
+ (let ((no-snippets
+ (cl-every (lambda (table) (= (hash-table-count table) 0))
+ (list yas--scheduled-jit-loads
+ yas--parents yas--tables))))
+ (yas--message (if (or no-snippets errors) 2 3)
+ (if no-jit "Snippets loaded %s."
+ "Prepared just-in-time loading of snippets %s.")
+ (cond (errors
+ "with some errors. Check *Messages*")
+ (no-snippets
+ "(but no snippets found)")
+ (t
+ "successfully")))))))
+
+(defvar yas-after-reload-hook nil
+ "Hooks run after `yas-reload-all'.")
+
+(defun yas--load-pending-jits ()
+ (dolist (mode (yas--modes-to-activate))
+ (let ((funs (reverse (gethash mode yas--scheduled-jit-loads))))
+ ;; must reverse to maintain coherence with `yas-snippet-dirs'
+ (dolist (fun funs)
+ (yas--message 4 "Loading for `%s', just-in-time: %s!" mode fun)
+ (funcall fun))
+ (remhash mode yas--scheduled-jit-loads))))
+
+(defun yas-escape-text (text)
+ "Escape TEXT for snippet."
+ (when text
+ (replace-regexp-in-string "[\\$]" "\\\\\\&" text)))
+
+\f
+;;; Snippet compilation function
+
+(defun yas-compile-directory (top-level-dir)
+ "Create .yas-compiled-snippets.el files under subdirs of TOP-LEVEL-DIR.
+
+This works by stubbing a few functions, then calling
+`yas-load-directory'."
+ (interactive "DTop level snippet directory?")
+ (let ((yas--creating-compiled-snippets t))
+ (yas-load-directory top-level-dir nil)))
+
+(defun yas-recompile-all ()
+ "Compile every dir in `yas-snippet-dirs'."
+ (interactive)
+ (mapc #'yas-compile-directory (yas-snippet-dirs)))
+
+
+;;; JIT loading
+;;;
+
+(defvar yas--scheduled-jit-loads (make-hash-table)
+ "Alist of mode-symbols to forms to be evaled when `yas-minor-mode' kicks in.")
+
+(defun yas--schedule-jit (mode fun)
+ (push fun (gethash mode yas--scheduled-jit-loads)))
+
+
+\f
+;;; Some user level functions
+
+(defun yas-about ()
+ (interactive)
+ (message "yasnippet (version %s) -- pluskid/joaotavora/npostavs"
+ (or (ignore-errors (car (let ((default-directory yas--loaddir))
+ (process-lines "git" "describe"
+ "--tags" "--dirty"))))
+ (when (and (featurep 'package)
+ (fboundp 'package-desc-version)
+ (fboundp 'package-version-join))
+ (defvar package-alist)
+ (ignore-errors
+ (let* ((yas-pkg (cdr (assq 'yasnippet package-alist)))
+ (version (package-version-join
+ (package-desc-version (car yas-pkg)))))
+ ;; Special case for MELPA's bogus version numbers.
+ (if (string-match "\\`20..[01][0-9][0-3][0-9][.][0-9]\\{3,4\\}\\'"
+ version)
+ (concat yas--version "-snapshot" version)
+ version))))
+ yas--version)))
+
+\f
+;;; Apropos snippet menu:
+;;
+;; The snippet menu keymaps are stored by mode in hash table called
+;; `yas--menu-table'. They are linked to the main menu in
+;; `yas--menu-keymap-get-create' and are initially created empty,
+;; reflecting the table hierarchy.
+;;
+;; They can be populated in two mutually exclusive ways: (1) by
+;; reading `yas--template-group', which in turn is populated by the "#
+;; group:" directives of the snippets or the ".yas-make-groups" file
+;; or (2) by using a separate `yas-define-menu' call, which declares a
+;; menu structure based on snippets uuids.
+;;
+;; Both situations are handled in `yas--update-template-menu', which
+;; uses the predicate `yas--template-menu-managed-by-yas-define-menu'
+;; that can tell between the two situations.
+;;
+;; Note:
+;;
+;; * if `yas-define-menu' is used it must run before
+;; `yas-define-snippets' and the UUIDS must match, otherwise we get
+;; duplicate entries. The `yas--template' objects are created in
+;; `yas-define-menu', holding nothing but the menu entry,
+;; represented by a pair of ((menu-item NAME :keys KEYS) TYPE) and
+;; stored in `yas--template-menu-binding-pair'. The (menu-item ...)
+;; part is then stored in the menu keymap itself which make the item
+;; appear to the user. These limitations could probably be revised.
+;;
+;; * The `yas--template-perm-group' slot is only used in
+;; `yas-describe-tables'.
+;;
+(defun yas--template-menu-binding-pair-get-create (template &optional type)
+ "Get TEMPLATE's menu binding or assign it a new one.
+
+TYPE may be `:stay', signaling this menu binding should be
+static in the menu."
+ (or (yas--template-menu-binding-pair template)
+ (let (;; (key (yas--template-key template))
+ ;; (keybinding (yas--template-keybinding template))
+ )
+ (setf (yas--template-menu-binding-pair template)
+ (cons `(menu-item ,(or (yas--template-name template)
+ (yas--template-uuid template))
+ ,(yas--make-menu-binding template)
+ :keys ,nil)
+ type)))))
+(defun yas--template-menu-managed-by-yas-define-menu (template)
+ "Non-nil if TEMPLATE's menu entry was included in a `yas-define-menu' call."
+ (cdr (yas--template-menu-binding-pair template)))
+
+
+(defun yas--show-menu-p (mode)
+ (cond ((eq yas-use-menu 'abbreviate)
+ (cl-find mode
+ (mapcar #'yas--table-mode
+ (yas--get-snippet-tables))))
+ (yas-use-menu t)))
+
+(defun yas--delete-from-keymap (keymap uuid)
+ "Recursively delete items with UUID from KEYMAP and its submenus."
+
+ ;; XXX: This used to skip any submenus named \"parent mode\"
+ ;;
+ ;; First of all, recursively enter submenus, i.e. the tree is
+ ;; searched depth first so that stale submenus can be found in the
+ ;; higher passes.
+ ;;
+ (mapc #'(lambda (item)
+ (when (and (consp (cdr-safe item))
+ (keymapp (nth 2 (cdr item))))
+ (yas--delete-from-keymap (nth 2 (cdr item)) uuid)))
+ (cdr keymap))
+ ;; Set the uuid entry to nil
+ ;;
+ (define-key keymap (vector (make-symbol uuid)) nil)
+ ;; Destructively modify keymap
+ ;;
+ (setcdr keymap (cl-delete-if (lambda (item)
+ (cond ((not (listp item)) nil)
+ ((null (cdr item)))
+ ((and (keymapp (nth 2 (cdr item)))
+ (null (cdr (nth 2 (cdr item))))))))
+ (cdr keymap))))
+
+(defun yas-define-menu (mode menu &optional omit-items)
+ "Define a snippet menu for MODE according to MENU, omitting OMIT-ITEMS.
+
+MENU is a list, its elements can be:
+
+- (yas-item UUID) : Creates an entry the snippet identified with
+ UUID. The menu entry for a snippet thus identified is
+ permanent, i.e. it will never move (be reordered) in the menu.
+
+- (yas-separator) : Creates a separator
+
+- (yas-submenu NAME SUBMENU) : Creates a submenu with NAME,
+ SUBMENU has the same form as MENU. NAME is also added to the
+ list of groups of the snippets defined thereafter.
+
+OMIT-ITEMS is a list of snippet uuids that will always be
+omitted from MODE's menu, even if they're manually loaded."
+ (let* ((table (yas--table-get-create mode))
+ (hash (yas--table-uuidhash table)))
+ (yas--define-menu-1 table
+ (yas--menu-keymap-get-create mode)
+ menu
+ hash)
+ (dolist (uuid omit-items)
+ (let ((template (or (gethash uuid hash)
+ (puthash uuid
+ (yas--make-template :table table
+ :uuid uuid)
+ hash))))
+ (setf (yas--template-menu-binding-pair template) (cons nil :none))))))
+
+(defun yas--define-menu-1 (table menu-keymap menu uuidhash &optional group-list)
+ "Helper for `yas-define-menu'."
+ (cl-loop
+ for (type name submenu) in (reverse menu)
+ collect (cond
+ ((or (eq type 'yas-item)
+ (and yas-alias-to-yas/prefix-p
+ (eq type 'yas/item)))
+ (let ((template (or (gethash name uuidhash)
+ (puthash name
+ (yas--make-template
+ :table table
+ :perm-group group-list
+ :uuid name)
+ uuidhash))))
+ (car (yas--template-menu-binding-pair-get-create
+ template :stay))))
+ ((or (eq type 'yas-submenu)
+ (and yas-alias-to-yas/prefix-p
+ (eq type 'yas/submenu)))
+ (let ((subkeymap (make-sparse-keymap)))
+ (yas--define-menu-1 table subkeymap submenu uuidhash
+ (append group-list (list name)))
+ `(menu-item ,name ,subkeymap)))
+ ((or (eq type 'yas-separator)
+ (and yas-alias-to-yas/prefix-p
+ (eq type 'yas/separator)))
+ '(menu-item "----"))
+ (t (yas--message 1 "Don't know anything about menu entry %s" type)
+ nil))
+ into menu-entries
+ finally do (push (apply #'vector menu-entries) (cdr menu-keymap))))
+\f
+(defun yas--define (mode key template &optional name condition group)
+ "Define a snippet. Expanding KEY into TEMPLATE.
+
+NAME is a description to this template. Also update the menu if
+`yas-use-menu' is t. CONDITION is the condition attached to
+this snippet. If you attach a condition to a snippet, then it
+will only be expanded when the condition evaluated to non-nil."
+ (yas-define-snippets mode
+ (list (list key template name condition group))))
+
+(defun yas-hippie-try-expand (first-time?)
+ "Integrate with hippie expand.
+
+Just put this function in `hippie-expand-try-functions-list'."
+ (when yas-minor-mode
+ (if (not first-time?)
+ (let ((yas-fallback-behavior 'return-nil))
+ (yas-expand))
+ (undo 1)
+ nil)))
+
+
+;;; Apropos condition-cache:
+;;;
+;;;
+;;;
+;;;
+(defmacro yas-define-condition-cache (func doc &rest body)
+ "Define a function FUNC with doc DOC and body BODY.
+BODY is executed at most once every snippet expansion attempt, to check
+expansion conditions.
+
+It doesn't make any sense to call FUNC programatically."
+ `(defun ,func () ,(if (and doc
+ (stringp doc))
+ (concat doc
+"\n\nFor use in snippets' conditions. Within each
+snippet-expansion routine like `yas-expand', computes actual
+value for the first time then always returns a cached value.")
+ (setq body (cons doc body))
+ nil)
+ (let ((timestamp-and-value (get ',func 'yas--condition-cache)))
+ (if (equal (car timestamp-and-value) yas--condition-cache-timestamp)
+ (cdr timestamp-and-value)
+ (let ((new-value (progn
+ ,@body
+ )))
+ (put ',func 'yas--condition-cache (cons yas--condition-cache-timestamp new-value))
+ new-value)))))
+
+(defalias 'yas-expand 'yas-expand-from-trigger-key)
+(defun yas-expand-from-trigger-key (&optional field)
+ "Expand a snippet before point.
+
+If no snippet expansion is possible, fall back to the behaviour
+defined in `yas-fallback-behavior'.
+
+Optional argument FIELD is for non-interactive use and is an
+object satisfying `yas--field-p' to restrict the expansion to."
+ (interactive)
+ (setq yas--condition-cache-timestamp (current-time))
+ (let (templates-and-pos)
+ (unless (and yas-expand-only-for-last-commands
+ (not (member last-command yas-expand-only-for-last-commands)))
+ (setq templates-and-pos (if field
+ (save-restriction
+ (narrow-to-region (yas--field-start field)
+ (yas--field-end field))
+ (yas--templates-for-key-at-point))
+ (yas--templates-for-key-at-point))))
+ (if templates-and-pos
+ (yas--expand-or-prompt-for-template
+ (nth 0 templates-and-pos)
+ ;; Delete snippet key and active region when expanding.
+ (min (if (use-region-p) (region-beginning) most-positive-fixnum)
+ (nth 1 templates-and-pos))
+ (max (if (use-region-p) (region-end) most-negative-fixnum)
+ (nth 2 templates-and-pos)))
+ (yas--fallback))))
+
+(defun yas--maybe-expand-from-keymap-filter (cmd)
+ (let* ((yas--condition-cache-timestamp (current-time))
+ (vec (cl-subseq (this-command-keys-vector)
+ (if current-prefix-arg
+ (length (this-command-keys))
+ 0)))
+ (templates (cl-mapcan (lambda (table)
+ (yas--fetch table vec))
+ (yas--get-snippet-tables))))
+ (if templates (or cmd templates))))
+
+(defun yas-expand-from-keymap ()
+ "Directly expand some snippets, searching `yas--direct-keymaps'."
+ (interactive)
+ (setq yas--condition-cache-timestamp (current-time))
+ (let* ((templates (yas--maybe-expand-from-keymap-filter nil)))
+ (when templates
+ (yas--expand-or-prompt-for-template templates))))
+
+(defun yas--expand-or-prompt-for-template (templates &optional start end)
+ "Expand one of TEMPLATES from START to END.
+
+Prompt the user if TEMPLATES has more than one element, else
+expand immediately. Common gateway for
+`yas-expand-from-trigger-key' and `yas-expand-from-keymap'."
+ (let ((yas--current-template (or (and (cl-rest templates) ;; more than one
+ (yas--prompt-for-template (mapcar #'cdr templates)))
+ (cdar templates))))
+ (when yas--current-template
+ (yas-expand-snippet (yas--template-content yas--current-template)
+ start
+ end
+ (yas--template-expand-env yas--current-template)))))
+
+;; Apropos the trigger key and the fallback binding:
+;;
+;; When `yas-minor-mode-map' binds <tab>, that correctly overrides
+;; org-mode's <tab>, for example and searching for fallbacks correctly
+;; returns `org-cycle'. However, most other modes bind "TAB". TODO,
+;; improve this explanation.
+;;
+(defun yas--fallback ()
+ "Fallback after expansion has failed.
+
+Common gateway for `yas-expand-from-trigger-key' and
+`yas-expand-from-keymap'."
+ (cond ((eq yas-fallback-behavior 'return-nil)
+ ;; return nil
+ nil)
+ ((eq yas-fallback-behavior 'yas--fallback)
+ (error (concat "yasnippet fallback loop!\n"
+ "This can happen when you bind `yas-expand' "
+ "outside of the `yas-minor-mode-map'.")))
+ ((eq yas-fallback-behavior 'call-other-command)
+ (let* ((yas-fallback-behavior 'yas--fallback)
+ ;; Also bind `yas-minor-mode' to prevent fallback
+ ;; loops when other extensions use mechanisms similar
+ ;; to `yas--keybinding-beyond-yasnippet'. (github #525
+ ;; and #526)
+ ;;
+ (yas-minor-mode nil)
+ (beyond-yasnippet (yas--keybinding-beyond-yasnippet)))
+ (yas--message 4 "Falling back to %s" beyond-yasnippet)
+ (cl-assert (or (null beyond-yasnippet) (commandp beyond-yasnippet)))
+ (setq this-command beyond-yasnippet)
+ (when beyond-yasnippet
+ (call-interactively beyond-yasnippet))))
+ ((and (listp yas-fallback-behavior)
+ (cdr yas-fallback-behavior)
+ (eq 'apply (car yas-fallback-behavior)))
+ (let ((command-or-fn (cadr yas-fallback-behavior))
+ (args (cddr yas-fallback-behavior))
+ (yas-fallback-behavior 'yas--fallback)
+ (yas-minor-mode nil))
+ (if args
+ (apply command-or-fn args)
+ (when (commandp command-or-fn)
+ (setq this-command command-or-fn)
+ (call-interactively command-or-fn)))))
+ (t
+ ;; also return nil if all the other fallbacks have failed
+ nil)))
+
+(defun yas--keybinding-beyond-yasnippet ()
+ "Get current keys's binding as if YASsnippet didn't exist."
+ (let* ((yas-minor-mode nil)
+ (yas--direct-keymaps nil)
+ (keys (this-single-command-keys)))
+ (or (key-binding keys t)
+ (key-binding (yas--fallback-translate-input keys) t))))
+
+(defun yas--fallback-translate-input (keys)
+ "Emulate `read-key-sequence', at least what I think it does.
+
+Keys should be an untranslated key vector. Returns a translated
+vector of keys. FIXME not thoroughly tested."
+ (let ((retval [])
+ (i 0))
+ (while (< i (length keys))
+ (let ((j i)
+ (translated local-function-key-map))
+ (while (and (< j (length keys))
+ translated
+ (keymapp translated))
+ (setq translated (cdr (assoc (aref keys j) (remove 'keymap translated)))
+ j (1+ j)))
+ (setq retval (vconcat retval (cond ((symbolp translated)
+ `[,translated])
+ ((vectorp translated)
+ translated)
+ (t
+ (substring keys i j)))))
+ (setq i j)))
+ retval))
+
+\f
+;;; Utils for snippet development:
+
+(defun yas--all-templates (tables)
+ "Get `yas--template' objects in TABLES, applicable for buffer and point.
+
+Honours `yas-choose-tables-first', `yas-choose-keys-first' and
+`yas-buffer-local-condition'"
+ (when yas-choose-tables-first
+ (setq tables (list (yas--prompt-for-table tables))))
+ (mapcar #'cdr
+ (if yas-choose-keys-first
+ (let ((key (yas--prompt-for-keys
+ (cl-mapcan #'yas--table-all-keys tables))))
+ (when key
+ (cl-mapcan (lambda (table)
+ (yas--fetch table key))
+ tables)))
+ (cl-remove-duplicates (cl-mapcan #'yas--table-templates tables)
+ :test #'equal))))
+
+(defun yas--lookup-snippet-1 (name mode)
+ "Get the snippet called NAME in MODE's tables."
+ (let ((yas-choose-tables-first nil) ; avoid prompts
+ (yas-choose-keys-first nil))
+ (cl-find name (yas--all-templates
+ (yas--get-snippet-tables mode))
+ :key #'yas--template-name :test #'string=)))
+
+(defun yas-lookup-snippet (name &optional mode noerror)
+ "Get the snippet content for the snippet NAME in MODE's tables.
+
+MODE defaults to the current buffer's `major-mode'. If NOERROR
+is non-nil, then don't signal an error if there isn't any snippet
+called NAME.
+
+Honours `yas-buffer-local-condition'."
+ (let ((snippet (yas--lookup-snippet-1 name mode)))
+ (cond
+ (snippet (yas--template-content snippet))
+ (noerror nil)
+ (t (error "No snippet named: %s" name)))))
+
+(defun yas-insert-snippet (&optional no-condition)
+ "Choose a snippet to expand, pop-up a list of choices according
+to `yas-prompt-functions'.
+
+With prefix argument NO-CONDITION, bypass filtering of snippets
+by condition."
+ (interactive "P")
+ (setq yas--condition-cache-timestamp (current-time))
+ (let* ((yas-buffer-local-condition (or (and no-condition
+ 'always)
+ yas-buffer-local-condition))
+ (templates (yas--all-templates (yas--get-snippet-tables)))
+ (yas--current-template (and templates
+ (or (and (cl-rest templates) ;; more than one template for same key
+ (yas--prompt-for-template templates))
+ (car templates))))
+ (where (if (region-active-p)
+ (cons (region-beginning) (region-end))
+ (cons (point) (point)))))
+ (if yas--current-template
+ (yas-expand-snippet (yas--template-content yas--current-template)
+ (car where)
+ (cdr where)
+ (yas--template-expand-env yas--current-template))
+ (yas--message 1 "No snippets can be inserted here!"))))
+
+(defun yas-visit-snippet-file ()
+ "Choose a snippet to edit, selection like `yas-insert-snippet'.
+
+Only success if selected snippet was loaded from a file. Put the
+visited file in `snippet-mode'."
+ (interactive)
+ (let* ((yas-buffer-local-condition 'always)
+ (templates (yas--all-templates (yas--get-snippet-tables)))
+ (template (and templates
+ (or (yas--prompt-for-template templates
+ "Choose a snippet template to edit: ")
+ (car templates)))))
+
+ (if template
+ (yas--visit-snippet-file-1 template)
+ (message "No snippets tables active!"))))
+
+(defun yas--visit-snippet-file-1 (template)
+ "Helper for `yas-visit-snippet-file'."
+ (let ((file (yas--template-get-file template)))
+ (cond ((and file (file-readable-p file))
+ (find-file-other-window file)
+ (snippet-mode)
+ (set (make-local-variable 'yas--editing-template) template))
+ (file
+ (message "Original file %s no longer exists!" file))
+ (t
+ (switch-to-buffer (format "*%s*"(yas--template-name template)))
+ (let ((type 'snippet))
+ (when (listp (yas--template-content template))
+ (insert (format "# type: command\n"))
+ (setq type 'command))
+ (insert (format "# key: %s\n" (yas--template-key template)))
+ (insert (format "# name: %s\n" (yas--template-name template)))
+ (when (yas--template-keybinding template)
+ (insert (format "# binding: %s\n" (yas--template-keybinding template))))
+ (when (yas--template-expand-env template)
+ (insert (format "# expand-env: %s\n" (yas--template-expand-env template))))
+ (when (yas--template-condition template)
+ (insert (format "# condition: %s\n" (yas--template-condition template))))
+ (insert "# --\n")
+ (insert (if (eq type 'command)
+ (pp-to-string (yas--template-content template))
+ (yas--template-content template))))
+ (snippet-mode)
+ (set (make-local-variable 'yas--editing-template) template)
+ (set (make-local-variable 'default-directory)
+ (car (cdr (car (yas--guess-snippet-directories (yas--template-table template))))))))))
+
+(defun yas--guess-snippet-directories-1 (table)
+ "Guess possible snippet subdirectories for TABLE."
+ (cons (file-name-as-directory (yas--table-name table))
+ (cl-mapcan #'yas--guess-snippet-directories-1
+ (yas--table-parents table))))
+
+(defun yas--guess-snippet-directories (&optional table)
+ "Try to guess suitable directories based on the current active
+tables (or optional TABLE).
+
+Returns a list of elements (TABLE . DIRS) where TABLE is a
+`yas--table' object and DIRS is a list of all possible directories
+where snippets of table might exist."
+ (let ((main-dir (car (or (yas-snippet-dirs)
+ (setq yas-snippet-dirs
+ (list yas--default-user-snippets-dir)))))
+ (tables (if table (list table)
+ (yas--get-snippet-tables))))
+ ;; HACK! the snippet table created here is actually registered!
+ ;;
+ (unless (or table (gethash major-mode yas--tables))
+ (push (yas--table-get-create major-mode)
+ tables))
+
+ (mapcar #'(lambda (table)
+ (cons table
+ (mapcar #'(lambda (subdir)
+ (expand-file-name subdir main-dir))
+ (yas--guess-snippet-directories-1 table))))
+ tables)))
+
+(defun yas--make-directory-maybe (table-and-dirs &optional main-table-string)
+ "Return a dir inside TABLE-AND-DIRS, prompts for creation if none exists."
+ (or (cl-some (lambda (dir) (when (file-directory-p dir) dir))
+ (cdr table-and-dirs))
+ (let ((candidate (cl-first (cdr table-and-dirs))))
+ (unless (file-writable-p (file-name-directory candidate))
+ (error (yas--format "%s is not writable." candidate)))
+ (if (y-or-n-p (format "Guessed directory (%s) for%s%s table \"%s\" does not exist! Create? "
+ candidate
+ (if (gethash (yas--table-mode (car table-and-dirs))
+ yas--tables)
+ ""
+ " brand new")
+ (or main-table-string
+ "")
+ (yas--table-name (car table-and-dirs))))
+ (progn
+ (make-directory candidate 'also-make-parents)
+ ;; create the .yas-parents file here...
+ candidate)))))
+
+;; NOTE: Using the traditional "*new snippet*" stops whitespace mode
+;; from activating (it doesn't like the leading "*").
+(defconst yas-new-snippet-buffer-name "+new-snippet+")
+
+(defun yas-new-snippet (&optional no-template)
+ "Pops a new buffer for writing a snippet.
+
+Expands a snippet-writing snippet, unless the optional prefix arg
+NO-TEMPLATE is non-nil."
+ (interactive "P")
+ (let ((guessed-directories (yas--guess-snippet-directories))
+ (yas-selected-text (or yas-selected-text
+ (and (region-active-p)
+ (buffer-substring-no-properties
+ (region-beginning) (region-end))))))
+
+ (switch-to-buffer yas-new-snippet-buffer-name)
+ (erase-buffer)
+ (kill-all-local-variables)
+ (snippet-mode)
+ (yas-minor-mode 1)
+ (set (make-local-variable 'yas--guessed-modes)
+ (mapcar (lambda (d) (yas--table-mode (car d)))
+ guessed-directories))
+ (set (make-local-variable 'default-directory)
+ (car (cdr (car guessed-directories))))
+ (if (and (not no-template) yas-new-snippet-default)
+ (yas-expand-snippet yas-new-snippet-default))))
+
+(defun yas--compute-major-mode-and-parents (file)
+ "Given FILE, find the nearest snippet directory for a given mode.
+
+Returns a list (MODE-SYM PARENTS), the mode's symbol and a list
+representing one or more of the mode's parents.
+
+Note that MODE-SYM need not be the symbol of a real major mode,
+neither do the elements of PARENTS."
+ (let* ((file-dir (and file
+ (directory-file-name
+ (or (cl-some (lambda (special)
+ (locate-dominating-file file special))
+ '(".yas-setup.el"
+ ".yas-make-groups"
+ ".yas-parents"))
+ (directory-file-name (file-name-directory file))))))
+ (parents-file-name (concat file-dir "/.yas-parents"))
+ (major-mode-name (and file-dir
+ (file-name-nondirectory file-dir)))
+ (major-mode-sym (or (and major-mode-name
+ (intern major-mode-name))))
+ (parents (when (file-readable-p parents-file-name)
+ (mapcar #'intern
+ (split-string
+ (with-temp-buffer
+ (insert-file-contents parents-file-name)
+ (buffer-substring-no-properties (point-min)
+ (point-max))))))))
+ (when major-mode-sym
+ (cons major-mode-sym (remove major-mode-sym parents)))))
+
+(defvar yas--editing-template nil
+ "Supporting variable for `yas-load-snippet-buffer' and `yas--visit-snippet'.")
+
+(defvar yas--current-template nil
+ "Holds the current template being expanded into a snippet.")
+
+(defvar yas--guessed-modes nil
+ "List of guessed modes supporting `yas-load-snippet-buffer'.")
+
+(defun yas--read-table ()
+ "Ask user for a snippet table, help with some guessing."
+ (let ((prompt (if (and (featurep 'ido)
+ ido-mode)
+ 'ido-completing-read 'completing-read)))
+ (unless yas--guessed-modes
+ (set (make-local-variable 'yas--guessed-modes)
+ (or (yas--compute-major-mode-and-parents buffer-file-name))))
+ (intern
+ (funcall prompt (format "Choose or enter a table (yas guesses %s): "
+ (if yas--guessed-modes
+ (cl-first yas--guessed-modes)
+ "nothing"))
+ (mapcar #'symbol-name yas--guessed-modes)
+ nil
+ nil
+ nil
+ nil
+ (if (cl-first yas--guessed-modes)
+ (symbol-name (cl-first yas--guessed-modes)))))))
+
+(defun yas-load-snippet-buffer (table &optional interactive)
+ "Parse and load current buffer's snippet definition into TABLE.
+TABLE is a symbol name passed to `yas--table-get-create'. When
+called interactively, prompt for the table name.
+Return the `yas--template' object created"
+ (interactive (list (yas--read-table) t))
+ (cond
+ ;; We have `yas--editing-template', this buffer's content comes from a
+ ;; template which is already loaded and neatly positioned,...
+ ;;
+ (yas--editing-template
+ (yas--define-snippets-1 (yas--parse-template (yas--template-load-file yas--editing-template))
+ (yas--template-table yas--editing-template)))
+ ;; Try to use `yas--guessed-modes'. If we don't have that use the
+ ;; value from `yas--compute-major-mode-and-parents'
+ ;;
+ (t
+ (unless yas--guessed-modes
+ (set (make-local-variable 'yas--guessed-modes) (or (yas--compute-major-mode-and-parents buffer-file-name))))
+ (let* ((table (yas--table-get-create table)))
+ (set (make-local-variable 'yas--editing-template)
+ (yas--define-snippets-1 (yas--parse-template buffer-file-name)
+ table)))))
+ (when interactive
+ (yas--message 3 "Snippet \"%s\" loaded for %s."
+ (yas--template-name yas--editing-template)
+ (yas--table-name (yas--template-table yas--editing-template))))
+ yas--editing-template)
+
+(defun yas-maybe-load-snippet-buffer ()
+ "Added to `after-save-hook' in `snippet-mode'."
+ (let* ((mode (intern (file-name-sans-extension
+ (file-name-nondirectory
+ (directory-file-name default-directory)))))
+ (current-snippet
+ (apply #'yas--define-snippets-2 (yas--table-get-create mode)
+ (yas--parse-template buffer-file-name)))
+ (uuid (yas--template-uuid current-snippet)))
+ (unless (equal current-snippet
+ (if uuid (yas--get-template-by-uuid mode uuid)
+ (yas--lookup-snippet-1
+ (yas--template-name current-snippet) mode)))
+ (yas-load-snippet-buffer mode t))))
+
+(defun yas-load-snippet-buffer-and-close (table &optional kill)
+ "Load and save the snippet, then `quit-window' if saved.
+Loading is performed by `yas-load-snippet-buffer'. If the
+snippet is new, ask the user whether (and where) to save it. If
+the snippet already has a file, just save it.
+
+The prefix argument KILL is passed to `quit-window'.
+
+Don't use this from a Lisp program, call `yas-load-snippet-buffer'
+and `kill-buffer' instead."
+ (interactive (list (yas--read-table) current-prefix-arg))
+ (let ((template (yas-load-snippet-buffer table t)))
+ (when (and (buffer-modified-p)
+ (y-or-n-p
+ (format "[yas] Loaded for %s. Also save snippet buffer?"
+ (yas--table-name (yas--template-table template)))))
+ (let ((default-directory (car (cdr (car (yas--guess-snippet-directories
+ (yas--template-table template))))))
+ (default-file-name (yas--template-name template)))
+ (unless (or buffer-file-name (not default-file-name))
+ (setq buffer-file-name
+ (read-file-name "File to save snippet in: "
+ nil nil nil default-file-name))
+ (rename-buffer (file-name-nondirectory buffer-file-name) t))
+ (save-buffer)))
+ (quit-window kill)))
+
+(defun yas-tryout-snippet (&optional debug)
+ "Test current buffer's snippet template in other buffer."
+ (interactive "P")
+ (let* ((major-mode-and-parent (yas--compute-major-mode-and-parents buffer-file-name))
+ (parsed (yas--parse-template))
+ (test-mode (or (and (car major-mode-and-parent)
+ (fboundp (car major-mode-and-parent))
+ (car major-mode-and-parent))
+ (cl-first yas--guessed-modes)
+ (intern (read-from-minibuffer (yas--format "Please input a mode: ")))))
+ (yas--current-template
+ (and parsed
+ (fboundp test-mode)
+ (yas--make-template :table nil ;; no tables for ephemeral snippets
+ :key (nth 0 parsed)
+ :content (nth 1 parsed)
+ :name (nth 2 parsed)
+ :expand-env (nth 5 parsed)))))
+ (cond (yas--current-template
+ (let ((buffer-name (format "*testing snippet: %s*" (yas--template-name yas--current-template))))
+ (kill-buffer (get-buffer-create buffer-name))
+ (switch-to-buffer (get-buffer-create buffer-name))
+ (setq buffer-undo-list nil)
+ (condition-case nil (funcall test-mode) (error nil))
+ (yas-minor-mode 1)
+ (setq buffer-read-only nil)
+ (yas-expand-snippet (yas--template-content yas--current-template)
+ (point-min)
+ (point-max)
+ (yas--template-expand-env yas--current-template))
+ (when (and debug
+ (require 'yasnippet-debug nil t)
+ (fboundp 'yas-debug-snippet-vars))
+ (add-hook 'post-command-hook #'yas-debug-snippet-vars nil t))))
+ (t
+ (yas--message 1 "Cannot test snippet for unknown major mode")))))
+
+(defun yas-active-keys ()
+ "Return all active trigger keys for current buffer and point."
+ (cl-remove-duplicates
+ (cl-remove-if-not #'stringp (cl-mapcan #'yas--table-all-keys
+ (yas--get-snippet-tables)))
+ :test #'string=))
+
+(defun yas--template-fine-group (template)
+ (car (last (or (yas--template-group template)
+ (yas--template-perm-group template)))))
+
+(defun yas-describe-table-by-namehash ()
+ "Display snippet tables by NAMEHASH."
+ (interactive)
+ (with-current-buffer (get-buffer-create "*YASnippet Tables by NAMEHASH*")
+ (let ((inhibit-read-only t))
+ (erase-buffer)
+ (insert "YASnippet tables by NAMEHASH: \n")
+ (maphash
+ (lambda (_mode table)
+ (insert (format "\nSnippet table `%s':\n\n" (yas--table-name table)))
+ (maphash
+ (lambda (key _v)
+ (insert (format " key %s maps snippets: %s\n" key
+ (let ((names))
+ (maphash #'(lambda (k _v)
+ (push k names))
+ (gethash key (yas--table-hash table)))
+ names))))
+ (yas--table-hash table)))
+ yas--tables))
+ (view-mode +1)
+ (goto-char 1)
+ (display-buffer (current-buffer))))
+
+(defun yas-describe-tables (&optional with-nonactive)
+ "Display snippets for each table."
+ (interactive "P")
+ (let ((original-buffer (current-buffer))
+ (tables (yas--get-snippet-tables)))
+ (with-current-buffer (get-buffer-create "*YASnippet Tables*")
+ (let ((inhibit-read-only t))
+ (when with-nonactive
+ (maphash #'(lambda (_k v)
+ (cl-pushnew v tables))
+ yas--tables))
+ (erase-buffer)
+ (insert "YASnippet tables:\n")
+ (dolist (table tables)
+ (yas--describe-pretty-table table original-buffer))
+ (yas--create-snippet-xrefs))
+ (help-mode)
+ (goto-char 1)
+ (display-buffer (current-buffer)))))
+
+(defun yas--describe-pretty-table (table &optional original-buffer)
+ (insert (format "\nSnippet table `%s'"
+ (yas--table-name table)))
+ (if (yas--table-parents table)
+ (insert (format " parents: %s\n"
+ (mapcar #'yas--table-name
+ (yas--table-parents table))))
+ (insert "\n"))
+ (insert (make-string 100 ?-) "\n")
+ (insert "group state name key binding\n")
+ (let ((groups-hash (make-hash-table :test #'equal)))
+ (maphash #'(lambda (_k v)
+ (let ((group (or (yas--template-fine-group v)
+ "(top level)")))
+ (when (yas--template-name v)
+ (puthash group
+ (cons v (gethash group groups-hash))
+ groups-hash))))
+ (yas--table-uuidhash table))
+ (maphash
+ #'(lambda (group templates)
+ (setq group (truncate-string-to-width group 25 0 ? "..."))
+ (insert (make-string 100 ?-) "\n")
+ (dolist (p templates)
+ (let* ((name (truncate-string-to-width (propertize (format "\\\\snippet `%s'" (yas--template-name p))
+ 'yasnippet p)
+ 50 0 ? "..."))
+ (group (prog1 group
+ (setq group (make-string (length group) ? ))))
+ (condition-string (let ((condition (yas--template-condition p)))
+ (if (and condition
+ original-buffer)
+ (with-current-buffer original-buffer
+ (if (yas--eval-condition condition)
+ "(y)"
+ "(s)"))
+ "(a)")))
+ (key-description-string (key-description (yas--template-keybinding p)))
+ (template-key-padding (if (string= key-description-string "") nil ? )))
+ (insert group " "
+ condition-string " "
+ name (if (string-match "\\.\\.\\.$" name)
+ "'" " ")
+ " "
+ (truncate-string-to-width (or (yas--template-key p) "")
+ 15 0 template-key-padding "...")
+ (or template-key-padding "")
+ (truncate-string-to-width key-description-string
+ 15 0 nil "...")
+ "\n"))))
+ groups-hash)))
+
+
+\f
+;;; User convenience functions, for using in `yas-key-syntaxes'
+
+(defun yas-try-key-from-whitespace (_start-point)
+ "As `yas-key-syntaxes' element, look for whitespace delimited key.
+
+A newline will be considered whitespace even if the mode syntax
+marks it as something else (typically comment ender)."
+ (skip-chars-backward "^[:space:]\n"))
+
+(defun yas-shortest-key-until-whitespace (_start-point)
+ "Like `yas-longest-key-from-whitespace' but take the shortest key."
+ (when (/= (skip-chars-backward "^[:space:]\n" (1- (point))) 0)
+ 'again))
+
+(defun yas-longest-key-from-whitespace (start-point)
+ "As `yas-key-syntaxes' element, look for longest key between point and whitespace.
+
+A newline will be considered whitespace even if the mode syntax
+marks it as something else (typically comment ender)."
+ (if (= (point) start-point)
+ (yas-try-key-from-whitespace start-point)
+ (forward-char))
+ (unless (<= start-point (1+ (point)))
+ 'again))
+
+
+\f
+;;; User convenience functions, for using in snippet definitions
+
+(defvar yas-modified-p nil
+ "Non-nil if field has been modified by user or transformation.")
+
+(defvar yas-moving-away-p nil
+ "Non-nil if user is about to exit field.")
+
+(defvar yas-text nil
+ "Contains current field text.")
+
+(defun yas-substr (str pattern &optional subexp)
+ "Search PATTERN in STR and return SUBEXPth match.
+
+If found, the content of subexp group SUBEXP (default 0) is
+ returned, or else the original STR will be returned."
+ (let ((grp (or subexp 0)))
+ (save-match-data
+ (if (string-match pattern str)
+ (match-string-no-properties grp str)
+ str))))
+
+(defun yas-choose-value (&rest possibilities)
+ "Prompt for a string in POSSIBILITIES and return it.
+
+The last element of POSSIBILITIES may be a list of strings."
+ (unless (or yas-moving-away-p
+ yas-modified-p)
+ (let* ((last-link (last possibilities))
+ (last-elem (car last-link)))
+ (when (listp last-elem)
+ (setcar last-link (car last-elem))
+ (setcdr last-link (cdr last-elem))))
+ (cl-some (lambda (fn)
+ (funcall fn "Choose: " possibilities))
+ yas-prompt-functions)))
+
+(defun yas-key-to-value (alist)
+ (unless (or yas-moving-away-p
+ yas-modified-p)
+ (let ((key (read-key-sequence "")))
+ (when (stringp key)
+ (or (cdr (cl-find key alist :key #'car :test #'string=))
+ key)))))
+
+(defun yas-throw (text)
+ "Signal `yas-exception' with TEXT as the reason."
+ (signal 'yas-exception (list text)))
+(put 'yas-exception 'error-conditions '(error yas-exception))
+(put 'yas-exception 'error-message "[yas] Exception")
+
+(defun yas-verify-value (possibilities)
+ "Verify that the current field value is in POSSIBILITIES.
+Otherwise signal `yas-exception'."
+ (when (and yas-moving-away-p (cl-notany (lambda (pos) (string= pos yas-text)) possibilities))
+ (yas-throw (format "Field only allows %s" possibilities))))
+
+(defun yas-field-value (number)
+ "Get the string for field with NUMBER.
+
+Use this in primary and mirror transformations to tget."
+ (let* ((snippet (car (yas-active-snippets)))
+ (field (and snippet
+ (yas--snippet-find-field snippet number))))
+ (when field
+ (yas--field-text-for-display field))))
+
+(defun yas-text ()
+ "Return `yas-text' if that exists and is non-empty, else nil."
+ (if (and yas-text
+ (not (string= "" yas-text)))
+ yas-text))
+
+(defun yas-selected-text ()
+ "Return `yas-selected-text' if that exists and is non-empty, else nil."
+ (if (and yas-selected-text
+ (not (string= "" yas-selected-text)))
+ yas-selected-text))
+
+(defun yas--get-field-once (number &optional transform-fn)
+ (unless yas-modified-p
+ (if transform-fn
+ (funcall transform-fn (yas-field-value number))
+ (yas-field-value number))))
+
+(defun yas-default-from-field (number)
+ (unless yas-modified-p
+ (yas-field-value number)))
+
+(defun yas-inside-string ()
+ "Return non-nil if the point is inside a string according to font-lock."
+ (equal 'font-lock-string-face (get-char-property (1- (point)) 'face)))
+
+(defun yas-unimplemented (&optional missing-feature)
+ (if yas--current-template
+ (if (y-or-n-p (format "This snippet is unimplemented (missing %s) Visit the snippet definition? "
+ (or missing-feature
+ "something")))
+ (yas--visit-snippet-file-1 yas--current-template))
+ (message "No implementation. Missing %s" (or missing-feature "something"))))
+
+\f
+;;; Snippet expansion and field management
+
+(defvar yas--active-field-overlay nil
+ "Overlays the currently active field.")
+
+(defvar yas--field-protection-overlays nil
+ "Two overlays protect the current active field.")
+
+(defvar yas-selected-text nil
+ "The selected region deleted on the last snippet expansion.")
+
+(defvar yas--start-column nil
+ "The column where the snippet expansion started.")
+
+(make-variable-buffer-local 'yas--active-field-overlay)
+(make-variable-buffer-local 'yas--field-protection-overlays)
+(put 'yas--active-field-overlay 'permanent-local t)
+(put 'yas--field-protection-overlays 'permanent-local t)
+
+(cl-defstruct (yas--snippet (:constructor yas--make-snippet (expand-env)))
+ "A snippet.
+
+..."
+ expand-env
+ (fields '())
+ (exit nil)
+ (id (yas--snippet-next-id) :read-only t)
+ (control-overlay nil)
+ active-field
+ ;; stacked expansion: the `previous-active-field' slot saves the
+ ;; active field where the child expansion took place
+ previous-active-field
+ force-exit)
+
+(cl-defstruct (yas--field (:constructor yas--make-field (number start end parent-field)))
+ "A field.
+
+NUMBER is the field number.
+START and END are mostly buffer markers, but see \"apropos markers-to-points\".
+PARENT-FIELD is a `yas--field' this field is nested under, or nil.
+MIRRORS is a list of `yas--mirror's
+TRANSFORM is a lisp form.
+MODIFIED-P is a boolean set to true once user inputs text.
+NEXT is another `yas--field' or `yas--mirror' or `yas--exit'.
+"
+ number
+ start end
+ parent-field
+ (mirrors '())
+ (transform nil)
+ (modified-p nil)
+ next)
+
+
+(cl-defstruct (yas--mirror (:constructor yas--make-mirror (start end transform)))
+ "A mirror.
+
+START and END are mostly buffer markers, but see \"apropos markers-to-points\".
+TRANSFORM is a lisp form.
+PARENT-FIELD is a `yas--field' this mirror is nested under, or nil.
+NEXT is another `yas--field' or `yas--mirror' or `yas--exit'
+DEPTH is a count of how many nested mirrors can affect this mirror"
+ start end
+ (transform nil)
+ parent-field
+ next
+ depth)
+
+(cl-defstruct (yas--exit (:constructor yas--make-exit (marker)))
+ marker
+ next)
+
+(defmacro yas--letenv (env &rest body)
+ "Evaluate BODY with bindings from ENV.
+ENV is a lisp expression that evaluates to list of elements with
+the form (VAR FORM), where VAR is a symbol and FORM is a lisp
+expression that evaluates to its value."
+ (declare (debug (form body)) (indent 1))
+ (let ((envvar (make-symbol "envvar")))
+ `(let ((,envvar ,env))
+ (cl-progv
+ (mapcar #'car ,envvar)
+ (mapcar (lambda (v-f) (eval (cadr v-f))) ,envvar)
+ ,@body))))
+
+(defun yas--snippet-map-markers (fun snippet)
+ "Apply FUN to all marker (sub)fields in SNIPPET.
+Update each field with the result of calling FUN."
+ (dolist (field (yas--snippet-fields snippet))
+ (setf (yas--field-start field) (funcall fun (yas--field-start field)))
+ (setf (yas--field-end field) (funcall fun (yas--field-end field)))
+ (dolist (mirror (yas--field-mirrors field))
+ (setf (yas--mirror-start mirror) (funcall fun (yas--mirror-start mirror)))
+ (setf (yas--mirror-end mirror) (funcall fun (yas--mirror-end mirror)))))
+ (let ((snippet-exit (yas--snippet-exit snippet)))
+ (when snippet-exit
+ (setf (yas--exit-marker snippet-exit)
+ (funcall fun (yas--exit-marker snippet-exit))))))
+
+(defun yas--snippet-live-p (snippet)
+ "Return non-nil if SNIPPET hasn't been committed."
+ (catch 'live
+ (yas--snippet-map-markers (lambda (m)
+ (if (markerp m) m
+ (throw 'live nil)))
+ snippet)
+ t))
+
+(defun yas--apply-transform (field-or-mirror field &optional empty-on-nil-p)
+ "Calculate transformed string for FIELD-OR-MIRROR from FIELD.
+
+If there is no transform for ht field, return nil.
+
+If there is a transform but it returns nil, return the empty
+string iff EMPTY-ON-NIL-P is true."
+ (let* ((yas-text (yas--field-text-for-display field))
+ (yas-modified-p (yas--field-modified-p field))
+ (transform (if (yas--mirror-p field-or-mirror)
+ (yas--mirror-transform field-or-mirror)
+ (yas--field-transform field-or-mirror)))
+ (start-point (if (yas--mirror-p field-or-mirror)
+ (yas--mirror-start field-or-mirror)
+ (yas--field-start field-or-mirror)))
+ (transformed (and transform
+ (save-excursion
+ (goto-char start-point)
+ (let ((ret (yas--eval-for-string transform)))
+ (or ret (and empty-on-nil-p "")))))))
+ transformed))
+
+(defsubst yas--replace-all (from to &optional text)
+ "Replace all occurrences from FROM to TO.
+
+With optional string TEXT do it in that string."
+ (if text
+ (replace-regexp-in-string (regexp-quote from) to text t t)
+ (goto-char (point-min))
+ (while (search-forward from nil t)
+ (replace-match to t t text))))
+
+(defun yas--snippet-find-field (snippet number)
+ (cl-find-if (lambda (field)
+ (eq number (yas--field-number field)))
+ (yas--snippet-fields snippet)))
+
+(defun yas--snippet-sort-fields (snippet)
+ "Sort the fields of SNIPPET in navigation order."
+ (setf (yas--snippet-fields snippet)
+ (sort (yas--snippet-fields snippet)
+ #'yas--snippet-field-compare)))
+
+(defun yas--snippet-field-compare (field1 field2)
+ "Compare FIELD1 and FIELD2.
+
+The field with a number is sorted first. If they both have a
+number, compare through the number. If neither have, compare
+through the field's start point"
+ (let ((n1 (yas--field-number field1))
+ (n2 (yas--field-number field2)))
+ (if n1
+ (if n2
+ (or (zerop n2) (and (not (zerop n1))
+ (< n1 n2)))
+ (not (zerop n1)))
+ (if n2
+ (zerop n2)
+ (< (yas--field-start field1)
+ (yas--field-start field2))))))
+
+(defun yas--field-probably-deleted-p (snippet field)
+ "Guess if SNIPPET's FIELD should be skipped."
+ (and
+ ;; field must be zero length
+ ;;
+ (zerop (- (yas--field-start field) (yas--field-end field)))
+ ;; field must have been modified
+ ;;
+ (yas--field-modified-p field)
+ ;; either:
+ (or
+ ;; 1) it's a nested field
+ ;;
+ (yas--field-parent-field field)
+ ;; 2) ends just before the snippet end
+ ;;
+ (and (eq field (car (last (yas--snippet-fields snippet))))
+ (= (yas--field-start field) (overlay-end (yas--snippet-control-overlay snippet)))))
+ ;; the field numbered 0, just before the exit marker, should
+ ;; never be skipped
+ ;;
+ (not (and (yas--field-number field)
+ (zerop (yas--field-number field))))))
+
+(defun yas-active-snippets (&optional beg end)
+ "Return a sorted list of active snippets.
+The most recently-inserted snippets are returned first.
+
+Only snippets overlapping the region BEG ... END are returned.
+Overlapping has the same meaning as described in `overlays-in'.
+If END is omitted, it defaults to (1+ BEG). If BEG is omitted,
+it defaults to point. A non-nil, non-buffer position BEG is
+equivalent to a range covering the whole buffer."
+ (unless beg
+ (setq beg (point)))
+ (cond ((not (or (integerp beg) (markerp beg)))
+ (setq beg (point-min) end (point-max)))
+ ((not end)
+ (setq end (1+ beg))))
+ (cl-sort
+ (delete-dups ;; Snippets have multiple overlays.
+ (delq nil
+ (mapcar (lambda (ov) (overlay-get ov 'yas--snippet))
+ (overlays-in beg end))))
+ #'>= :key #'yas--snippet-id))
+
+(define-obsolete-function-alias 'yas--snippets-at-point
+ 'yas-active-snippets "0.12")
+
+(defun yas-next-field-or-maybe-expand ()
+ "Try to expand a snippet at a key before point.
+
+Otherwise delegate to `yas-next-field'."
+ (interactive)
+ (if yas-triggers-in-field
+ (let ((yas-fallback-behavior 'return-nil)
+ (active-field (overlay-get yas--active-field-overlay 'yas--field)))
+ (when active-field
+ (unless (yas-expand-from-trigger-key active-field)
+ (yas-next-field))))
+ (yas-next-field)))
+
+(defun yas-next-field-will-exit-p (&optional arg)
+ "Return non-nil if (yas-next-field ARG) would exit the current snippet."
+ (let ((snippet (car (yas-active-snippets)))
+ (active (overlay-get yas--active-field-overlay 'yas--field)))
+ (when snippet
+ (not (yas--find-next-field arg snippet active)))))
+
+(defun yas--find-next-field (n snippet active)
+ "Return the Nth field after the ACTIVE one in SNIPPET."
+ (let ((live-fields (cl-remove-if
+ (lambda (field)
+ (and (not (eq field active))
+ (yas--field-probably-deleted-p snippet field)))
+ (yas--snippet-fields snippet))))
+ (nth (abs n) (memq active (if (>= n 0) live-fields (reverse live-fields))))))
+
+(defun yas-next-field (&optional arg)
+ "Navigate to the ARGth next field.
+
+If there's none, exit the snippet."
+ (interactive)
+ (unless arg (setq arg 1))
+ (let* ((snippet (car (yas-active-snippets)))
+ (active-field (overlay-get yas--active-field-overlay 'yas--field))
+ (target-field (yas--find-next-field arg snippet active-field)))
+ (yas--letenv (yas--snippet-expand-env snippet)
+ ;; Apply transform to active field.
+ (when active-field
+ (let ((yas-moving-away-p t))
+ (when (yas--field-update-display active-field)
+ (yas--update-mirrors snippet))))
+ ;; Now actually move...
+ (if target-field
+ (yas--move-to-field snippet target-field)
+ (yas-exit-snippet snippet)))))
+
+(defun yas--place-overlays (snippet field)
+ "Correctly place overlays for SNIPPET's FIELD."
+ (yas--make-move-field-protection-overlays snippet field)
+ ;; Only move active field overlays if this is field is from the
+ ;; innermost snippet.
+ (when (eq snippet (car (yas-active-snippets (1- (yas--field-start field))
+ (1+ (yas--field-end field)))))
+ (yas--make-move-active-field-overlay snippet field)))
+
+(defun yas--move-to-field (snippet field)
+ "Update SNIPPET to move to field FIELD.
+
+Also create some protection overlays"
+ (goto-char (yas--field-start field))
+ (yas--place-overlays snippet field)
+ (overlay-put yas--active-field-overlay 'yas--snippet snippet)
+ (overlay-put yas--active-field-overlay 'yas--field field)
+ (let ((number (yas--field-number field)))
+ ;; check for the special ${0: ...} field
+ (if (and number (zerop number))
+ (progn
+ (set-mark (yas--field-end field))
+ (setf (yas--snippet-force-exit snippet)
+ (or (yas--field-transform field)
+ t)))
+ ;; make this field active
+ (setf (yas--snippet-active-field snippet) field)
+ ;; primary field transform: first call to snippet transform
+ (unless (yas--field-modified-p field)
+ (if (yas--field-update-display field)
+ (yas--update-mirrors snippet)
+ (setf (yas--field-modified-p field) nil))))))
+
+(defun yas-prev-field ()
+ "Navigate to prev field. If there's none, exit the snippet."
+ (interactive)
+ (yas-next-field -1))
+
+(defun yas-abort-snippet (&optional snippet)
+ (interactive)
+ (let ((snippet (or snippet
+ (car (yas-active-snippets)))))
+ (when snippet
+ (setf (yas--snippet-force-exit snippet) t))))
+
+(defun yas-exit-snippet (snippet)
+ "Goto exit-marker of SNIPPET."
+ (interactive (list (cl-first (yas-active-snippets))))
+ (when snippet
+ (setf (yas--snippet-force-exit snippet) t)
+ (goto-char (if (yas--snippet-exit snippet)
+ (yas--exit-marker (yas--snippet-exit snippet))
+ (overlay-end (yas--snippet-control-overlay snippet))))))
+
+(defun yas-exit-all-snippets ()
+ "Exit all snippets."
+ (interactive)
+ (mapc #'(lambda (snippet)
+ (yas-exit-snippet snippet)
+ (yas--check-commit-snippet))
+ (yas-active-snippets 'all)))
+
+\f
+;;; Some low level snippet-routines:
+
+(defvar yas--inhibit-overlay-hooks nil
+ "Bind this temporarily to non-nil to prevent running `yas--on-*-modification'.")
+
+(defvar yas-snippet-beg nil "Beginning position of the last snippet committed.")
+(defvar yas-snippet-end nil "End position of the last snippet committed.")
+
+(defun yas--commit-snippet (snippet)
+ "Commit SNIPPET, but leave point as it is.
+
+This renders the snippet as ordinary text."
+
+ (let ((control-overlay (yas--snippet-control-overlay snippet)))
+ ;;
+ ;; Save the end of the moribund snippet in case we need to revive it
+ ;; its original expansion.
+ ;;
+ (when (and control-overlay
+ (overlay-buffer control-overlay))
+ (setq yas-snippet-beg (overlay-start control-overlay))
+ (setq yas-snippet-end (overlay-end control-overlay))
+ (delete-overlay control-overlay)
+ (setf (yas--snippet-control-overlay snippet) nil))
+
+ (let ((yas--inhibit-overlay-hooks t))
+ (when yas--active-field-overlay
+ (delete-overlay yas--active-field-overlay))
+ (when yas--field-protection-overlays
+ (mapc #'delete-overlay yas--field-protection-overlays)))
+
+ ;; stacked expansion: if the original expansion took place from a
+ ;; field, make sure we advance it here at least to
+ ;; `yas-snippet-end'...
+ ;;
+ (let ((previous-field (yas--snippet-previous-active-field snippet)))
+ (when (and yas-snippet-end previous-field)
+ (yas--advance-end-maybe previous-field yas-snippet-end)))
+
+ ;; Convert all markers to points,
+ ;;
+ (yas--markers-to-points snippet)
+
+ ;; Take care of snippet revival
+ ;;
+ (if yas-snippet-revival
+ (push `(apply yas--snippet-revive ,yas-snippet-beg ,yas-snippet-end ,snippet)
+ buffer-undo-list)
+ ;; Dismember the snippet... this is useful if we get called
+ ;; again from `yas--take-care-of-redo'....
+ (setf (yas--snippet-fields snippet) nil)))
+
+ (yas--message 4 "Snippet %s exited." (yas--snippet-id snippet)))
+
+(defvar yas--snippets-to-move nil)
+(make-variable-buffer-local 'yas--snippets-to-move)
+
+(defun yas--prepare-snippets-for-move (beg end buf pos)
+ "Gather snippets in BEG..END for moving to POS in BUF."
+ (let ((to-move nil)
+ (snippets (yas-active-snippets beg end))
+ (dst-base-line (with-current-buffer buf
+ (count-lines (point-min) pos))))
+ (when snippets
+ (dolist (snippet snippets)
+ (yas--snippet-map-markers
+ (lambda (m)
+ (goto-char m)
+ (beginning-of-line)
+ (prog1 (cons (count-lines (point-min) (point))
+ (yas--snapshot-marker-location m))
+ (set-marker m nil)))
+ snippet)
+ (let ((ctrl-ov (yas--snapshot-overlay-line-location
+ (yas--snippet-control-overlay snippet))))
+ (push (list ctrl-ov dst-base-line snippet) to-move)
+ (delete-overlay (car ctrl-ov))))
+ (with-current-buffer buf
+ (setq yas--snippets-to-move (nconc to-move yas--snippets-to-move))))))
+
+(defun yas--on-buffer-kill ()
+ ;; Org mode uses temp buffers for fontification and "native tab",
+ ;; move all the snippets to the original org-mode buffer when it's
+ ;; killed.
+ (let ((org-marker nil))
+ (when (and yas-minor-mode
+ (or (bound-and-true-p org-edit-src-from-org-mode)
+ (bound-and-true-p org-src--from-org-mode))
+ (markerp
+ (setq org-marker
+ (or (bound-and-true-p org-edit-src-beg-marker)
+ (bound-and-true-p org-src--beg-marker)))))
+ (yas--prepare-snippets-for-move
+ (point-min) (point-max)
+ (marker-buffer org-marker) org-marker))))
+
+(add-hook 'kill-buffer-hook #'yas--on-buffer-kill)
+
+(defun yas--finish-moving-snippets ()
+ "Finish job started in `yas--prepare-snippets-for-move'."
+ (cl-loop for (ctrl-ov base-line snippet) in yas--snippets-to-move
+ for base-pos = (progn (goto-char (point-min))
+ (forward-line base-line) (point))
+ do (yas--snippet-map-markers
+ (lambda (l-m-r-w)
+ (goto-char base-pos)
+ (forward-line (nth 0 l-m-r-w))
+ (save-restriction
+ (narrow-to-region (line-beginning-position)
+ (line-end-position))
+ (yas--restore-marker-location (cdr l-m-r-w)))
+ (nth 1 l-m-r-w))
+ snippet)
+ (goto-char base-pos)
+ (yas--restore-overlay-location ctrl-ov)
+ (yas--maybe-move-to-active-field snippet))
+ (setq yas--snippets-to-move nil))
+
+(defun yas--safely-call-fun (fun)
+ "Call FUN and catch any errors."
+ (condition-case error
+ (funcall fun)
+ ((debug error)
+ (yas--message 2 "Error running %s: %s" fun
+ (error-message-string error)))))
+
+(defun yas--safely-run-hook (hook)
+ "Call HOOK's functions.
+HOOK should be a symbol, a hook variable, as in `run-hooks'."
+ (let ((debug-on-error (and (not (memq yas-good-grace '(t hooks)))
+ debug-on-error)))
+ (yas--safely-call-fun (apply-partially #'run-hooks hook))))
+
+(defun yas--check-commit-snippet ()
+ "Check if point exited the currently active field of the snippet.
+
+If so cleans up the whole snippet up."
+ (let* ((snippets (yas-active-snippets 'all))
+ (snippets-left snippets)
+ (snippet-exit-transform)
+ ;; Record the custom snippet `yas-after-exit-snippet-hook'
+ ;; set in the expand-env field.
+ (snippet-exit-hook yas-after-exit-snippet-hook))
+ (dolist (snippet snippets)
+ (let ((active-field (yas--snippet-active-field snippet)))
+ (yas--letenv (yas--snippet-expand-env snippet)
+ ;; Note: the `force-exit' field could be a transform in case of
+ ;; ${0: ...}, see `yas--move-to-field'.
+ (setq snippet-exit-transform (yas--snippet-force-exit snippet))
+ (cond ((or snippet-exit-transform
+ (not (and active-field (yas--field-contains-point-p active-field))))
+ (setq snippets-left (delete snippet snippets-left))
+ (setf (yas--snippet-force-exit snippet) nil)
+ (setq snippet-exit-hook yas-after-exit-snippet-hook)
+ (yas--commit-snippet snippet))
+ ((and active-field
+ (or (not yas--active-field-overlay)
+ (not (overlay-buffer yas--active-field-overlay))))
+ ;;
+ ;; stacked expansion: this case is mainly for recent
+ ;; snippet exits that place us back int the field of
+ ;; another snippet
+ ;;
+ (save-excursion
+ (yas--move-to-field snippet active-field)
+ (yas--update-mirrors snippet)))
+ (t
+ nil)))))
+ (unless (or (null snippets) snippets-left)
+ (when snippet-exit-transform
+ (yas--eval-for-effect snippet-exit-transform))
+ (let ((yas-after-exit-snippet-hook snippet-exit-hook))
+ (yas--safely-run-hook 'yas-after-exit-snippet-hook)))))
+
+;; Apropos markers-to-points:
+;;
+;; This was found useful for performance reasons, so that an excessive
+;; number of live markers aren't kept around in the
+;; `buffer-undo-list'. We don't reuse the original marker object
+;; because that leaves an unreadable object in the history list and
+;; undo-tree persistence has trouble with that.
+;;
+;; This shouldn't bring horrible problems with undo/redo, but you
+;; never know.
+;;
+(defun yas--markers-to-points (snippet)
+ "Save all markers of SNIPPET as positions."
+ (yas--snippet-map-markers (lambda (m)
+ (prog1 (marker-position m)
+ (set-marker m nil)))
+ snippet))
+
+(defun yas--points-to-markers (snippet)
+ "Restore SNIPPET's marker positions, saved by `yas--markers-to-points'."
+ (yas--snippet-map-markers #'copy-marker snippet))
+
+(defun yas--maybe-move-to-active-field (snippet)
+ "Try to move to SNIPPET's active (or first) field and return it if found."
+ (let ((target-field (or (yas--snippet-active-field snippet)
+ (car (yas--snippet-fields snippet)))))
+ (when target-field
+ (yas--move-to-field snippet target-field)
+ target-field)))
+
+(defun yas--field-contains-point-p (field &optional point)
+ (let ((point (or point
+ (point))))
+ (and (>= point (yas--field-start field))
+ (<= point (yas--field-end field)))))
+
+(defun yas--field-text-for-display (field)
+ "Return the propertized display text for field FIELD."
+ (buffer-substring (yas--field-start field) (yas--field-end field)))
+
+(defun yas--undo-in-progress ()
+ "True if some kind of undo is in progress."
+ (or undo-in-progress
+ (eq this-command 'undo)
+ (eq this-command 'redo)))
+
+(defun yas--make-control-overlay (snippet start end)
+ "Create the control overlay that surrounds the snippet and
+holds the keymap."
+ (let ((overlay (make-overlay start
+ end
+ nil
+ nil
+ t)))
+ (overlay-put overlay 'keymap yas-keymap)
+ (overlay-put overlay 'priority yas-overlay-priority)
+ (overlay-put overlay 'yas--snippet snippet)
+ overlay))
+
+(defun yas-skip-and-clear-or-delete-char (&optional field)
+ "Clears unmodified field if at field start, skips to next tab.
+
+Otherwise deletes a character normally by calling `delete-char'."
+ (interactive)
+ (let ((field (or field
+ (and yas--active-field-overlay
+ (overlay-buffer yas--active-field-overlay)
+ (overlay-get yas--active-field-overlay 'yas--field)))))
+ (cond ((and field
+ (not (yas--field-modified-p field))
+ (eq (point) (marker-position (yas--field-start field))))
+ (yas--skip-and-clear field)
+ (yas-next-field 1))
+ (t
+ (call-interactively 'delete-char)))))
+
+(defun yas--skip-and-clear (field &optional from)
+ "Deletes the region of FIELD and sets it's modified state to t.
+If given, FROM indicates position to start at instead of FIELD's beginning."
+ ;; Just before skipping-and-clearing the field, mark its children
+ ;; fields as modified, too. If the children have mirrors-in-fields
+ ;; this prevents them from updating erroneously (we're skipping and
+ ;; deleting!).
+ ;;
+ (yas--mark-this-and-children-modified field)
+ (unless (= (yas--field-start field) (yas--field-end field))
+ (delete-region (or from (yas--field-start field)) (yas--field-end field))))
+
+(defun yas--mark-this-and-children-modified (field)
+ (setf (yas--field-modified-p field) t)
+ (let ((fom (yas--field-next field)))
+ (while (and fom
+ (yas--fom-parent-field fom))
+ (when (and (eq (yas--fom-parent-field fom) field)
+ (yas--field-p fom))
+ (yas--mark-this-and-children-modified fom))
+ (setq fom (yas--fom-next fom)))))
+
+(defun yas--make-move-active-field-overlay (snippet field)
+ "Place the active field overlay in SNIPPET's FIELD.
+
+Move the overlay, or create it if it does not exit."
+ (if (and yas--active-field-overlay
+ (overlay-buffer yas--active-field-overlay))
+ (move-overlay yas--active-field-overlay
+ (yas--field-start field)
+ (yas--field-end field))
+ (setq yas--active-field-overlay
+ (make-overlay (yas--field-start field)
+ (yas--field-end field)
+ nil nil t))
+ (overlay-put yas--active-field-overlay 'priority yas-overlay-priority)
+ (overlay-put yas--active-field-overlay 'face 'yas-field-highlight-face)
+ (overlay-put yas--active-field-overlay 'yas--snippet snippet)
+ (overlay-put yas--active-field-overlay 'modification-hooks '(yas--on-field-overlay-modification))
+ (overlay-put yas--active-field-overlay 'insert-in-front-hooks
+ '(yas--on-field-overlay-modification))
+ (overlay-put yas--active-field-overlay 'insert-behind-hooks
+ '(yas--on-field-overlay-modification))))
+
+(defun yas--skip-and-clear-field-p (field beg _end length)
+ "Tell if newly modified FIELD should be cleared and skipped.
+BEG, END and LENGTH like overlay modification hooks."
+ (and (= length 0) ; A 0 pre-change length indicates insertion.
+ (= beg (yas--field-start field)) ; Insertion at field start?
+ (not (yas--field-modified-p field))))
+
+(defun yas--on-field-overlay-modification (overlay after? beg end &optional length)
+ "Clears the field and updates mirrors, conditionally.
+
+Only clears the field if it hasn't been modified and point is at
+field start. This hook does nothing if an undo is in progress."
+ (unless (or (not after?)
+ yas--inhibit-overlay-hooks
+ (not (overlayp yas--active-field-overlay)) ; Avoid Emacs bug #21824.
+ ;; If a single change hits multiple overlays of the same
+ ;; snippet, then we delete the snippet the first time,
+ ;; and then subsequent calls get a deleted overlay.
+ ;; Don't delete the snippet again!
+ (not (overlay-buffer overlay))
+ (yas--undo-in-progress))
+ (let* ((inhibit-modification-hooks nil)
+ (yas--inhibit-overlay-hooks t)
+ (field (overlay-get overlay 'yas--field))
+ (snippet (overlay-get yas--active-field-overlay 'yas--snippet)))
+ (if (yas--snippet-live-p snippet)
+ (save-match-data
+ (yas--letenv (yas--snippet-expand-env snippet)
+ (when (yas--skip-and-clear-field-p field beg end length)
+ ;; We delete text starting from the END of insertion.
+ (yas--skip-and-clear field end))
+ (setf (yas--field-modified-p field) t)
+ (yas--advance-end-maybe field (overlay-end overlay))
+ (save-excursion
+ (yas--field-update-display field))
+ (yas--update-mirrors snippet)))
+ (lwarn '(yasnippet zombie) :warning "Killing zombie snippet!")
+ (delete-overlay overlay)))))
+
+(defun yas--auto-fill ()
+ (let* ((orig-point (point))
+ (end (progn (forward-paragraph) (point)))
+ (beg (progn (backward-paragraph) (point)))
+ (snippets (yas-active-snippets beg end))
+ (remarkers nil)
+ (reoverlays nil))
+ (dolist (snippet snippets)
+ (dolist (m (yas--collect-snippet-markers snippet))
+ (when (and (<= beg m) (<= m end))
+ (push (yas--snapshot-marker-location m beg end) remarkers)))
+ (push (yas--snapshot-overlay-location
+ (yas--snippet-control-overlay snippet) beg end)
+ reoverlays))
+ (goto-char orig-point)
+ (let ((yas--inhibit-overlay-hooks t))
+ (funcall yas--original-auto-fill-function))
+ (save-excursion
+ (setq end (progn (forward-paragraph) (point)))
+ (setq beg (progn (backward-paragraph) (point))))
+ (save-excursion
+ (save-restriction
+ (narrow-to-region beg end)
+ (mapc #'yas--restore-marker-location remarkers)
+ (mapc #'yas--restore-overlay-location reoverlays))
+ (mapc (lambda (snippet)
+ (yas--letenv (yas--snippet-expand-env snippet)
+ (yas--update-mirrors snippet)))
+ snippets))))
+
+\f
+;;; Apropos protection overlays:
+;;
+;; These exist for nasty users who will try to delete parts of the
+;; snippet outside the active field. Actual protection happens in
+;; `yas--on-protection-overlay-modification'.
+;;
+;; As of github #537 this no longer inhibits the command by issuing an
+;; error: all the snippets at point, including nested snippets, are
+;; automatically commited and the current command can proceed.
+;;
+(defun yas--make-move-field-protection-overlays (snippet field)
+ "Place protection overlays surrounding SNIPPET's FIELD.
+
+Move the overlays, or create them if they do not exit."
+ (let ((start (yas--field-start field))
+ (end (yas--field-end field)))
+ ;; First check if the (1+ end) is contained in the buffer,
+ ;; otherwise we'll have to do a bit of cheating and silently
+ ;; insert a newline. the `(1+ (buffer-size))' should prevent this
+ ;; when using stacked expansion
+ ;;
+ (when (< (buffer-size) end)
+ (save-excursion
+ (let ((yas--inhibit-overlay-hooks t))
+ (goto-char (point-max))
+ (newline))))
+ ;; go on to normal overlay creation/moving
+ ;;
+ (cond ((and yas--field-protection-overlays
+ (cl-every #'overlay-buffer yas--field-protection-overlays))
+ (move-overlay (nth 0 yas--field-protection-overlays)
+ (1- start) start)
+ (move-overlay (nth 1 yas--field-protection-overlays) end (1+ end)))
+ (t
+ (setq yas--field-protection-overlays
+ (list (make-overlay (1- start) start nil t nil)
+ (make-overlay end (1+ end) nil t nil)))
+ (dolist (ov yas--field-protection-overlays)
+ (overlay-put ov 'face 'yas--field-debug-face)
+ (overlay-put ov 'yas--snippet snippet)
+ ;; (overlay-put ov 'evaporate t)
+ (overlay-put ov 'modification-hooks '(yas--on-protection-overlay-modification)))))))
+
+(defun yas--on-protection-overlay-modification (_overlay after? beg end &optional length)
+ "Commit the snippet if the protection overlay is being killed."
+ (unless (or yas--inhibit-overlay-hooks
+ (not after?)
+ (= length (- end beg)) ; deletion or insertion
+ (yas--undo-in-progress))
+ (let ((snippets (yas-active-snippets)))
+ (yas--message 2 "Committing snippets. Action would destroy a protection overlay.")
+ (cl-loop for snippet in snippets
+ do (yas--commit-snippet snippet)))))
+
+(add-to-list 'debug-ignored-errors "^Exit the snippet first!$")
+
+\f
+;;; Snippet expansion and "stacked" expansion:
+;;
+;; Stacked expansion is when you try to expand a snippet when already
+;; inside a snippet expansion.
+;;
+;; The parent snippet does not run its fields modification hooks
+;; (`yas--on-field-overlay-modification' and
+;; `yas--on-protection-overlay-modification') while the child snippet
+;; is active. This means, among other things, that the mirrors of the
+;; parent snippet are not updated, this only happening when one exits
+;; the child snippet.
+;;
+;; Unfortunately, this also puts some ugly (and not fully-tested)
+;; bits of code in `yas-expand-snippet' and
+;; `yas--commit-snippet'. I've tried to mark them with "stacked
+;; expansion:".
+;;
+;; This was thought to be safer in an undo/redo perspective, but
+;; maybe the correct implementation is to make the globals
+;; `yas--active-field-overlay' and `yas--field-protection-overlays' be
+;; snippet-local and be active even while the child snippet is
+;; running. This would mean a lot of overlay modification hooks
+;; running, but if managed correctly (including overlay priorities)
+;; they should account for all situations...
+
+(defun yas-expand-snippet (content &optional start end expand-env)
+ "Expand snippet CONTENT at current point.
+
+Text between START and END will be deleted before inserting
+template. EXPAND-ENV is a list of (SYM VALUE) let-style dynamic bindings
+considered when expanding the snippet."
+ (cl-assert (and yas-minor-mode
+ (memq 'yas--post-command-handler post-command-hook))
+ nil
+ "[yas] `yas-expand-snippet' needs properly setup `yas-minor-mode'")
+ (run-hooks 'yas-before-expand-snippet-hook)
+
+ (let* ((clear-field
+ (let ((field (and yas--active-field-overlay
+ (overlay-buffer yas--active-field-overlay)
+ (overlay-get yas--active-field-overlay 'yas--field))))
+ (and field (yas--skip-and-clear-field-p
+ field (point) (point) 0)
+ field)))
+ (start (cond (start)
+ ((region-active-p)
+ (region-beginning))
+ (clear-field
+ (yas--field-start clear-field))
+ (t (point))))
+ (end (cond (end)
+ ((region-active-p)
+ (region-end))
+ (clear-field
+ (yas--field-end clear-field))
+ (t (point))))
+ (to-delete (and (> end start)
+ (buffer-substring-no-properties start end)))
+ (yas-selected-text
+ (cond (yas-selected-text)
+ ((and (region-active-p)
+ (not clear-field))
+ to-delete)))
+ snippet)
+ (goto-char start)
+ (setq yas--indent-original-column (current-column))
+ ;; Delete the region to delete, this *does* get undo-recorded.
+ (when to-delete
+ (delete-region start end))
+
+ (cond ((listp content)
+ ;; x) This is a snippet-command
+ ;;
+ (yas--eval-for-effect content))
+ (t
+ ;; x) This is a snippet-snippet :-)
+ (setq yas--start-column (current-column))
+ ;; Stacked expansion: also shoosh the overlay modification hooks.
+ (let ((yas--inhibit-overlay-hooks t))
+ (setq snippet
+ (yas--snippet-create content expand-env start (point))))
+
+ ;; stacked-expansion: This checks for stacked expansion, save the
+ ;; `yas--previous-active-field' and advance its boundary.
+ ;;
+ (let ((existing-field (and yas--active-field-overlay
+ (overlay-buffer yas--active-field-overlay)
+ (overlay-get yas--active-field-overlay 'yas--field))))
+ (when existing-field
+ (setf (yas--snippet-previous-active-field snippet) existing-field)
+ (yas--advance-end-maybe existing-field (overlay-end yas--active-field-overlay))))
+
+ ;; Exit the snippet immediately if no fields
+ ;;
+ (unless (yas--snippet-fields snippet)
+ (yas-exit-snippet snippet))
+
+ ;; Now, schedule a move to the first field
+ ;;
+ (let ((first-field (car (yas--snippet-fields snippet))))
+ (when first-field
+ (sit-for 0) ;; fix issue 125
+ (yas--letenv (yas--snippet-expand-env snippet)
+ (yas--move-to-field snippet first-field))
+ (when (and (eq (yas--field-number first-field) 0)
+ (> (length (yas--field-text-for-display
+ first-field))
+ 0))
+ ;; Keep region for ${0:exit text}.
+ (setq deactivate-mark nil))))
+ (yas--message 4 "snippet %d expanded." (yas--snippet-id snippet))
+ t))))
+
+(defun yas--take-care-of-redo (snippet)
+ "Commits SNIPPET, which in turn pushes an undo action for reviving it.
+
+Meant to exit in the `buffer-undo-list'."
+ ;; slightly optimize: this action is only needed for snippets with
+ ;; at least one field
+ (when (yas--snippet-fields snippet)
+ (yas--commit-snippet snippet)))
+
+(defun yas--snippet-revive (beg end snippet)
+ "Revives SNIPPET and creates a control overlay from BEG to END.
+
+BEG and END are, we hope, the original snippets boundaries.
+All the markers/points exiting existing inside SNIPPET should point
+to their correct locations *at the time the snippet is revived*.
+
+After revival, push the `yas--take-care-of-redo' in the
+`buffer-undo-list'"
+ ;; Reconvert all the points to markers
+ (yas--points-to-markers snippet)
+ ;; When at least one editable field existed in the zombie snippet,
+ ;; try to revive the whole thing...
+ (when (yas--maybe-move-to-active-field snippet)
+ (setf (yas--snippet-control-overlay snippet) (yas--make-control-overlay snippet beg end))
+ (overlay-put (yas--snippet-control-overlay snippet) 'yas--snippet snippet)
+ (push `(apply yas--take-care-of-redo ,beg ,end ,snippet)
+ buffer-undo-list)))
+
+(defun yas--snippet-create (content expand-env begin end)
+ "Create a snippet from a template inserted at BEGIN to END.
+
+Returns the newly created snippet."
+ (save-restriction
+ (let ((snippet (yas--make-snippet expand-env)))
+ (yas--letenv expand-env
+ ;; Put a single undo action for the expanded snippet's
+ ;; content.
+ (let ((buffer-undo-list t))
+ ;; Some versions of cc-mode fail when inserting snippet
+ ;; content in a narrowed buffer.
+ (goto-char begin)
+ (insert content)
+ (setq end (+ end (length content)))
+ (narrow-to-region begin end)
+ (goto-char (point-min))
+ (yas--snippet-parse-create snippet))
+ (push (cons (point-min) (point-max))
+ buffer-undo-list)
+
+ ;; Indent, collecting undo information normally.
+ (yas--indent snippet)
+
+ ;; Follow up with `yas--take-care-of-redo' on the newly
+ ;; inserted snippet boundaries.
+ (push `(apply yas--take-care-of-redo ,snippet)
+ buffer-undo-list)
+
+ ;; Sort and link each field
+ (yas--snippet-sort-fields snippet)
+
+ ;; Create keymap overlay for snippet
+ (setf (yas--snippet-control-overlay snippet)
+ (yas--make-control-overlay snippet (point-min) (point-max)))
+
+ ;; Move to end
+ (goto-char (point-max))
+
+ snippet))))
+
+\f
+;;; Apropos adjacencies and "fom's":
+;;
+;; Once the $-constructs bits like "$n" and "${:n" are deleted in the
+;; recently expanded snippet, we might actually have many fields,
+;; mirrors (and the snippet exit) in the very same position in the
+;; buffer. Therefore we need to single-link the
+;; fields-or-mirrors-or-exit (which I have abbreviated to "fom")
+;; according to their original positions in the buffer.
+;;
+;; Then we have operation `yas--advance-end-maybe' and
+;; `yas--advance-start-maybe', which conditionally push the starts and
+;; ends of these foms down the chain.
+;;
+;; This allows for like the printf with the magic ",":
+;;
+;; printf ("${1:%s}\\n"${1:$(if (string-match "%" text) "," "\);")} \
+;; $2${1:$(if (string-match "%" text) "\);" "")}$0
+;;
+(defun yas--fom-start (fom)
+ (cond ((yas--field-p fom)
+ (yas--field-start fom))
+ ((yas--mirror-p fom)
+ (yas--mirror-start fom))
+ (t
+ (yas--exit-marker fom))))
+
+(defun yas--fom-end (fom)
+ (cond ((yas--field-p fom)
+ (yas--field-end fom))
+ ((yas--mirror-p fom)
+ (yas--mirror-end fom))
+ (t
+ (yas--exit-marker fom))))
+
+(defun yas--fom-next (fom)
+ (cond ((yas--field-p fom)
+ (yas--field-next fom))
+ ((yas--mirror-p fom)
+ (yas--mirror-next fom))
+ (t
+ (yas--exit-next fom))))
+
+(defun yas--fom-parent-field (fom)
+ (cond ((yas--field-p fom)
+ (yas--field-parent-field fom))
+ ((yas--mirror-p fom)
+ (yas--mirror-parent-field fom))
+ (t
+ nil)))
+
+(defun yas--calculate-adjacencies (snippet)
+ "Calculate adjacencies for fields or mirrors of SNIPPET.
+
+This is according to their relative positions in the buffer, and
+has to be called before the $-constructs are deleted."
+ (let* ((fom-set-next-fom
+ (lambda (fom nextfom)
+ (cond ((yas--field-p fom)
+ (setf (yas--field-next fom) nextfom))
+ ((yas--mirror-p fom)
+ (setf (yas--mirror-next fom) nextfom))
+ (t
+ (setf (yas--exit-next fom) nextfom)))))
+ (compare-fom-begs
+ (lambda (fom1 fom2)
+ (if (= (yas--fom-start fom2) (yas--fom-start fom1))
+ (yas--mirror-p fom2)
+ (>= (yas--fom-start fom2) (yas--fom-start fom1)))))
+ (link-foms fom-set-next-fom))
+ ;; make some yas--field, yas--mirror and yas--exit soup
+ (let ((soup))
+ (when (yas--snippet-exit snippet)
+ (push (yas--snippet-exit snippet) soup))
+ (dolist (field (yas--snippet-fields snippet))
+ (push field soup)
+ (dolist (mirror (yas--field-mirrors field))
+ (push mirror soup)))
+ (setq soup
+ (sort soup compare-fom-begs))
+ (when soup
+ (cl-reduce link-foms soup)))))
+
+(defun yas--calculate-mirrors-in-fields (snippet mirror)
+ "Attempt to assign a parent field of SNIPPET to the mirror MIRROR.
+
+Use the tightest containing field if more than one field contains
+the mirror. Intended to be called *before* the dollar-regions are
+deleted."
+ (let ((min (point-min))
+ (max (point-max)))
+ (dolist (field (yas--snippet-fields snippet))
+ (when (and (<= (yas--field-start field) (yas--mirror-start mirror))
+ (<= (yas--mirror-end mirror) (yas--field-end field))
+ (< min (yas--field-start field))
+ (< (yas--field-end field) max))
+ (setq min (yas--field-start field)
+ max (yas--field-end field))
+ (setf (yas--mirror-parent-field mirror) field)))))
+
+(defun yas--advance-end-maybe (fom newend)
+ "Maybe advance FOM's end to NEWEND if it needs it.
+
+If it does, also:
+
+* call `yas--advance-start-maybe' on FOM's next fom.
+
+* in case FOM is field call `yas--advance-end-maybe' on its parent
+ field
+
+Also, if FOM is an exit-marker, always call
+`yas--advance-start-maybe' on its next fom. This is because
+exit-marker have identical start and end markers."
+ (cond ((and fom (< (yas--fom-end fom) newend))
+ (set-marker (yas--fom-end fom) newend)
+ (yas--advance-start-maybe (yas--fom-next fom) newend)
+ (yas--advance-end-of-parents-maybe (yas--fom-parent-field fom) newend))
+ ((yas--exit-p fom)
+ (yas--advance-start-maybe (yas--fom-next fom) newend))))
+
+(defun yas--advance-start-maybe (fom newstart)
+ "Maybe advance FOM's start to NEWSTART if it needs it.
+
+If it does, also call `yas--advance-end-maybe' on FOM."
+ (when (and fom (< (yas--fom-start fom) newstart))
+ (set-marker (yas--fom-start fom) newstart)
+ (yas--advance-end-maybe fom newstart)))
+
+(defun yas--advance-end-of-parents-maybe (field newend)
+ "Like `yas--advance-end-maybe' but for parent fields.
+
+Only works for fields and doesn't care about the start of the
+next FOM. Works its way up recursively for parents of parents."
+ (when (and field
+ (< (yas--field-end field) newend))
+ (set-marker (yas--field-end field) newend)
+ (yas--advance-end-of-parents-maybe (yas--field-parent-field field) newend)))
+
+(defvar yas--dollar-regions nil
+ "When expanding the snippet the \"parse-create\" functions add
+cons cells to this var.")
+
+(defvar yas--backquote-markers-and-strings nil
+ "List of (MARKER . STRING) marking where the values from
+backquoted Lisp expressions should be inserted at the end of
+expansion.")
+
+(defvar yas--indent-markers nil
+ "List of markers for manual indentation.")
+
+(defun yas--snippet-parse-create (snippet)
+ "Parse a recently inserted snippet template, creating all
+necessary fields, mirrors and exit points.
+
+Meant to be called in a narrowed buffer, does various passes"
+ (let ((parse-start (point)))
+ ;; Avoid major-mode's syntax propertizing function, since we
+ ;; change the syntax-table while calling `scan-sexps'.
+ (let ((syntax-propertize-function nil))
+ (setq yas--dollar-regions nil) ; Reset the yas--dollar-regions.
+ (yas--protect-escapes nil '(?`)) ; Protect just the backquotes.
+ (goto-char parse-start)
+ (yas--save-backquotes) ; Replace all backquoted expressions.
+ (yas--protect-escapes) ; Protect escaped characters.
+ (goto-char parse-start)
+ (yas--indent-parse-create) ; Parse indent markers: `$>'.
+ (goto-char parse-start)
+ (yas--field-parse-create snippet) ; Parse fields with {}.
+ (goto-char parse-start)
+ (yas--simple-mirror-parse-create snippet) ; Parse simple mirrors & fields.
+ (goto-char parse-start)
+ (yas--transform-mirror-parse-create snippet) ; Parse mirror transforms.
+ ;; Invalidate any syntax-propertizing done while
+ ;; `syntax-propertize-function' was nil.
+ (syntax-ppss-flush-cache parse-start))
+ ;; Set "next" links of fields & mirrors.
+ (yas--calculate-adjacencies snippet)
+ (save-restriction
+ (widen) ; Delete $-constructs.
+ (yas--delete-regions yas--dollar-regions))
+ ;; Make sure to do this insertion *after* deleting the dollar
+ ;; regions, otherwise we invalidate the calculated positions of
+ ;; all the fields following $0.
+ (let ((exit (yas--snippet-exit snippet)))
+ (goto-char (if exit (yas--exit-marker exit) (point-max))))
+ (when (eq yas-wrap-around-region 'cua)
+ (setq yas-wrap-around-region ?0))
+ (cond ((and yas-wrap-around-region yas-selected-text)
+ (insert yas-selected-text))
+ ((and (characterp yas-wrap-around-region)
+ (get-register yas-wrap-around-region))
+ (insert (prog1 (get-register yas-wrap-around-region)
+ (set-register yas-wrap-around-region nil)))))
+ (yas--restore-backquotes) ; Restore backquoted expression values.
+ (goto-char parse-start)
+ (yas--restore-escapes) ; Restore escapes.
+ (yas--update-mirrors snippet) ; Update mirrors for the first time.
+ (goto-char parse-start)))
+
+;; HACK: Some implementations of `indent-line-function' (called via
+;; `indent-according-to-mode') delete text before they insert (like
+;; cc-mode), some make complicated regexp replacements (looking at
+;; you, org-mode). To find place where the marker "should" go after
+;; indentation, we create a regexp based on what the line looks like
+;; before, putting a capture group where the marker is. The regexp
+;; matches any whitespace with [[:space:]]* to allow for the
+;; indentation changing whitespace. Additionally, we try to preserve
+;; the amount of whitespace *following* the marker, because
+;; indentation generally affects whitespace at the beginning, not the
+;; end.
+;;
+;; Two other cases where we apply a similar strategy:
+;;
+;; 1. Handling `auto-fill-mode', in this case we need to use the
+;; current paragraph instead of line.
+;;
+;; 2. Moving snippets from an `org-src' temp buffer into the main org
+;; buffer, in this case we need to count the line offsets (because org
+;; may add indentation on each line making character positions
+;; unreliable).
+;;
+;; This is all best-effort heuristic stuff, but it should cover 99% of
+;; use-cases.
+
+(defun yas--snapshot-marker-location (marker &optional beg end)
+ "Returns info for restoring MARKER's location after indent.
+The returned value is a list of the form (MARKER REGEXP WS-COUNT)."
+ (unless beg (setq beg (line-beginning-position)))
+ (unless end (setq end (line-end-position)))
+ (let ((before (split-string (buffer-substring-no-properties beg marker)
+ "[[:space:]\n]+" t))
+ (after (split-string (buffer-substring-no-properties marker end)
+ "[[:space:]\n]+" t)))
+ (list marker
+ (concat "[[:space:]\n]*"
+ (mapconcat (lambda (s)
+ (if (eq s marker) "\\(\\)"
+ (regexp-quote s)))
+ (nconc before (list marker) after)
+ "[[:space:]\n]*"))
+ (progn (goto-char marker)
+ (skip-chars-forward "[:space:]\n" end)
+ (- (point) marker)))))
+
+(defun yas--snapshot-overlay-location (overlay beg end)
+ "Like `yas--snapshot-marker-location' for overlays.
+The returned format is (OVERLAY (RE WS) (RE WS)). Either of
+the (RE WS) lists may be nil if the start or end, respectively,
+of the overlay is outside the range BEG .. END."
+ (let ((obeg (overlay-start overlay))
+ (oend (overlay-end overlay)))
+ (list overlay
+ (when (and (<= beg obeg) (< obeg end))
+ (cdr (yas--snapshot-marker-location obeg beg end)))
+ (when (and (<= beg oend) (< oend end))
+ (cdr (yas--snapshot-marker-location oend beg end))))))
+
+(defun yas--snapshot-overlay-line-location (overlay)
+ "Return info for restoring OVERLAY's line based location.
+The returned format is (OVERLAY (LINE RE WS) (LINE RE WS))."
+ (let ((loc-beg (progn (goto-char (overlay-start overlay))
+ (yas--snapshot-marker-location (point))))
+ (loc-end (progn (goto-char (overlay-end overlay))
+ (yas--snapshot-marker-location (point)))))
+ (setcar loc-beg (count-lines (point-min) (progn (goto-char (car loc-beg))
+ (line-beginning-position))))
+ (setcar loc-end (count-lines (point-min) (progn (goto-char (car loc-end))
+ (line-beginning-position))))
+ (list overlay loc-beg loc-end)))
+
+(defun yas--goto-saved-location (regexp ws-count)
+ "Move point to location saved by `yas--snapshot-marker-location'.
+Buffer must be narrowed to BEG..END used to create the snapshot info."
+ (goto-char (point-min))
+ (if (not (looking-at regexp))
+ (lwarn '(yasnippet re-marker) :warning
+ "Couldn't find: %S" regexp)
+ (goto-char (match-beginning 1))
+ (skip-chars-forward "[:space:]\n")
+ (skip-chars-backward "[:space:]\n" (- (point) ws-count))))
+
+(defun yas--restore-marker-location (re-marker)
+ "Restores marker based on info from `yas--snapshot-marker-location'.
+Buffer must be narrowed to BEG..END used to create the snapshot info."
+ (apply #'yas--goto-saved-location (cdr re-marker))
+ (set-marker (car re-marker) (point)))
+
+(defun yas--restore-overlay-location (ov-locations)
+ "Restores marker based on info from `yas--snapshot-marker-location'.
+Buffer must be narrowed to BEG..END used to create the snapshot info."
+ (cl-destructuring-bind (overlay loc-beg loc-end) ov-locations
+ (move-overlay overlay
+ (if (not loc-beg) (overlay-start overlay)
+ (apply #'yas--goto-saved-location loc-beg)
+ (point))
+ (if (not loc-end) (overlay-end overlay)
+ (apply #'yas--goto-saved-location loc-end)
+ (point)))))
+
+
+(defun yas--restore-overlay-line-location (ov-locations)
+ "Restores overlay based on info from `yas--snapshot-overlay-line-location'."
+ (save-restriction
+ (move-overlay (car ov-locations)
+ (save-excursion
+ (forward-line (car (nth 1 ov-locations)))
+ (narrow-to-region (line-beginning-position) (line-end-position))
+ (apply #'yas--goto-saved-location (cdr (nth 1 ov-locations)))
+ (point))
+ (save-excursion
+ (forward-line (car (nth 2 ov-locations)))
+ (narrow-to-region (line-beginning-position) (line-end-position))
+ (apply #'yas--goto-saved-location (cdr (nth 2 ov-locations)))
+ (point)))))
+
+(defun yas--indent-region (from to snippet)
+ "Indent the lines between FROM and TO with `indent-according-to-mode'.
+The SNIPPET's markers are preserved."
+ (save-excursion
+ (save-restriction
+ (widen)
+ (let* ((snippet-markers (yas--collect-snippet-markers snippet))
+ (to (set-marker (make-marker) to)))
+ (goto-char from)
+ (cl-loop for bol = (line-beginning-position)
+ for eol = (line-end-position)
+ if (or yas-also-indent-empty-lines
+ (/= bol eol))
+ do
+ ;; Indent each non-empty line.
+ (let ((remarkers nil))
+ (dolist (m snippet-markers)
+ (when (and (<= bol m) (<= m eol))
+ (push (yas--snapshot-marker-location m bol eol)
+ remarkers)))
+ (unwind-protect
+ (progn (back-to-indentation)
+ (indent-according-to-mode))
+ (save-restriction
+ (narrow-to-region bol (line-end-position))
+ (mapc #'yas--restore-marker-location remarkers))))
+ while (and (zerop (forward-line 1))
+ (< (point) to)))))))
+
+(defvar yas--indent-original-column nil)
+(defun yas--indent (snippet)
+ ;; Indent lines that had indent markers (`$>') on them.
+ (save-excursion
+ (dolist (marker yas--indent-markers)
+ (unless (eq yas-indent-line 'auto)
+ (goto-char marker)
+ (yas--indent-region (line-beginning-position)
+ (line-end-position)
+ snippet))
+ ;; Finished with this marker.
+ (set-marker marker nil))
+ (setq yas--indent-markers nil))
+ ;; Now do stuff for `fixed' and `auto'.
+ (save-excursion
+ (cond ((eq yas-indent-line 'fixed)
+ (while (and (zerop (forward-line))
+ (zerop (current-column)))
+ (indent-to-column yas--indent-original-column)))
+ ((eq yas-indent-line 'auto)
+ (unless yas-also-auto-indent-first-line
+ (forward-line 1))
+ (yas--indent-region (line-beginning-position)
+ (point-max)
+ snippet)))))
+
+(defun yas--collect-snippet-markers (snippet)
+ "Make a list of all the markers used by SNIPPET."
+ (let (markers)
+ (yas--snippet-map-markers (lambda (m) (push m markers) m) snippet)
+ markers))
+
+(defun yas--escape-string (escaped)
+ (concat "YASESCAPE" (format "%d" escaped) "PROTECTGUARD"))
+
+(defun yas--protect-escapes (&optional text escaped)
+ "Protect all escaped characters with their numeric ASCII value.
+
+With optional string TEXT do it in string instead of buffer."
+ (let ((changed-text text)
+ (text-provided-p text))
+ (mapc #'(lambda (escaped)
+ (setq changed-text
+ (yas--replace-all (concat "\\" (char-to-string escaped))
+ (yas--escape-string escaped)
+ (when text-provided-p changed-text))))
+ (or escaped yas--escaped-characters))
+ changed-text))
+
+(defun yas--restore-escapes (&optional text escaped)
+ "Restore all escaped characters from their numeric ASCII value.
+
+With optional string TEXT do it in string instead of the buffer."
+ (let ((changed-text text)
+ (text-provided-p text))
+ (mapc #'(lambda (escaped)
+ (setq changed-text
+ (yas--replace-all (yas--escape-string escaped)
+ (char-to-string escaped)
+ (when text-provided-p changed-text))))
+ (or escaped yas--escaped-characters))
+ changed-text))
+
+(defun yas--save-backquotes ()
+ "Save all the \"\\=`(lisp-expression)\\=`\"-style expressions
+with their evaluated value into `yas--backquote-markers-and-strings'."
+ (let* ((yas--snippet-buffer (current-buffer))
+ (yas--change-detected nil)
+ (detect-change (lambda (_beg _end)
+ (when (eq (current-buffer) yas--snippet-buffer)
+ (setq yas--change-detected t)))))
+ (while (re-search-forward yas--backquote-lisp-expression-regexp nil t)
+ (let ((current-string (match-string-no-properties 1)) transformed)
+ (save-restriction (widen)
+ (delete-region (match-beginning 0) (match-end 0)))
+ (let ((before-change-functions
+ (cons detect-change before-change-functions)))
+ (setq transformed (yas--eval-for-string (yas--read-lisp
+ (yas--restore-escapes
+ current-string '(?`))))))
+ (goto-char (match-beginning 0))
+ (when transformed
+ (let ((marker (make-marker))
+ (before-change-functions (cdr before-change-functions)))
+ (save-restriction
+ (widen)
+ (insert "Y") ;; quite horrendous, I love it :)
+ (set-marker marker (point))
+ (insert "Y"))
+ (push (cons marker transformed) yas--backquote-markers-and-strings)))))
+ (when yas--change-detected
+ (lwarn '(yasnippet backquote-change) :warning
+ "`%s' modified buffer in a backquote expression.
+ To hide this warning, add (yasnippet backquote-change) to `warning-suppress-types'."
+ (if yas--current-template
+ (yas--template-name yas--current-template)
+ "Snippet")))))
+
+(defun yas--restore-backquotes ()
+ "Replace markers in `yas--backquote-markers-and-strings' with their values."
+ (while yas--backquote-markers-and-strings
+ (let* ((marker-and-string (pop yas--backquote-markers-and-strings))
+ (marker (car marker-and-string))
+ (string (cdr marker-and-string)))
+ (save-excursion
+ (goto-char marker)
+ (save-restriction
+ (widen)
+ (delete-char -1)
+ (insert string)
+ (delete-char 1))
+ (set-marker marker nil)))))
+
+(defun yas--scan-sexps (from count)
+ (ignore-errors
+ (save-match-data ; `scan-sexps' may modify match data.
+ (with-syntax-table (standard-syntax-table)
+ (let ((parse-sexp-lookup-properties nil))
+ (scan-sexps from count))))))
+
+(defun yas--make-marker (pos)
+ "Create a marker at POS with nil `marker-insertion-type'."
+ (let ((marker (set-marker (make-marker) pos)))
+ (set-marker-insertion-type marker nil)
+ marker))
+
+(defun yas--indent-parse-create ()
+ "Parse the \"$>\" indentation markers just inserted."
+ (setq yas--indent-markers ())
+ (while (search-forward "$>" nil t)
+ (delete-region (match-beginning 0) (match-end 0))
+ ;; Mark the beginning of the line.
+ (push (yas--make-marker (line-beginning-position))
+ yas--indent-markers))
+ (setq yas--indent-markers (nreverse yas--indent-markers)))
+
+(defun yas--field-parse-create (snippet &optional parent-field)
+ "Parse most field expressions in SNIPPET, except for the simple one \"$n\".
+
+The following count as a field:
+
+* \"${n: text}\", for a numbered field with default text, as long as N is not 0;
+
+* \"${n: text$(expression)}, the same with a Lisp expression;
+ this is caught with the curiously named `yas--multi-dollar-lisp-expression-regexp'
+
+* the same as above but unnumbered, (no N:) and number is calculated automatically.
+
+When multiple expressions are found, only the last one counts."
+ ;;
+ (save-excursion
+ (while (re-search-forward yas--field-regexp nil t)
+ (let* ((real-match-end-0 (yas--scan-sexps (1+ (match-beginning 0)) 1))
+ (number (and (match-string-no-properties 1)
+ (string-to-number (match-string-no-properties 1))))
+ (brand-new-field (and real-match-end-0
+ ;; break if on "$(" immediately
+ ;; after the ":", this will be
+ ;; caught as a mirror with
+ ;; transform later.
+ (not (string-match-p "\\`\\$[ \t\n]*("
+ (match-string-no-properties 2)))
+ ;; allow ${0: some exit text}
+ ;; (not (and number (zerop number)))
+ (yas--make-field number
+ (yas--make-marker (match-beginning 2))
+ (yas--make-marker (1- real-match-end-0))
+ parent-field))))
+ (when brand-new-field
+ (goto-char real-match-end-0)
+ (push (cons (1- real-match-end-0) real-match-end-0)
+ yas--dollar-regions)
+ (push (cons (match-beginning 0) (match-beginning 2))
+ yas--dollar-regions)
+ (push brand-new-field (yas--snippet-fields snippet))
+ (save-excursion
+ (save-restriction
+ (narrow-to-region (yas--field-start brand-new-field) (yas--field-end brand-new-field))
+ (goto-char (point-min))
+ (yas--field-parse-create snippet brand-new-field)))))))
+ ;; if we entered from a parent field, now search for the
+ ;; `yas--multi-dollar-lisp-expression-regexp'. This is used for
+ ;; primary field transformations
+ ;;
+ (when parent-field
+ (save-excursion
+ (while (re-search-forward yas--multi-dollar-lisp-expression-regexp nil t)
+ (let* ((real-match-end-1 (yas--scan-sexps (match-beginning 1) 1)))
+ ;; commit the primary field transformation if:
+ ;;
+ ;; 1. we don't find it in yas--dollar-regions (a subnested
+ ;; field) might have already caught it.
+ ;;
+ ;; 2. we really make sure we have either two '$' or some
+ ;; text and a '$' after the colon ':'. This is a FIXME: work
+ ;; my regular expressions and end these ugly hacks.
+ ;;
+ (when (and real-match-end-1
+ (not (member (cons (match-beginning 0)
+ real-match-end-1)
+ yas--dollar-regions))
+ (not (eq ?:
+ (char-before (1- (match-beginning 1))))))
+ (let ((lisp-expression-string (buffer-substring-no-properties (match-beginning 1)
+ real-match-end-1)))
+ (setf (yas--field-transform parent-field)
+ (yas--read-lisp (yas--restore-escapes lisp-expression-string))))
+ (push (cons (match-beginning 0) real-match-end-1)
+ yas--dollar-regions)))))))
+
+(defun yas--transform-mirror-parse-create (snippet)
+ "Parse the \"${n:$(lisp-expression)}\" mirror transformations in SNIPPET."
+ (while (re-search-forward yas--transform-mirror-regexp nil t)
+ (let* ((real-match-end-0 (yas--scan-sexps (1+ (match-beginning 0)) 1))
+ (number (string-to-number (match-string-no-properties 1)))
+ (field (and number
+ (not (zerop number))
+ (yas--snippet-find-field snippet number)))
+ (brand-new-mirror
+ (and real-match-end-0
+ field
+ (yas--make-mirror (yas--make-marker (match-beginning 0))
+ (yas--make-marker (match-beginning 0))
+ (yas--read-lisp
+ (yas--restore-escapes
+ (buffer-substring-no-properties (match-beginning 2)
+ (1- real-match-end-0))))))))
+ (when brand-new-mirror
+ (push brand-new-mirror
+ (yas--field-mirrors field))
+ (yas--calculate-mirrors-in-fields snippet brand-new-mirror)
+ (push (cons (match-beginning 0) real-match-end-0) yas--dollar-regions)))))
+
+(defun yas--simple-mirror-parse-create (snippet)
+ "Parse the simple \"$n\" fields/mirrors/exitmarkers in SNIPPET."
+ (while (re-search-forward yas--simple-mirror-regexp nil t)
+ (let ((number (string-to-number (match-string-no-properties 1))))
+ (cond ((zerop number)
+ (setf (yas--snippet-exit snippet)
+ (yas--make-exit (yas--make-marker (match-end 0))))
+ (push (cons (match-beginning 0) (yas--exit-marker (yas--snippet-exit snippet)))
+ yas--dollar-regions))
+ (t
+ (let ((field (yas--snippet-find-field snippet number)))
+ (if field
+ (let ((brand-new-mirror (yas--make-mirror
+ (yas--make-marker (match-beginning 0))
+ (yas--make-marker (match-beginning 0))
+ nil)))
+ (push brand-new-mirror
+ (yas--field-mirrors field))
+ (yas--calculate-mirrors-in-fields snippet brand-new-mirror))
+ (push (yas--make-field number
+ (yas--make-marker (match-beginning 0))
+ (yas--make-marker (match-beginning 0))
+ nil)
+ (yas--snippet-fields snippet))))
+ (push (cons (match-beginning 0) (match-end 0))
+ yas--dollar-regions))))))
+
+(defun yas--delete-regions (regions)
+ "Sort disjuct REGIONS by start point, then delete from the back."
+ (mapc #'(lambda (reg)
+ (delete-region (car reg) (cdr reg)))
+ (sort regions
+ #'(lambda (r1 r2)
+ (>= (car r1) (car r2))))))
+
+(defun yas--calculate-mirror-depth (mirror &optional traversed)
+ (let* ((parent (yas--mirror-parent-field mirror))
+ (parents-mirrors (and parent
+ (yas--field-mirrors parent))))
+ (or (yas--mirror-depth mirror)
+ (setf (yas--mirror-depth mirror)
+ (cond ((memq mirror traversed) 0)
+ ((and parent parents-mirrors)
+ (1+ (cl-reduce
+ #'max parents-mirrors
+ :key (lambda (m)
+ (yas--calculate-mirror-depth
+ m (cons mirror traversed))))))
+ (parent 1)
+ (t 0))))))
+
+(defun yas--update-mirrors (snippet)
+ "Update all the mirrors of SNIPPET."
+ (save-restriction
+ (widen)
+ (save-excursion
+ (cl-loop
+ for (field . mirror)
+ in (cl-sort
+ ;; Make a list of (FIELD . MIRROR).
+ (cl-mapcan (lambda (field)
+ (mapcar (lambda (mirror)
+ (cons field mirror))
+ (yas--field-mirrors field)))
+ (yas--snippet-fields snippet))
+ ;; Then sort this list so that entries with mirrors with
+ ;; parent fields appear before. This was important for
+ ;; fixing #290, and also handles the case where a mirror in
+ ;; a field causes another mirror to need reupdating.
+ #'> :key (lambda (fm) (yas--calculate-mirror-depth (cdr fm))))
+ ;; Before updating a mirror with a parent-field, maybe advance
+ ;; its start (#290).
+ do (let ((parent-field (yas--mirror-parent-field mirror)))
+ (when parent-field
+ (yas--advance-start-maybe mirror (yas--fom-start parent-field))))
+ ;; Update this mirror.
+ do (yas--mirror-update-display mirror field)
+ ;; Delay indenting until we're done all mirrors. We must do
+ ;; this to avoid losing whitespace between fields that are
+ ;; still empty (i.e., they will be non-empty after updating).
+ when (eq yas-indent-line 'auto)
+ collect (cons (yas--mirror-start mirror) (yas--mirror-end mirror))
+ into indent-regions
+ ;; `yas--place-overlays' is needed since the active field and
+ ;; protected overlays might have been changed because of insertions
+ ;; in `yas--mirror-update-display'.
+ do (let ((active-field (yas--snippet-active-field snippet)))
+ (when active-field (yas--place-overlays snippet active-field)))
+ finally do
+ (let ((yas--inhibit-overlay-hooks t))
+ (cl-loop for (beg . end) in (cl-sort indent-regions #'< :key #'car)
+ do (yas--indent-region beg end snippet)))))))
+
+(defun yas--mirror-update-display (mirror field)
+ "Update MIRROR according to FIELD (and mirror transform)."
+
+ (let* ((mirror-parent-field (yas--mirror-parent-field mirror))
+ (reflection (and (not (and mirror-parent-field
+ (yas--field-modified-p mirror-parent-field)))
+ (or (yas--apply-transform mirror field 'empty-on-nil)
+ (yas--field-text-for-display field)))))
+ (when (and reflection
+ (not (string= reflection (buffer-substring-no-properties (yas--mirror-start mirror)
+ (yas--mirror-end mirror)))))
+ (goto-char (yas--mirror-start mirror))
+ (let ((yas--inhibit-overlay-hooks t))
+ (insert reflection))
+ (if (> (yas--mirror-end mirror) (point))
+ (delete-region (point) (yas--mirror-end mirror))
+ (set-marker (yas--mirror-end mirror) (point))
+ (yas--advance-start-maybe (yas--mirror-next mirror) (point))
+ ;; super-special advance
+ (yas--advance-end-of-parents-maybe mirror-parent-field (point))))))
+
+(defun yas--field-update-display (field)
+ "Much like `yas--mirror-update-display', but for fields."
+ (when (yas--field-transform field)
+ (let ((transformed (and (not (eq (yas--field-number field) 0))
+ (yas--apply-transform field field))))
+ (when (and transformed
+ (not (string= transformed (buffer-substring-no-properties (yas--field-start field)
+ (yas--field-end field)))))
+ (setf (yas--field-modified-p field) t)
+ (goto-char (yas--field-start field))
+ (let ((yas--inhibit-overlay-hooks t))
+ (insert transformed)
+ (if (> (yas--field-end field) (point))
+ (delete-region (point) (yas--field-end field))
+ (set-marker (yas--field-end field) (point))
+ (yas--advance-start-maybe (yas--field-next field) (point)))
+ t)))))
+
+\f
+;;; Post-command hook:
+;;
+(defun yas--post-command-handler ()
+ "Handles various yasnippet conditions after each command."
+ (condition-case err
+ (progn (yas--finish-moving-snippets)
+ (cond ((eq 'undo this-command)
+ ;;
+ ;; After undo revival the correct field is sometimes not
+ ;; restored correctly, this condition handles that
+ ;;
+ (let* ((snippet (car (yas-active-snippets)))
+ (target-field
+ (and snippet
+ (cl-find-if-not
+ (lambda (field)
+ (yas--field-probably-deleted-p snippet field))
+ (remq nil
+ (cons (yas--snippet-active-field snippet)
+ (yas--snippet-fields snippet)))))))
+ (when target-field
+ (yas--move-to-field snippet target-field))))
+ ((not (yas--undo-in-progress))
+ ;; When not in an undo, check if we must commit the snippet
+ ;; (user exited it).
+ (yas--check-commit-snippet))))
+ ((debug error) (signal (car err) (cdr err)))))
+\f
+;;; Fancy docs:
+;;
+;; The docstrings for some functions are generated dynamically
+;; depending on the context.
+;;
+(put 'yas-expand 'function-documentation
+ '(yas--expand-from-trigger-key-doc t))
+(defun yas--expand-from-trigger-key-doc (context)
+ "A doc synthesizer for `yas--expand-from-trigger-key-doc'."
+ (let* ((yas-fallback-behavior (and context yas-fallback-behavior))
+ (fallback-description
+ (cond ((eq yas-fallback-behavior 'call-other-command)
+ (let* ((fallback (yas--keybinding-beyond-yasnippet)))
+ (or (and fallback
+ (format "call command `%s'."
+ (pp-to-string fallback)))
+ "do nothing (`yas-expand' doesn't override\nanything).")))
+ ((eq yas-fallback-behavior 'return-nil)
+ "do nothing.")
+ (t "defer to `yas-fallback-behavior' (which see)."))))
+ (concat "Expand a snippet before point. If no snippet
+expansion is possible, "
+ fallback-description
+ "\n\nOptional argument FIELD is for non-interactive use and is an
+object satisfying `yas--field-p' to restrict the expansion to.")))
+
+(put 'yas-expand-from-keymap 'function-documentation
+ '(yas--expand-from-keymap-doc t))
+(defun yas--expand-from-keymap-doc (context)
+ "A doc synthesizer for `yas--expand-from-keymap-doc'."
+ (add-hook 'temp-buffer-show-hook #'yas--snippet-description-finish-runonce)
+ (concat "Expand/run snippets from keymaps, possibly falling back to original binding.\n"
+ (when (and context (eq this-command 'describe-key))
+ (let* ((vec (this-single-command-keys))
+ (templates (cl-mapcan (lambda (table)
+ (yas--fetch table vec))
+ (yas--get-snippet-tables)))
+ (yas--direct-keymaps nil)
+ (fallback (key-binding vec)))
+ (concat "In this case, "
+ (when templates
+ (concat "these snippets are bound to this key:\n"
+ (yas--template-pretty-list templates)
+ "\n\nIf none of these expands, "))
+ (or (and fallback
+ (format "fallback `%s' will be called." (pp-to-string fallback)))
+ "no fallback keybinding is called."))))))
+
+(defun yas--template-pretty-list (templates)
+ (let ((acc)
+ (yas-buffer-local-condition 'always))
+ (dolist (plate templates)
+ (setq acc (concat acc "\n*) "
+ (propertize (concat "\\\\snippet `" (car plate) "'")
+ 'yasnippet (cdr plate)))))
+ acc))
+
+(define-button-type 'help-snippet-def
+ :supertype 'help-xref
+ 'help-function (lambda (template) (yas--visit-snippet-file-1 template))
+ 'help-echo (purecopy "mouse-2, RET: find snippets's definition"))
+
+(defun yas--snippet-description-finish-runonce ()
+ "Final adjustments for the help buffer when snippets are concerned."
+ (yas--create-snippet-xrefs)
+ (remove-hook 'temp-buffer-show-hook
+ #'yas--snippet-description-finish-runonce))
+
+(defun yas--create-snippet-xrefs ()
+ (save-excursion
+ (goto-char (point-min))
+ (while (search-forward-regexp "\\\\\\\\snippet[ \s\t]+`\\([^']+\\)'" nil t)
+ (let ((template (get-text-property (match-beginning 1)
+ 'yasnippet)))
+ (when template
+ (help-xref-button 1 'help-snippet-def template)
+ (delete-region (match-end 1) (match-end 0))
+ (delete-region (match-beginning 0) (match-beginning 1)))))))
+\f
+;;; Utils
+
+(defvar yas-verbosity 3
+ "Log level for `yas--message' 4 means trace most anything, 0 means nothing.")
+
+(defun yas--message (level message &rest args)
+ "When LEVEL is at or below `yas-verbosity', log MESSAGE and ARGS."
+ (when (>= yas-verbosity level)
+ (message "%s" (apply #'yas--format message args))))
+
+(defun yas--warning (format-control &rest format-args)
+ (let ((msg (apply #'format format-control format-args)))
+ (display-warning 'yasnippet msg :warning)
+ (yas--message 1 msg)))
+
+(defun yas--format (format-control &rest format-args)
+ (apply #'format (concat "[yas] " format-control) format-args))
+
+\f
+;;; Some hacks:
+;;
+;; The functions
+;;
+;; `locate-dominating-file'
+;; `region-active-p'
+;;
+;; added for compatibility in emacsen < 23
+(unless (>= emacs-major-version 23)
+ (unless (fboundp 'region-active-p)
+ (defun region-active-p () (and transient-mark-mode mark-active)))
+
+ (unless (fboundp 'locate-dominating-file)
+ (defvar locate-dominating-stop-dir-regexp
+ "\\`\\(?:[\\/][\\/][^\\/]+[\\/]\\|/\\(?:net\\|afs\\|\\.\\.\\.\\)/\\)\\'"
+ "Regexp of directory names which stop the search in `locate-dominating-file'.
+Any directory whose name matches this regexp will be treated like
+a kind of root directory by `locate-dominating-file' which will stop its search
+when it bumps into it.
+The default regexp prevents fruitless and time-consuming attempts to find
+special files in directories in which filenames are interpreted as hostnames,
+or mount points potentially requiring authentication as a different user.")
+
+ (defun locate-dominating-file (file name)
+ "Look up the directory hierarchy from FILE for a file named NAME.
+Stop at the first parent directory containing a file NAME,
+and return the directory. Return nil if not found."
+ ;; We used to use the above locate-dominating-files code, but the
+ ;; directory-files call is very costly, so we're much better off doing
+ ;; multiple calls using the code in here.
+ ;;
+ ;; Represent /home/luser/foo as ~/foo so that we don't try to look for
+ ;; `name' in /home or in /.
+ (setq file (abbreviate-file-name file))
+ (let ((root nil)
+ try)
+ (while (not (or root
+ (null file)
+ ;; FIXME: Disabled this heuristic because it is sometimes
+ ;; inappropriate.
+ ;; As a heuristic, we stop looking up the hierarchy of
+ ;; directories as soon as we find a directory belonging
+ ;; to another user. This should save us from looking in
+ ;; things like /net and /afs. This assumes that all the
+ ;; files inside a project belong to the same user.
+ ;; (let ((prev-user user))
+ ;; (setq user (nth 2 (file-attributes file)))
+ ;; (and prev-user (not (equal user prev-user))))
+ (string-match locate-dominating-stop-dir-regexp file)))
+ (setq try (file-exists-p (expand-file-name name file)))
+ (cond (try (setq root file))
+ ((equal file (setq file (file-name-directory
+ (directory-file-name file))))
+ (setq file nil))))
+ root))))
+
+\f
+;;; Backward compatibility to yasnippet <= 0.7
+
+(defun yas-initialize ()
+ "For backward compatibility, enable `yas-minor-mode' globally."
+ (declare (obsolete "Use (yas-global-mode 1) instead." "0.8"))
+ (yas-global-mode 1))
+
+(defvar yas--backported-syms '(;; `defcustom's
+ ;;
+ yas-snippet-dirs
+ yas-prompt-functions
+ yas-indent-line
+ yas-also-auto-indent-first-line
+ yas-snippet-revival
+ yas-triggers-in-field
+ yas-fallback-behavior
+ yas-choose-keys-first
+ yas-choose-tables-first
+ yas-use-menu
+ yas-trigger-symbol
+ yas-wrap-around-region
+ yas-good-grace
+ yas-visit-from-menu
+ yas-expand-only-for-last-commands
+ yas-field-highlight-face
+
+ ;; these vars can be customized as well
+ ;;
+ yas-keymap
+ yas-verbosity
+ yas-extra-modes
+ yas-key-syntaxes
+ yas-after-exit-snippet-hook
+ yas-before-expand-snippet-hook
+ yas-buffer-local-condition
+ yas-dont-activate
+
+ ;; prompting functions
+ ;;
+ yas-x-prompt
+ yas-ido-prompt
+ yas-no-prompt
+ yas-completing-prompt
+ yas-dropdown-prompt
+
+ ;; interactive functions
+ ;;
+ yas-expand
+ yas-minor-mode
+ yas-global-mode
+ yas-direct-keymaps-reload
+ yas-minor-mode-on
+ yas-load-directory
+ yas-reload-all
+ yas-compile-directory
+ yas-recompile-all
+ yas-about
+ yas-expand-from-trigger-key
+ yas-expand-from-keymap
+ yas-insert-snippet
+ yas-visit-snippet-file
+ yas-new-snippet
+ yas-load-snippet-buffer
+ yas-tryout-snippet
+ yas-describe-tables
+ yas-next-field-or-maybe-expand
+ yas-next-field
+ yas-prev-field
+ yas-abort-snippet
+ yas-exit-snippet
+ yas-exit-all-snippets
+ yas-skip-and-clear-or-delete-char
+ yas-initialize
+
+ ;; symbols that I "exported" for use
+ ;; in snippets and hookage
+ ;;
+ yas-expand-snippet
+ yas-define-snippets
+ yas-define-menu
+ yas-snippet-beg
+ yas-snippet-end
+ yas-modified-p
+ yas-moving-away-p
+ yas-substr
+ yas-choose-value
+ yas-key-to-value
+ yas-throw
+ yas-verify-value
+ yas-field-value
+ yas-text
+ yas-selected-text
+ yas-default-from-field
+ yas-inside-string
+ yas-unimplemented
+ yas-define-condition-cache
+ yas-hippie-try-expand
+
+ ;; debug definitions
+ ;; yas-debug-snippet-vars
+ ;; yas-exterminate-package
+ ;; yas-debug-test
+
+ ;; testing definitions
+ ;; yas-should-expand
+ ;; yas-should-not-expand
+ ;; yas-mock-insert
+ ;; yas-make-file-or-dirs
+ ;; yas-variables
+ ;; yas-saving-variables
+ ;; yas-call-with-snippet-dirs
+ ;; yas-with-snippet-dirs
+)
+ "Backported yasnippet symbols.
+
+They are mapped to \"yas/*\" variants.")
+
+(when yas-alias-to-yas/prefix-p
+ (dolist (sym yas--backported-syms)
+ (let ((backported (intern (replace-regexp-in-string "\\`yas-" "yas/" (symbol-name sym)))))
+ (when (boundp sym)
+ (make-obsolete-variable backported sym "yasnippet 0.8")
+ (defvaralias backported sym))
+ (when (fboundp sym)
+ (make-obsolete backported sym "yasnippet 0.8")
+ (defalias backported sym))))
+ (make-obsolete 'yas/root-directory 'yas-snippet-dirs "yasnippet 0.8")
+ (defvaralias 'yas/root-directory 'yas-snippet-dirs))
+
+(defvar yas--exported-syms
+ (let (exported)
+ (mapatoms (lambda (atom)
+ (if (and (or (and (boundp atom)
+ (not (get atom 'byte-obsolete-variable)))
+ (and (fboundp atom)
+ (not (get atom 'byte-obsolete-info))))
+ (string-match-p "\\`yas-[^-]" (symbol-name atom)))
+ (push atom exported))))
+ exported)
+ "Exported yasnippet symbols.
+
+i.e. the ones with \"yas-\" single dash prefix. I will try to
+keep them in future yasnippet versions and other elisp libraries
+can more or less safely rely upon them.")
+
+\f
+(provide 'yasnippet)
+;; Local Variables:
+;; coding: utf-8
+;; indent-tabs-mode: nil
+;; End:
+;;; yasnippet.el ends here