update
Stefan Bund [Fri, 18 Jan 2019 16:38:15 +0000 (17:38 +0100)]
35 files changed:
UBUNTU-PACKAGES
auto-install/atomic-chrome.el [new file with mode: 0644]
elpa/archives/gnu/archive-contents [new file with mode: 0644]
elpa/archives/gnu/archive-contents.signed [new file with mode: 0644]
elpa/gnupg/pubring.gpg [new file with mode: 0644]
elpa/gnupg/secring.gpg [new file with mode: 0644]
elpa/gnupg/trustdb.gpg [new file with mode: 0644]
elpa/let-alist-1.0.5.signed [new file with mode: 0644]
elpa/let-alist-1.0.5/let-alist-autoloads.el [new file with mode: 0644]
elpa/let-alist-1.0.5/let-alist-pkg.el [new file with mode: 0644]
elpa/let-alist-1.0.5/let-alist.el [new file with mode: 0644]
elpa/websocket-1.8.signed [new file with mode: 0644]
elpa/websocket-1.8/COPYING [new file with mode: 0644]
elpa/websocket-1.8/ChangeLog [new file with mode: 0644]
elpa/websocket-1.8/README.org [new file with mode: 0644]
elpa/websocket-1.8/testserver.py [new file with mode: 0644]
elpa/websocket-1.8/websocket-autoloads.el [new file with mode: 0644]
elpa/websocket-1.8/websocket-functional-test.el [new file with mode: 0644]
elpa/websocket-1.8/websocket-pkg.el [new file with mode: 0644]
elpa/websocket-1.8/websocket.el [new file with mode: 0644]
emacs-custom.el
gnuplot/load.el [moved from gnuplot/autoload.el with 100% similarity]
python/init_python.el
setup/bindings.el
setup/eshell.el
setup/flyspell.el
setup/gnuplot.el
setup/magit.el
setup/mywin.el
setup/nxml.el
setup/rtags.el
setup/solarized-emacs.el
setup/sticky.el [new file with mode: 0644]
setup/x2go-hack.el
setup/zzz_finish.el

index d09c225..e78deb1 100644 (file)
@@ -4,4 +4,5 @@ python-ropemacs
 pyflakes
 cmake
 llvm
-libclang-dev
\ No newline at end of file
+libclang-dev
+yaml-mode
diff --git a/auto-install/atomic-chrome.el b/auto-install/atomic-chrome.el
new file mode 100644 (file)
index 0000000..f1750da
--- /dev/null
@@ -0,0 +1,368 @@
+;;; atomic-chrome.el --- Edit Chrome text area with Emacs using Atomic Chrome
+
+;; Copyright (C) 2016 alpha22jp <alpha22jp@gmail.com>
+
+;; Author: alpha22jp <alpha22jp@gmail.com>
+;; Package-Requires: ((emacs "24.3") (let-alist "1.0.4") (websocket "1.4"))
+;; Package-Version: 20171022.107
+;; Keywords: chrome edit textarea
+;; URL: https://github.com/alpha22jp/atomic-chrome
+;; Version: 2.0.0
+
+;; This program is free software; you can redistribute it and/or modify it under
+;; the terms of the GNU General Public License as published by the Free Software
+;; Foundation; either version 2 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, write to the Free Software Foundation, Inc., 51
+;; Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; This is the Emacs version of Atomic Chrome which is an extension for Google
+;; Chrome browser that allows you to edit text areas of the browser in Emacs.
+;;
+;; It's similar to Edit with Emacs, but has some advantages as below with the
+;; help of websocket.
+;;
+;; * Live update
+;;   The input on Emacs is reflected to the browser instantly and continuously.
+;; * Bidirectional communication
+;;   You can edit both on the browser and Emacs, they are synced to the same.
+
+;;; Code:
+
+(eval-when-compile (require 'cl))
+(require 'json)
+(require 'let-alist)
+(require 'websocket)
+
+(defgroup atomic-chrome nil
+  "Edit Chrome text area with Emacs using Atomic Chrome."
+  :prefix "atomic-chrome-"
+  :group 'applications)
+
+(defcustom atomic-chrome-extension-type-list '(atomic-chrome ghost-text)
+  "List of chrome extension type available."
+  :type '(repeat (choice (const :tag "Atomic Chrome" atomic-chrome)
+                         (const :tag "Ghost Text" ghost-text)))
+  :group 'atomic-chrome)
+
+(defcustom atomic-chrome-buffer-open-style 'split
+  "Specify the style to open new buffer for editing."
+  :type '(choice (const :tag "Open buffer with full window" full)
+                 (const :tag "Open buffer with splitted window" split)
+                 (const :tag "Open buffer with new frame" frame))
+  :group 'atomic-chrome)
+
+(defcustom atomic-chrome-buffer-frame-width 80
+  "Width of editing buffer frame."
+  :type 'integer
+  :group 'atomic-chrome)
+
+(defcustom atomic-chrome-buffer-frame-height 25
+  "Height of editing buffer frame."
+  :type 'integer
+  :group 'atomic-chrome)
+
+(defcustom atomic-chrome-enable-auto-update t
+  "If non-nil, edit on Emacs is reflected to Chrome instantly, \
+otherwise you need to type \"C-xC-s\" manually."
+  :type 'boolean
+  :group 'atomic-chrome)
+
+(defcustom atomic-chrome-enable-bidirectional-edit t
+  "If non-nil, you can edit both on Chrome text area and Emacs, \
+otherwise edit on Chrome is ignored while editing on Emacs."
+  :type 'boolean
+  :group 'atomic-chrome)
+
+(defcustom atomic-chrome-default-major-mode 'text-mode
+  "Default major mode for editing buffer."
+  :type 'function
+  :group 'atomic-chrome)
+
+(defcustom atomic-chrome-url-major-mode-alist nil
+  "Association list of URL regexp and corresponding major mode \
+which is used to select major mode for specified website."
+  :type '(alist :key-type (regexp :tag "regexp")
+                :value-type (function :tag "major mode"))
+  :group 'atomic-chrome)
+
+(defcustom atomic-chrome-edit-mode-hook nil
+  "Customizable hook which run when the editing buffer is created."
+  :type 'hook
+  :group 'atomic-chrome)
+
+(defcustom atomic-chrome-edit-done-hook nil
+  "Customizable hook which run when the editing buffer is closed."
+  :type 'hook
+  :group 'atomic-chrome)
+
+(defvar atomic-chrome-server-atomic-chrome nil
+  "Websocket server connection handle for Atomic Chrome.")
+
+(defvar atomic-chrome-server-ghost-text nil
+  "Websocket server connection handle for Ghost Text.")
+
+(defvar atomic-chrome-buffer-table (make-hash-table :test 'equal)
+  "Hash table of editing buffer and its assciated data.
+Each element has a list consisting of (websocket, frame).")
+
+(defun atomic-chrome-get-websocket (buffer)
+  "Lookup websocket associated with buffer BUFFER \
+from `atomic-chrome-buffer-table'."
+  (nth 0 (gethash buffer atomic-chrome-buffer-table)))
+
+(defun atomic-chrome-get-frame (buffer)
+  "Lookup frame associated with buffer BUFFER \
+from `atomic-chrome-buffer-table'."
+  (nth 1 (gethash buffer atomic-chrome-buffer-table)))
+
+(defun atomic-chrome-get-buffer-by-socket (socket)
+  "Lookup buffer which is associated to the websocket SOCKET \
+from `atomic-chrome-buffer-table'."
+  (let (buffer)
+    (cl-loop for key being the hash-keys of atomic-chrome-buffer-table
+             using (hash-values val)
+             do (when (equal (nth 0 val) socket) (setq buffer key)))
+    buffer))
+
+(defun atomic-chrome-close-connection ()
+  "Close client connection associated with current buffer."
+  (let ((socket (atomic-chrome-get-websocket (current-buffer))))
+    (when socket
+      (remhash (current-buffer) atomic-chrome-buffer-table)
+      (websocket-close socket))))
+
+(defun atomic-chrome-send-buffer-text ()
+  "Send request to update text with current buffer content."
+  (interactive)
+  (let ((socket (atomic-chrome-get-websocket (current-buffer)))
+        (text (buffer-substring-no-properties (point-min) (point-max))))
+    (when (and socket text)
+      (websocket-send-text
+       socket
+       (json-encode
+        (if (eq (websocket-server-conn socket) atomic-chrome-server-ghost-text)
+            (list (cons "text" text))
+          (list '("type" . "updateText")
+                (cons "payload" (list (cons "text" text))))))))))
+
+(defun atomic-chrome-set-major-mode (url)
+  "Set major mode for editing buffer depending on URL.
+`atomic-chrome-url-major-mode-alist' can be used to select major mode.
+The specified major mode is used if URL matches to one of the alist,
+otherwise fallback to `atomic-chrome-default-major-mode'"
+  (funcall (or (and url (assoc-default url
+                                       atomic-chrome-url-major-mode-alist
+                                       'string-match))
+               atomic-chrome-default-major-mode)))
+
+(defun atomic-chrome-show-edit-buffer (buffer title)
+  "Show editing buffer BUFFER by creating a frame with title TITLE, \
+or raising the selected frame depending on `atomic-chrome-buffer-open-style'."
+  (let ((edit-frame nil)
+        (frame-params (list (cons 'name (format "Atomic Chrome: %s" title))
+                            (cons 'width atomic-chrome-buffer-frame-width)
+                            (cons 'height atomic-chrome-buffer-frame-height))))
+    (when (eq atomic-chrome-buffer-open-style 'frame)
+      (setq edit-frame
+            (if (memq window-system '(ns mac))
+                ;; Avoid using make-frame-on-display for Mac OS.
+                (make-frame frame-params)
+              (make-frame-on-display
+               (if (eq system-type 'windows-nt) "w32" (getenv "DISPLAY"))
+               frame-params)))
+      (select-frame edit-frame))
+    (if (eq atomic-chrome-buffer-open-style 'split)
+        (pop-to-buffer buffer)
+      (switch-to-buffer buffer))
+    (raise-frame edit-frame)
+    (select-frame-set-input-focus (window-frame (selected-window)))
+    edit-frame))
+
+(defun atomic-chrome-create-buffer (socket url title text)
+  "Create buffer associated with websocket specified by SOCKET.
+URL is used to determine the major mode of the buffer created,
+TITLE is used for the buffer name and TEXT is inserted to the buffer."
+  (let ((buffer (generate-new-buffer title)))
+    (with-current-buffer buffer
+      (puthash buffer
+             (list socket (atomic-chrome-show-edit-buffer buffer title))
+             atomic-chrome-buffer-table)
+      (atomic-chrome-set-major-mode url)
+      (insert text))))
+
+(defun atomic-chrome-close-edit-buffer (buffer)
+  "Close buffer BUFFER if it's one of Atomic Chrome edit buffers."
+  (let ((frame (atomic-chrome-get-frame buffer)))
+    (with-current-buffer buffer
+      (save-restriction
+        (run-hooks 'atomic-chrome-edit-done-hook)
+        (when frame (delete-frame frame))
+        (if (eq atomic-chrome-buffer-open-style 'split)
+            (quit-window t)
+          (kill-buffer buffer))))))
+
+(defun atomic-chrome-close-current-buffer ()
+  "Close current buffer and connection from client."
+  (interactive)
+  (atomic-chrome-close-edit-buffer (current-buffer)))
+
+(defun atomic-chrome-update-buffer (socket text)
+  "Update text on buffer associated with SOCKET to TEXT."
+  (let ((buffer (atomic-chrome-get-buffer-by-socket socket)))
+    (when buffer
+      (with-current-buffer buffer
+        (erase-buffer)
+        (insert text)))))
+
+(defun atomic-chrome-on-message (socket frame)
+  "Function to handle data received from websocket client specified by SOCKET, \
+where FRAME show raw data received."
+  (let ((msg (json-read-from-string
+              (decode-coding-string
+               (encode-coding-string (websocket-frame-payload frame) 'utf-8)
+               'utf-8))))
+    (let-alist msg
+      (if (eq (websocket-server-conn socket) atomic-chrome-server-ghost-text)
+          (if (atomic-chrome-get-buffer-by-socket socket)
+              (atomic-chrome-update-buffer socket .text)
+            (atomic-chrome-create-buffer socket .url .title .text))
+        (cond ((string= .type "register")
+               (atomic-chrome-create-buffer socket .payload.url .payload.title .payload.text))
+              ((string= .type "updateText")
+               (when atomic-chrome-enable-bidirectional-edit
+                 (atomic-chrome-update-buffer socket .payload.text))))))))
+
+(defun atomic-chrome-on-close (socket)
+  "Function to handle request from client to close websocket SOCKET."
+  (let ((buffer (atomic-chrome-get-buffer-by-socket socket)))
+    (when buffer (atomic-chrome-close-edit-buffer buffer))))
+
+(defvar atomic-chrome-edit-mode-map
+  (let ((map (make-sparse-keymap)))
+    (define-key map (kbd "C-x C-s") 'atomic-chrome-send-buffer-text)
+    (define-key map (kbd "C-c C-c") 'atomic-chrome-close-current-buffer)
+    map)
+  "Keymap for minor mode `atomic-chrome-edit-mode'.")
+
+(define-minor-mode atomic-chrome-edit-mode
+  "Minor mode enabled on buffers opened by Emacs Chrome server."
+  :group 'atomic-chrome
+  :lighter " AtomicChrome"
+  :init-value nil
+  :keymap atomic-chrome-edit-mode-map
+  (when atomic-chrome-edit-mode
+    (add-hook 'kill-buffer-hook 'atomic-chrome-close-connection nil t)
+    (when atomic-chrome-enable-auto-update
+      (add-hook 'post-command-hook 'atomic-chrome-send-buffer-text nil t))))
+
+(defun atomic-chrome-turn-on-edit-mode ()
+  "Turn on `atomic-chrome-edit-mode' if the buffer is an editing buffer."
+  (when (gethash (current-buffer) atomic-chrome-buffer-table)
+    (atomic-chrome-edit-mode t)))
+
+(define-global-minor-mode global-atomic-chrome-edit-mode
+  atomic-chrome-edit-mode atomic-chrome-turn-on-edit-mode)
+
+(defun atomic-chrome-start-websocket-server (port)
+  "Create websocket server on port PORT."
+  (websocket-server
+   port
+   :host 'local
+   :on-message #'atomic-chrome-on-message
+   :on-open nil
+   :on-close #'atomic-chrome-on-close))
+
+(defun atomic-chrome-start-httpd ()
+  "Start the HTTP server for Ghost Text query."
+  (interactive)
+  (make-network-process
+   :name "atomic-chrome-httpd"
+   :family 'ipv4
+   :host 'local
+   :service 4001
+   :filter 'atomic-chrome-httpd-process-filter
+   :filter-multibyte nil
+   :server t
+   :noquery t))
+
+(defun atomic-chrome-normalize-header (header)
+  "Destructively capitalize the components of HEADER."
+  (mapconcat #'capitalize (split-string header "-") "-"))
+
+(defun atomic-chrome-httpd-parse-string (string)
+  "Parse client http header STRING into alist."
+  (let* ((lines (split-string string "[\n\r]+"))
+         (req (list (split-string (car lines))))
+         (post (cadr (split-string string "\r\n\r\n"))))
+    (dolist (line (butlast (cdr lines)))
+      (push (list (atomic-chrome-normalize-header (car (split-string line ": ")))
+                  (mapconcat #'identity
+                             (cdr (split-string line ": ")) ": "))
+            req))
+    (push (list "Content" post) req)
+    (reverse req)))
+
+(defun atomic-chrome-httpd-process-filter (proc string)
+  "Process filter of PROC which run each time client make a request.
+STRING is the string process received."
+  (setf string (concat (process-get proc :previous-string) string))
+  (let* ((request (atomic-chrome-httpd-parse-string string))
+         (content-length (cadr (assoc "Content-Length" request)))
+         (uri (cl-cadar request))
+         (content (cadr (assoc "Content" request))))
+    (if (and content-length
+             (< (string-bytes content) (string-to-number content-length)))
+        (process-put proc :previous-string string)
+      (atomic-chrome-httpd-send-response proc))))
+
+(defun atomic-chrome-httpd-send-response (proc)
+  "Send an HTTP 200 OK response back to process PROC."
+  (when (processp proc)
+    (unless atomic-chrome-server-ghost-text
+      (setq atomic-chrome-server-ghost-text
+            (atomic-chrome-start-websocket-server 64293)))
+    (let ((header "HTTP/1.0 200 OK\nContent-Type: application/json\n")
+          (body (json-encode '(:ProtocolVersion 1 :WebSocketPort 64293))))
+      (process-send-string proc (concat header "\n" body))
+      (process-send-eof proc))))
+
+;;;###autoload
+(defun atomic-chrome-start-server ()
+  "Start websocket server for atomic-chrome."
+  (interactive)
+  (and (not atomic-chrome-server-atomic-chrome)
+       (memq 'atomic-chrome atomic-chrome-extension-type-list)
+       (setq atomic-chrome-server-atomic-chrome
+             (atomic-chrome-start-websocket-server 64292)))
+  (and (not (process-status "atomic-chrome-httpd"))
+       (memq 'ghost-text atomic-chrome-extension-type-list)
+       (atomic-chrome-start-httpd))
+  (global-atomic-chrome-edit-mode 1))
+
+;;;###autoload
+(defun atomic-chrome-stop-server nil
+  "Stop websocket server for atomic-chrome."
+  (interactive)
+  (when atomic-chrome-server-atomic-chrome
+    (websocket-server-close atomic-chrome-server-atomic-chrome)
+    (setq atomic-chrome-server-atomic-chrome nil))
+  (when atomic-chrome-server-ghost-text
+    (websocket-server-close atomic-chrome-server-ghost-text)
+    (setq atomic-chrome-server-ghost-text nil))
+  (when (process-status "atomic-chrome-httpd")
+    (delete-process "atomic-chrome-httpd"))
+  (global-atomic-chrome-edit-mode 0))
+
+(provide 'atomic-chrome)
+
+;;; atomic-chrome.el ends here
diff --git a/elpa/archives/gnu/archive-contents b/elpa/archives/gnu/archive-contents
new file mode 100644 (file)
index 0000000..2b1441e
--- /dev/null
@@ -0,0 +1,1179 @@
+(1
+ (ace-window .
+            [(0 9 0)
+             ((avy
+               (0 2 0)))
+             "Quickly switch windows." single
+             ((:url . "https://github.com/abo-abo/ace-window")
+              (:keywords "window" "location"))])
+ (ack .
+      [(1 5)
+       nil "interface to ack-like tools" tar
+       ((:keywords "tools" "processes" "convenience")
+       (:url . "https://github.com/leoliu/ack-el"))])
+ (ada-mode .
+          [(5 3 1)
+           ((wisi
+             (1 1 6))
+            (cl-lib
+             (0 4))
+            (emacs
+             (24 3)))
+           "major-mode for editing Ada sources" tar
+           ((:keywords "languages" "ada")
+            (:url . "http://www.nongnu.org/ada-mode/"))])
+ (ada-ref-man .
+             [(2012 3)
+              nil "Ada Reference Manual 2012" tar
+              ((:keywords "languages" "ada")
+               (:url . "http://stephe-leake.org/ada/arm.html"))])
+ (adaptive-wrap .
+               [(0 5 1)
+                nil "Smart line-wrapping with wrap-prefix" single
+                ((:url . "http://elpa.gnu.org/packages/adaptive-wrap.html")
+                 (:keywords))])
+ (adjust-parens .
+               [(3 0)
+                nil "Indent and dedent Lisp code, automatically adjust close parens" tar
+                ((:url . "http://elpa.gnu.org/packages/adjust-parens.html"))])
+ (aggressive-indent .
+                   [(1 8 3)
+                    ((emacs
+                      (24 1))
+                     (cl-lib
+                      (0 5)))
+                    "Minor mode to aggressively keep your code always indented" single
+                    ((:url . "https://github.com/Malabarba/aggressive-indent-mode")
+                     (:keywords "indent" "lisp" "maint" "tools"))])
+ (ahungry-theme .
+               [(1 5 0)
+                ((emacs
+                  (24)))
+                "Ahungry color theme for Emacs.  Make sure to (load-theme 'ahungry)." tar
+                ((:keywords "ahungry" "palette" "color" "theme" "emacs" "color-theme" "deftheme")
+                 (:url . "https://github.com/ahungry/color-theme-ahungry"))])
+ (all .
+      [(1 0)
+       nil "Edit all lines matching a given regexp" single
+       ((:url . "http://elpa.gnu.org/packages/all.html")
+       (:keywords "matching"))])
+ (ampc .
+       [(0 2)
+       nil "Asynchronous Music Player Controller" single
+       ((:url . "http://elpa.gnu.org/packages/ampc.html")
+        (:keywords "ampc" "mpc" "mpd"))])
+ (arbitools .
+           [(0 71)
+            ((cl-lib
+              (0 5)))
+            "Package for chess tournaments administration" single
+            ((:url . "http://elpa.gnu.org/packages/arbitools.html")
+             (:keywords))])
+ (ascii-art-to-unicode .
+                      [(1 11)
+                       nil "a small artist adjunct" single
+                       ((:url . "http://www.gnuvola.org/software/aa2u/")
+                        (:keywords "ascii" "unicode" "box-drawing"))])
+ (async .
+       [(1 9 2)
+        nil "Asynchronous processing in Emacs" tar
+        ((:keywords "async")
+         (:url . "http://elpa.gnu.org/packages/async.html"))])
+ (auctex .
+        [(11 91 0)
+         nil "Integrated environment for *TeX*" tar
+         ((:url . "http://www.gnu.org/software/auctex/"))])
+ (aumix-mode .
+            [(7)
+             nil "run the aumix program in a buffer" single
+             ((:url . "http://user42.tuxfamily.org/aumix-mode/index.html")
+              (:keywords "multimedia" "mixer" "aumix"))])
+ (auto-correct .
+              [(1 1)
+               nil "Remembers and automatically fixes past corrections" single
+               ((:url . "http://elpa.gnu.org/packages/auto-correct.html")
+                (:keywords "editing"))])
+ (auto-overlays .
+               [(0 10 9)
+                nil "Automatic regexp-delimited overlays" tar
+                ((:keywords "extensions")
+                 (:url . "http://www.dr-qubit.org/emacs.php"))])
+ (avy .
+      [(0 4 0)
+       ((emacs
+        (24 1))
+       (cl-lib
+        (0 5)))
+       "tree-based completion" tar
+       ((:keywords "point" "location")
+       (:url . "https://github.com/abo-abo/avy"))])
+ (beacon .
+        [(1 3 2)
+         ((seq
+           (2 14)))
+         "Highlight the cursor whenever the window scrolls" single
+         ((:url . "https://github.com/Malabarba/beacon")
+          (:keywords "convenience"))])
+ (bug-hunter .
+            [(1 3 1)
+             ((seq
+               (1 3))
+              (cl-lib
+               (0 5)))
+             "Hunt down errors by bisecting elisp files" single
+             ((:url . "https://github.com/Malabarba/elisp-bug-hunter")
+              (:keywords "lisp"))])
+ (caps-lock .
+           [(1 0)
+            nil "Caps-lock as a minor mode" single
+            ((:url . "http://elpa.gnu.org/packages/caps-lock.html")
+             (:keywords))])
+ (captain .
+         [(1 0 1)
+          nil "CAPiTalization is Automatic IN emacs" single
+          ((:url . "http://elpa.gnu.org/packages/captain.html")
+           (:keywords "editing"))])
+ (chess .
+       [(2 0 4)
+        ((cl-lib
+          (0 5)))
+        "Play chess in GNU Emacs" tar
+        ((:keywords "games")
+         (:url . "http://elpa.gnu.org/packages/chess.html"))])
+ (cl-generic .
+            [(0 3)
+             nil "Forward cl-generic compatibility for Emacs<25" single
+             ((:url . "http://elpa.gnu.org/packages/cl-generic.html")
+              (:keywords))])
+ (cl-lib .
+        [(0 6 1)
+         nil "Properly prefixed CL functions and macros" single
+         ((:url . "http://elpa.gnu.org/packages/cl-lib.html")
+          (:keywords))])
+ (cl-print .
+          [(1 0)
+           ((emacs
+             (25)))
+           "CL-style generic printing" single
+           ((:url . "http://elpa.gnu.org/packages/cl-print.html")
+            (:keywords))])
+ (cobol-mode .
+            [(1 0 0)
+             ((cl-lib
+               (0 5)))
+             "Mode for editing COBOL code" single
+             ((:url . "http://elpa.gnu.org/packages/cobol-mode.html")
+              (:keywords "languages"))])
+ (coffee-mode .
+             [(0 4 1 1)
+              nil "Major mode for CoffeeScript files" single
+              ((:url . "http://github.com/defunkt/coffee-mode")
+               (:keywords "coffeescript" "major" "mode"))])
+ (compact-docstrings .
+                    [(0 1)
+                     nil "Shrink blank lines in docstrings and doc comments" single
+                     ((:url . "https://github.com/cpitclaudel/compact-docstrings")
+                      (:keywords "convenience" "faces" "lisp" "maint" "c"))])
+ (company .
+         [(0 9 4)
+          ((emacs
+            (24 3)))
+          "Modular text completion framework" tar
+          ((:keywords "abbrev" "convenience" "matching")
+           (:url . "http://company-mode.github.io/"))])
+ (company-ebdb .
+              [(1)
+               ((company
+                 (0 9 4))
+                (ebdb
+                 (0 2)))
+               "company-mode completion backend for EBDB in message-mode" single
+               ((:url . "http://elpa.gnu.org/packages/company-ebdb.html")
+                (:keywords))])
+ (company-math .
+              [(1 1)
+               ((company
+                 (0 8 0))
+                (math-symbol-lists
+                 (1 0)))
+               "Completion backends for unicode math symbols and latex tags" tar
+               ((:keywords "unicode" "symbols" "completion")
+                (:url . "https://github.com/vspinu/company-math"))])
+ (company-statistics .
+                    [(0 2 3)
+                     ((emacs
+                       (24 3))
+                      (company
+                       (0 8 5)))
+                     "Sort candidates using completion history" tar
+                     ((:keywords "abbrev" "convenience" "matching")
+                      (:url . "https://github.com/company-mode/company-statistics"))])
+ (context-coloring .
+                  [(8 1 0)
+                   ((emacs
+                     (24 3)))
+                   "Highlight by scope" tar
+                   ((:keywords "convenience" "faces" "tools")
+                    (:url . "https://github.com/jacksonrayhamilton/context-coloring"))])
+ (counsel-ebdb .
+              [(1)
+               ((ivy
+                 (0 8 0))
+                (ebdb
+                 (0 2)))
+               "Counsel integration for EBDB" single
+               ((:url . "http://elpa.gnu.org/packages/counsel-ebdb.html")
+                (:keywords))])
+ (crisp .
+       [(1 3 4)
+        nil "CRiSP/Brief Emacs emulator" single
+        ((:url . "http://elpa.gnu.org/packages/crisp.html")
+         (:keywords "emulations" "brief" "crisp"))])
+ (csv-mode .
+          [(1 6)
+           nil "Major mode for editing comma/char separated values" single
+           ((:url . "http://elpa.gnu.org/packages/csv-mode.html")
+            (:keywords "convenience"))])
+ (cycle-quotes .
+              [(0 1)
+               nil "Cycle between quote styles" tar
+               ((:keywords "convenience")
+                (:url . "http://elpa.gnu.org/packages/cycle-quotes.html"))])
+ (darkroom .
+          [(0 1)
+           ((cl-lib
+             (0 5)))
+           "Remove visual distractions and focus on writing" single
+           ((:url . "http://elpa.gnu.org/packages/darkroom.html")
+            (:keywords "convenience" "emulations"))])
+ (dash .
+       [(2 12 0)
+       nil "A modern list library for Emacs" tar
+       ((:keywords "lists")
+        (:url . "http://elpa.gnu.org/packages/dash.html"))])
+ (dbus-codegen .
+              [(0 1)
+               ((cl-lib
+                 (0 5)))
+               "Lisp code generation for D-Bus." single
+               ((:url . "http://elpa.gnu.org/packages/dbus-codegen.html")
+                (:keywords "comm" "dbus" "convenience"))])
+ (debbugs .
+         [(0 14)
+          ((soap-client
+            (3 1 1))
+           (cl-lib
+            (0 5)))
+          "SOAP library to access debbugs servers" tar
+          ((:keywords "comm" "hypermedia")
+           (:url . "http://elpa.gnu.org/packages/debbugs.html"))])
+ (delight .
+         [(1 5)
+          nil "A dimmer switch for your lighter text." single
+          ((:url . "https://savannah.nongnu.org/projects/delight")
+           (:keywords "convenience"))])
+ (dict-tree .
+           [(0 14)
+            ((trie
+              (0 3))
+             (tNFA
+              (0 1 1))
+             (heap
+              (0 3)))
+            "Dictionary data structure" single
+            ((:url . "http://www.dr-qubit.org/emacs.php")
+             (:keywords "extensions" "matching" "data structures trie" "tree" "dictionary" "completion" "regexp"))])
+ (diff-hl .
+         [(1 8 4)
+          ((cl-lib
+            (0 2)))
+          "Highlight uncommitted changes using VC" tar
+          ((:keywords "vc" "diff")
+           (:url . "https://github.com/dgutov/diff-hl"))])
+ (diffview .
+          [(1 0)
+           nil "View diffs in side-by-side format" single
+           ((:url . "https://github.com/mgalgs/diffview-mode")
+            (:keywords "convenience" "diff"))])
+ (dired-du .
+          [(0 5)
+           ((emacs
+             (24 4))
+            (cl-lib
+             (0 5)))
+           "Dired with recursive directory sizes" tar
+           ((:keywords "files" "unix" "convenience")
+            (:url . "http://elpa.gnu.org/packages/dired-du.html"))])
+ (dismal .
+        [(1 5)
+         ((cl-lib
+           (0)))
+         "Dis Mode Ain't Lotus: Spreadsheet program Emacs" tar
+         ((:url . "http://elpa.gnu.org/packages/dismal.html"))])
+ (djvu .
+       [(0 5)
+       nil "Edit and view Djvu files via djvused" single
+       ((:url . "http://elpa.gnu.org/packages/djvu.html")
+        (:keywords "files" "wp"))])
+ (docbook .
+         [(0 1)
+          nil "Info-like viewer for DocBook" single
+          ((:url . "http://elpa.gnu.org/packages/docbook.html")
+           (:keywords "docs" "help"))])
+ (dts-mode .
+          [(0 1 0)
+           nil "Major mode for Device Tree source files" single
+           ((:url . "http://elpa.gnu.org/packages/dts-mode.html")
+            (:keywords "languages"))])
+ (easy-kill .
+           [(0 9 3)
+            ((emacs
+              (24))
+             (cl-lib
+              (0 5)))
+            "kill & mark things easily" tar
+            ((:keywords "killing" "convenience")
+             (:url . "https://github.com/leoliu/easy-kill"))])
+ (ebdb .
+       [(0 3 3)
+       ((emacs
+         (25 1))
+        (cl-lib
+         (0 5))
+        (seq
+         (2 15)))
+       "Contact management package" tar
+       ((:keywords "convenience" "mail")
+        (:url . "https://github.com/girzel/ebdb"))])
+ (ebdb-gnorb .
+            [(1 0 2)
+             ((gnorb
+               (1 1 0))
+              (ebdb
+               (0 2)))
+             "Utilities for connecting EBDB to Gnorb" single
+             ((:url . "http://elpa.gnu.org/packages/ebdb-gnorb.html")
+              (:keywords))])
+ (ebdb-i18n-chn .
+               [(1 2)
+                ((pyim
+                  (1 6 0))
+                 (ebdb
+                  (0 2)))
+                "China-specific internationalization support for EBDB" single
+                ((:url . "http://elpa.gnu.org/packages/ebdb-i18n-chn.html")
+                 (:keywords))])
+ (ediprolog .
+           [(1 2)
+            nil "Emacs Does Interactive Prolog" single
+            ((:url . "http://elpa.gnu.org/packages/ediprolog.html")
+             (:keywords "languages" "processes"))])
+ (el-search .
+           [(1 3 2)
+            ((emacs
+              (25))
+             (stream
+              (2 2 4)))
+            "Expression based interactive search for Emacs Lisp" tar
+            ((:keywords "lisp")
+             (:url . "http://elpa.gnu.org/packages/el-search.html"))])
+ (eldoc-eval .
+            [(0 1)
+             nil "Enable eldoc support when minibuffer is in use." single
+             ((:url . "http://elpa.gnu.org/packages/eldoc-eval.html")
+              (:keywords))])
+ (electric-spacing .
+                  [(5 0)
+                   nil "Insert operators with surrounding spaces smartly" single
+                   ((:url . "http://elpa.gnu.org/packages/electric-spacing.html")
+                    (:keywords))])
+ (enwc .
+       [(2 0)
+       ((emacs
+         (25 1)))
+       "The Emacs Network Client" tar
+       ((:keywords "external" "network" "wicd" "manager" "nm")
+        (:url . "http://elpa.gnu.org/packages/enwc.html"))])
+ (epoch-view .
+            [(0 0 1)
+             nil "Minor mode to visualize epoch timestamps" single
+             ((:url . "http://elpa.gnu.org/packages/epoch-view.html")
+              (:keywords "data" "timestamp" "epoch" "unix"))])
+ (ergoemacs-mode .
+                [(5 14 7 3)
+                 ((emacs
+                   (24 1))
+                  (undo-tree
+                   (0 6 5)))
+                 "Emacs mode based on common modern interface and ergonomics." tar
+                 ((:keywords "convenience")
+                  (:url . "https://github.com/ergoemacs/ergoemacs-mode"))])
+ (excorporate .
+             [(0 7 6)
+              ((emacs
+                (24 1))
+               (fsm
+                (0 2))
+               (soap-client
+                (3 1 1))
+               (url-http-ntlm
+                (2 0 3)))
+              "Exchange integration" tar
+              ((:keywords "calendar")
+               (:url . "http://elpa.gnu.org/packages/excorporate.html"))])
+ (exwm .
+       [(0 15)
+       ((xelb
+         (0 12)))
+       "Emacs X Window Manager" tar
+       ((:keywords "unix")
+        (:url . "https://github.com/ch11ng/exwm"))])
+ (f90-interface-browser .
+                       [(1 1)
+                        nil "Parse and browse f90 interfaces" single
+                        ((:url . "http://github.com/wence-/f90-iface/")
+                         (:keywords))])
+ (flylisp .
+         [(0 2)
+          ((emacs
+            (24 1))
+           (cl-lib
+            (0 4)))
+          "Color unbalanced parentheses and parentheses inconsistent with indentation" single
+          ((:url . "http://elpa.gnu.org/packages/flylisp.html")
+           (:keywords))])
+ (fsm .
+      [(0 2 1)
+       ((emacs
+        (24 1))
+       (cl-lib
+        (0 5)))
+       "state machine library" single
+       ((:url . "http://elpa.gnu.org/packages/fsm.html")
+       (:keywords "extensions"))])
+ (ggtags .
+        [(0 8 12)
+         ((emacs
+           (24))
+          (cl-lib
+           (0 5)))
+         "emacs frontend to GNU Global source code tagging system" single
+         ((:url . "https://github.com/leoliu/ggtags")
+          (:keywords "tools" "convenience"))])
+ (gited .
+       [(0 3 3)
+        ((emacs
+          (24 4))
+         (cl-lib
+          (0 5)))
+        "Operate on Git branches like dired" tar
+        ((:keywords "git" "vc" "convenience")
+         (:url . "http://elpa.gnu.org/packages/gited.html"))])
+ (gnome-c-style .
+               [(0 1)
+                nil "minor mode for editing GNOME-style C source code" tar
+                ((:keywords "gnome" "c" "coding style")
+                 (:url . "http://elpa.gnu.org/packages/gnome-c-style.html"))])
+ (gnorb .
+       [(1 2 4)
+        ((cl-lib
+          (0 5)))
+        "Glue code between Gnus, Org, and BBDB" tar
+        ((:keywords "mail" "org" "gnus" "bbdb" "todo" "task")
+         (:url . "http://elpa.gnu.org/packages/gnorb.html"))])
+ (gnugo .
+       [(3 1 0)
+        ((ascii-art-to-unicode
+          (1 5))
+         (xpm
+          (1 0 1))
+         (cl-lib
+          (0 5)))
+        "play GNU Go in a buffer" tar
+        ((:keywords "games" "processes")
+         (:url . "http://www.gnuvola.org/software/gnugo/"))])
+ (heap .
+       [(0 5)
+       nil "Heap (a.k.a. priority queue) data structure" single
+       ((:url . "http://www.dr-qubit.org/emacs.php")
+        (:keywords "extensions" "data structures" "heap" "priority queue"))])
+ (helm-ebdb .
+           [(1)
+            ((helm
+              (1 0))
+             (ebdb
+              (0 2)))
+            "Helm integration for EBDB" single
+            ((:url . "http://elpa.gnu.org/packages/helm-ebdb.html")
+             (:keywords "mail" "convenience"))])
+ (highlight-escape-sequences .
+                            [(0 3)
+                             nil "Highlight escape sequences" single
+                             ((:url . "https://github.com/dgutov/highlight-escape-sequences")
+                              (:keywords "convenience"))])
+ (hook-helpers .
+              [(1 1)
+               ((emacs
+                 (25 1)))
+               "Anonymous, modifiable hook functions" tar
+               ((:keywords "development" "hooks")
+                (:url . "https://savannah.nongnu.org/projects/hook-helpers-el/"))])
+ (html5-schema .
+              [(0 1)
+               nil "Add HTML5 schemas for use by nXML" tar
+               ((:keywords "html" "xml")
+                (:url . "https://github.com/validator/validator"))])
+ (hydra .
+       [(0 14 0)
+        ((cl-lib
+          (0 5)))
+        "Make bindings that stick around." tar
+        ((:keywords "bindings")
+         (:url . "https://github.com/abo-abo/hydra"))])
+ (hyperbole .
+           [(6 0 2)
+            ((emacs
+              (24 4)))
+            "GNU Hyperbole: The Everyday Hypertextual Information Manager" tar
+            ((:keywords "comm" "convenience" "files" "frames" "hypermedia" "languages" "mail" "matching" "mouse" "multimedia" "outlines" "tools" "wp")
+             (:url . "http://www.gnu.org/software/hyperbole"))])
+ (ioccur .
+        [(2 4)
+         nil "Incremental occur" single
+         ((:url . "http://elpa.gnu.org/packages/ioccur.html")
+          (:keywords))])
+ (iterators .
+           [(0 1)
+            ((emacs
+              (25)))
+            "Functions for working with iterators" single
+            ((:url . "http://elpa.gnu.org/packages/iterators.html")
+             (:keywords "extensions" "elisp"))])
+ (ivy .
+      [(0 9 1)
+       ((emacs
+        (24 1)))
+       "Incremental Vertical completYon" tar
+       ((:keywords "matching")
+       (:url . "https://github.com/abo-abo/swiper"))])
+ (javaimp .
+         [(0 6)
+          nil "Add and reorder Java import statements in Maven projects" tar
+          ((:keywords "java" "maven" "programming")
+           (:url . "http://elpa.gnu.org/packages/javaimp.html"))])
+ (jgraph-mode .
+             [(1 1)
+              ((cl-lib
+                (0 5)))
+              "Major mode for Jgraph files" single
+              ((:url . "http://elpa.gnu.org/packages/jgraph-mode.html")
+               (:keywords "tex" "wp"))])
+ (js2-mode .
+          [(20170721)
+           ((emacs
+             (24 1))
+            (cl-lib
+             (0 5)))
+           "Improved JavaScript editing mode" tar
+           ((:keywords "languages" "javascript")
+            (:url . "https://github.com/mooz/js2-mode/"))])
+ (json-mode .
+           [(0 1)
+            ((emacs
+              (25 1)))
+            "Major mode for editing JSON files" single
+            ((:url . "http://elpa.gnu.org/packages/json-mode.html")
+             (:keywords "data"))])
+ (jumpc .
+       [(3 0)
+        nil "jump to previous insertion points" single
+        ((:url . "http://elpa.gnu.org/packages/jumpc.html")
+         (:keywords))])
+ (kmb .
+      [(0 1)
+       ((emacs
+        (24 1)))
+       "Kill buffers matching a regexp w/o confirmation" single
+       ((:url . "http://elpa.gnu.org/packages/kmb.html")
+       (:keywords "lisp" "convenience"))])
+ (landmark .
+          [(1 0)
+           nil "Neural-network robot that learns landmarks" single
+           ((:url . "http://elpa.gnu.org/packages/landmark.html")
+            (:keywords "games" "neural network" "adaptive search" "chemotaxis"))])
+ (let-alist .
+   [(1 0 5)
+    ((emacs
+      (24 1)))
+    "Easily let-bind values of an assoc-list by their names" single
+    ((:url . "http://elpa.gnu.org/packages/let-alist.html")
+     (:keywords "extensions" "lisp"))])
+ (lex .
+      [(1 1)
+       nil "Lexical analyser construction" tar
+       ((:url . "http://elpa.gnu.org/packages/lex.html"))])
+ (lmc .
+      [(1 4)
+       ((emacs
+        (24))
+       (cl-lib
+        (0 5)))
+       "Little Man Computer in Elisp" single
+       ((:url . "http://elpa.gnu.org/packages/lmc.html")
+       (:keywords))])
+ (load-dir .
+          [(0 0 5)
+           ((cl-lib
+             (0 5)))
+           "Load all Emacs Lisp files in a given directory" single
+           ((:url . "http://elpa.gnu.org/packages/load-dir.html")
+            (:keywords "lisp" "files" "convenience"))])
+ (load-relative .
+               [(1 3)
+                nil "relative file load (within a multi-file Emacs package)" single
+                ((:url . "http://github.com/rocky/emacs-load-relative")
+                 (:keywords "internal"))])
+ (loc-changes .
+             [(1 2)
+              nil "keep track of positions even after buffer changes" single
+              ((:url . "http://github.com/rocky/emacs-loc-changes")
+               (:keywords))])
+ (loccur .
+        [(1 2 3)
+         ((cl-lib
+           (0)))
+         "Perform an occur-like folding in current buffer" single
+         ((:url . "https://github.com/fourier/loccur")
+          (:keywords "matching"))])
+ (markchars .
+           [(0 2 0)
+            nil "Mark chars fitting certain characteristics" single
+            ((:url . "http://elpa.gnu.org/packages/markchars.html")
+             (:keywords))])
+ (math-symbol-lists .
+                   [(1 1)
+                    nil "Lists of Unicode math symbols and latex commands" tar
+                    ((:keywords "unicode" "symbols" "mathematics")
+                     (:url . "https://github.com/vspinu/math-symbol-lists"))])
+ (memory-usage .
+              [(0 2)
+               nil "Analyze the memory usage of Emacs in various ways" single
+               ((:url . "http://elpa.gnu.org/packages/memory-usage.html")
+                (:keywords "maint"))])
+ (metar .
+       [(0 3)
+        ((cl-lib
+          (0 5)))
+        "Retrieve and decode METAR weather information" single
+        ((:url . "http://elpa.gnu.org/packages/metar.html")
+         (:keywords "comm"))])
+ (midi-kbd .
+          [(0 2)
+           ((emacs
+             (25)))
+           "Create keyboard events from Midi input" single
+           ((:url . "http://elpa.gnu.org/packages/midi-kbd.html")
+            (:keywords "convenience" "hardware" "multimedia"))])
+ (minibuffer-line .
+                 [(0 1)
+                  nil "Display status info in the minibuffer window" single
+                  ((:url . "http://elpa.gnu.org/packages/minibuffer-line.html")
+                   (:keywords))])
+ (minimap .
+         [(1 2)
+          nil "Sidebar showing a \"mini-map\" of a buffer" single
+          ((:url . "http://elpa.gnu.org/packages/minimap.html")
+           (:keywords))])
+ (multishell .
+            [(1 1 5)
+             nil "Easily use multiple shell buffers, local and remote." tar
+             ((:keywords "processes")
+              (:url . "https://github.com/kenmanheimer/EmacsMultishell"))])
+ (muse .
+       [(3 20)
+       nil "Authoring and publishing tool for Emacs" tar
+       ((:keywords "hypermedia")
+        (:url . "http://mwolson.org/projects/EmacsMuse.html"))])
+ (myers .
+       [(0 1)
+        ((emacs
+          (25)))
+        "Random-access singly-linked lists" single
+        ((:url . "http://elpa.gnu.org/packages/myers.html")
+         (:keywords "list" "containers"))])
+ (nameless .
+          [(1 0 2)
+           ((emacs
+             (24 4)))
+           "Hide package namespace in your emacs-lisp code" single
+           ((:url . "https://github.com/Malabarba/nameless")
+            (:keywords "convenience" "lisp"))])
+ (names .
+       [(20151201 0)
+        ((emacs
+          (24 1))
+         (cl-lib
+          (0 5)))
+        "Namespaces for emacs-lisp. Avoid name clobbering without hiding symbols." tar
+        ((:keywords "extensions" "lisp")
+         (:url . "https://github.com/Malabarba/names"))])
+ (nhexl-mode .
+            [(0 2)
+             ((emacs
+               (24))
+              (cl-lib
+               (0 5)))
+             "Minor mode to edit files via hex-dump format" single
+             ((:url . "http://elpa.gnu.org/packages/nhexl-mode.html")
+              (:keywords "data"))])
+ (nlinum .
+        [(1 7)
+         nil "Show line numbers in the margin" single
+         ((:url . "http://elpa.gnu.org/packages/nlinum.html")
+          (:keywords "convenience"))])
+ (notes-mode .
+            [(1 30)
+             nil "Indexing system for on-line note-taking" tar
+             ((:url . "http://elpa.gnu.org/packages/notes-mode.html"))])
+ (ntlm .
+       [(2 1 0)
+       nil "NTLM (NT LanManager) authentication support" single
+       ((:url . "http://elpa.gnu.org/packages/ntlm.html")
+        (:keywords "ntlm" "sasl" "comm"))])
+ (num3-mode .
+           [(1 2)
+            nil "highlight groups of digits in long numbers" single
+            ((:url . "http://elpa.gnu.org/packages/num3-mode.html")
+             (:keywords "faces" "minor-mode"))])
+ (oauth2 .
+        [(0 11)
+         nil "OAuth 2.0 Authorization Protocol" single
+         ((:url . "http://elpa.gnu.org/packages/oauth2.html")
+          (:keywords "comm"))])
+ (omn-mode .
+          [(1 2)
+           nil "Support for OWL Manchester Notation" single
+           ((:url . "http://elpa.gnu.org/packages/omn-mode.html")
+            (:keywords))])
+ (on-screen .
+           [(1 3 2)
+            ((cl-lib
+              (0)))
+            "guide your eyes while scrolling" single
+            ((:url . "https://github.com/michael-heerdegen/on-screen.el")
+             (:keywords "convenience"))])
+ (org .
+      [(20171004)
+       nil "Outline-based notes management and organizer" tar nil])
+ (org-edna .
+          [(1 0 -3 1)
+           ((emacs
+             (25 1))
+            (seq
+             (2 19))
+            (org
+             (9 0 5)))
+           "Extensible Dependencies 'N' Actions" tar
+           ((:keywords "convenience" "text" "org")
+            (:url . "https://savannah.nongnu.org/projects/org-edna-el/"))])
+ (osc .
+      [(0 1)
+       nil "Open Sound Control protocol library" single
+       ((:url . "http://elpa.gnu.org/packages/osc.html")
+       (:keywords "comm" "processes" "multimedia"))])
+ (other-frame-window .
+                    [(1 0 4)
+                     ((emacs
+                       (24 4)))
+                     "Minor mode to enable global prefix keys for other frame/window buffer placement" single
+                     ((:url . "http://elpa.gnu.org/packages/other-frame-window.html")
+                      (:keywords "frame" "window"))])
+ (pabbrev .
+         [(4 2 1)
+          nil "Predictive abbreviation expansion" single
+          ((:url . "http://elpa.gnu.org/packages/pabbrev.html")
+           (:keywords))])
+ (parsec .
+        [(0 1 3)
+         ((emacs
+           (24))
+          (cl-lib
+           (0 5)))
+         "Parser combinator library" tar
+         ((:keywords "extensions")
+          (:url . "https://github.com/cute-jumper/parsec.el"))])
+ (pinentry .
+          [(0 1)
+           nil "GnuPG Pinentry server implementation" single
+           ((:url . "http://elpa.gnu.org/packages/pinentry.html")
+            (:keywords "gnupg"))])
+ (poker .
+       [(0 2)
+        nil "Texas hold 'em poker" single
+        ((:url . "http://elpa.gnu.org/packages/poker.html")
+         (:keywords "games"))])
+ (psgml .
+       [(1 3 4)
+        nil "SGML-editing mode with parsing support" tar
+        ((:keywords "languages")
+         (:url . "http://elpa.gnu.org/packages/psgml.html"))])
+ (python .
+        [(0 25 2)
+         ((emacs
+           (24 1))
+          (cl-lib
+           (1 0)))
+         "Python's flying circus support for Emacs" single
+         ((:url . "https://github.com/fgallina/python.el")
+          (:keywords "languages"))])
+ (quarter-plane .
+               [(0 1)
+                nil "Minor mode for quarter-plane style editing" single
+                ((:url . "http://elpa.gnu.org/packages/quarter-plane.html")
+                 (:keywords "convenience" "wp"))])
+ (queue .
+       [(0 2)
+        nil "Queue data structure" single
+        ((:url . "http://www.dr-qubit.org/emacs.php")
+         (:keywords "extensions" "data structures" "queue"))])
+ (rainbow-mode .
+              [(0 13)
+               nil "Colorize color names in buffers" single
+               ((:url . "http://elpa.gnu.org/packages/rainbow-mode.html")
+                (:keywords "faces"))])
+ (rcirc-color .
+             [(0 3)
+              nil "color nicks" single
+              ((:url . "http://elpa.gnu.org/packages/rcirc-color.html")
+               (:keywords "comm"))])
+ (rcirc-menu .
+            [(1 1)
+             nil "A menu of all your rcirc connections" single
+             ((:url . "http://elpa.gnu.org/packages/rcirc-menu.html")
+              (:keywords "comm"))])
+ (realgud .
+         [(1 4 4)
+          ((load-relative
+            (1 3))
+           (loc-changes
+            (1 2))
+           (test-simple
+            (1 3 0))
+           (cl-lib
+            (0 5))
+           (emacs
+            (24)))
+          "A modular front-end for interacting with external debuggers" tar
+          ((:keywords "gdb" "python" "perl" "go" "bash" "nodejs" "zsh" "bashdb" "zshdb" "remake" "make" "trepan" "perldb")
+           (:url . "http://github.com/realgud/realgud/"))])
+ (register-list .
+               [(0 1)
+                nil "Interactively list/edit registers" single
+                ((:url . "http://elpa.gnu.org/packages/register-list.html")
+                 (:keywords "register"))])
+ (rich-minority .
+               [(1 0 1)
+                ((cl-lib
+                  (0 5)))
+                "Clean-up and Beautify the list of minor-modes." single
+                ((:url . "https://github.com/Malabarba/rich-minority")
+                 (:keywords "mode-line" "faces"))])
+ (rnc-mode .
+          [(0 2)
+           nil "Emacs mode to edit Relax-NG Compact files" single
+           ((:url . "http://elpa.gnu.org/packages/rnc-mode.html")
+            (:keywords "xml" "relaxng"))])
+ (rudel .
+       [(0 3 1)
+        ((emacs
+          (24))
+         (cl-lib
+          (0 5))
+         (cl-generic
+          (0 3)))
+        "A collaborative editing framework for Emacs" tar
+        ((:keywords "rudel" "collaboration")
+         (:url . "http://rudel.sourceforge.net/"))])
+ (scroll-restore .
+                [(1 0)
+                 nil "restore original position after scrolling" single
+                 ((:url . "http://elpa.gnu.org/packages/scroll-restore.html")
+                  (:keywords "scrolling"))])
+ (sed-mode .
+          [(1 0)
+           nil "Major mode to edit sed scripts" single
+           ((:url . "http://elpa.gnu.org/packages/sed-mode.html")
+            (:keywords))])
+ (seq .
+      [(2 20)
+       nil "Sequence manipulation functions" tar
+       ((:keywords "sequences")
+       (:url . "http://elpa.gnu.org/packages/seq.html"))])
+ (shen-mode .
+           [(0 1)
+            nil "A major mode for editing shen source code" tar
+            ((:keywords "languages" "shen")
+             (:url . "http://elpa.gnu.org/packages/shen-mode.html"))])
+ (sisu-mode .
+           [(7 1 8)
+            nil "Major mode for SiSU markup text" single
+            ((:url . "http://www.sisudoc.org/")
+             (:keywords "text" "syntax" "processes" "tools"))])
+ (smart-yank .
+            [(0 1 1)
+             ((emacs
+               (24)))
+             "A different approach of yank pointer handling" single
+             ((:url . "http://elpa.gnu.org/packages/smart-yank.html")
+              (:keywords "convenience"))])
+ (sml-mode .
+          [(6 7)
+           ((emacs
+             (24))
+            (cl-lib
+             (0 5)))
+           "Major mode for editing (Standard) ML" single
+           ((:url . "http://elpa.gnu.org/packages/sml-mode.html")
+            (:keywords "sml"))])
+ (soap-client .
+             [(3 1 3)
+              ((cl-lib
+                (0 6 1)))
+              "Access SOAP web services" tar
+              ((:keywords "soap" "web-services" "comm" "hypermedia")
+               (:url . "http://elpa.gnu.org/packages/soap-client.html"))])
+ (sokoban .
+         [(1 4 6)
+          ((emacs
+            (23 1)))
+          "Implementation of Sokoban for Emacs." tar
+          ((:keywords "games")
+           (:url . "http://elpa.gnu.org/packages/sokoban.html"))])
+ (sotlisp .
+         [(1 6 2)
+          ((emacs
+            (24 1)))
+          "Write lisp at the speed of thought." single
+          ((:url . "https://github.com/Malabarba/speed-of-thought-lisp")
+           (:keywords "convenience" "lisp"))])
+ (spinner .
+         [(1 7 3)
+          nil "Add spinners and progress-bars to the mode-line for ongoing operations" single
+          ((:url . "https://github.com/Malabarba/spinner.el")
+           (:keywords "processes" "mode-line"))])
+ (stream .
+        [(2 2 4)
+         ((emacs
+           (25)))
+         "Implementation of streams" tar
+         ((:keywords "stream" "laziness" "sequences")
+          (:url . "http://elpa.gnu.org/packages/stream.html"))])
+ (svg .
+      [(0 1)
+       ((emacs
+        (25)))
+       "svg image creation functions" single
+       ((:url . "http://elpa.gnu.org/packages/svg.html")
+       (:keywords "image"))])
+ (svg-clock .
+           [(1 0)
+            ((svg
+              (0 1))
+             (emacs
+              (25 0)))
+            "Analog clock using Scalable Vector Graphics" single
+            ((:url . "http://elpa.gnu.org/packages/svg-clock.html")
+             (:keywords "demo" "svg" "clock"))])
+ (tNFA .
+       [(0 1 1)
+       ((queue
+         (0 1)))
+       "Tagged non-deterministic finite-state automata" single
+       ((:url . "http://www.dr-qubit.org/emacs.php")
+        (:keywords "extensions" "matching" "data structures tnfa" "nfa" "dfa" "finite state automata" "automata" "regexp"))])
+ (temp-buffer-browse .
+                    [(1 5)
+                     ((emacs
+                       (24)))
+                     "temp buffer browse mode" single
+                     ((:url . "http://elpa.gnu.org/packages/temp-buffer-browse.html")
+                      (:keywords "convenience"))])
+ (test-simple .
+             [(1 3 0)
+              ((cl-lib
+                (0)))
+              "Simple Unit Test Framework for Emacs Lisp" single
+              ((:url . "http://github.com/rocky/emacs-test-simple")
+               (:keywords "unit-test"))])
+ (timerfunctions .
+                [(1 4 2)
+                 ((cl-lib
+                   (0 5)))
+                 "Enhanced versions of some timer.el functions" single
+                 ((:url . "http://elpa.gnu.org/packages/timerfunctions.html")
+                  (:keywords))])
+ (tiny .
+       [(0 2 1)
+       nil "Quickly generate linear ranges in Emacs" tar
+       ((:keywords "convenience")
+        (:url . "https://github.com/abo-abo/tiny"))])
+ (tramp-theme .
+             [(0 2)
+              ((emacs
+                (24 1)))
+              "Custom theme for remote buffers" single
+              ((:url . "http://elpa.gnu.org/packages/tramp-theme.html")
+               (:keywords "convenience" "faces"))])
+ (transcribe .
+            [(1 5 2)
+             nil "Package for audio transcriptions" single
+             ((:url . "http://elpa.gnu.org/packages/transcribe.html")
+              (:keywords))])
+ (trie .
+       [(0 4)
+       ((tNFA
+         (0 1 1))
+        (heap
+         (0 3)))
+       "Trie data structure" single
+       ((:url . "http://www.dr-qubit.org/emacs.php")
+        (:keywords "extensions" "matching" "data structures trie" "ternary search tree" "tree" "completion" "regexp"))])
+ (undo-tree .
+           [(0 6 5)
+            nil "Treat undo history as a tree" single
+            ((:url . "http://www.dr-qubit.org/emacs.php")
+             (:keywords "convenience" "files" "undo" "redo" "history" "tree"))])
+ (uni-confusables .
+                 [(0 1)
+                  nil "Unicode confusables table" tar
+                  ((:url . "http://elpa.gnu.org/packages/uni-confusables.html"))])
+ (url-http-ntlm .
+               [(2 0 4)
+                ((cl-lib
+                  (0 5))
+                 (ntlm
+                  (2 1 0)))
+                "NTLM authentication for the url library" single
+                ((:url . "http://elpa.gnu.org/packages/url-http-ntlm.html")
+                 (:keywords "comm" "data" "processes" "hypermedia"))])
+ (validate .
+          [(1 0 4)
+           ((emacs
+             (24 1))
+            (cl-lib
+             (0 5))
+            (seq
+             (2 16)))
+           "Schema validation for Emacs-lisp" single
+           ((:url . "http://elpa.gnu.org/packages/validate.html")
+            (:keywords "lisp"))])
+ (vdiff .
+       [(0 2 3)
+        ((emacs
+          (24 4))
+         (hydra
+          (0 13 0)))
+        "A diff tool similar to  vimdiff" single
+        ((:url . "https://github.com/justbur/emacs-vdiff")
+         (:keywords "diff"))])
+ (vigenere .
+          [(1 0)
+           ((emacs
+             (25 1)))
+           "Run a vigenere cipher on a block of text ;" single
+           ((:url . "https://elpa.gnu.org/packages/vigenere.html")
+            (:keywords "data" "vigenere" "cipher"))])
+ (vlf .
+      [(1 7)
+       nil "View Large Files" tar
+       ((:keywords "large files" "utilities")
+       (:url . "https://github.com/m00natic/vlfi"))])
+ (w3 .
+     [(4 0 49)
+      nil "Fully customizable, largely undocumented web browser for Emacs" tar
+      ((:keywords "faces" "help" "comm" "news" "mail" "processes" "mouse" "hypermedia")
+       (:url . "http://elpa.gnu.org/packages/w3.html"))])
+ (wcheck-mode .
+             [(2016 1 30)
+              nil "General interface for text checkers" single
+              ((:url . "https://github.com/tlikonen/wcheck-mode")
+               (:keywords "text" "spell" "check" "languages" "ispell"))])
+ (wconf .
+       [(0 2 1)
+        ((emacs
+          (24 4)))
+        "Minimal window layout manager" single
+        ((:url . "https://github.com/ilohmar/wconf")
+         (:keywords "windows" "frames" "layout"))])
+ (web-server .
+            [(0 1 1)
+             ((emacs
+               (24 3)))
+             "Emacs Web Server" tar
+             ((:keywords "http" "server" "network")
+              (:url . "https://github.com/eschulte/emacs-web-server"))])
+ (websocket .
+           [(1 8)
+            ((cl-lib
+              (0 5)))
+            "Emacs WebSocket client and server" tar
+            ((:keywords "communication" "websocket" "server")
+             (:url . "http://elpa.gnu.org/packages/websocket.html"))])
+ (which-key .
+           [(3 0 2)
+            ((emacs
+              (24 4)))
+            "Display available keybindings in popup" tar
+            ((:url . "https://github.com/justbur/emacs-which-key"))])
+ (windresize .
+            [(0 1)
+             nil "Resize windows interactively" single
+             ((:url . "http://elpa.gnu.org/packages/windresize.html")
+              (:keywords "window"))])
+ (wisi .
+       [(1 1 6)
+       ((cl-lib
+         (0 4))
+        (emacs
+         (24 3)))
+       "Utilities for implementing an indentation/navigation engine using a generalized LALR parser" tar
+       ((:keywords "parser" "indentation" "navigation")
+        (:url . "http://www.nongnu.org/ada-mode/wisi/wisi.html"))])
+ (wpuzzle .
+         [(1 1)
+          nil "find as many word in a given time" single
+          ((:url . "http://elpa.gnu.org/packages/wpuzzle.html")
+           (:keywords))])
+ (xclip .
+       [(1 3)
+        nil "use xclip to copy&paste" single
+        ((:url . "http://elpa.gnu.org/packages/xclip.html")
+         (:keywords "convenience" "tools"))])
+ (xelb .
+       [(0 12)
+       ((emacs
+         (24 4))
+        (cl-generic
+         (0 2)))
+       "X protocol Emacs Lisp Binding" tar
+       ((:keywords "unix")
+        (:url . "https://github.com/ch11ng/xelb"))])
+ (xpm .
+      [(1 0 4)
+       nil "edit XPM images" tar
+       ((:keywords "multimedia" "xpm")
+       (:url . "http://www.gnuvola.org/software/xpm/"))])
+ (yasnippet .
+           [(0 12 2)
+            ((cl-lib
+              (0 5)))
+            "Yet another snippet extension for Emacs." tar
+            ((:keywords "convenience" "emulation")
+             (:url . "http://github.com/joaotavora/yasnippet"))])
+ (ztree .
+       [(1 0 5)
+        ((cl-lib
+          (0)))
+        "Text mode directory tree" tar
+        ((:keywords "files" "tools")
+         (:url . "https://github.com/fourier/ztree"))]))
diff --git a/elpa/archives/gnu/archive-contents.signed b/elpa/archives/gnu/archive-contents.signed
new file mode 100644 (file)
index 0000000..6a92838
--- /dev/null
@@ -0,0 +1 @@
+Good signature from 474F05837FBDEF9B GNU ELPA Signing Agent <elpasign@elpa.gnu.org> (trust undefined) created at 2017-10-05T11:10:02+0200 using DSA
\ No newline at end of file
diff --git a/elpa/gnupg/pubring.gpg b/elpa/gnupg/pubring.gpg
new file mode 100644 (file)
index 0000000..e76e685
Binary files /dev/null and b/elpa/gnupg/pubring.gpg differ
diff --git a/elpa/gnupg/secring.gpg b/elpa/gnupg/secring.gpg
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/elpa/gnupg/trustdb.gpg b/elpa/gnupg/trustdb.gpg
new file mode 100644 (file)
index 0000000..1a45757
Binary files /dev/null and b/elpa/gnupg/trustdb.gpg differ
diff --git a/elpa/let-alist-1.0.5.signed b/elpa/let-alist-1.0.5.signed
new file mode 100644 (file)
index 0000000..8d89df9
--- /dev/null
@@ -0,0 +1 @@
+Good signature from 474F05837FBDEF9B GNU ELPA Signing Agent <elpasign@elpa.gnu.org> (trust undefined) created at 2017-02-01T11:05:02+0100 using DSA
\ No newline at end of file
diff --git a/elpa/let-alist-1.0.5/let-alist-autoloads.el b/elpa/let-alist-1.0.5/let-alist-autoloads.el
new file mode 100644 (file)
index 0000000..37bc69c
--- /dev/null
@@ -0,0 +1,50 @@
+;;; let-alist-autoloads.el --- automatically extracted autoloads
+;;
+;;; Code:
+(add-to-list 'load-path (or (file-name-directory #$) (car load-path)))
+\f
+;;;### (autoloads nil "let-alist" "let-alist.el" (23053 39403 444445
+;;;;;;  274000))
+;;; Generated autoloads from let-alist.el
+
+(autoload 'let-alist "let-alist" "\
+Let-bind dotted symbols to their cdrs in ALIST and execute BODY.
+Dotted symbol is any symbol starting with a `.'.  Only those present
+in BODY are let-bound and this search is done at compile time.
+
+For instance, the following code
+
+  (let-alist alist
+    (if (and .title .body)
+        .body
+      .site
+      .site.contents))
+
+essentially expands to
+
+  (let ((.title (cdr (assq \\='title alist)))
+        (.body  (cdr (assq \\='body alist)))
+        (.site  (cdr (assq \\='site alist)))
+        (.site.contents (cdr (assq \\='contents (cdr (assq \\='site alist))))))
+    (if (and .title .body)
+        .body
+      .site
+      .site.contents))
+
+If you nest `let-alist' invocations, the inner one can't access
+the variables of the outer one. You can, however, access alists
+inside the original alist by using dots inside the symbol, as
+displayed in the example above.
+
+\(fn ALIST &rest BODY)" nil t)
+
+(put 'let-alist 'lisp-indent-function '1)
+
+;;;***
+\f
+;; Local Variables:
+;; version-control: never
+;; no-byte-compile: t
+;; no-update-autoloads: t
+;; End:
+;;; let-alist-autoloads.el ends here
diff --git a/elpa/let-alist-1.0.5/let-alist-pkg.el b/elpa/let-alist-1.0.5/let-alist-pkg.el
new file mode 100644 (file)
index 0000000..247d8c9
--- /dev/null
@@ -0,0 +1 @@
+(define-package "let-alist" "1.0.5" "Easily let-bind values of an assoc-list by their names" '((emacs "24.1")) :url "http://elpa.gnu.org/packages/let-alist.html" :keywords '("extensions" "lisp"))
diff --git a/elpa/let-alist-1.0.5/let-alist.el b/elpa/let-alist-1.0.5/let-alist.el
new file mode 100644 (file)
index 0000000..43973c2
--- /dev/null
@@ -0,0 +1,182 @@
+;;; let-alist.el --- Easily let-bind values of an assoc-list by their names -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2014-2017 Free Software Foundation, Inc.
+
+;; Author: Artur Malabarba <emacs@endlessparentheses.com>
+;; Package-Requires: ((emacs "24.1"))
+;; Version: 1.0.5
+;; Keywords: extensions lisp
+;; Prefix: let-alist
+;; Separator: -
+
+;; This is an Elpa :core package. Don't use functionality that is not
+;; compatible with Emacs 24.1.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This package offers a single macro, `let-alist'.  This macro takes a
+;; first argument (whose value must be an alist) and a body.
+;;
+;; The macro expands to a let form containing body, where each dotted
+;; symbol inside body is let-bound to their cdrs in the alist.  Dotted
+;; symbol is any symbol starting with a `.'.  Only those present in
+;; the body are let-bound and this search is done at compile time.
+;;
+;; For instance, the following code
+;;
+;;   (let-alist alist
+;;     (if (and .title .body)
+;;         .body
+;;       .site
+;;       .site.contents))
+;;
+;; essentially expands to
+;;
+;;   (let ((.title (cdr (assq 'title alist)))
+;;         (.body  (cdr (assq 'body alist)))
+;;         (.site  (cdr (assq 'site alist)))
+;;         (.site.contents (cdr (assq 'contents (cdr (assq 'site alist))))))
+;;     (if (and .title .body)
+;;         .body
+;;       .site
+;;       .site.contents))
+;;
+;; If you nest `let-alist' invocations, the inner one can't access
+;; the variables of the outer one. You can, however, access alists
+;; inside the original alist by using dots inside the symbol, as
+;; displayed in the example above by the `.site.contents'.
+;;
+;;; Code:
+\f
+
+(defun let-alist--deep-dot-search (data)
+  "Return alist of symbols inside DATA that start with a `.'.
+Perform a deep search and return an alist where each car is the
+symbol, and each cdr is the same symbol without the `.'."
+  (cond
+   ((symbolp data)
+    (let ((name (symbol-name data)))
+      (when (string-match "\\`\\." name)
+        ;; Return the cons cell inside a list, so it can be appended
+        ;; with other results in the clause below.
+        (list (cons data (intern (replace-match "" nil nil name)))))))
+   ((not (consp data)) nil)
+   ((eq (car data) 'let-alist)
+    ;; For nested â€˜let-alist’ forms, ignore symbols appearing in the
+    ;; inner body because they don’t refer to the alist currently
+    ;; being processed.  See Bug#24641.
+    (let-alist--deep-dot-search (cadr data)))
+   (t (append (let-alist--deep-dot-search (car data))
+              (let-alist--deep-dot-search (cdr data))))))
+
+(defun let-alist--access-sexp (symbol variable)
+  "Return a sexp used to access SYMBOL inside VARIABLE."
+  (let* ((clean (let-alist--remove-dot symbol))
+         (name (symbol-name clean)))
+    (if (string-match "\\`\\." name)
+        clean
+      (let-alist--list-to-sexp
+       (mapcar #'intern (nreverse (split-string name "\\.")))
+       variable))))
+
+(defun let-alist--list-to-sexp (list var)
+  "Turn symbols LIST into recursive calls to `cdr' `assq' on VAR."
+  `(cdr (assq ',(car list)
+              ,(if (cdr list) (let-alist--list-to-sexp (cdr list) var)
+                 var))))
+
+(defun let-alist--remove-dot (symbol)
+  "Return SYMBOL, sans an initial dot."
+  (let ((name (symbol-name symbol)))
+    (if (string-match "\\`\\." name)
+        (intern (replace-match "" nil nil name))
+      symbol)))
+
+\f
+;;; The actual macro.
+;;;###autoload
+(defmacro let-alist (alist &rest body)
+  "Let-bind dotted symbols to their cdrs in ALIST and execute BODY.
+Dotted symbol is any symbol starting with a `.'.  Only those present
+in BODY are let-bound and this search is done at compile time.
+
+For instance, the following code
+
+  (let-alist alist
+    (if (and .title .body)
+        .body
+      .site
+      .site.contents))
+
+essentially expands to
+
+  (let ((.title (cdr (assq \\='title alist)))
+        (.body  (cdr (assq \\='body alist)))
+        (.site  (cdr (assq \\='site alist)))
+        (.site.contents (cdr (assq \\='contents (cdr (assq \\='site alist))))))
+    (if (and .title .body)
+        .body
+      .site
+      .site.contents))
+
+If you nest `let-alist' invocations, the inner one can't access
+the variables of the outer one. You can, however, access alists
+inside the original alist by using dots inside the symbol, as
+displayed in the example above."
+  (declare (indent 1) (debug t))
+  (let ((var (make-symbol "alist")))
+    `(let ((,var ,alist))
+       (let ,(mapcar (lambda (x) `(,(car x) ,(let-alist--access-sexp (car x) var)))
+                     (delete-dups (let-alist--deep-dot-search body)))
+         ,@body))))
+
+;;;; ChangeLog:
+
+;; 2015-12-01  Artur Malabarba  <bruce.connor.am@gmail.com>
+;; 
+;;     packages/let-alist: Define it as a :core package
+;; 
+;; 2015-06-11  Artur Malabarba  <bruce.connor.am@gmail.com>
+;; 
+;;     * let-alist (let-alist--deep-dot-search): Fix cons
+;; 
+;; 2015-03-07  Artur Malabarba  <bruce.connor.am@gmail.com>
+;; 
+;;     let-alist: Update copyright
+;; 
+;; 2014-12-22  Artur Malabarba  <bruce.connor.am@gmail.com>
+;; 
+;;     packages/let-alist: Use `make-symbol' instead of `gensym'.
+;; 
+;; 2014-12-20  Artur Malabarba  <bruce.connor.am@gmail.com>
+;; 
+;;     packages/let-alist: Enable access to deeper alists
+;; 
+;; 2014-12-14  Artur Malabarba  <bruce.connor.am@gmail.com>
+;; 
+;;     let-alist.el: Add lexical binding. Version bump.
+;; 
+;; 2014-12-11  Artur Malabarba  <bruce.connor.am@gmail.com>
+;; 
+;;     let-alist: New package
+;; 
+
+
+(provide 'let-alist)
+
+;;; let-alist.el ends here
diff --git a/elpa/websocket-1.8.signed b/elpa/websocket-1.8.signed
new file mode 100644 (file)
index 0000000..ab75e0e
--- /dev/null
@@ -0,0 +1 @@
+Good signature from 474F05837FBDEF9B GNU ELPA Signing Agent <elpasign@elpa.gnu.org> (trust undefined) created at 2017-06-12T11:10:03+0200 using DSA
\ No newline at end of file
diff --git a/elpa/websocket-1.8/COPYING b/elpa/websocket-1.8/COPYING
new file mode 100644 (file)
index 0000000..ecbc059
--- /dev/null
@@ -0,0 +1,339 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  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
+this service 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 make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  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.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+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
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the 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 a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                            NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE 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.
+
+                     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
+convey 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 2 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, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision 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, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This 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.
\ No newline at end of file
diff --git a/elpa/websocket-1.8/ChangeLog b/elpa/websocket-1.8/ChangeLog
new file mode 100644 (file)
index 0000000..ca8f6f5
--- /dev/null
@@ -0,0 +1,119 @@
+2017-06-11  Andrew Hyatt  <ahyatt@gmail.com>
+
+       Update to emacs-websocket version 1.8.
+
+       * websocket.el (websocket-mask): Mask multibyte characters correctly.
+       * websocket.el (websocket-server): Don't ask to terminate the
+        connection.
+       * websocket-functional-test.el: Test out multibyte characters.
+       * websocket-functional-test.el: Disable trust checking for echo server
+        connection.
+
+2016-07-11  Paul Eggert         <eggert@cs.ucla.edu>
+
+       Fix some quoting problems in doc strings
+
+       Most of these are minor issues involving, e.g., quoting `like this' 
+       instead of 'like this'.  A few involve escaping ` and ' with a preceding
+       \= when the characters should not be turned into curved single quotes.
+
+2016-05-10  Stefan Monnier  <monnier@iro.umontreal.ca>
+
+       * websocket/websocket.el (websocket-server-accept): Mark arg as unused
+
+       * websocket/websocket-functional-test.el: Fix compilation warnings.
+
+2016-05-09  Andrew Hyatt  <ahyatt@gmail.com>
+
+       Version 1.6, mostly fixes for fragmented headers.
+
+       * websocket.el (websocket-verify-response-code, websocket-outer-filter):
+        Fix handling of fragmented headers.
+       * websocket.el (websocket-server): Accept host for listening on.
+       * websocket-functional-test.el: Stop stopping the listener process on
+        Windows.
+
+2016-01-24  Stefan Monnier  <monnier@iro.umontreal.ca>
+
+       Fix maintainer address
+
+2015-07-19  Andrew Hyatt  <ahyatt@gmail.com>
+
+       Add ability to handle cookies.
+
+       * websocket.el (websocket-open, websocket-process-headers,
+        websocket-out-filter, websocket-create-headers): Add ability to set
+        and accept cookies, using the url-cookie library.  Also make sure the
+        port is included in the Host header.
+
+2015-04-03  Andrew Hyatt  <ahyatt@gmail.com>
+
+       Version 1.4, fix for ping/pong & 32-bit emacs.
+
+       * websocket.el (websocket-encode-frame, websocket-read-frame,
+       websocket-process-frame, websocket-check) Fixes incorrect handling of
+       ping/pong messages in websockets.
+       (websocket-to-bytes) Fixes error computing low-bytes in 32-bit emacs.
+
+2014-08-23  Andrew Hyatt  <ahyatt@gmail.com>
+
+       Upgrade to version 1.3.
+
+       * websocket.el: (websocket-version):Update to 1.3
+       (websocket-close): Remove unnecessary call to process-buffer.
+       (websocket-close): Remove use of buffers in connections.
+       (websocket-open): Remove use of buffers in connections.
+       (websocket-open): Throw clear error when connection cannot be made.
+       (websocket-create-headers): Remove unnecessary Origin header.
+
+2013-12-14  Andrew Hyatt  <ahyatt@gmail.com>
+
+       Remove the ERT testing file, which had too many FSF-unsigned changes.
+
+       This brings this package into FSF compliance.
+
+       * README.org: Mention the fact that the ERT tests are in the github 
+       repository.
+
+       * websocket-test.el: Removed.
+
+2013-09-21  Andrew Hyatt  <ahyatt@gmail.com>
+
+       websocket.el: Set version to 1.2, after last set of server fixes.
+
+2013-09-15  Andrew Hyatt  <ahyatt@gmail.com>
+
+       2013-09-15 Andrew Hyatt  <ahyatt@gmail.com>
+
+               * websocket.el (websocket-mask-frames, websocket-encode-frame,
+                websocket, websocket-send): Get rid of
+                `websocket-mask-frames' variable, which was a mistake, and
+                make masking mandatory for clients and forbidden for
+                servers.
+              * websocket-test.el (websocket-encode-frame,
+                websocket-outer-filter): Alter tests to pass new argument
+                for `websocket-encode-frame'.
+
+               * websocket.el (websocket-close, websocket-open,
+                websocket-server-accept): Only call the on-close callback on
+                process state change if the process is now closed or
+                similar, and always call the on-close callback from
+                `websocket-close'
+              * websocket-test.el (websocket-close): Add an on-close callback
+                which the `websocket-close' method now expects.
+
+               * magit-functiona-test.el: Assert on ready-state, and increase
+                the sleep time for the wss test.
+
+2013-08-02  Stefan Monnier  <monnier@iro.umontreal.ca>
+
+       * packages/websocket/websocket.el: Fix version number.
+
+2013-08-01  Stefan Monnier  <monnier@iro.umontreal.ca>
+
+       * packages/websocket: Cleanup copyright and code.
+
+2013-08-01  Stefan Monnier  <monnier@iro.umontreal.ca>
+
+       Add websocket git revno bc5c2a2ee2b993a18e8e23ed725829d403508753.
+
diff --git a/elpa/websocket-1.8/README.org b/elpa/websocket-1.8/README.org
new file mode 100644 (file)
index 0000000..db5abba
--- /dev/null
@@ -0,0 +1,35 @@
+* Description
+This is a elisp library for websocket clients to talk to websocket
+servers, and for websocket servers to accept connections from
+websocket clients. This library is designed to be used by other
+library writers, to write apps that use websockets, and is not useful
+by itself.
+
+An example of how to use the library is in the
+[[https://github.com/ahyatt/emacs-websocket/blob/master/websocket-functional-test.el][websocket-functional-test.el]] file.
+
+This library is compatible with emacs 23 and 24, although only emacs
+24 support secure websockets.
+
+NOTE: Due to FSF attribution restrictions, ERT tests are only not
+present in the emacs ELPA repository.  They can only be found in the
+github repository at https://github.com/ahyatt/emacs-websocket/.
+
+* Version release checklist
+
+Each version that is released should be checked with this checklist:
+
+- [ ] All ert test passing (see note above on ERT tests)
+- [ ] Functional test passing on emacs 23 and 24
+- [ ] websocket.el byte compiling cleanly.
+
+* Existing clients:
+
+- [[https://github.com/tkf/emacs-ipython-notebook][Emacs IPython Notebook]]
+- [[https://github.com/syohex/emacs-realtime-markdown-viewer][Emacs Realtime Markdown Viewer]]
+- [[https://github.com/jscheid/kite][Kite]]
+
+If you are using this module for your own emacs package, please let me
+know by editing this file, adding your project, and sending a pull
+request to this repository.
+
diff --git a/elpa/websocket-1.8/testserver.py b/elpa/websocket-1.8/testserver.py
new file mode 100644 (file)
index 0000000..5cfcb96
--- /dev/null
@@ -0,0 +1,34 @@
+import logging
+import tornado
+import tornado.web
+from tornado import httpserver
+from tornado import ioloop
+from tornado import websocket
+
+
+class EchoWebSocket(websocket.WebSocketHandler):
+
+    def open(self):
+        logging.info("OPEN")
+
+    def on_message(self, message):
+        logging.info(u"ON_MESSAGE: {0}".format(message))
+        self.write_message(u"You said: {0}".format(message))
+
+    def on_close(self):
+        logging.info("ON_CLOSE")
+
+    def allow_draft76(self):
+        return False
+
+
+if __name__ == "__main__":
+    import tornado.options
+    tornado.options.parse_command_line()
+    application = tornado.web.Application([
+        (r"/", EchoWebSocket),
+    ])
+    server = httpserver.HTTPServer(application)
+    server.listen(9999)
+    logging.info("STARTED: Server start listening")
+    ioloop.IOLoop.instance().start()
diff --git a/elpa/websocket-1.8/websocket-autoloads.el b/elpa/websocket-1.8/websocket-autoloads.el
new file mode 100644 (file)
index 0000000..b2bc340
--- /dev/null
@@ -0,0 +1,16 @@
+;;; websocket-autoloads.el --- automatically extracted autoloads
+;;
+;;; Code:
+(add-to-list 'load-path (or (file-name-directory #$) (car load-path)))
+\f
+;;;### (autoloads nil nil ("websocket-functional-test.el" "websocket-pkg.el"
+;;;;;;  "websocket.el") (23053 39388 567397 365000))
+
+;;;***
+\f
+;; Local Variables:
+;; version-control: never
+;; no-byte-compile: t
+;; no-update-autoloads: t
+;; End:
+;;; websocket-autoloads.el ends here
diff --git a/elpa/websocket-1.8/websocket-functional-test.el b/elpa/websocket-1.8/websocket-functional-test.el
new file mode 100644 (file)
index 0000000..80eb004
--- /dev/null
@@ -0,0 +1,162 @@
+;;; websocket-functional-test.el --- Simple functional testing
+
+;; Copyright (c) 2013, 2016  Free Software Foundation, Inc.
+
+;; This program is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation; either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Usage: emacs -batch -Q -L . -l websocket-functional-test.el
+;;
+;; Note: this functional tests requires that you have python with the
+;; Tornado web server.  See http://www.tornadoweb.org/en/stable/ for
+;; information on aquiring.
+
+(require 'tls)   ;; tests a particular bug we had on emacs 23
+(setq debug-on-error t)
+(require 'websocket)
+(eval-when-compile (require 'cl))
+
+;;;;;;;;;;;;;;;;;;;;;;;
+;; Local server test ;;
+;;;;;;;;;;;;;;;;;;;;;;;
+
+(message "Testing with local server")
+
+(setq websocket-debug t)
+
+(defvar wstest-server-buffer (get-buffer-create "*wstest-server*"))
+(defvar wstest-server-name "wstest-server")
+(defvar wstest-server-proc
+  (start-process wstest-server-name wstest-server-buffer
+                 "python" "testserver.py" "--log_to_stderr" "--logging=debug"))
+(sleep-for 1)
+
+(defvar wstest-msgs nil)
+(defvar wstest-closed nil)
+
+(message "Opening the websocket")
+
+(defvar wstest-ws
+  (websocket-open
+   "ws://127.0.0.1:9999"
+   :on-message (lambda (_websocket frame)
+                 (push (websocket-frame-text frame) wstest-msgs)
+                 (message "ws frame: %S" (websocket-frame-text frame))
+                 (error "Test error (expected)"))
+   :on-close (lambda (_websocket) (setq wstest-closed t))))
+
+(defun wstest-pop-to-debug ()
+  "Open websocket log buffer. Not used in testing. Just for debugging."
+  (interactive)
+  (pop-to-buffer (websocket-get-debug-buffer-create wstest-ws)))
+
+(sleep-for 0.1)
+(assert (websocket-openp wstest-ws))
+
+(assert (null wstest-msgs))
+
+(websocket-send-text wstest-ws "你好")
+
+(sleep-for 0.1)
+(assert (equal (car wstest-msgs) "You said: ä½ å¥½"))
+(setf (websocket-on-error wstest-ws) (lambda (_ws _type _err)))
+(websocket-send-text wstest-ws "Hi after error!")
+(sleep-for 0.1)
+(assert (equal (car wstest-msgs) "You said: Hi after error!"))
+
+(websocket-close wstest-ws)
+(assert (null (websocket-openp wstest-ws)))
+
+(if (not (eq system-type 'windows-nt))
+    ; Windows doesn't have support for the SIGSTP signal, so we'll just kill
+    ; the process.
+    (stop-process wstest-server-proc))
+(kill-process wstest-server-proc)
+
+;; Make sure the processes are closed.  This happens asynchronously,
+;; so let's wait for it.
+(sleep-for 1)
+(assert (null (process-list)) t)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Remote server test, with wss ;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; echo.websocket.org has an untrusted certificate, for the test to
+;; proceed, we need to disable trust checking.
+(setq tls-checktrust nil)
+
+(when (>= (string-to-number (substring emacs-version 0 2)) 24)
+  (message "Testing with wss://echo.websocket.org")
+  (when (eq system-type 'windows-nt)
+    (message "Windows users must have gnutls DLLs in the emacs bin directory."))
+  (setq wstest-ws
+        (websocket-open
+         "wss://echo.websocket.org"
+         :on-open (lambda (_websocket)
+                    (message "Websocket opened"))
+         :on-message (lambda (_websocket frame)
+                       (push (websocket-frame-text frame) wstest-msgs)
+                       (message "ws frame: %S" (websocket-frame-text frame)))
+         :on-close (lambda (_websocket)
+                     (message "Websocket closed")
+                     (setq wstest-closed t)))
+        wstest-msgs nil)
+  (sleep-for 0.3)
+  (assert (websocket-openp wstest-ws))
+  (assert (eq 'open (websocket-ready-state wstest-ws)))
+  (assert (null wstest-msgs))
+  (websocket-send-text wstest-ws "Hi!")
+  (sleep-for 1)
+  (assert (equal (car wstest-msgs) "Hi!"))
+  (websocket-close wstest-ws))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Local client and server ;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(message "Testing with emacs websocket server.")
+(message "If this does not pass, make sure your firewall allows the connection.")
+(setq wstest-closed nil)
+(let ((server-conn (websocket-server
+                    9998
+                    :host 'local
+                    :on-message (lambda (ws frame)
+                                  (message "Server received text!")
+                                  (websocket-send-text
+                                   ws (websocket-frame-text frame)))
+                    :on-open (lambda (_websocket) "Client connection opened!")
+                    :on-close (lambda (_websocket)
+                                (setq wstest-closed t)))))
+  (setq wstest-msgs nil
+        wstest-ws
+        (websocket-open
+         "ws://localhost:9998"
+         :on-message (lambda (_websocket frame)
+                       (message "ws frame: %S" (websocket-frame-text frame))
+                       (push
+                        (websocket-frame-text frame) wstest-msgs))))
+
+  (assert (websocket-openp wstest-ws))
+  (websocket-send-text wstest-ws "你好")
+  (sleep-for 0.3)
+  (assert (equal (car wstest-msgs) "你好"))
+  (websocket-server-close server-conn))
+(assert wstest-closed)
+(websocket-close wstest-ws)
+
+(sleep-for 1)
+(assert (null (process-list)) t)
+(message "\nAll tests passed!\n")
diff --git a/elpa/websocket-1.8/websocket-pkg.el b/elpa/websocket-1.8/websocket-pkg.el
new file mode 100644 (file)
index 0000000..347295b
--- /dev/null
@@ -0,0 +1,2 @@
+;; Generated package description from websocket.el
+(define-package "websocket" "1.8" "Emacs WebSocket client and server" 'nil :url "http://elpa.gnu.org/packages/websocket.html" :keywords '("communication" "websocket" "server"))
diff --git a/elpa/websocket-1.8/websocket.el b/elpa/websocket-1.8/websocket.el
new file mode 100644 (file)
index 0000000..3784a30
--- /dev/null
@@ -0,0 +1,1046 @@
+;;; websocket.el --- Emacs WebSocket client and server
+
+;; Copyright (c) 2013, 2016  Free Software Foundation, Inc.
+
+;; Author: Andrew Hyatt <ahyatt@gmail.com>
+;; Keywords: Communication, Websocket, Server
+;; Version: 1.8
+;;
+;; This program is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation; either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;; This implements RFC 6455, which can be found at
+;; http://tools.ietf.org/html/rfc6455.
+;;
+;; This library contains code to connect Emacs as a client to a
+;; websocket server, and for Emacs to act as a server for websocket
+;; connections.
+;;
+;; Websockets clients are created by calling `websocket-open', which
+;; returns a `websocket' struct.  Users of this library use the
+;; websocket struct, and can call methods `websocket-send-text', which
+;; sends text over the websocket, or `websocket-send', which sends a
+;; `websocket-frame' struct, enabling finer control of what is sent.
+;; A callback is passed to `websocket-open' that will retrieve
+;; websocket frames called from the websocket.  Websockets are
+;; eventually closed with `websocket-close'.
+;;
+;; Server functionality is similar.  A server is started with
+;; `websocket-server' called with a port and the callbacks to use,
+;; which returns a process.  The process can later be closed with
+;; `websocket-server-close'.  A `websocket' struct is also created
+;; for every connection, and is exposed through the callbacks.
+
+(require 'bindat)
+(require 'url-parse)
+(require 'url-cookie)
+(eval-when-compile (require 'cl))
+
+;;; Code:
+
+(defstruct (websocket
+            (:constructor nil)
+            (:constructor websocket-inner-create))
+  "A websocket structure.
+This follows the W3C Websocket API, except translated to elisp
+idioms.  The API is implemented in both the websocket struct and
+additional methods.  Due to how defstruct slots are accessed, all
+API methods are prefixed with \"websocket-\" and take a websocket
+as an argument, so the distrinction between the struct API and
+the additional helper APIs are not visible to the caller.
+
+A websocket struct is created with `websocket-open'.
+
+`ready-state' contains one of `connecting', `open', or
+`closed', depending on the state of the websocket.
+
+The W3C API \"bufferedAmount\" call is not currently implemented,
+since there is no elisp API to get the buffered amount from the
+subprocess.  There may, in fact, be output data buffered,
+however, when the `on-message' or `on-close' callbacks are
+called.
+
+`on-open', `on-message', `on-close', and `on-error' are described
+in `websocket-open'.
+
+The `negotiated-extensions' slot lists the extensions accepted by
+both the client and server, and `negotiated-protocols' does the
+same for the protocols.
+"
+  ;; API
+  (ready-state 'connecting)
+  client-data
+  on-open
+  on-message
+  on-close
+  on-error
+  negotiated-protocols
+  negotiated-extensions
+  (server-p nil :read-only t)
+
+  ;; Other data - clients should not have to access this.
+  (url (assert nil) :read-only t)
+  (protocols nil :read-only t)
+  (extensions nil :read-only t)
+  (conn (assert nil) :read-only t)
+  ;; Only populated for servers, this is the server connection.
+  server-conn
+  accept-string
+  (inflight-input nil))
+
+(defvar websocket-version "1.5"
+  "Version numbers of this version of websocket.el.")
+
+(defvar websocket-debug nil
+  "Set to true to output debugging info to a per-websocket buffer.
+The buffer is ` *websocket URL debug*' where URL is the
+URL of the connection.")
+
+(defconst websocket-guid "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
+  "The websocket GUID as defined in RFC 6455.
+Do not change unless the RFC changes.")
+
+(defvar websocket-callback-debug-on-error nil
+  "If true, when an error happens in a client callback, invoke the debugger.
+Having this on can cause issues with missing frames if the debugger is
+exited by quitting instead of continuing, so it's best to have this set
+to nil unless it is especially needed.")
+
+(defmacro websocket-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))
+
+(websocket-document-function websocket-on-open
+  "Accessor for websocket on-open callback.
+See `websocket-open' for details.
+
+\(fn WEBSOCKET)")
+
+(websocket-document-function websocket-on-message
+  "Accessor for websocket on-message callback.
+See `websocket-open' for details.
+
+\(fn WEBSOCKET)")
+
+(websocket-document-function websocket-on-close
+  "Accessor for websocket on-close callback.
+See `websocket-open' for details.
+
+\(fn WEBSOCKET)")
+
+(websocket-document-function websocket-on-error
+  "Accessor for websocket on-error callback.
+See `websocket-open' for details.
+
+\(fn WEBSOCKET)")
+
+(defun websocket-genbytes (nbytes)
+  "Generate NBYTES random bytes."
+  (let ((s (make-string nbytes ?\s)))
+    (dotimes (i nbytes)
+      (aset s i (random 256)))
+    s))
+
+(defun websocket-try-callback (websocket-callback callback-type websocket
+                                                  &rest rest)
+  "Invoke function WEBSOCKET-CALLBACK with WEBSOCKET and REST args.
+If an error happens, it is handled according to
+`websocket-callback-debug-on-error'."
+  ;; This looks like it should be able to done more efficiently, but
+  ;; I'm not sure that's the case.  We can't do it as a macro, since
+  ;; we want it to change whenever websocket-callback-debug-on-error
+  ;; changes.
+  (let ((args rest)
+        (debug-on-error websocket-callback-debug-on-error))
+    (push websocket args)
+    (if websocket-callback-debug-on-error
+        (condition-case err
+            (apply (funcall websocket-callback websocket) args)
+          ((debug error) (funcall (websocket-on-error websocket)
+                                  websocket callback-type err)))
+      (condition-case err
+          (apply (funcall websocket-callback websocket) args)
+        (error (funcall (websocket-on-error websocket) websocket
+                        callback-type err))))))
+
+(defun websocket-genkey ()
+  "Generate a key suitable for the websocket handshake."
+  (base64-encode-string (websocket-genbytes 16)))
+
+(defun websocket-calculate-accept (key)
+  "Calculate the expect value of the accept header.
+This is based on the KEY from the Sec-WebSocket-Key header."
+  (base64-encode-string
+   (sha1 (concat key websocket-guid) nil nil t)))
+
+(defun websocket-get-bytes (s n)
+  "From string S, retrieve the value of N bytes.
+Return the value as an unsigned integer.  The value N must be a
+power of 2, up to 8.
+
+We support getting frames up to 536870911 bytes (2^29 - 1),
+approximately 537M long."
+  (if (= n 8)
+    (let* ((32-bit-parts
+            (bindat-get-field (bindat-unpack '((:val vec 2 u32)) s) :val))
+           (cval
+            (logior (lsh (aref 32-bit-parts 0) 32) (aref 32-bit-parts 1))))
+      (if (and (= (aref 32-bit-parts 0) 0)
+               (= (lsh (aref 32-bit-parts 1) -29) 0))
+          cval
+        (signal 'websocket-unparseable-frame
+                "Frame value found too large to parse!")))
+    ;; n is not 8
+    (bindat-get-field
+     (condition-case _
+         (bindat-unpack
+          `((:val
+             ,(cond ((= n 1) 'u8)
+                    ((= n 2) 'u16)
+                    ((= n 4) 'u32)
+                    ;; This is an error with the library,
+                    ;; not a user-facing, meaningful error.
+                    (t (error
+                        "websocket-get-bytes: Unknown N: %s" n)))))
+          s)
+       (args-out-of-range (signal 'websocket-unparseable-frame
+                                  (format "Frame unexpectedly shortly: %s" s))))
+     :val)))
+
+(defun websocket-to-bytes (val nbytes)
+  "Encode the integer VAL in NBYTES of data.
+NBYTES much be a power of 2, up to 8.
+
+This supports encoding values up to 536870911 bytes (2^29 - 1),
+approximately 537M long."
+  (when (and (< nbytes 8)
+             (> val (expt 2 (* 8 nbytes))))
+    ;; not a user-facing error, this must be caused from an error in
+    ;; this library
+    (error "websocket-to-bytes: Value %d could not be expressed in %d bytes"
+           val nbytes))
+  (if (= nbytes 8)
+      (progn
+        (let ((hi-32bits (lsh val -32))
+              ;; Test for systems that don't have > 32 bits, and
+              ;; for those systems just return the value.
+              (low-32bits (if (= 0 (expt 2 32))
+                              val
+                            (logand #xffffffff val))))
+          (when (or (> hi-32bits 0) (> (lsh low-32bits -29) 0))
+            (signal 'websocket-frame-too-large val))
+          (bindat-pack `((:val vec 2 u32))
+                       `((:val . [,hi-32bits ,low-32bits])))))
+    (bindat-pack
+     `((:val ,(cond ((= nbytes 1) 'u8)
+                    ((= nbytes 2) 'u16)
+                    ((= nbytes 4) 'u32)
+                    ;; Library error, not system error
+                    (t (error "websocket-to-bytes: Unknown NBYTES: %s" nbytes)))))
+     `((:val . ,val)))))
+
+(defun websocket-get-opcode (s)
+  "Retrieve the opcode from first byte of string S."
+  (websocket-ensure-length s 1)
+  (let ((opcode (logand #xf (websocket-get-bytes s 1))))
+    (cond ((= opcode 0) 'continuation)
+          ((= opcode 1) 'text)
+          ((= opcode 2) 'binary)
+          ((= opcode 8) 'close)
+          ((= opcode 9) 'ping)
+          ((= opcode 10) 'pong))))
+
+(defun websocket-get-payload-len (s)
+  "Parse out the payload length from the string S.
+We start at position 0, and return a cons of the payload length and how
+many bytes were consumed from the string."
+  (websocket-ensure-length s 1)
+  (let* ((initial-val (logand 127 (websocket-get-bytes s 1))))
+    (cond ((= initial-val 127)
+           (websocket-ensure-length s 9)
+           (cons (websocket-get-bytes (substring s 1) 8) 9))
+          ((= initial-val 126)
+           (websocket-ensure-length s 3)
+           (cons (websocket-get-bytes (substring s 1) 2) 3))
+          (t (cons initial-val 1)))))
+
+(defstruct websocket-frame opcode payload length completep)
+
+(defun websocket-frame-text (frame)
+  "Given FRAME, return the payload as a utf-8 encoded string."
+  (assert (websocket-frame-p frame))
+  (decode-coding-string (websocket-frame-payload frame) 'utf-8))
+
+(defun websocket-mask (key data)
+  "Using string KEY, mask string DATA according to the RFC.
+This is used to both mask and unmask data."
+  ;; If we don't make the string unibyte here, a string of bytes that should be
+  ;; interpreted as a unibyte string will instead be interpreted as a multibyte
+  ;; string of the same length (for example, 6 multibyte chars for ä½ å¥½ instead
+  ;; of the correct 6 unibyte chars, which would convert into 2 multibyte
+  ;; chars).
+  (string-make-unibyte (apply
+                        'string
+                        (loop for b across data
+                              for i from 0 to (length data)
+                              collect
+                              (logxor (websocket-get-bytes (substring key (mod i 4)) 1) b)))))
+
+(defun websocket-ensure-length (s n)
+  "Ensure the string S has at most N bytes.
+Otherwise we throw the error `websocket-incomplete-frame'."
+  (when (< (length s) n)
+    (throw 'websocket-incomplete-frame nil)))
+
+(defun websocket-encode-frame (frame should-mask)
+  "Encode the FRAME struct to the binary representation.
+We mask the frame or not, depending on SHOULD-MASK."
+  (let* ((opcode (websocket-frame-opcode frame))
+         (payload (websocket-frame-payload frame))
+         (fin (websocket-frame-completep frame))
+         (payloadp (and payload
+                        (memq opcode '(continuation ping pong text binary))))
+         (mask-key (when should-mask (websocket-genbytes 4))))
+    (apply 'unibyte-string
+           (let ((val (append (list
+                            (logior (cond ((eq opcode 'continuation) 0)
+                                          ((eq opcode 'text) 1)
+                                          ((eq opcode 'binary) 2)
+                                          ((eq opcode 'close) 8)
+                                          ((eq opcode 'ping) 9)
+                                          ((eq opcode 'pong) 10))
+                                    (if fin 128 0)))
+                           (when payloadp
+                             (list
+                              (logior
+                               (if should-mask 128 0)
+                               (cond ((< (length payload) 126) (length payload))
+                                     ((< (length payload) 65536) 126)
+                                     (t 127)))))
+                           (when (and payloadp (>= (length payload) 126))
+                             (append (websocket-to-bytes
+                                      (length payload)
+                                      (cond ((< (length payload) 126) 1)
+                                            ((< (length payload) 65536) 2)
+                                            (t 8))) nil))
+                           (when (and payloadp should-mask)
+                             (append mask-key nil))
+                           (when payloadp
+                             (append (if should-mask (websocket-mask mask-key payload)
+                                       payload)
+                                     nil)))))
+             ;; We have to make sure the non-payload data is a full 32-bit frame
+             (if (= 1 (length val))
+                 (append val '(0)) val)))))
+
+(defun websocket-read-frame (s)
+  "Read from string S a `websocket-frame' struct with the contents.
+This only gets complete frames.  Partial frames need to wait until
+the frame finishes.  If the frame is not completed, return NIL."
+  (catch 'websocket-incomplete-frame
+    (websocket-ensure-length s 1)
+    (let* ((opcode (websocket-get-opcode s))
+           (fin (logand 128 (websocket-get-bytes s 1)))
+           (payloadp (memq opcode '(continuation text binary ping pong)))
+           (payload-len (when payloadp
+                          (websocket-get-payload-len (substring s 1))))
+           (maskp (and
+                   payloadp
+                   (= 128 (logand 128 (websocket-get-bytes (substring s 1) 1)))))
+           (payload-start (when payloadp (+ (if maskp 5 1) (cdr payload-len))))
+           (payload-end (when payloadp (+ payload-start (car payload-len))))
+           (unmasked-payload (when payloadp
+                               (websocket-ensure-length s payload-end)
+                               (substring s payload-start payload-end))))
+      (make-websocket-frame
+       :opcode opcode
+       :payload
+       (if maskp
+           (let ((masking-key (substring s (+ 1 (cdr payload-len))
+                                         (+ 5 (cdr payload-len)))))
+             (websocket-mask masking-key unmasked-payload))
+         unmasked-payload)
+       :length (if payloadp payload-end 1)
+       :completep (> fin 0)))))
+
+(defun websocket-format-error (err)
+  "Format an error message like command level does.
+ERR should be a cons of error symbol and error data."
+
+  ;; Formatting code adapted from `edebug-report-error'
+  (concat (or (get (car err) 'error-message)
+              (format "peculiar error (%s)" (car err)))
+          (when (cdr err)
+            (format ": %s"
+                    (mapconcat #'prin1-to-string
+                               (cdr err) ", ")))))
+
+(defun websocket-default-error-handler (_websocket type err)
+  "The default error handler used to handle errors in callbacks."
+  (display-warning 'websocket
+                   (format "in callback `%S': %s"
+                           type
+                           (websocket-format-error err))
+                   :error))
+
+;; Error symbols in use by the library
+(put 'websocket-unsupported-protocol 'error-conditions
+     '(error websocket-error websocket-unsupported-protocol))
+(put 'websocket-unsupported-protocol 'error-message "Unsupported websocket protocol")
+(put 'websocket-wss-needs-emacs-24 'error-conditions
+     '(error websocket-error websocket-unsupported-protocol
+             websocket-wss-needs-emacs-24))
+(put 'websocket-wss-needs-emacs-24 'error-message
+     "wss protocol is not supported for Emacs before version 24.")
+(put 'websocket-received-error-http-response 'error-conditions
+     '(error websocket-error websocket-received-error-http-response))
+(put 'websocket-received-error-http-response 'error-message
+     "Error response received from websocket server")
+(put 'websocket-invalid-header 'error-conditions
+     '(error websocket-error websocket-invalid-header))
+(put 'websocket-invalid-header 'error-message
+     "Invalid HTTP header sent")
+(put 'websocket-illegal-frame 'error-conditions
+     '(error websocket-error websocket-illegal-frame))
+(put 'websocket-illegal-frame 'error-message
+     "Cannot send illegal frame to websocket")
+(put 'websocket-closed 'error-conditions
+     '(error websocket-error websocket-closed))
+(put 'websocket-closed 'error-message
+     "Cannot send message to a closed websocket")
+(put 'websocket-unparseable-frame 'error-conditions
+     '(error websocket-error websocket-unparseable-frame))
+(put 'websocket-unparseable-frame 'error-message
+     "Received an unparseable frame")
+(put 'websocket-frame-too-large 'error-conditions
+     '(error websocket-error websocket-frame-too-large))
+(put 'websocket-frame-too-large 'error-message
+     "The frame being sent is too large for this emacs to handle")
+
+(defun websocket-intersect (a b)
+  "Simple list intersection, should function like Common Lisp's `intersection'."
+  (let ((result))
+    (dolist (elem a (nreverse result))
+      (when (member elem b)
+        (push elem result)))))
+
+(defun websocket-get-debug-buffer-create (websocket)
+  "Get or create the buffer corresponding to WEBSOCKET."
+  (let ((buf (get-buffer-create (format "*websocket %s debug*"
+                                    (websocket-url websocket)))))
+    (when (= 0 (buffer-size buf))
+      (buffer-disable-undo buf))
+    buf))
+
+(defun websocket-debug (websocket msg &rest args)
+  "In the WEBSOCKET's debug buffer, send MSG, with format ARGS."
+  (when websocket-debug
+    (let ((buf (websocket-get-debug-buffer-create websocket)))
+      (save-excursion
+        (with-current-buffer buf
+          (goto-char (point-max))
+          (insert "[WS] ")
+          (insert (apply 'format (append (list msg) args)))
+          (insert "\n"))))))
+
+(defun websocket-verify-response-code (output)
+  "Verify that OUTPUT contains a valid HTTP response code.
+The only acceptable one to websocket is responce code 101.
+A t value will be returned on success, and an error thrown
+if not."
+  (unless (string-match "^HTTP/1.1 \\([[:digit:]]+\\)" output)
+    (signal 'websocket-invalid-header "Invalid HTTP status line"))
+  (unless (equal "101" (match-string 1 output))
+    (signal 'websocket-received-error-http-response
+           (string-to-number (match-string 1 output))))
+  t)
+
+(defun websocket-parse-repeated-field (output field)
+  "From header-containing OUTPUT, parse out the list from a
+possibly repeated field."
+  (let ((pos 0)
+        (extensions))
+    (while (and pos
+                (string-match (format "\r\n%s: \\(.*\\)\r\n" field)
+                              output pos))
+      (when (setq pos (match-end 1))
+        (setq extensions (append extensions (split-string
+                                             (match-string 1 output) ", ?")))))
+    extensions))
+
+(defun websocket-process-frame (websocket frame)
+  "Using the WEBSOCKET's filter and connection, process the FRAME.
+This returns a lambda that should be executed when all frames have
+been processed.  If the frame has a payload, the lambda has the frame
+passed to the filter slot of WEBSOCKET.  If the frame is a ping,
+the lambda has a reply with a pong.  If the frame is a close, the lambda
+has connection termination."
+  (let ((opcode (websocket-frame-opcode frame)))
+    (lexical-let ((lex-ws websocket)
+                  (lex-frame frame))
+      (cond ((memq opcode '(continuation text binary))
+             (lambda () (websocket-try-callback 'websocket-on-message 'on-message
+                                           lex-ws lex-frame)))
+            ((eq opcode 'ping)
+             (lambda () (websocket-send lex-ws
+                                        (make-websocket-frame
+                                         :opcode 'pong
+                                         :payload (websocket-frame-payload lex-frame)
+                                         :completep t))))
+            ((eq opcode 'close)
+             (lambda () (delete-process (websocket-conn lex-ws))))
+            (t (lambda ()))))))
+
+(defun websocket-process-input-on-open-ws (websocket text)
+  "This handles input processing for both the client and server filters."
+  (let ((current-frame)
+        (processing-queue)
+        (start-point 0))
+    (while (setq current-frame (websocket-read-frame
+                                (substring text start-point)))
+      (push (websocket-process-frame websocket current-frame) processing-queue)
+      (incf start-point (websocket-frame-length current-frame)))
+    (when (> (length text) start-point)
+      (setf (websocket-inflight-input websocket)
+            (substring text start-point)))
+    (dolist (to-process (nreverse processing-queue))
+      (funcall to-process))))
+
+(defun websocket-send-text (websocket text)
+  "To the WEBSOCKET, send TEXT as a complete frame."
+  (websocket-send
+   websocket
+   (make-websocket-frame :opcode 'text
+                         :payload (encode-coding-string
+                                   text 'raw-text)
+                         :completep t)))
+
+(defun websocket-check (frame)
+  "Check FRAME for correctness, returning true if correct."
+  (or
+   ;; Text, binary, and continuation frames need payloads
+   (and (memq (websocket-frame-opcode frame) '(text binary continuation))
+        (websocket-frame-payload frame))
+   ;; Pings and pongs may optionally have them
+   (memq (websocket-frame-opcode frame) '(ping pong))
+   ;; And close shouldn't have any payload, and should always be complete.
+   (and (eq (websocket-frame-opcode frame) 'close)
+        (not (websocket-frame-payload frame))
+        (websocket-frame-completep frame))))
+
+(defun websocket-send (websocket frame)
+  "To the WEBSOCKET server, send the FRAME.
+This will raise an error if the frame is illegal.
+
+The error signaled may be of type `websocket-illegal-frame' if
+the frame is malformed in some way, also having the condition
+type of `websocket-error'.  The data associated with the signal
+is the frame being sent.
+
+If the websocket is closed a signal `websocket-closed' is sent,
+also with `websocket-error' condition.  The data in the signal is
+also the frame.
+
+The frame may be too large for this buid of Emacs, in which case
+`websocket-frame-too-large' is returned, with the data of the
+size of the frame which was too large to process.  This also has
+the `websocket-error' condition."
+  (unless (websocket-check frame)
+    (signal 'websocket-illegal-frame frame))
+  (websocket-debug websocket "Sending frame, opcode: %s payload: %s"
+                   (websocket-frame-opcode frame)
+                   (websocket-frame-payload frame))
+  (websocket-ensure-connected websocket)
+  (unless (websocket-openp websocket)
+    (signal 'websocket-closed frame))
+  (process-send-string (websocket-conn websocket)
+                       ;; We mask only when we're a client, following the spec.
+                       (websocket-encode-frame frame (not (websocket-server-p websocket)))))
+
+(defun websocket-openp (websocket)
+  "Check WEBSOCKET and return non-nil if it is open, and either
+connecting or open."
+  (and websocket
+       (not (eq 'close (websocket-ready-state websocket)))
+       (member (process-status (websocket-conn websocket)) '(open run))))
+
+(defun websocket-close (websocket)
+  "Close WEBSOCKET and erase all the old websocket data."
+  (websocket-debug websocket "Closing websocket")
+  (websocket-try-callback 'websocket-on-close 'on-close websocket)
+  (when (websocket-openp websocket)
+    (websocket-send websocket
+                    (make-websocket-frame :opcode 'close
+                                          :completep t))
+    (setf (websocket-ready-state websocket) 'closed))
+  (delete-process (websocket-conn websocket)))
+
+(defun websocket-ensure-connected (websocket)
+  "If the WEBSOCKET connection is closed, open it."
+  (unless (and (websocket-conn websocket)
+               (ecase (process-status (websocket-conn websocket))
+                 ((run open listen) t)
+                 ((stop exit signal closed connect failed nil) nil)))
+    (websocket-close websocket)
+    (websocket-open (websocket-url websocket)
+                    :protocols (websocket-protocols websocket)
+                    :extensions (websocket-extensions websocket)
+                    :on-open (websocket-on-open websocket)
+                    :on-message (websocket-on-message websocket)
+                    :on-close (websocket-on-close websocket)
+                    :on-error (websocket-on-error websocket))))
+
+;;;;;;;;;;;;;;;;;;;;;;
+;; Websocket client ;;
+;;;;;;;;;;;;;;;;;;;;;;
+
+(defun* websocket-open (url &key protocols extensions (on-open 'identity)
+                            (on-message (lambda (_w _f))) (on-close 'identity)
+                            (on-error 'websocket-default-error-handler))
+  "Open a websocket connection to URL, returning the `websocket' struct.
+The PROTOCOL argument is optional, and setting it will declare to
+the server that this client supports the protocols in the list
+given.  We will require that the server also has to support that
+protocols.
+
+Similar logic applies to EXTENSIONS, which is a list of conses,
+the car of which is a string naming the extension, and the cdr of
+which is the list of parameter strings to use for that extension.
+The parameter strings are of the form \"key=value\" or \"value\".
+EXTENSIONS can be NIL if none are in use.  An example value would
+be (\"deflate-stream\" . (\"mux\" \"max-channels=4\")).
+
+Cookies that are set via `url-cookie-store' will be used during
+communication with the server, and cookies received from the
+server will be stored in the same cookie storage that the
+`url-cookie' package uses.
+
+Optionally you can specify
+ON-OPEN, ON-MESSAGE and ON-CLOSE callbacks as well.
+
+The ON-OPEN callback is called after the connection is
+established with the websocket as the only argument.  The return
+value is unused.
+
+The ON-MESSAGE callback is called after receiving a frame, and is
+called with the websocket as the first argument and
+`websocket-frame' struct as the second.  The return value is
+unused.
+
+The ON-CLOSE callback is called after the connection is closed, or
+failed to open.  It is called with the websocket as the only
+argument, and the return value is unused.
+
+The ON-ERROR callback is called when any of the other callbacks
+have an error.  It takes the websocket as the first argument, and
+a symbol as the second argument either `on-open', `on-message',
+or `on-close', and the error as the third argument. Do NOT
+rethrow the error, or else you may miss some websocket messages.
+You similarly must not generate any other errors in this method.
+If you want to debug errors, set
+`websocket-callback-debug-on-error' to t, but this also can be
+dangerous is the debugger is quit out of.  If not specified,
+`websocket-default-error-handler' is used.
+
+For each of these event handlers, the client code can store
+arbitrary data in the `client-data' slot in the returned
+websocket.
+
+The following errors might be thrown in this method or in
+websocket processing, all of them having the error-condition
+`websocket-error' in addition to their own symbol:
+
+`websocket-unsupported-protocol': Data in the error signal is the
+protocol that is unsupported.  For example, giving a URL starting
+with http by mistake raises this error.
+
+`websocket-wss-needs-emacs-24': Trying to connect wss protocol
+using Emacs < 24 raises this error.  You can catch this error
+also by `websocket-unsupported-protocol'.
+
+`websocket-received-error-http-response': Data in the error
+signal is the integer error number.
+
+`websocket-invalid-header': Data in the error is a string
+describing the invalid header received from the server.
+
+`websocket-unparseable-frame': Data in the error is a string
+describing the problem with the frame.
+"
+  (let* ((name (format "websocket to %s" url))
+         (url-struct (url-generic-parse-url url))
+         (key (websocket-genkey))
+         (coding-system-for-read 'binary)
+         (coding-system-for-write 'binary)
+         (conn (if (member (url-type url-struct) '("ws" "wss"))
+                   (let* ((type (if (equal (url-type url-struct) "ws")
+                                    'plain 'tls))
+                          (port (if (= 0 (url-port url-struct))
+                                    (if (eq type 'tls) 443 80)
+                                  (url-port url-struct)))
+                          (host (url-host url-struct)))
+                       (if (eq type 'plain)
+                           (make-network-process :name name :buffer nil :host host
+                                                 :service port :nowait nil)
+                         (condition-case-unless-debug nil
+                             (open-network-stream name nil host port :type type :nowait nil)
+                           (wrong-number-of-arguments
+                            (signal 'websocket-wss-needs-emacs-24 "wss")))))
+                 (signal 'websocket-unsupported-protocol (url-type url-struct))))
+         (websocket (websocket-inner-create
+                     :conn conn
+                     :url url
+                     :on-open on-open
+                     :on-message on-message
+                     :on-close on-close
+                     :on-error on-error
+                     :protocols protocols
+                     :extensions (mapcar 'car extensions)
+                     :accept-string
+                     (websocket-calculate-accept key))))
+    (unless conn (error "Could not establish the websocket connection to %s" url))
+    (process-put conn :websocket websocket)
+    (set-process-filter conn
+                        (lambda (process output)
+                          (let ((websocket (process-get process :websocket)))
+                            (websocket-outer-filter websocket output))))
+    (set-process-sentinel
+     conn
+     (lambda (process change)
+       (let ((websocket (process-get process :websocket)))
+         (websocket-debug websocket "State change to %s" change)
+         (when (and
+                (member (process-status process) '(closed failed exit signal))
+                (not (eq 'closed (websocket-ready-state websocket))))
+           (websocket-try-callback 'websocket-on-close 'on-close websocket)))))
+    (set-process-query-on-exit-flag conn nil)
+    (process-send-string conn
+                         (format "GET %s HTTP/1.1\r\n"
+                                 (let ((path (url-filename url-struct)))
+                                   (if (> (length path) 0) path "/"))))
+    (websocket-debug websocket "Sending handshake, key: %s, acceptance: %s"
+                     key (websocket-accept-string websocket))
+    (process-send-string conn
+                         (websocket-create-headers url key protocols extensions))
+    (websocket-debug websocket "Websocket opened")
+    websocket))
+
+(defun websocket-process-headers (url headers)
+  "On opening URL, process the HEADERS sent from the server."
+  (when (string-match "Set-Cookie: \(.*\)\r\n" headers)
+    ;; The url-current-object is assumed to be set by
+    ;; url-cookie-handle-set-cookie.
+    (let ((url-current-object (url-generic-parse-url url)))
+      (url-cookie-handle-set-cookie (match-string 1 headers)))))
+
+(defun websocket-outer-filter (websocket output)
+  "Filter the WEBSOCKET server's OUTPUT.
+This will parse headers and process frames repeatedly until there
+is no more output or the connection closes.  If the websocket
+connection is invalid, the connection will be closed."
+  (websocket-debug websocket "Received: %s" output)
+  (let ((start-point)
+        (text (concat (websocket-inflight-input websocket) output))
+        (header-end-pos))
+    (setf (websocket-inflight-input websocket) nil)
+    ;; If we've received the complete header, check to see if we've
+    ;; received the desired handshake.
+    (when (and (eq 'connecting (websocket-ready-state websocket)))
+      (if (and (setq header-end-pos (string-match "\r\n\r\n" text))
+               (setq start-point (+ 4 header-end-pos)))
+          (progn
+            (condition-case err
+                (progn
+                  (websocket-verify-response-code text)
+                  (websocket-verify-headers websocket text)
+                  (websocket-process-headers (websocket-url websocket) text))
+              (error
+               (websocket-close websocket)
+               (signal (car err) (cdr err))))
+            (setf (websocket-ready-state websocket) 'open)
+            (websocket-try-callback 'websocket-on-open 'on-open websocket))
+        (setf (websocket-inflight-input websocket) text)))
+    (when (eq 'open (websocket-ready-state websocket))
+      (websocket-process-input-on-open-ws
+       websocket (substring text (or start-point 0))))))
+
+(defun websocket-verify-headers (websocket output)
+  "Based on WEBSOCKET's data, ensure the headers in OUTPUT are valid.
+The output is assumed to have complete headers.  This function
+will either return t or call `error'.  This has the side-effect
+of populating the list of server extensions to WEBSOCKET."
+  (let ((accept-string
+         (concat "Sec-WebSocket-Accept: " (websocket-accept-string websocket))))
+    (websocket-debug websocket "Checking for accept header: %s" accept-string)
+    (unless (string-match (regexp-quote accept-string) output)
+      (signal 'websocket-invalid-header
+              "Incorrect handshake from websocket: is this really a websocket connection?")))
+  (let ((case-fold-search t))
+    (websocket-debug websocket "Checking for upgrade header")
+    (unless (string-match "\r\nUpgrade: websocket\r\n" output)
+      (signal 'websocket-invalid-header
+              "No 'Upgrade: websocket' header found"))
+    (websocket-debug websocket "Checking for connection header")
+    (unless (string-match "\r\nConnection: upgrade\r\n" output)
+      (signal 'websocket-invalid-header
+              "No 'Connection: upgrade' header found"))
+    (when (websocket-protocols websocket)
+      (dolist (protocol (websocket-protocols websocket))
+        (websocket-debug websocket "Checking for protocol match: %s"
+                         protocol)
+        (let ((protocols
+               (if (string-match (format "\r\nSec-Websocket-Protocol: %s\r\n"
+                                         protocol)
+                                 output)
+                   (list protocol)
+                 (signal 'websocket-invalid-header
+                         "Incorrect or missing protocol returned by the server."))))
+          (setf (websocket-negotiated-protocols websocket) protocols))))
+    (let* ((extensions (websocket-parse-repeated-field
+                        output
+                        "Sec-WebSocket-Extensions"))
+           (extra-extensions))
+      (dolist (ext extensions)
+        (let ((x (first (split-string ext "; ?"))))
+          (unless (or (member x (websocket-extensions websocket))
+                      (member x extra-extensions))
+            (push x extra-extensions))))
+      (when extra-extensions
+        (signal 'websocket-invalid-header
+                (format "Non-requested extensions returned by server: %S"
+                        extra-extensions)))
+      (setf (websocket-negotiated-extensions websocket) extensions)))
+  t)
+
+;;;;;;;;;;;;;;;;;;;;;;
+;; Websocket server ;;
+;;;;;;;;;;;;;;;;;;;;;;
+
+(defvar websocket-server-websockets nil
+  "A list of current websockets live on any server.")
+
+(defun* websocket-server (port &rest plist)
+  "Open a websocket server on PORT.
+If the plist contains a `:host' HOST pair, this value will be
+used to configure the addresses the socket listens on. The symbol
+`local' specifies the local host. If unspecified or nil, the
+socket will listen on all addresses.
+
+This also takes a plist of callbacks: `:on-open', `:on-message',
+`:on-close' and `:on-error', which operate exactly as documented
+in the websocket client function `websocket-open'.  Returns the
+connection, which should be kept in order to pass to
+`websocket-server-close'."
+  (let* ((conn (make-network-process
+                :name (format "websocket server on port %s" port)
+                :server t
+                :family 'ipv4
+                :noquery t
+                :filter 'websocket-server-filter
+                :log 'websocket-server-accept
+                :filter-multibyte nil
+                :plist plist
+                :host (plist-get plist :host)
+                :service port)))
+    conn))
+
+(defun websocket-server-close (conn)
+  "Closes the websocket, as well as all open websockets for this server."
+  (let ((to-delete))
+    (dolist (ws websocket-server-websockets)
+      (when (eq (websocket-server-conn ws) conn)
+        (if (eq (websocket-ready-state ws) 'closed)
+            (unless (member ws to-delete)
+              (push ws to-delete))
+          (websocket-close ws))))
+    (dolist (ws to-delete)
+      (setq websocket-server-websockets (remove ws websocket-server-websockets))))
+  (delete-process conn))
+
+(defun websocket-server-accept (server client _message)
+  "Accept a new websocket connection from a client."
+  (let ((ws (websocket-inner-create
+             :server-conn server
+             :conn client
+             :url client
+             :server-p t
+             :on-open (or (process-get server :on-open) 'identity)
+             :on-message (or (process-get server :on-message) (lambda (_ws _frame)))
+             :on-close (lexical-let ((user-method
+                                      (or (process-get server :on-close) 'identity)))
+                         (lambda (ws)
+                           (setq websocket-server-websockets
+                                 (remove ws websocket-server-websockets))
+                           (funcall user-method ws)))
+             :on-error (or (process-get server :on-error)
+                           'websocket-default-error-handler)
+             :protocols (process-get server :protocol)
+             :extensions (mapcar 'car (process-get server :extensions)))))
+    (unless (member ws websocket-server-websockets)
+      (push ws websocket-server-websockets))
+    (process-put client :websocket ws)
+    (set-process-coding-system client 'binary 'binary)
+    (set-process-sentinel client
+     (lambda (process change)
+       (let ((websocket (process-get process :websocket)))
+         (websocket-debug websocket "State change to %s" change)
+         (when (and
+                (member (process-status process) '(closed failed exit signal))
+                (not (eq 'closed (websocket-ready-state websocket))))
+           (websocket-try-callback 'websocket-on-close 'on-close websocket)))))))
+
+(defun websocket-create-headers (url key protocol extensions)
+  "Create connections headers for the given URL, KEY, PROTOCOL and EXTENSIONS.
+These are defined as in `websocket-open'."
+  (let* ((parsed-url (url-generic-parse-url url))
+         (host-port (if (url-port-if-non-default parsed-url)
+                        (format "%s:%s" (url-host parsed-url) (url-port parsed-url))
+                      (url-host parsed-url)))
+         (cookie-header (url-cookie-generate-header-lines
+                         host-port (car (url-path-and-query parsed-url))
+                         (equal (url-type parsed-url) "wss"))))
+    (format (concat "Host: %s\r\n"
+                    "Upgrade: websocket\r\n"
+                    "Connection: Upgrade\r\n"
+                    "Sec-WebSocket-Key: %s\r\n"
+                    "Sec-WebSocket-Version: 13\r\n"
+                    (when protocol
+                      (concat
+                       (mapconcat
+                        (lambda (protocol)
+                          (format "Sec-WebSocket-Protocol: %s" protocol))
+                        protocol "\r\n")
+                       "\r\n"))
+                    (when extensions
+                      (format "Sec-WebSocket-Extensions: %s\r\n"
+                              (mapconcat
+                               (lambda (ext)
+                                 (concat
+                                  (car ext)
+                                  (when (cdr ext) "; ")
+                                  (when (cdr ext)
+                                    (mapconcat 'identity (cdr ext) "; "))))
+                               extensions ", ")))
+                    (when cookie-header cookie-header)
+                    "\r\n")
+            host-port
+            key
+            protocol)))
+
+(defun websocket-get-server-response (websocket client-protocols client-extensions)
+  "Get the websocket response from client WEBSOCKET."
+  (let ((separator "\r\n"))
+      (concat "HTTP/1.1 101 Switching Protocols" separator
+              "Upgrade: websocket" separator
+              "Connection: Upgrade" separator
+              "Sec-WebSocket-Accept: "
+              (websocket-accept-string websocket) separator
+              (let ((protocols
+                         (websocket-intersect client-protocols
+                                              (websocket-protocols websocket))))
+                    (when protocols
+                      (concat
+                       (mapconcat
+                        (lambda (protocol) (format "Sec-WebSocket-Protocol: %s"
+                                              protocol)) protocols separator)
+                       separator)))
+              (let ((extensions (websocket-intersect
+                                   client-extensions
+                                   (websocket-extensions websocket))))
+                  (when extensions
+                    (concat
+                     (mapconcat
+                      (lambda (extension) (format "Sec-Websocket-Extensions: %s"
+                                             extension)) extensions separator)
+                     separator)))
+              separator)))
+
+(defun websocket-server-filter (process output)
+  "This acts on all OUTPUT from websocket clients PROCESS."
+  (let* ((ws (process-get process :websocket))
+         (text (concat (websocket-inflight-input ws) output)))
+    (setf (websocket-inflight-input ws) nil)
+    (cond ((eq (websocket-ready-state ws) 'connecting)
+           ;; check for connection string
+           (let ((end-of-header-pos
+                  (let ((pos (string-match "\r\n\r\n" text)))
+                    (when pos (+ 4 pos)))))
+               (if end-of-header-pos
+                   (progn
+                     (let ((header-info (websocket-verify-client-headers text)))
+                       (if header-info
+                           (progn (setf (websocket-accept-string ws)
+                                        (websocket-calculate-accept
+                                         (plist-get header-info :key)))
+                                  (process-send-string
+                                   process
+                                   (websocket-get-server-response
+                                    ws (plist-get header-info :protocols)
+                                    (plist-get header-info :extensions)))
+                                  (setf (websocket-ready-state ws) 'open)
+                                  (websocket-try-callback 'websocket-on-open
+                                                          'on-open ws))
+                         (message "Invalid client headers found in: %s" output)
+                         (process-send-string process "HTTP/1.1 400 Bad Request\r\n\r\n")
+                         (websocket-close ws)))
+                     (when (> (length text) (+ 1 end-of-header-pos))
+                       (websocket-server-filter process (substring
+                                                           text
+                                                           end-of-header-pos))))
+                 (setf (websocket-inflight-input ws) text))))
+          ((eq (websocket-ready-state ws) 'open)
+           (websocket-process-input-on-open-ws ws text))
+          ((eq (websocket-ready-state ws) 'closed)
+           (message "WARNING: Should not have received further input on closed websocket")))))
+
+(defun websocket-verify-client-headers (output)
+  "Verify the headers from the WEBSOCKET client connection in OUTPUT.
+Unlike `websocket-verify-headers', this is a quieter routine.  We
+don't want to error due to a bad client, so we just print out
+messages and a plist containing `:key', the websocket key,
+`:protocols' and `:extensions'."
+  (block nil
+    (let ((case-fold-search t)
+          (plist))
+      (unless (string-match "HTTP/1.1" output)
+        (message "Websocket client connection: HTTP/1.1 not found")
+        (return nil))
+      (unless (string-match "^Host: " output)
+        (message "Websocket client connection: Host header not found")
+        (return nil))
+      (unless (string-match "^Upgrade: websocket\r\n" output)
+        (message "Websocket client connection: Upgrade: websocket not found")
+        (return nil))
+      (if (string-match "^Sec-WebSocket-Key: \\([[:graph:]]+\\)\r\n" output)
+          (setq plist (plist-put plist :key (match-string 1 output)))
+        (message "Websocket client connect: No key sent")
+        (return nil))
+      (unless (string-match "^Sec-WebSocket-Version: 13" output)
+        (message "Websocket client connect: Websocket version 13 not found")
+        (return nil))
+      (when (string-match "^Sec-WebSocket-Protocol:" output)
+        (setq plist (plist-put plist :protocols (websocket-parse-repeated-field
+                                                 output
+                                                 "Sec-Websocket-Protocol"))))
+      (when (string-match "^Sec-WebSocket-Extensions:" output)
+        (setq plist (plist-put plist :extensions (websocket-parse-repeated-field
+                                                  output
+                                                  "Sec-Websocket-Extensions"))))
+      plist)))
+
+(provide 'websocket)
+
+;;; websocket.el ends here
index b4b4465..b1147e1 100644 (file)
  '(diff-mode-hook (quote ((lambda nil (diff-auto-refine-mode 1)))))
  '(diff-switches "-u")
  '(dtrt-indent-mode t nil (dtrt-indent))
+ '(ediff-window-setup-function (quote ediff-setup-windows-plain))
  '(edit-server-done-hook nil)
  '(edit-server-new-frame nil)
  '(fill-column 98)
- '(flymake-allowed-file-name-masks
-   (quote
-    (("\\.java\\'" flymake-simple-make-java-init flymake-simple-java-cleanup)
-     ("[0-9]+\\.tex\\'" flymake-master-tex-init flymake-master-cleanup)
-     ("\\.tex\\'" flymake-simple-tex-init))))
  '(flyspell-delay 30)
  '(flyspell-delayed-commands nil)
  '(frame-background-mode (quote light))
@@ -60,9 +56,9 @@
  '(hs-isearch-open nil)
  '(ido-mode (quote both) nil (ido))
  '(indent-tabs-mode nil)
- '(ispell-dictionary "deutsch8")
+ '(ispell-dictionary "american")
  '(ispell-extra-args (quote ("--sug-mode=ultra")))
- '(ispell-program-name "c:/cygwin/bin/aspell.exe")
+ '(ispell-program-name "aspell")
  '(line-move-visual nil)
  '(ls-lisp-dirs-first t)
  '(magit-default-tracking-name-function (quote magit-default-tracking-name-branch-only))
@@ -82,7 +78,8 @@
  '(rtags-use-helm nil t)
  '(safe-local-variable-values
    (quote
-    ((elisp-project-autoload-file-name . "sqi-autoload.el")
+    ((ispell-local-dictionary . de_DE-neu)
+     (elisp-project-autoload-file-name . "sqi-autoload.el")
      (elisp-project-autoload-file-name . "cc-autoload.el")
      (ccide-auto-format-tag . "auto-uncrustify")
      (ccide-uncrustify-config . "~/src/search.uncrustify")
similarity index 100%
rename from gnuplot/autoload.el
rename to gnuplot/load.el
index 9067c16..4c71a2d 100644 (file)
@@ -4,6 +4,9 @@
 ;(require 'python-mode)
 ;(provide 'python)
 ;(provide 'python21)
+
+(global-unset-key "\C-xpn")
+
 (require 'python)
 
 ;; pymacs
@@ -25,8 +28,6 @@
 
 (define-key ropemacs-local-keymap "\M-/" 'hippie-expand)
 
-(global-unset-key "\C-xpn")
-
 (defun write-file-py-cleanup-imports ()
   (save-excursion
     (condition-case nil
 ;;;   2) Yasnippet
 ;;;   all with AutoComplete.el
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(defun prefix-list-elements (list prefix)
-  (let (value)
-    (nreverse
-     (dolist (element list value)
-      (setq value (cons (format "%s%s" prefix element) value))))))
-(defvar ac-source-rope
-  '((candidates
-     . (lambda ()
-         (prefix-list-elements (rope-completions) ac-target))))
-  "Source for Rope")
-(defun ac-python-find ()
-  "Python `ac-find-function'."
-  (require 'thingatpt)
-  (let ((symbol (car-safe (bounds-of-thing-at-point 'symbol))))
-    (if (null symbol)
+(if nil
+  (defun prefix-list-elements (list prefix)
+    (let (value)
+      (nreverse
+       (dolist (element list value)
+         (setq value (cons (format "%s%s" prefix element) value))))))
+  (defvar ac-source-rope
+    '((candidates
+       . (lambda ()
+           (prefix-list-elements (rope-completions) ac-target))))
+    "Source for Rope")
+  (defun ac-python-find ()
+    "Python `ac-find-function'."
+    (require 'thingatpt)
+    (let ((symbol (car-safe (bounds-of-thing-at-point 'symbol))))
+      (if (null symbol)
         (if (string= "." (buffer-substring (- (point) 1) (point)))
-            (point)
+          (point)
           nil)
-      symbol)))
-(defun ac-python-candidate ()
-  "Python `ac-candidates-function'"
-  (let (candidates)
-    (dolist (source ac-sources)
-      (if (symbolp source)
+        symbol)))
+  (defun ac-python-candidate ()
+    "Python `ac-candidates-function'"
+    (let (candidates)
+      (dolist (source ac-sources)
+        (if (symbolp source)
           (setq source (symbol-value source)))
-      (let* ((ac-limit (or (cdr-safe (assq 'limit source)) ac-limit))
-             (requires (cdr-safe (assq 'requires source)))
-             cand)
-        (if (or (null requires)
-                (>= (length ac-target) requires))
+        (let* ((ac-limit (or (cdr-safe (assq 'limit source)) ac-limit))
+               (requires (cdr-safe (assq 'requires source)))
+               cand)
+          (if (or (null requires)
+                  (>= (length ac-target) requires))
             (setq cand
                   (delq nil
                         (mapcar (lambda (candidate)
                                   (propertize candidate 'source source))
                                 (funcall (cdr (assq 'candidates source)))))))
-        (if (and (> ac-limit 1)
-                 (> (length cand) ac-limit))
+          (if (and (> ac-limit 1)
+                   (> (length cand) ac-limit))
             (setcdr (nthcdr (1- ac-limit) cand) nil))
-        (setq candidates (append candidates cand))))
-    (delete-dups candidates)))
-(add-hook 'python-mode-hook
-          (lambda ()
-                 (auto-complete-mode 1)
-                 (set (make-local-variable 'ac-sources)
-                      (append ac-sources '(ac-source-rope) '(ac-source-yasnippet)))
-                 (set (make-local-variable 'ac-find-function) 'ac-python-find)
-                 (set (make-local-variable 'ac-candidate-function) 'ac-python-candidate)
-                 (set (make-local-variable 'ac-auto-start) nil)))
-;;Ryan's python specific tab completion
-(defun ryan-python-tab ()
-  ; Try the following:
-  ; 1) Do a yasnippet expansion
-  ; 2) Do a Rope code completion
-  ; 3) Do an indent
-  (interactive)
-  (if (eql (ac-start) 0)
+          (setq candidates (append candidates cand))))
+      (delete-dups candidates)))
+  (add-hook 'python-mode-hook
+            (lambda ()
+              (auto-complete-mode 1)
+              (set (make-local-variable 'ac-sources)
+                   (append ac-sources '(ac-source-rope) '(ac-source-yasnippet)))
+              (set (make-local-variable 'ac-find-function) 'ac-python-find)
+              (set (make-local-variable 'ac-candidate-function) 'ac-python-candidate)
+              (set (make-local-variable 'ac-auto-start) nil)))
+  ;;Ryan's python specific tab completion
+  (defun ryan-python-tab ()
+                                        ; Try the following:
+                                        ; 1) Do a yasnippet expansion
+                                        ; 2) Do a Rope code completion
+                                        ; 3) Do an indent
+    (interactive)
+    (if (eql (ac-start) 0)
       (indent-for-tab-command)))
-(defadvice ac-start (before advice-turn-on-auto-start activate)
-  (set (make-local-variable 'ac-auto-start) t))
-(defadvice ac-cleanup (after advice-turn-off-auto-start activate)
-  (set (make-local-variable 'ac-auto-start) nil))
+  (defadvice ac-start (before advice-turn-on-auto-start activate)
+    (set (make-local-variable 'ac-auto-start) t))
+  (defadvice ac-cleanup (after advice-turn-off-auto-start activate)
+    (set (make-local-variable 'ac-auto-start) nil))
+  )
 ;(define-key py-mode-map "\t" 'ryan-python-tab)
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;; End Auto Completion
index 8e4e79c..8112606 100644 (file)
@@ -1,5 +1,5 @@
 (global-set-key "\M-/" 'hippie-expand)
-(global-set-key "\C-c'w" 'which-func-mode)
+(global-set-key "\C-c'w" 'which-function-mode)
 (global-set-key "\C-c'h" 'highlight-changes-mode)
 (global-set-key "\C-c'f" 'auto-fill-mode)
 (global-set-key "\C-c'v" 'visual-line-mode)
@@ -8,6 +8,7 @@
 (global-set-key "\C-c'g" 'toggle-debug-on-quit)
 (global-set-key "\C-c'c" 'toggle-case-fold-search)
 (global-set-key "\C-c's" 'flyspell-mode)
+(global-set-key "\C-c'S" 'flyspell-prog-mode)
 (global-set-key "\C-c'a" 'global-auto-revert-mode)
 (global-set-key "\C-cF" 'ffap)
 
   ;; * everything as globaly configured
   ;; * as above but disable lines-tail
   ;; * nothing
+  ;; * as above but visualize tabs
+
+  ;; if mode is not set, detect current mode and set it to the next value in the list
   (if (null mode)
       (if (local-variable-p 'whitespace-style)
           (if (null whitespace-style)
-              (setq mode 'default)
-            (setq mode 'none))
+              (setq mode 'tabs)
+            (if (memq 'tab-mark whitespace-style)
+                (setq mode 'default)
+              (setq mode 'none)))
         (setq mode 'longlines)))
   (cond ((eq mode 'default)
          (kill-local-variable 'whitespace-style))
         ((eq mode 'longlines)
          (setq-local whitespace-style (remove 'lines-tail (default-value 'whitespace-style))))
+        ((eq mode 'tabs)
+         (setq-local whitespace-style '(tab-mark)))
         ((eq mode 'none)
          (setq-local whitespace-style nil)))
   (whitespace-mode -1)
 (global-set-key "\C-c' " 'toggle-whitespace-mode)
 
 (setq confirm-kill-emacs 'yes-or-no-p)
+
+(defun kill-buffers-in-directory (directoryName &optional includeNonFiles)
+  (interactive (list
+                (ido-read-directory-name
+                 (if current-prefix-arg "Kill buffers in directory:" "Kill files in directory: "))
+                current-prefix-arg))
+  (setq directoryName (expand-file-name directoryName))
+  (if (not (string-suffix-p "/" directoryName))
+    (setq directoryName (concat directoryName "/")))
+  (loop for buffer in (buffer-list)
+        for bufferDirectory = (progn
+                                (set-buffer buffer)
+                                (if includeNonFiles default-directory
+                                    (and buffer-file-name (file-name-directory buffer-file-name))))
+        if (and bufferDirectory (string-prefix-p directoryName (expand-file-name bufferDirectory)))
+        do (kill-buffer buffer)))
+
+(global-set-key "\C-xK" 'kill-buffers-in-directory)
index 1f836ac..3a72ff0 100644 (file)
         (eshell-buffer (get-buffer "*eshell*")))
     (if (not eshell-buffer)
         (error "no *eshell* buffer found"))
-    (pop-to-buffer (get-buffer "*eshell*"))
+    (my-pop-to-buffer (get-buffer "*eshell*"))
     (goto-char (point-max))
     (setq default-directory dir)
-    (insert "\n")
-    (eshell-send-input)))
+    (eshell-interrupt-process)))
 
 (global-set-key "\C-cE" 'eshell-switch-directory-current-buffer)
+
+(setenv "PATH" (concat (getenv "PATH")
+                       ":"
+                       (expand-file-name "~/bin")
+                       ":"
+                       (expand-file-name "~/.local/bin")))
index 1352979..6f580fd 100644 (file)
@@ -2,5 +2,5 @@
 
 ; Speed up interactivity in flyspell (it's unusable on windows otherwise)
 
-(defadvice flyspell-check-pre-word-p (around flyspell-delay-all activate)
-  (setq ad-return-value nil))
+; (defadvice flyspell-check-pre-word-p (around flyspell-delay-all activate)
+;   (setq ad-return-value nil))
index b0ed624..d54f242 100644 (file)
@@ -5,10 +5,10 @@
                                          buffer-file-name))))
                    (file-name-as-directory "gnuplot"))))
   (add-to-list 'load-path dir)
-  (load (concat dir "autoload.el")))
+  (load (concat dir "load.el")))
 
 (defun gnuplot ()
   (interactive)
   (gnuplot-make-gnuplot-buffer)
   (sit-for .1)
-  (switch-to-buffer "*gnuplot*"))
\ No newline at end of file
+  (switch-to-buffer "*gnuplot*"))
index 8ae6b76..91c70f2 100644 (file)
 
 (require 'magit)
 
-(setq magit-refs-local-branch-format "%C %-48n %U%m\n")
-(setq magit-refs-remote-branch-format "%C %-48n %m\n")
+;; Add additional %-escapes ...
+(defun magit-insert-branch-1
+    (section branch format current branches face
+             &optional hash message upstream ahead behind gone)
+  "For internal use, don't add to a hook."
+  (let* ((head  (or (car magit-refresh-args) current "HEAD"))
+         (count (and branch
+                     (magit-refs-format-commit-count branch head format)))
+         (mark  (cond ((or (equal branch head)
+                           (and (not branch) (equal head "HEAD")))
+                       (if (equal branch current)
+                           (propertize "@" 'face 'magit-head)
+                         (propertize "#" 'face 'magit-tag)))
+                      ((equal branch current)
+                       (propertize "." 'face 'magit-head)))))
+    (when upstream
+      (setq upstream (propertize upstream 'face
+                                 (if (member upstream branches)
+                                     'magit-branch-local
+                                   'magit-branch-remote))))
+    (magit-insert-heading
+      (format-spec
+       format
+       `((?a . ,(or ahead ""))
+         (?b . ,(or behind ""))
+         (?c . ,(or mark count ""))
+         (?C . ,(or mark " "))
+         (?h . ,(or (propertize hash 'face 'magit-hash) ""))
+         (?m . ,(or message ""))
+         (?n . ,(propertize (or branch "(detached)") 'face face))
+         (?u . ,(or upstream ""))
+         (?U . ,(if upstream (format (propertize " [%s]" 'face 'magit-dimmed)  upstream) ""))
+         (?d . ,(if upstream
+                  (let ((msg (cond
+                              (gone
+                               (concat (propertize gone 'face 'error)))
+                              ((or ahead behind)
+                               (concat (and ahead (format "ahead %s" ahead))
+                                       (and ahead behind ", ")
+                                       (and behind (format "behind %s" behind))))
+                              (t nil))))
+                    (if msg
+                      (format (propertize "[%s] " 'face 'magit-dimmed) msg)
+                      ""))
+                  ""))
+         (?D . ,(if upstream
+                    (format (propertize "[%s%s] " 'face 'magit-dimmed)
+                            upstream
+                            (cond
+                             (gone
+                              (concat ": " (propertize gone 'face 'error)))
+                             ((or ahead behind)
+                              (concat ": "
+                                      (and ahead (format "ahead %s" ahead))
+                                      (and ahead behind ", ")
+                                      (and behind (format "behind %s" behind))))
+                             (t "")))
+                  "")))))
+    (when magit-show-margin
+      (magit-refs-format-margin branch))
+    (magit-refs-insert-cherry-commits head branch section)))
+
+(setq magit-refs-local-branch-format "%C %-48n %-1.1u %d%m")
+(setq magit-refs-remote-branch-format "%C %-48n   %m")
 
 (when (eq system-type 'windows-nt)
 
     ad-do-it))
 
 (global-set-key "\C-cGS" 'magit-status)
+(global-set-key "\C-cGW" 'magit-file-popup)
 
 (defun my-shell-command-to-string (cmd)
   (shell-command cmd " *my-shell-command-to-string*")
 (magit-define-popup-switch 'magit-log-popup
   ?f "first parent" "--first-parent")
 
+(defun magit-reset-to-upstream ()
+  (interactive)
+  (magit-run-git "reset" "--hard" "@{u}"))
+
+(magit-define-popup-action 'magit-pull-popup
+  ?X "HARD Reset to upstream (force pull after remote rebase)" 'magit-reset-to-upstream)
+
 (require 'ffap)
 
 (defun g0dil-magit-old-version-jump-to-current ()
index 4fde816..11891c8 100644 (file)
@@ -22,7 +22,7 @@ to 80."
 window smaller than MIN-HEIGHT lines."
   (interactive)
   ;; this algorithm is copied from window.el / balance-windows()
-  (let ((min-height (or min-height i(+ window-min-height 0)))
+  (let ((min-height (or min-height (+ window-min-height 0)))
         (count -1)
         size)
         ;; Don't count the lines that are above the uppermost windows.
@@ -61,6 +61,15 @@ window smaller than MIN-HEIGHT lines."
 
 (defvar my-windows-count nil)
 
+(defun get-top-windows ()
+  (let (topwindows)
+    (walk-windows (function (lambda (w)
+                              (let ((e (window-edges w)))
+                                (if (< (nth 1 e) window-min-height)
+                                  (setq topwindows (cons (cons (nth 0 e) w) topwindows)))))))
+    (loop for w in (sort topwindows (function (lambda (a b) (< (car a) (car b)))))
+          collect (cdr w) )))
+
 (defun setup-my-windows (&optional n)
   (interactive "P")
   (if n
@@ -73,27 +82,22 @@ window smaller than MIN-HEIGHT lines."
          (min width) (distribute t)
          (currentbuffer (current-buffer))
          (currentwindow (selected-window))
-         topwindows firstwindow newwindow newtopwindows)
-    (walk-windows (function (lambda (w)
-                              (let ((e (window-edges w)))
-                                (if (< (nth 1 e) window-min-height)
-                                    (setq topwindows (cons (list (nth 0 e)
-                                                                 w
-                                                                 (window-buffer w)
-                                                                 (window-point w)
-                                                                 (window-start w)
-                                                                 (equal w currentwindow))
-                                                           topwindows))))))
-                            'nomini)
-    (setq topwindows (sort topwindows (function (lambda (a b) (< (car a) (car b))))))
-    (setq topwindows (loop for w in topwindows
-                           for (pos win buf point start iscurrent) = w
-                           if (not (member (buffer-name buf) setup-my-windows-junk-buffers))
-                           collect w))
+         (topwindows (loop for w in (get-top-windows)
+                           for b = (window-buffer w)
+                           if (not (member (buffer-name b)
+                                           setup-my-windows-junk-buffers))
+                           collect (list (nth 0 (window-edges w))
+                                         w
+                                         b
+                                         (window-point w)
+                                         (window-start w)
+                                         (equal w currentwindow))))
+         firstwindow newwindow newtopwindows newbottomwindow)
     (delete-other-windows (nth 1 (car topwindows)))
     (save-selected-window
-      (select-window (split-window-vertically
-                      (- (window-height) (max 5 (/ (* (frame-height) 15) 100)) -1)))
+      (setq newbottomwindow (split-window-vertically
+                             (- (window-height) (max 5 (/ (* (frame-height) 15) 100)) -1)))
+      (select-window newbottomwindow)
       (switch-to-buffer (get-buffer-create "*compilation*"))
       (if (eq currentbuffer (current-buffer))
           (setq newwindow (selected-window))))
@@ -148,19 +152,39 @@ window smaller than MIN-HEIGHT lines."
       (pjb-balance-windows t))
     (select-window newwindow)
     (if (not (member (buffer-name currentbuffer) setup-my-windows-junk-buffers))
-        (switch-to-buffer currentbuffer))))
+        (switch-to-buffer currentbuffer))
+    newbottomwindow))
 
 (defun my-split-window-sensibly (window)
   (if (and (> (window-height window) (- (frame-height (window-frame window)) window-min-height))
            (> (window-height window) (max 5 (/ (* (frame-height) 15) 100))))
       (split-window-sensibly window)))
 
+(defun my-pop-to-buffer (buffer)
+  ;; display buffer in rightmost window if not displayed currently
+  (let ((w (get-buffer-window buffer)))
+    (unless w
+      (setq w (car (last (get-top-windows)))))
+    (select-window w)
+    (switch-to-buffer buffer)))
+
+(defun my-display-at-bottom (&optional buffer)
+  ;; call my-setup-window and display current-buffer or BUFFER in bottom frame
+  (interactive)
+  (if (not buffer) (setq buffer (current-buffer)))
+  (bury-buffer)
+  ;; why does save-selected-window not work here ???
+  (save-selected-window
+    (select-window (setup-my-windows))
+    (switch-to-buffer buffer)))
+
 (setq split-window-preferred-function 'my-split-window-sensibly)
 
 (global-set-key "\C-x7" 'split-window-3-horizontally)
 (global-set-key "\C-x8" (lambda () (interactive) (split-window-n-horizontally 100 50)))
 (global-set-key "\C-x9" 'setup-my-windows)
 (global-set-key "\C-\M-_" (lambda () (interactive) (safe-shrink-window 5)))
+(global-set-key "\C-x_" 'my-display-at-bottom)
 
 (defun my-swap-window-to-right (&optional below)
   "If swap buffer in this window with buffer on the right. If BELOW is set,
@@ -217,8 +241,10 @@ the buffer stack in the current window."
 
 (defun safe-max-window ()
   (interactive)
-  (safe-max-window-horizontally)
-  (maximize-window 5))
+  (maximize-window 5)
+  (condition-case nil
+      (safe-max-window-horizontally)
+    (error nil)))
 
 (global-set-key "\C-x=" 'safe-max-window)
 (global-set-key "\C-x-" 'maximize-window-15)
index 9423ef2..2b8b733 100644 (file)
 
 (add-to-list 'hs-special-modes-alist '(nxml-mode ("\\(<[^/>]*>\\)$" 1) "</[^/>]*>$"))
 
-(defun nxml-enable-hs ()
+(defun nxml-setup ()
   (setq nxml-sexp-element-flag t)
-  (hs-minor-mode 1))
+  (hs-minor-mode 1)
+  (setq tab-width 2)
+  (toggle-whitespace-mode 'tabs))
 
-(add-hook 'nxml-mode-hook 'nxml-enable-hs)
+(add-hook 'nxml-mode-hook 'nxml-setup)
 
 (defun hs-nxml-enter ()
   (interactive)
index 0d47656..b78dd64 100644 (file)
@@ -33,6 +33,8 @@
     (function rtags-find-symbol-at-point))
   (define-key c-mode-base-map (kbd "\C-c,")
     (function rtags-find-references-at-point))
+  (define-key c-mode-base-map (kbd "\C-cn")
+    (function rtags-next-diag))
   ;; disable prelude's use of C-c r, as this is the rtags keyboard prefix
   ;; (define-key prelude-mode-map (kbd "C-c r") nil)
   ;; install standard rtags keybindings. Do M-. on the symbol below to
index c57a3b3..411d8bc 100644 (file)
@@ -10,3 +10,4 @@
 ;(setq solarized-use-less-bold nil)
 (require 'solarized-light-theme)
 ;(set-face-attribute 'show-paren-match nil :weight 'extra-bold)
+(set-face-attribute 'show-paren-match nil :foreground nil)
diff --git a/setup/sticky.el b/setup/sticky.el
new file mode 100644 (file)
index 0000000..edae8f1
--- /dev/null
@@ -0,0 +1,6 @@
+(define-minor-mode sticky-buffer-mode
+  "Make the current window always display this buffer."
+  nil " sticky" nil
+  (set-window-dedicated-p (selected-window) sticky-buffer-mode))
+
+(global-set-key "\C-xS" 'sticky-buffer-mode)
index 56ca33a..64af9db 100644 (file)
@@ -1,8 +1,16 @@
 (defvar ssh-agent-auth-sock-link "~/.ssh/ssh_auth_sock")
 
+(defun g0dil-set-ssh-agent()
+  (message "SSH_AUTH_SOCK set to %s" ssh-agent-auth-sock-link)
+  (setenv "SSH_AUTH_SOCK" (expand-file-name ssh-agent-auth-sock-link)))
+
 (defun g0dil-x2go-fix-ssh-agent ()
   (let ((agent (getenv "SSH_AUTH_SOCK")))
-    (if (string-match "^.*/\.x2go/.*/ssh-agent.PID" agent)
-        (setenv "SSH_AUTH_SOCK" (expand-file-name ssh-agent-auth-sock-link)))))
+    (if (and agent (string-match "^.*/\.x2go/.*/ssh-agent.PID" agent))
+      (g0dil-set-ssh-agent))))
+
+(defun g0dil-fix-ssh-agent ()
+  (if (file-exists-p ssh-agent-auth-sock-link)
+    (g0dil-set-ssh-agent)))
 
-(g0dil-x2go-fix-ssh-agent)
+(g0dil-fix-ssh-agent)
index 7cdb7ca..9f65e4b 100644 (file)
 (defadvice display-buffer-use-some-window (around no-resize activate)
   (flet ((window-resize (&rest args) nil))
     ad-do-it))
+
+; After everybody has had a chance to mess with flymake, remove the flymake modes which just don't work
+(setq flymake-allowed-file-name-masks
+      (loop for elt in flymake-allowed-file-name-masks
+            if (not (member (car elt) '("\\.xml\\'" "\\.html?\\'" "\\.cs\\'" "\\.p[ml]\\'"
+                                        "\\.h\\'" "\\.\\(?:c\\(?:pp\\|xx\\|\\+\\+\\)?\\|CC\\)\\'")))
+            collect elt))