Install some packages
This commit is contained in:
		
							
								
								
									
										92
									
								
								elpa/alert-20160824.821/alert-autoloads.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								elpa/alert-20160824.821/alert-autoloads.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,92 @@ | ||||
| ;;; alert-autoloads.el --- automatically extracted autoloads | ||||
| ;; | ||||
| ;;; Code: | ||||
| (add-to-list 'load-path (directory-file-name (or (file-name-directory #$) (car load-path)))) | ||||
|  | ||||
| ;;;### (autoloads nil "alert" "alert.el" (22533 17539 221493 451000)) | ||||
| ;;; Generated autoloads from alert.el | ||||
|  | ||||
| (autoload 'alert-add-rule "alert" "\ | ||||
| Programmatically add an alert configuration rule. | ||||
|  | ||||
| Normally, users should custoimze `alert-user-configuration'. | ||||
| This facility is for module writers and users that need to do | ||||
| things the Lisp way. | ||||
|  | ||||
| Here is a rule the author currently uses with ERC, so that the | ||||
| fringe gets colored whenever people chat on BitlBee: | ||||
|  | ||||
| \(alert-add-rule :status   \\='(buried visible idle) | ||||
|                 :severity \\='(moderate high urgent) | ||||
|                 :mode     \\='erc-mode | ||||
|                 :predicate | ||||
|                 #\\='(lambda (info) | ||||
|                     (string-match (concat \"\\\\`[^&].*@BitlBee\\\\\\='\") | ||||
|                                   (erc-format-target-and/or-network))) | ||||
|                 :persistent | ||||
|                 #\\='(lambda (info) | ||||
|                     ;; If the buffer is buried, or the user has been | ||||
|                     ;; idle for `alert-reveal-idle-time' seconds, | ||||
|                     ;; make this alert persistent.  Normally, alerts | ||||
|                     ;; become persistent after | ||||
|                     ;; `alert-persist-idle-time' seconds. | ||||
|                     (memq (plist-get info :status) \\='(buried idle))) | ||||
|                 :style \\='fringe | ||||
|                 :continue t) | ||||
|  | ||||
| \(fn &key SEVERITY STATUS MODE CATEGORY TITLE MESSAGE PREDICATE ICON (style alert-default-style) PERSISTENT CONTINUE NEVER-PERSIST APPEND)" nil nil) | ||||
|  | ||||
| (autoload 'alert "alert" "\ | ||||
| Alert the user that something has happened. | ||||
| MESSAGE is what the user will see.  You may also use keyword | ||||
| arguments to specify additional details.  Here is a full example: | ||||
|  | ||||
| \(alert \"This is a message\" | ||||
|        :severity \\='high          ;; The default severity is `normal' | ||||
|        :title \"Title\"           ;; An optional title | ||||
|        :category \\='example       ;; A symbol to identify the message | ||||
|        :mode \\='text-mode         ;; Normally determined automatically | ||||
|        :buffer (current-buffer) ;; This is the default | ||||
|        :data nil                ;; Unused by alert.el itself | ||||
|        :persistent nil          ;; Force the alert to be persistent; | ||||
|                                 ;; it is best not to use this | ||||
|        :never-persist nil       ;; Force this alert to never persist | ||||
|        :style \\='fringe)          ;; Force a given style to be used; | ||||
|                                 ;; this is only for debugging! | ||||
|  | ||||
| If no :title is given, the buffer-name of :buffer is used.  If | ||||
| :buffer is nil, it is the current buffer at the point of call. | ||||
|  | ||||
| :data is an opaque value which modules can pass through to their | ||||
| own styles if they wish. | ||||
|  | ||||
| Here are some more typical examples of usage: | ||||
|  | ||||
|   ;; This is the most basic form usage | ||||
|   (alert \"This is an alert\") | ||||
|  | ||||
|   ;; You can adjust the severity for more important messages | ||||
|   (alert \"This is an alert\" :severity \\='high) | ||||
|  | ||||
|   ;; Or decrease it for purely informative ones | ||||
|   (alert \"This is an alert\" :severity \\='trivial) | ||||
|  | ||||
|   ;; Alerts can have optional titles.  Otherwise, the title is the | ||||
|   ;; buffer-name of the (current-buffer) where the alert originated. | ||||
|   (alert \"This is an alert\" :title \"My Alert\") | ||||
|  | ||||
|   ;; Further, alerts can have categories.  This allows users to | ||||
|   ;; selectively filter on them. | ||||
|   (alert \"This is an alert\" :title \"My Alert\" | ||||
|          :category \\='some-category-or-other) | ||||
|  | ||||
| \(fn MESSAGE &key (severity (quote normal)) TITLE ICON CATEGORY BUFFER MODE DATA STYLE PERSISTENT NEVER-PERSIST)" nil nil) | ||||
|  | ||||
| ;;;*** | ||||
|  | ||||
| ;; Local Variables: | ||||
| ;; version-control: never | ||||
| ;; no-byte-compile: t | ||||
| ;; no-update-autoloads: t | ||||
| ;; End: | ||||
| ;;; alert-autoloads.el ends here | ||||
							
								
								
									
										2
									
								
								elpa/alert-20160824.821/alert-pkg.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								elpa/alert-20160824.821/alert-pkg.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| ;;; -*- no-byte-compile: t -*- | ||||
| (define-package "alert" "20160824.821" "Growl-style notification system for Emacs" '((gntp "0.1") (log4e "0.3.0")) :url "https://github.com/jwiegley/alert" :keywords '("notification" "emacs" "message")) | ||||
							
								
								
									
										1045
									
								
								elpa/alert-20160824.821/alert.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1045
									
								
								elpa/alert-20160824.821/alert.el
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										225
									
								
								elpa/circe-20160608.1315/circe-autoloads.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										225
									
								
								elpa/circe-20160608.1315/circe-autoloads.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,225 @@ | ||||
| ;;; circe-autoloads.el --- automatically extracted autoloads | ||||
| ;; | ||||
| ;;; Code: | ||||
| (add-to-list 'load-path (directory-file-name (or (file-name-directory #$) (car load-path)))) | ||||
|  | ||||
| ;;;### (autoloads nil "circe" "circe.el" (22533 17540 927532 375000)) | ||||
| ;;; Generated autoloads from circe.el | ||||
|  | ||||
| (autoload 'circe-version "circe" "\ | ||||
| Display Circe's version. | ||||
|  | ||||
| \(fn)" t nil) | ||||
|  | ||||
| (autoload 'circe "circe" "\ | ||||
| Connect to IRC. | ||||
|  | ||||
| Connect to the given network specified by NETWORK-OR-SERVER. | ||||
|  | ||||
| When this function is called, it collects options from the | ||||
| SERVER-OPTIONS argument, the user variable | ||||
| `circe-network-options', and the defaults found in | ||||
| `circe-network-defaults', in this order. | ||||
|  | ||||
| If NETWORK-OR-SERVER is not found in any of these variables, the | ||||
| argument is assumed to be the host name for the server, and all | ||||
| relevant settings must be passed via SERVER-OPTIONS. | ||||
|  | ||||
| All SERVER-OPTIONS are treated as variables by getting the string | ||||
| \"circe-\" prepended to their name. This variable is then set | ||||
| locally in the server buffer. | ||||
|  | ||||
| See `circe-network-options' for a list of common options. | ||||
|  | ||||
| \(fn NETWORK-OR-SERVER &rest SERVER-OPTIONS)" t nil) | ||||
|  | ||||
| ;;;*** | ||||
|  | ||||
| ;;;### (autoloads nil "circe-color-nicks" "circe-color-nicks.el" | ||||
| ;;;;;;  (22533 17540 792529 295000)) | ||||
| ;;; Generated autoloads from circe-color-nicks.el | ||||
|  | ||||
| (autoload 'enable-circe-color-nicks "circe-color-nicks" "\ | ||||
| Enable the Color Nicks module for Circe. | ||||
| This module colors all encountered nicks in a cross-server fashion. | ||||
|  | ||||
| \(fn)" t nil) | ||||
|  | ||||
| ;;;*** | ||||
|  | ||||
| ;;;### (autoloads nil "circe-highlight-all-nicks" "circe-highlight-all-nicks.el" | ||||
| ;;;;;;  (22533 17541 95536 208000)) | ||||
| ;;; Generated autoloads from circe-highlight-all-nicks.el | ||||
|  | ||||
| (autoload 'enable-circe-highlight-all-nicks "circe-highlight-all-nicks" "\ | ||||
| Enable the Highlight Nicks module for Circe. | ||||
| This module highlights all occurances of nicks in the current | ||||
| channel in messages of other people. | ||||
|  | ||||
| \(fn)" t nil) | ||||
|  | ||||
| ;;;*** | ||||
|  | ||||
| ;;;### (autoloads nil "circe-lagmon" "circe-lagmon.el" (22533 17540 | ||||
| ;;;;;;  882531 348000)) | ||||
| ;;; Generated autoloads from circe-lagmon.el | ||||
|  | ||||
| (defvar circe-lagmon-mode nil "\ | ||||
| Non-nil if Circe-Lagmon mode is enabled. | ||||
| See the `circe-lagmon-mode' command | ||||
| for a description of this minor mode. | ||||
| Setting this variable directly does not take effect; | ||||
| either customize it (see the info node `Easy Customization') | ||||
| or call the function `circe-lagmon-mode'.") | ||||
|  | ||||
| (custom-autoload 'circe-lagmon-mode "circe-lagmon" nil) | ||||
|  | ||||
| (autoload 'circe-lagmon-mode "circe-lagmon" "\ | ||||
| Circe-lagmon-mode monitors the amount of lag on your | ||||
| connection to each server, and displays the lag time in seconds | ||||
| in the mode-line. | ||||
|  | ||||
| \(fn &optional ARG)" t nil) | ||||
|  | ||||
| ;;;*** | ||||
|  | ||||
| ;;;### (autoloads nil "circe-new-day-notifier" "circe-new-day-notifier.el" | ||||
| ;;;;;;  (22533 17541 242539 562000)) | ||||
| ;;; Generated autoloads from circe-new-day-notifier.el | ||||
|  | ||||
| (autoload 'enable-circe-new-day-notifier "circe-new-day-notifier" "\ | ||||
|  | ||||
|  | ||||
| \(fn)" t nil) | ||||
|  | ||||
| (autoload 'disable-circe-new-day-notifier "circe-new-day-notifier" "\ | ||||
|  | ||||
|  | ||||
| \(fn)" t nil) | ||||
|  | ||||
| ;;;*** | ||||
|  | ||||
| ;;;### (autoloads nil "lui-autopaste" "lui-autopaste.el" (22533 17541 | ||||
| ;;;;;;  5534 154000)) | ||||
| ;;; Generated autoloads from lui-autopaste.el | ||||
|  | ||||
| (autoload 'enable-lui-autopaste "lui-autopaste" "\ | ||||
| Enable the lui autopaste feature. | ||||
|  | ||||
| If you enter more than `lui-autopaste-lines' at once, Lui will | ||||
| ask if you would prefer to use a paste service instead. If you | ||||
| agree, Lui will paste your input to `lui-autopaste-function' and | ||||
| replace it with the resulting URL. | ||||
|  | ||||
| \(fn)" t nil) | ||||
|  | ||||
| (autoload 'disable-lui-autopaste "lui-autopaste" "\ | ||||
| Disable the lui autopaste feature. | ||||
|  | ||||
| \(fn)" t nil) | ||||
|  | ||||
| ;;;*** | ||||
|  | ||||
| ;;;### (autoloads nil "lui-irc-colors" "lui-irc-colors.el" (22533 | ||||
| ;;;;;;  17541 310541 113000)) | ||||
| ;;; Generated autoloads from lui-irc-colors.el | ||||
|  | ||||
| (autoload 'enable-lui-irc-colors "lui-irc-colors" "\ | ||||
| Enable IRC color interpretation for Lui. | ||||
|  | ||||
| \(fn)" t nil) | ||||
|  | ||||
| ;;;*** | ||||
|  | ||||
| ;;;### (autoloads nil "lui-track-bar" "lui-track-bar.el" (22533 17540 | ||||
| ;;;;;;  837530 321000)) | ||||
| ;;; Generated autoloads from lui-track-bar.el | ||||
|  | ||||
| (autoload 'enable-lui-track-bar "lui-track-bar" "\ | ||||
| Enable a bar in Lui buffers that shows where you stopped reading. | ||||
|  | ||||
| \(fn)" t nil) | ||||
|  | ||||
| ;;;*** | ||||
|  | ||||
| ;;;### (autoloads nil "shorten" "shorten.el" (22533 17541 129536 | ||||
| ;;;;;;  984000)) | ||||
| ;;; Generated autoloads from shorten.el | ||||
|  | ||||
| (autoload 'shorten-strings "shorten" "\ | ||||
| Takes a list of strings and returns an alist ((STRING | ||||
| . SHORTENED-STRING) ...).  Uses `shorten-split-function' to split | ||||
| the strings, and `shorten-join-function' to join shortened | ||||
| components back together into SHORTENED-STRING.  See also | ||||
| `shorten-validate-component-function'. | ||||
|  | ||||
| \(fn STRINGS)" nil nil) | ||||
|  | ||||
| ;;;*** | ||||
|  | ||||
| ;;;### (autoloads nil "tracking" "tracking.el" (22533 17540 713527 | ||||
| ;;;;;;  492000)) | ||||
| ;;; Generated autoloads from tracking.el | ||||
|  | ||||
| (defvar tracking-mode nil "\ | ||||
| Non-nil if Tracking mode is enabled. | ||||
| See the `tracking-mode' command | ||||
| for a description of this minor mode. | ||||
| Setting this variable directly does not take effect; | ||||
| either customize it (see the info node `Easy Customization') | ||||
| or call the function `tracking-mode'.") | ||||
|  | ||||
| (custom-autoload 'tracking-mode "tracking" nil) | ||||
|  | ||||
| (autoload 'tracking-mode "tracking" "\ | ||||
| Allow cycling through modified buffers. | ||||
| This mode in itself does not track buffer modification, but | ||||
| provides an API for programs to add buffers as modified (using | ||||
| `tracking-add-buffer'). | ||||
|  | ||||
| Once this mode is active, modified buffers are shown in the mode | ||||
| line. The user can cycle through them using | ||||
| \\[tracking-next-buffer]. | ||||
|  | ||||
| \(fn &optional ARG)" t nil) | ||||
|  | ||||
| (autoload 'tracking-add-buffer "tracking" "\ | ||||
| Add BUFFER as being modified with FACES. | ||||
| This does check whether BUFFER is currently visible. | ||||
|  | ||||
| If FACES is given, it lists the faces that might be appropriate | ||||
| for BUFFER in the mode line. The highest-priority face of these | ||||
| and the current face of the buffer, if any, is used. Priority is | ||||
| decided according to `tracking-faces-priorities'. | ||||
|  | ||||
| \(fn BUFFER &optional FACES)" nil nil) | ||||
|  | ||||
| (autoload 'tracking-remove-buffer "tracking" "\ | ||||
| Remove BUFFER from being tracked. | ||||
|  | ||||
| \(fn BUFFER)" nil nil) | ||||
|  | ||||
| (autoload 'tracking-next-buffer "tracking" "\ | ||||
| Switch to the next active buffer. | ||||
|  | ||||
| \(fn)" t nil) | ||||
|  | ||||
| (autoload 'tracking-previous-buffer "tracking" "\ | ||||
| Switch to the last active buffer. | ||||
|  | ||||
| \(fn)" t nil) | ||||
|  | ||||
| ;;;*** | ||||
|  | ||||
| ;;;### (autoloads nil nil ("circe-chanop.el" "circe-compat.el" "circe-pkg.el" | ||||
| ;;;;;;  "irc.el" "lcs.el" "lui-format.el" "lui-logging.el" "lui.el" | ||||
| ;;;;;;  "make-tls-process.el") (22533 17541 344541 889000)) | ||||
|  | ||||
| ;;;*** | ||||
|  | ||||
| ;; Local Variables: | ||||
| ;; version-control: never | ||||
| ;; no-byte-compile: t | ||||
| ;; no-update-autoloads: t | ||||
| ;; End: | ||||
| ;;; circe-autoloads.el ends here | ||||
							
								
								
									
										97
									
								
								elpa/circe-20160608.1315/circe-chanop.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								elpa/circe-20160608.1315/circe-chanop.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,97 @@ | ||||
| ;;; circe-chanop.el --- Provide common channel operator commands | ||||
|  | ||||
| ;; Copyright (C) 2006, 2015  Jorgen Schaefer | ||||
|  | ||||
| ;; Author: Jorgen Schaefer <forcer@forcix.cx> | ||||
|  | ||||
| ;; This file is part of Circe. | ||||
|  | ||||
| ;; This program is free software; you can redistribute it and/or | ||||
| ;; modify it under the terms of the GNU General Public License | ||||
| ;; as published by the Free Software Foundation; either version 3 | ||||
| ;; of the License, or (at your option) any later version. | ||||
|  | ||||
| ;; This program is distributed in the hope that it will be useful, | ||||
| ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| ;; GNU General Public License for more details. | ||||
|  | ||||
| ;; You should have received a copy of the GNU General Public License | ||||
| ;; along with this program; if not, write to the Free Software | ||||
| ;; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||||
| ;; 02110-1301  USA | ||||
|  | ||||
| ;;; Commentary: | ||||
|  | ||||
| ;; This Circe module provides some often-used chanop commands. I was | ||||
| ;; very reluctant to add this. None of these commands will make it in | ||||
| ;; the core, or even be provided by default. You should have to go to | ||||
| ;; great lengths to use them. | ||||
|  | ||||
| ;; Always remember the Tao of IRC: | ||||
| ;; | ||||
| ;;     IGNORE is the weapon of an IRC knight. Not as clumsy or as | ||||
| ;;     random as a kickban. | ||||
|  | ||||
| ;;; Code: | ||||
|  | ||||
| (require 'circe) | ||||
|  | ||||
| (defun circe-command-MODE (mode) | ||||
|   "Set MODE in the current channel." | ||||
|   (interactive "sMode change: ") | ||||
|   (cond | ||||
|    ((not (string-match "^[+-]" mode)) | ||||
|     (irc-send-raw (circe-server-process) | ||||
|                   (format "MODE %s" mode))) | ||||
|    ((eq major-mode 'circe-channel-mode) | ||||
|     (irc-send-raw (circe-server-process) | ||||
|                   (format "MODE %s %s" circe-chat-target mode))) | ||||
|    (t | ||||
|     (circe-display-server-message "Not in a channel buffer.")))) | ||||
|  | ||||
| (defun circe-command-BANS (&optional ignored) | ||||
|   "Show channel bans" | ||||
|   (if (not circe-chat-target) | ||||
|       (circe-display-server-message "No target for current buffer") | ||||
|     (irc-send-raw (circe-server-process) | ||||
|                   (format "MODE %s +b" circe-chat-target)))) | ||||
|  | ||||
| (defun circe-command-KICK (nick &optional reason) | ||||
|   "Kick WHO from the current channel with optional REASON." | ||||
|   (interactive "sKick who: \nsWhy: ") | ||||
|   (if (not (eq major-mode 'circe-channel-mode)) | ||||
|       (circe-display-server-message "Not in a channel buffer.") | ||||
|     (when (not reason) | ||||
|       (if (string-match "^\\([^ ]*\\) +\\(.+\\)" nick) | ||||
|           (setq reason (match-string 2 nick) | ||||
|                 nick (match-string 1 nick)) | ||||
|         (setq reason "-"))) | ||||
|     (irc-send-raw (circe-server-process) | ||||
|                   (format "KICK %s %s :%s" | ||||
|                           circe-chat-target nick reason)))) | ||||
|  | ||||
| (defun circe-command-GETOP (&optional ignored) | ||||
|   "Ask chanserv for op on the current channel." | ||||
|   (interactive) | ||||
|   (if (not (eq major-mode 'circe-channel-mode)) | ||||
|       (circe-display-server-message "Not in a channel buffer.") | ||||
|     (irc-send-PRIVMSG (circe-server-process) | ||||
|                       "chanserv" | ||||
|                       (format "op %s" circe-chat-target)))) | ||||
|  | ||||
| (defun circe-command-DROPOP (&optional ignored) | ||||
|   "Lose op mode on the current channel." | ||||
|   (interactive) | ||||
|   (if (not (eq major-mode 'circe-channel-mode)) | ||||
|       (circe-display-server-message "Not in a channel buffer.") | ||||
|     (irc-send-raw (circe-server-process) | ||||
|                   (format "MODE %s -o %s" | ||||
|                           circe-chat-target | ||||
|                           (circe-nick))))) | ||||
|  | ||||
| ;; For KICKBAN (requested by Riastradh), we'd need a callback on a | ||||
| ;; USERHOST command. | ||||
|  | ||||
| (provide 'circe-chanop) | ||||
| ;;; circe-chanop.el ends here | ||||
							
								
								
									
										345
									
								
								elpa/circe-20160608.1315/circe-color-nicks.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										345
									
								
								elpa/circe-20160608.1315/circe-color-nicks.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,345 @@ | ||||
| ;;; circe-color-nicks.el --- Color nicks in the channel | ||||
|  | ||||
| ;; Copyright (C) 2012  Taylan Ulrich Bayırlı/Kammer | ||||
|  | ||||
| ;; Author: Taylan Ulrich Bayırlı/Kammer <taylanbayirli@gmail.com> | ||||
|  | ||||
| ;; This file is part of Circe. | ||||
|  | ||||
| ;; This program is free software; you can redistribute it and/or | ||||
| ;; modify it under the terms of the GNU General Public License | ||||
| ;; as published by the Free Software Foundation; either version 3 | ||||
| ;; of the License, or (at your option) any later version. | ||||
|  | ||||
| ;; This program is distributed in the hope that it will be useful, | ||||
| ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| ;; GNU General Public License for more details. | ||||
|  | ||||
| ;; You should have received a copy of the GNU General Public License | ||||
| ;; along with this program; if not, write to the Free Software | ||||
| ;; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||||
| ;; 02110-1301  USA | ||||
|  | ||||
| ;;; Commentary: | ||||
|  | ||||
| ;; This Circe module adds the ability to assign a color to each | ||||
| ;; nick in a channel. | ||||
|  | ||||
| ;; Some ideas/code copied from rcirc-colors.el. | ||||
|  | ||||
| ;; To use it, put the following into your .emacs: | ||||
|  | ||||
| ;; (require 'circe-color-nicks) | ||||
| ;; (enable-circe-color-nicks) | ||||
|  | ||||
| ;;; Code: | ||||
|  | ||||
| (require 'circe) | ||||
| (require 'color) | ||||
| (require 'cl-lib) | ||||
|  | ||||
| ;;;###autoload | ||||
| (defun enable-circe-color-nicks () | ||||
|   "Enable the Color Nicks module for Circe. | ||||
| This module colors all encountered nicks in a cross-server fashion." | ||||
|   (interactive) | ||||
|   (dolist (buf (buffer-list)) | ||||
|     (with-current-buffer buf | ||||
|       (when (eq major-mode 'circe-channel-mode) | ||||
|         (add-circe-color-nicks)))) | ||||
|   (add-hook 'circe-channel-mode-hook | ||||
|             'add-circe-color-nicks)) | ||||
|  | ||||
| (defun disable-circe-color-nicks () | ||||
|   "Disable the Color Nicks module for Circe. | ||||
| See `enable-circe-color-nicks'." | ||||
|   (interactive) | ||||
|   (dolist (buf (buffer-list)) | ||||
|     (with-current-buffer buf | ||||
|       (when (eq major-mode 'circe-channel-mode) | ||||
|         (remove-circe-color-nicks)))) | ||||
|   (remove-hook 'circe-channel-mode-hook | ||||
|                'add-circe-color-nicks)) | ||||
|  | ||||
| (defun add-circe-color-nicks () | ||||
|   "Add `circe-color-nicks' to `lui-pre-output-hook'." | ||||
|   (add-hook 'lui-pre-output-hook 'circe-color-nicks)) | ||||
|  | ||||
| (defun remove-circe-color-nicks () | ||||
|   "Remove `circe-color-nicks' from `lui-pre-output-hook'." | ||||
|   (remove-hook 'lui-pre-output-hook 'circe-color-nicks)) | ||||
|  | ||||
|  | ||||
| (defgroup circe-color-nicks nil | ||||
|   "Nicks colorization for Circe" | ||||
|   :prefix "circe-color-nicks-" | ||||
|   :group 'circe) | ||||
|  | ||||
| (defcustom circe-color-nicks-min-contrast-ratio 7 | ||||
|   "Minimum contrast ratio from background for generated colors; | ||||
| recommended is 7:1, or at least 4.5:1 (7 stands for 7:1 here). | ||||
| Lower value allows higher color spread, but could lead to less | ||||
| readability." | ||||
|   :group 'circe-color-nicks) | ||||
|  | ||||
| (defcustom circe-color-nicks-min-difference 17 | ||||
|   "Minimum difference from each other for generated colors." | ||||
|   :group 'circe-color-nicks) | ||||
|  | ||||
| (defcustom circe-color-nicks-min-fg-difference 17 | ||||
|   "Minimum difference from foreground for generated colors." | ||||
|   :group 'circe-color-nicks) | ||||
|  | ||||
| (defcustom circe-color-nicks-min-my-message-difference 0 | ||||
|   "Minimum difference from own nick color for generated colors." | ||||
|   :group 'circe-color-nicks) | ||||
|  | ||||
| (defcustom circe-color-nicks-everywhere nil | ||||
|   "Whether nicks should be colored in message bodies too." | ||||
|   :type 'boolean | ||||
|   :group 'circe-color-nicks) | ||||
|  | ||||
| (defcustom circe-color-nicks-message-blacklist nil | ||||
|   "Blacklist for nicks that shall never be highlighted inside | ||||
|   images." | ||||
|   :type '(repeat string) | ||||
|   :group 'circe-color-nicks) | ||||
|  | ||||
| (defcustom circe-color-nicks-pool-type 'adaptive | ||||
|   "Type of the color nick pool. | ||||
| Must be one of the following: | ||||
|  | ||||
| 'adaptive: Generate colors based on the current theme. | ||||
|  | ||||
| List of strings: Pick colors from the specified list of hex codes | ||||
| or color names (see `color-name-rgb-alist')." | ||||
|   :type '(choice (const :tag "Adaptive" adaptive) | ||||
|                  (repeat string)) | ||||
|   :group 'circe-color-nicks) | ||||
|  | ||||
|  | ||||
| ;;; See http://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G18 | ||||
|  | ||||
| (defsubst circe-w3-contrast-c-to-l (c) | ||||
|   (if (<= c 0.03928) | ||||
|       (/ c 12.92) | ||||
|     (expt (/ (+ c 0.055) 1.055) 2.4))) | ||||
|  | ||||
| (defsubst circe-w3-contrast-relative-luminance (rgb) | ||||
|   (apply #'+ | ||||
|          (cl-mapcar (lambda (color coefficient) | ||||
|                       (* coefficient | ||||
|                          (circe-w3-contrast-c-to-l color))) | ||||
|                     rgb | ||||
|                     '(0.2126 0.7152 0.0722)))) | ||||
|  | ||||
| (defsubst circe-w3-contrast-contrast-ratio (color1 color2) | ||||
|   (let ((l1 (+ 0.05 (circe-w3-contrast-relative-luminance color1))) | ||||
|         (l2 (+ 0.05 (circe-w3-contrast-relative-luminance color2)))) | ||||
|     (if (> l1 l2) | ||||
|         (/ l1 l2) | ||||
|         (/ l2 l1)))) | ||||
|  | ||||
|  | ||||
| (defun circe-color-alist () | ||||
|   "Return list of colors (name rgb lab) where rgb is 0 to 1." | ||||
|   (let ((alist (if (display-graphic-p) | ||||
|                    color-name-rgb-alist | ||||
|                  (mapcar (lambda (c) | ||||
|                            (cons (car c) (cddr c))) | ||||
|                          (tty-color-alist)))) | ||||
|         (valmax (float (car (color-values "#ffffff"))))) | ||||
|     (mapcar (lambda (c) | ||||
|               (let* ((name (car c)) | ||||
|                      (rgb (mapcar (lambda (v) | ||||
|                                     (/ v valmax)) | ||||
|                                   (cdr c))) | ||||
|                      (lab (apply #'color-srgb-to-lab rgb))) | ||||
|                 (list name rgb lab))) | ||||
|             alist))) | ||||
|  | ||||
| (defun circe-color-canonicalize-format (color) | ||||
|   "Turns COLOR into (name rgb lab) format.  Avoid calling this in | ||||
| a loop, it's very slow on a tty!" | ||||
|   (let* ((name color) | ||||
|          (rgb (circe-color-name-to-rgb color)) | ||||
|          (lab (apply #'color-srgb-to-lab rgb))) | ||||
|    (list name rgb lab))) | ||||
|  | ||||
| (defun circe-color-contrast-ratio (color1 color2) | ||||
|   "Gives the contrast ratio between two colors." | ||||
|   (circe-w3-contrast-contrast-ratio (nth 1 color1) (nth 1 color2))) | ||||
|  | ||||
| (defun circe-color-diff (color1 color2) | ||||
|   "Gives the difference between two colors per CIEDE2000." | ||||
|   (color-cie-de2000 (nth 2 color1) (nth 2 color2))) | ||||
|  | ||||
| (defun circe-color-name-to-rgb (color) | ||||
|   "Like `color-name-to-rgb' but also handles \"unspecified-bg\" | ||||
| and \"unspecified-fg\"." | ||||
|   (cond ((equal color "unspecified-bg") '(0 0 0)) | ||||
|         ((equal color "unspecified-fg") '(1 1 1)) | ||||
|         (t (color-name-to-rgb color)))) | ||||
|  | ||||
|  | ||||
| (defun circe-nick-color-appropriate-p (color bg fg my-msg) | ||||
|   "Tells whether COLOR is appropriate for being a nick color. | ||||
| BG, FG, and MY-MSG are the background, foreground, and my-message | ||||
| colors; these are expected as parameters instead of computed here | ||||
| because computing them repeatedly is a heavy operation." | ||||
|   (and (>= (circe-color-contrast-ratio color bg) | ||||
|            circe-color-nicks-min-contrast-ratio) | ||||
|        (>= (circe-color-diff color fg) | ||||
|            circe-color-nicks-min-fg-difference) | ||||
|        (>= (circe-color-diff color my-msg) | ||||
|            circe-color-nicks-min-my-message-difference))) | ||||
|  | ||||
| (defun circe-nick-colors-delete-similar (colors) | ||||
|   "Return list COLORS with pairs of colors filtered out that are | ||||
| too similar per `circe-color-nicks-min-difference'.  COLORS may | ||||
| be mutated." | ||||
|   (cl-mapl (lambda (rest) | ||||
|              (let ((color (car rest))) | ||||
|                (setcdr rest (cl-delete-if | ||||
|                              (lambda (c) | ||||
|                                (< (circe-color-diff color c) | ||||
|                                   circe-color-nicks-min-difference)) | ||||
|                              (cdr rest))))) | ||||
|            colors) | ||||
|   colors) | ||||
|  | ||||
| (defun circe-nick-color-generate-pool () | ||||
|   "Return a list of appropriate nick colors." | ||||
|   (if (consp circe-color-nicks-pool-type) | ||||
|       circe-color-nicks-pool-type | ||||
|     (let ((bg (circe-color-canonicalize-format (face-background 'default))) | ||||
|           (fg (circe-color-canonicalize-format (face-foreground 'default))) | ||||
|           (my-msg (circe-color-canonicalize-format | ||||
|                    (face-attribute | ||||
|                     'circe-my-message-face :foreground nil 'default)))) | ||||
|       (mapcar #'car (circe-nick-colors-delete-similar | ||||
|                      (cl-remove-if-not | ||||
|                       (lambda (c) | ||||
|                         (circe-nick-color-appropriate-p c bg fg my-msg)) | ||||
|                       (circe-color-alist))))))) | ||||
|  | ||||
| (defun circe-nick-color-pool-test () | ||||
|   "Display all appropriate nick colors in a temp buffer." | ||||
|   (interactive) | ||||
|   (switch-to-buffer (get-buffer-create "*Circe color test*")) | ||||
|   (erase-buffer) | ||||
|   (let ((pool (circe-nick-color-generate-pool))) | ||||
|     (while pool | ||||
|       (let ((pt (point))) | ||||
|         (insert "The quick brown fox jumped over the lazy dog.\n") | ||||
|         (put-text-property pt (point) 'face `(:foreground ,(pop pool))))))) | ||||
|  | ||||
| (defvar circe-nick-color-pool nil | ||||
|   "Pool of yet unused nick colors.") | ||||
|  | ||||
| (defvar circe-nick-color-mapping (make-hash-table :test 'equal) | ||||
|   "Hash-table from nicks to colors.") | ||||
|  | ||||
| (defun circe-nick-color-nick-list () | ||||
|   "Return list of all nicks that have a color assigned to them. | ||||
| Own and blacklisted nicks are excluded." | ||||
|   (let ((our-nick (circe-nick)) | ||||
|         (channel-nicks (circe-channel-nicks)) | ||||
|         nicks) | ||||
|     (maphash | ||||
|      (lambda (nick color) | ||||
|        (when (and (member nick channel-nicks) | ||||
|                   (not (string= our-nick nick)) | ||||
|                   (not (member nick circe-color-nicks-message-blacklist))) | ||||
|          (push nick nicks))) | ||||
|      circe-nick-color-mapping) | ||||
|     nicks)) | ||||
|  | ||||
| (defvar circe-nick-color-timestamps (make-hash-table :test 'equal) | ||||
|   "Hash-table from colors to the timestamp of their last use.") | ||||
|  | ||||
| (defun circe-nick-color-for-nick (nick) | ||||
|   "Return the color for NICK.  Assigns a color to NICK if one | ||||
| wasn't assigned already." | ||||
|   (let ((color (gethash nick circe-nick-color-mapping))) | ||||
|     (when (not color) | ||||
|       ;; NOTE use this as entry point for taking NICK into account for | ||||
|       ;; picking the new color | ||||
|       (setq color (circe-nick-color-pick)) | ||||
|       (puthash nick color circe-nick-color-mapping)) | ||||
|     (puthash color (float-time) circe-nick-color-timestamps) | ||||
|     color)) | ||||
|  | ||||
| (defun circe-nick-color-pick () | ||||
|   "Picks either a color from the pool of unused colors, or the | ||||
| color that was used least recently (i.e. nicks that have it | ||||
| assigned have been least recently active)." | ||||
|   (if (zerop (hash-table-count circe-nick-color-mapping)) | ||||
|       (setq circe-nick-color-pool (circe-nick-color-generate-pool))) | ||||
|   (or (pop circe-nick-color-pool) | ||||
|       (circe-nick-color-pick-least-recent))) | ||||
|  | ||||
| (defun circe-nick-color-pick-least-recent () | ||||
|   "Pick the color that was used least recently. | ||||
| See `circe-nick-color-pick', which is where this is used." | ||||
|   (let ((least-recent-color nil) | ||||
|         (oldest-time (float-time))) | ||||
|     (maphash | ||||
|      (lambda (color time) | ||||
|        (if (< time oldest-time) | ||||
|            (progn | ||||
|              (setq least-recent-color color) | ||||
|              (setq oldest-time time)))) | ||||
|      circe-nick-color-timestamps) | ||||
|     (if least-recent-color | ||||
|         least-recent-color | ||||
|       ;; Someone must have messed with `circe-nick-color-mapping', recover by | ||||
|       ;; re-filling the pool. | ||||
|       (setq circe-nick-color-pool (circe-nick-color-generate-pool)) | ||||
|       (pop circe-nick-color-pool)))) | ||||
|  | ||||
| (defun circe-color-nicks () | ||||
|   "Color nicks on this lui output line." | ||||
|   (when (eq major-mode 'circe-channel-mode) | ||||
|     (let ((nickstart (text-property-any (point-min) (point-max) | ||||
|                                         'lui-format-argument 'nick))) | ||||
|       (when nickstart | ||||
|         (goto-char nickstart) | ||||
|         (let ((nickend (next-single-property-change nickstart | ||||
|                                                     'lui-format-argument)) | ||||
|               (nick (plist-get (plist-get (text-properties-at nickstart) | ||||
|                                           'lui-keywords) | ||||
|                                :nick))) | ||||
|           (when (not (circe-server-my-nick-p nick)) | ||||
|             (let ((color (circe-nick-color-for-nick nick))) | ||||
|               (add-face-text-property nickstart nickend | ||||
|                                       `(:foreground ,color))))))) | ||||
|     (when circe-color-nicks-everywhere | ||||
|       (let ((body (text-property-any (point-min) (point-max) | ||||
|                                      'lui-format-argument 'body))) | ||||
|         (when body | ||||
|           (with-syntax-table circe-nick-syntax-table | ||||
|             (goto-char body) | ||||
|             (let* ((nicks (circe-nick-color-nick-list)) | ||||
|                    (regex (regexp-opt nicks 'words))) | ||||
|               (let (case-fold-search) | ||||
|                 (while (re-search-forward regex nil t) | ||||
|                   (let* ((nick (match-string-no-properties 0)) | ||||
|                          (color (circe-nick-color-for-nick nick))) | ||||
|                     (add-face-text-property (match-beginning 0) (match-end 0) | ||||
|                                             `(:foreground ,color)))))))))))) | ||||
|  | ||||
| (defun circe-nick-color-reset () | ||||
|   "Reset the nick color mapping (and some internal data). | ||||
|  | ||||
| This is useful if you switched between frames supporting | ||||
| different color ranges and would like nicks to get new colors | ||||
| appropriate to the new color range." | ||||
|   (interactive) | ||||
|   (setq circe-nick-color-pool (circe-nick-color-generate-pool)) | ||||
|   (setq circe-nick-color-mapping (make-hash-table :test 'equal)) | ||||
|   (setq circe-nick-color-timestamps (make-hash-table :test 'equal))) | ||||
|  | ||||
| (provide 'circe-color-nicks) | ||||
| ;;; circe-color-nicks.el ends here | ||||
							
								
								
									
										53
									
								
								elpa/circe-20160608.1315/circe-compat.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								elpa/circe-20160608.1315/circe-compat.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,53 @@ | ||||
| ;;; circe-compat.el --- Compatibility definitions | ||||
|  | ||||
| ;; Copyright (C) 2015  Jorgen Schaefer <contact@jorgenschaefer.de> | ||||
|  | ||||
| ;; Author: Jorgen Schaefer <contact@jorgenschaefer.de> | ||||
|  | ||||
| ;; This program is free software; you can redistribute it and/or | ||||
| ;; modify it under the terms of the GNU General Public License | ||||
| ;; as published by the Free Software Foundation; either version 3 | ||||
| ;; of the License, or (at your option) any later version. | ||||
|  | ||||
| ;; This program is distributed in the hope that it will be useful, | ||||
| ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| ;; GNU General Public License for more details. | ||||
|  | ||||
| ;; You should have received a copy of the GNU General Public License | ||||
| ;; along with this program. If not, see <http://www.gnu.org/licenses/>. | ||||
|  | ||||
| ;;; Commentary: | ||||
|  | ||||
| ;; Define functions and variables as needed by Circe to remain | ||||
| ;; compatible with older Emacsen. | ||||
|  | ||||
| ;;; Code: | ||||
|  | ||||
| (when (not (fboundp 'string-trim)) | ||||
|   (defun string-trim (string) | ||||
|     "Remove leading and trailing whitespace from STRING." | ||||
|     (if (string-match "\\` *\\(.*[^[:space:]]\\) *\\'" string) | ||||
|         (match-string 1 string) | ||||
|       string))) | ||||
|  | ||||
| (when (not (fboundp 'add-face-text-property)) | ||||
|   (defun add-face-text-property (start end face &optional append object) | ||||
|     (while (/= start end) | ||||
|       (let* ((next (next-single-property-change start 'face object end)) | ||||
|              (prev (get-text-property start 'face object)) | ||||
|              (value (if (listp prev) prev (list prev)))) | ||||
|         (put-text-property start next 'face | ||||
|                            (if append | ||||
|                                (append value (list face)) | ||||
|                              (append (list face) value)) | ||||
|                            object) | ||||
|         (setq start next))))) | ||||
|  | ||||
| (when (not (boundp 'mode-line-misc-info)) | ||||
|   (defvar mode-line-misc-info nil | ||||
|     "Misc info in the mode line.") | ||||
|   (add-to-list 'mode-line-format 'mode-line-misc-info t)) | ||||
|  | ||||
| (provide 'circe-compat) | ||||
| ;;; circe-compat.el ends here | ||||
							
								
								
									
										100
									
								
								elpa/circe-20160608.1315/circe-highlight-all-nicks.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								elpa/circe-20160608.1315/circe-highlight-all-nicks.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,100 @@ | ||||
| ;;; circe-highlight-all-nicks.el --- Highlight all nicks in the current channel | ||||
|  | ||||
| ;; Copyright (C) 2005  Jorgen Schaefer | ||||
|  | ||||
| ;; Author: Jorgen Schaefer <forcer@forcix.cx> | ||||
|  | ||||
| ;; This file is part of Circe. | ||||
|  | ||||
| ;; This program is free software; you can redistribute it and/or | ||||
| ;; modify it under the terms of the GNU General Public License | ||||
| ;; as published by the Free Software Foundation; either version 3 | ||||
| ;; of the License, or (at your option) any later version. | ||||
|  | ||||
| ;; This program is distributed in the hope that it will be useful, | ||||
| ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| ;; GNU General Public License for more details. | ||||
|  | ||||
| ;; You should have received a copy of the GNU General Public License | ||||
| ;; along with this program; if not, write to the Free Software | ||||
| ;; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||||
| ;; 02110-1301  USA | ||||
|  | ||||
| ;;; Commentary: | ||||
|  | ||||
| ;; This Circe module adds the ability to highlight every occurance of | ||||
| ;; a nick in the current channel in a message by other people. | ||||
|  | ||||
| ;; To use it, put the following into your .emacs: | ||||
|  | ||||
| ;; (require 'circe-highlight-all-nicks) | ||||
| ;; (enable-circe-highlight-all-nicks) | ||||
|  | ||||
| ;;; Code: | ||||
|  | ||||
| (require 'circe) | ||||
|  | ||||
| (defface circe-highlight-all-nicks-face | ||||
|   '((t (:foreground "green"))) | ||||
|   "The face used for nicks from the current channel. | ||||
| See `enable-circe-highlight-all-nicks'." | ||||
|   :group 'circe) | ||||
|  | ||||
| ;;;###autoload | ||||
| (defun enable-circe-highlight-all-nicks () | ||||
|   "Enable the Highlight Nicks module for Circe. | ||||
| This module highlights all occurances of nicks in the current | ||||
| channel in messages of other people." | ||||
|   (interactive) | ||||
|   (dolist (buf (buffer-list)) | ||||
|     (with-current-buffer buf | ||||
|       (when (eq major-mode 'circe-channel-mode) | ||||
|         (add-circe-highlight-all-nicks)))) | ||||
|   (add-hook 'circe-channel-mode-hook | ||||
|             'add-circe-highlight-all-nicks)) | ||||
|  | ||||
| (defun disable-circe-highlight-all-nicks () | ||||
|   "Disable the Highlight Nicks module for Circe. | ||||
| See `enable-circe-highlight-all-nicks'." | ||||
|   (interactive) | ||||
|   (dolist (buf (buffer-list)) | ||||
|     (with-current-buffer buf | ||||
|       (when (eq major-mode 'circe-channel-mode) | ||||
|         (remove-circe-highlight-all-nicks)))) | ||||
|   (remove-hook 'circe-channel-mode-hook | ||||
|                'add-circe-highlight-all-nicks)) | ||||
|  | ||||
| (defun add-circe-highlight-all-nicks () | ||||
|   "Add `circe-highlight-all-nicks' to `lui-pre-output-hook'." | ||||
|   (add-hook 'lui-pre-output-hook 'circe-highlight-all-nicks | ||||
|             nil t)) | ||||
|  | ||||
| (defun remove-circe-highlight-all-nicks () | ||||
|   "Remove `circe-highlight-all-nicks' from `lui-pre-output-hook'." | ||||
|   (remove-hook 'lui-pre-output-hook 'circe-highlight-all-nicks | ||||
|                t)) | ||||
|  | ||||
| (defun circe-highlight-all-nicks () | ||||
|   "Highlight all occurances of nicks of the current channel in the message." | ||||
|   (when (eq major-mode 'circe-channel-mode) | ||||
|     (let ((body (text-property-any (point-min) (point-max) | ||||
|                                    'lui-format-argument 'body)) | ||||
|           (nicks '()) | ||||
|           (regex nil)) | ||||
|       (when body | ||||
|         (let ((channel-nicks (circe-channel-nicks))) | ||||
|           (when channel-nicks | ||||
|             (mapc (lambda (nick) | ||||
|                     (when (not (circe-server-my-nick-p nick)) | ||||
|                       (setq nicks (cons nick nicks)))) | ||||
|                   channel-nicks))) | ||||
|         (setq regex (regexp-opt nicks 'words)) | ||||
|         (goto-char body) | ||||
|         (while (re-search-forward regex nil t) | ||||
|           (add-text-properties (match-beginning 0) | ||||
|                                (match-end 0) | ||||
|                                '(face circe-highlight-all-nicks-face))))))) | ||||
|  | ||||
| (provide 'circe-highlight-all-nicks) | ||||
| ;;; circe-highlight-all-nicks.el ends here | ||||
							
								
								
									
										243
									
								
								elpa/circe-20160608.1315/circe-lagmon.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										243
									
								
								elpa/circe-20160608.1315/circe-lagmon.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,243 @@ | ||||
| ;;; circe-lagmon.el --- Lag Monitor for Circe | ||||
|  | ||||
| ;; Copyright (C) 2011-2012 Jorgen Schaefer | ||||
|  | ||||
| ;; Author: John J Foerch <jjfoerch@earthlink.net>, | ||||
| ;;         Jorgen Schaefer | ||||
|  | ||||
| ;; This file is part of Circe. | ||||
|  | ||||
| ;; This program is free software; you can redistribute it and/or | ||||
| ;; modify it under the terms of the GNU General Public License | ||||
| ;; as published by the Free Software Foundation; either version 3 | ||||
| ;; of the License, or (at your option) any later version. | ||||
|  | ||||
| ;; This program is distributed in the hope that it will be useful, | ||||
| ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| ;; GNU General Public License for more details. | ||||
|  | ||||
| ;; You should have received a copy of the GNU General Public License | ||||
| ;; along with this program; if not, write to the Free Software | ||||
| ;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||||
| ;; 02110-1301, USA. | ||||
|  | ||||
| ;;; Commentary: | ||||
| ;;; | ||||
| ;;;   Circe-lagmon-mode monitors the amount of lag on your connection to | ||||
| ;;; each server, and displays the lag time in seconds in the mode-line. | ||||
| ;;; It works by managing two timers.  Timer1 sends CTCP LAGMON to yourself | ||||
| ;;; on each server every 60 seconds.  Each time around, timer1 starts | ||||
| ;;; timer2 to monitor for timeouts of these messages.  Timer2 cancels | ||||
| ;;; itself when all of the pings in the round have been answered. | ||||
| ;;; | ||||
|  | ||||
| ;;; Code: | ||||
|  | ||||
| (require 'circe) | ||||
|  | ||||
| ;;; User variables | ||||
|  | ||||
| (defgroup circe-lagmon nil | ||||
|   "Lag Monitor for Circe" | ||||
|   :prefix "circe-lagmon-" | ||||
|   :group 'circe) | ||||
|  | ||||
| (defcustom circe-lagmon-timer-tick 5 | ||||
|   "How often to check for lag. | ||||
|  | ||||
| Increase this to improve performance at the cost of accuracy." | ||||
|   :type 'number | ||||
|   :group 'circe-lagmon) | ||||
|  | ||||
| (defcustom circe-lagmon-check-interval 60 | ||||
|   "Interval in seconds at which to send the CTCP message." | ||||
|   :type 'number | ||||
|   :group 'circe-lagmon) | ||||
|  | ||||
| (defcustom circe-lagmon-reconnect-interval 120 | ||||
|   "Seconds after which to automatically reconnect upon a timeout | ||||
| of a lag monitor message. A value of nil disables the feature." | ||||
|   :type '(choice (const :tag "Disable auto-reconnect" nil) | ||||
|                  number) | ||||
|   :group 'circe-lagmon) | ||||
|  | ||||
| (defcustom circe-lagmon-mode-line-format-string "lag:%.1f " | ||||
|   "Format string for displaying the lag in the mode-line." | ||||
|   :type 'string | ||||
|   :group 'circe-lagmon) | ||||
|  | ||||
| (defcustom circe-lagmon-mode-line-unknown-lag-string "lag:? " | ||||
|   "Indicator string for displaying unknown lag in the mode-line." | ||||
|   :type 'string | ||||
|   :group 'circe-lagmon) | ||||
|  | ||||
| (defvar circe-lagmon-disabled nil | ||||
|   "A boolean value if lagmon should be disabled on this network. | ||||
|  | ||||
| Don't set this by hand, use `circe-network-options'.") | ||||
| (make-variable-buffer-local 'circe-lagmon-disabled) | ||||
|  | ||||
|  | ||||
| ;;; Internal variables | ||||
| ;;; | ||||
| (defvar circe-lagmon-timer nil) | ||||
|  | ||||
| (defvar circe-lagmon-server-lag nil) | ||||
| (make-variable-buffer-local 'circe-lagmon-server-lag) | ||||
|  | ||||
| (defvar circe-lagmon-last-send-time nil) | ||||
| (make-variable-buffer-local 'circe-lagmon-last-send-time) | ||||
|  | ||||
| (defvar circe-lagmon-last-receive-time nil) | ||||
| (make-variable-buffer-local 'circe-lagmon-last-receive-time) | ||||
|  | ||||
| (defun circe-lagmon-timer-tick () | ||||
|   "Function run periodically to check lag. | ||||
|  | ||||
| This will call `circe-lagmon-server-check' in every active server | ||||
| buffer. You can call it yourself if you like to force an update, | ||||
| there is no harm in running it too often, but it really should be | ||||
| run sufficiently often with the timer." | ||||
|   (dolist (buffer (circe-server-buffers)) | ||||
|     (with-current-buffer buffer | ||||
|       (when (and (eq major-mode 'circe-server-mode) | ||||
|                  circe-server-process | ||||
|                  (eq (irc-connection-state circe-server-process) | ||||
|                      'registered) | ||||
|                  (not circe-lagmon-disabled)) | ||||
|         (circe-lagmon-server-check))))) | ||||
|  | ||||
| (defun circe-lagmon-server-check () | ||||
|   "Check the current server for lag. | ||||
|  | ||||
| This will reconnect if we haven't heard back for too long, or | ||||
| send a request if it's time for that. See | ||||
| `circe-lagmon-reconnect-interval' and | ||||
| `circe-lagmon-check-interval' to configure the behavior.." | ||||
|   (let ((now (float-time))) | ||||
|     (cond | ||||
|      ;; No answer so far... | ||||
|      ((and circe-lagmon-last-send-time | ||||
|            (not circe-lagmon-last-receive-time)) | ||||
|       ;; Count up until the answer comes. | ||||
|       (let ((lag (/ (- now circe-lagmon-last-send-time) 2))) | ||||
|         (when (or (not circe-lagmon-server-lag) | ||||
|                   (> lag circe-lagmon-server-lag)) | ||||
|           (setq circe-lagmon-server-lag lag) | ||||
|           (circe-lagmon-force-mode-line-update))) | ||||
|       ;; Check for timeout. | ||||
|       (when (and circe-lagmon-reconnect-interval | ||||
|                  (> now | ||||
|                     (+ circe-lagmon-last-send-time | ||||
|                        circe-lagmon-reconnect-interval))) | ||||
|         (setq circe-lagmon-last-send-time nil | ||||
|               circe-lagmon-last-receive-time nil) | ||||
|         (circe-reconnect))) | ||||
|      ;; Nothing sent so far, or last send was too long ago. | ||||
|      ((or (not circe-lagmon-last-send-time) | ||||
|           (> now | ||||
|              (+ circe-lagmon-last-send-time | ||||
|                 circe-lagmon-check-interval))) | ||||
|       (irc-send-raw (circe-server-process) | ||||
|                     (format "PRIVMSG %s :\C-aLAGMON %s\C-a" | ||||
|                             (circe-nick) now) | ||||
|                     :nowait) | ||||
|       (setq circe-lagmon-last-send-time now | ||||
|             circe-lagmon-last-receive-time nil)) | ||||
|      ))) | ||||
|  | ||||
| (defun circe-lagmon-force-mode-line-update () | ||||
|   "Call force-mode-line-update on a circe server buffer and all | ||||
| of its chat buffers." | ||||
|   (force-mode-line-update) | ||||
|   (dolist (b (circe-server-chat-buffers)) | ||||
|     (with-current-buffer b | ||||
|       (force-mode-line-update)))) | ||||
|  | ||||
| (defun circe-lagmon-format-mode-line-entry () | ||||
|   "Format the mode-line entry for displaying the lag." | ||||
|   (let ((buf (cond | ||||
|               ((eq major-mode 'circe-server-mode) | ||||
|                (current-buffer)) | ||||
|               (circe-server-buffer | ||||
|                circe-server-buffer) | ||||
|               (t | ||||
|                nil)))) | ||||
|     (when buf | ||||
|       (with-current-buffer buf | ||||
|         (cond | ||||
|          (circe-lagmon-disabled | ||||
|           nil) | ||||
|          (circe-lagmon-server-lag | ||||
|           (format circe-lagmon-mode-line-format-string | ||||
|                   circe-lagmon-server-lag)) | ||||
|          (t | ||||
|           circe-lagmon-mode-line-unknown-lag-string)))))) | ||||
|  | ||||
| (defun circe-lagmon-init () | ||||
|   "Initialize the values of the lag monitor for one server, and | ||||
| start the lag monitor if it has not been started." | ||||
|   (setq circe-lagmon-server-lag nil | ||||
|         circe-lagmon-last-send-time nil | ||||
|         circe-lagmon-last-receive-time nil) | ||||
|   (circe-lagmon-force-mode-line-update) | ||||
|   (unless circe-lagmon-timer | ||||
|     (setq circe-lagmon-timer | ||||
|           (run-at-time nil circe-lagmon-timer-tick | ||||
|                        'circe-lagmon-timer-tick)))) | ||||
|  | ||||
| (defun circe-lagmon--rpl-welcome-handler (conn &rest ignored) | ||||
|   (with-current-buffer (irc-connection-get conn :server-buffer) | ||||
|     (circe-lagmon-init))) | ||||
|  | ||||
| (defun circe-lagmon--ctcp-lagmon-handler (conn event sender target argument) | ||||
|   (when (irc-current-nick-p conn (irc-userstring-nick sender)) | ||||
|     (with-current-buffer (irc-connection-get conn :server-buffer) | ||||
|       (let* ((now (float-time)) | ||||
|              (lag (/ (- now (string-to-number argument)) | ||||
|                      2))) | ||||
|         (setq circe-lagmon-server-lag lag | ||||
|               circe-lagmon-last-receive-time now) | ||||
|         (circe-lagmon-force-mode-line-update))))) | ||||
|  | ||||
| (defun circe-lagmon--nick-handler (conn event sender new-nick) | ||||
|   (when (irc-current-nick-p conn (irc-userstring-nick sender)) | ||||
|     (with-current-buffer (irc-connection-get conn :server-buffer) | ||||
|       (setq circe-lagmon-last-send-time nil)))) | ||||
|  | ||||
| ;;;###autoload | ||||
| (define-minor-mode circe-lagmon-mode | ||||
|   "Circe-lagmon-mode monitors the amount of lag on your | ||||
| connection to each server, and displays the lag time in seconds | ||||
| in the mode-line." | ||||
|   :global t | ||||
|   (let ((mode-line-entry '(:eval (circe-lagmon-format-mode-line-entry)))) | ||||
|     (remove-hook 'mode-line-modes mode-line-entry) | ||||
|     (let ((table (circe-irc-handler-table))) | ||||
|       (irc-handler-remove table "001" 'circe-lagmon--rpl-welcome-handler) | ||||
|       (irc-handler-remove table "irc.ctcp.LAGMON" | ||||
|                           'circe-lagmon--ctcp-lagmon-handler) | ||||
|       (irc-handler-remove table "NICK" 'circe-lagmon--nick-handler)) | ||||
|     (circe-set-display-handler "irc.ctcp.LAGMON" nil) | ||||
|     (when circe-lagmon-timer | ||||
|       (cancel-timer circe-lagmon-timer) | ||||
|       (setq circe-lagmon-timer nil)) | ||||
|     (when circe-lagmon-mode | ||||
|       (add-hook 'mode-line-modes mode-line-entry) | ||||
|       (let ((table (circe-irc-handler-table))) | ||||
|         (irc-handler-add table "001" 'circe-lagmon--rpl-welcome-handler) | ||||
|         (irc-handler-add table "irc.ctcp.LAGMON" | ||||
|                          'circe-lagmon--ctcp-lagmon-handler) | ||||
|         (irc-handler-add table "NICK" 'circe-lagmon--nick-handler)) | ||||
|       (circe-set-display-handler "irc.ctcp.LAGMON" 'circe-display-ignore) | ||||
|       (dolist (buffer (circe-server-buffers)) | ||||
|         (with-current-buffer buffer | ||||
|           (setq circe-lagmon-server-lag nil) | ||||
|           (when (and circe-server-process | ||||
|                      (eq (irc-connection-state circe-server-process) | ||||
|                          'registered)) | ||||
|             (circe-lagmon-init))))))) | ||||
|  | ||||
| (provide 'circe-lagmon) | ||||
| ;;; circe-lagmon.el ends here | ||||
							
								
								
									
										86
									
								
								elpa/circe-20160608.1315/circe-new-day-notifier.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								elpa/circe-20160608.1315/circe-new-day-notifier.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,86 @@ | ||||
| ;;; circe-new-day-notifier.el --- Send a message every midnight to all | ||||
| ;;; channels | ||||
|  | ||||
| ;; Copyright (C) 2015 Pásztor János | ||||
|  | ||||
| ;; Author: Pásztor János <model87@freemail.hu> | ||||
|  | ||||
| ;; This file is part of Circe. | ||||
|  | ||||
| ;; 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 St, Fifth Floor, Boston, MA | ||||
| ;; 02110-1301 USA | ||||
|  | ||||
| ;;; Commentary: | ||||
|  | ||||
| ;; This Circe module adds the ability to send a notification to all | ||||
| ;; channels every midnight | ||||
|  | ||||
| ;; Some ideas/code copied from circe-lagmon.el and | ||||
| ;; circe-color-nicks.el | ||||
|  | ||||
| ;; To use it, put the following into your .emacs: | ||||
|  | ||||
| ;; (require 'circe-new-day-notifier) | ||||
| ;; (enable-circe-new-day-notifier) | ||||
|  | ||||
| ;;; Code: | ||||
|  | ||||
| (require 'circe) | ||||
|  | ||||
| (defgroup circe-new-day-notifier nil | ||||
|   "Midnight notification to Circe" | ||||
|   :prefix "circe-new-day-notifier-" | ||||
|   :group 'circe) | ||||
|  | ||||
| (defcustom circe-new-day-notifier-format-message "*** Day changed to {day}" | ||||
|   "The format string which will be printed to the channels. It | ||||
| should contain {day} to print the date. See `circe-display' for | ||||
| further documentation" | ||||
|   :type 'string | ||||
|   :group 'circe-new-day-notifier) | ||||
|  | ||||
| (defcustom circe-new-day-notifier-date-format "%Y-%m-%d, %A" | ||||
|   "The date format, which will be used at | ||||
| circe-new-day-notifier-format-message. See `format-time-string' for | ||||
| documentation" | ||||
|   :type 'string | ||||
|   :group 'circe-new-day-notifier) | ||||
|  | ||||
| (defvar circe-new-day-notifier-timer nil) | ||||
|  | ||||
| ;;;###autoload | ||||
| (defun enable-circe-new-day-notifier () | ||||
|   (interactive) | ||||
|     (unless circe-new-day-notifier-timer | ||||
|       (setq circe-new-day-notifier-timer | ||||
|             (run-at-time "24:00:00" (* 24 60 60) 'circe-new-day-notification)))) | ||||
|  | ||||
| ;;;###autoload | ||||
| (defun disable-circe-new-day-notifier () | ||||
|   (interactive) | ||||
|   (when circe-new-day-notifier-timer | ||||
|     (cancel-timer circe-new-day-notifier-timer) | ||||
|     (setq circe-new-day-notifier-timer nil))) | ||||
|  | ||||
| (defun circe-new-day-notification () | ||||
|   "This function prints the new day notification to each query and chat buffer" | ||||
|   (dolist (buf (buffer-list)) | ||||
|     (with-current-buffer buf | ||||
|       (when (derived-mode-p 'circe-chat-mode) | ||||
|         (circe-display 'circe-new-day-notifier-format-message | ||||
|                        :day (format-time-string circe-new-day-notifier-date-format)))))) | ||||
|  | ||||
| (provide 'circe-new-day-notifier) | ||||
| ;;; circe-new-day-notifier.el ends here | ||||
							
								
								
									
										6
									
								
								elpa/circe-20160608.1315/circe-pkg.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								elpa/circe-20160608.1315/circe-pkg.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| (define-package "circe" "20160608.1315" "Client for IRC in Emacs" | ||||
|   '((cl-lib "0.5")) | ||||
|   :url "https://github.com/jorgenschaefer/circe") | ||||
| ;; Local Variables: | ||||
| ;; no-byte-compile: t | ||||
| ;; End: | ||||
							
								
								
									
										3586
									
								
								elpa/circe-20160608.1315/circe.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3586
									
								
								elpa/circe-20160608.1315/circe.el
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1406
									
								
								elpa/circe-20160608.1315/irc.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1406
									
								
								elpa/circe-20160608.1315/irc.el
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										202
									
								
								elpa/circe-20160608.1315/lcs.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										202
									
								
								elpa/circe-20160608.1315/lcs.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,202 @@ | ||||
| ;;; lcs.el --- find out the longest common sequence | ||||
|  | ||||
| ;;   Copyright (c) 2002-2003 by Alex Shinn, All rights reserved. | ||||
| ;;   Copyright (c) 2002-2003 by Shiro Kawai, All rights reserved. | ||||
| ;;   Copyright (c) 2006, 2012 by Jorgen Schaefer, All rights reserved. | ||||
|  | ||||
| ;; Authors: Alex Shinn, Shiro Kawai | ||||
| ;; Maintainer: Jorgen Schaefer <forcer@forcix.cx> | ||||
| ;; URL: https://github.com/jorgenschaefer/circe/wiki/lcs | ||||
|  | ||||
| ;;   Redistribution and use in source and binary forms, with or without | ||||
| ;;   modification, are permitted provided that the following conditions | ||||
| ;;   are met: | ||||
|  | ||||
| ;;   1. Redistributions of source code must retain the above copyright | ||||
| ;;      notice, this list of conditions and the following disclaimer. | ||||
|  | ||||
| ;;   2. Redistributions in binary form must reproduce the above copyright | ||||
| ;;      notice, this list of conditions and the following disclaimer in the | ||||
| ;;      documentation and/or other materials provided with the distribution. | ||||
|  | ||||
| ;;   3. Neither the name of the authors nor the names of its contributors | ||||
| ;;      may be used to endorse or promote products derived from this | ||||
| ;;      software without specific prior written permission. | ||||
|  | ||||
| ;;   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||||
| ;;   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||||
| ;;   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||||
| ;;   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||||
| ;;   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||||
| ;;   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED | ||||
| ;;   TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||||
| ;;   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||||
| ;;   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||||
| ;;   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||
| ;;   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  | ||||
| ;;; Commentary: | ||||
|  | ||||
| ;; lcs.el is a library for other Emacs Lisp programs not useful by | ||||
| ;; itself. | ||||
|  | ||||
| ;; This library provides functions to find the Longest Common Sequence | ||||
| ;; (LCS) of two sequences. This is used to create a unified diff of to | ||||
| ;; two lists. See `lcs-unified-diff' for a useful function to be | ||||
| ;; called. | ||||
|  | ||||
| ;; The code is more or less a literal translation of (part of) | ||||
| ;; Gauche's util/lcs.scm module to Emacs Lisp. | ||||
|  | ||||
| ;;; Code: | ||||
|  | ||||
| (put 'lcs-for 'lisp-indent-function 4) | ||||
| (defmacro lcs-for (var from to step &rest body) | ||||
|   "A simple FOR loop macro. | ||||
| Count VAR from FROM to TO by stepsize STEP. Evaluate BODY in each | ||||
| iteration." | ||||
|   (let ((sto (make-symbol "to")) | ||||
|         (sstep (make-symbol "step"))) | ||||
|     `(let ((,var ,from) | ||||
|            (,sto ,to) | ||||
|            (,sstep ,step)) | ||||
|        (while (<= ,var ,sto) | ||||
|          (progn | ||||
|            ,@body) | ||||
|          (setq ,var (+ ,var ,sstep)))))) | ||||
|  | ||||
| (defun lcs-split-at (lis pos) | ||||
|   "Return a cons cell of the first POS elements of LIS and the rest." | ||||
|   (let ((head nil)) | ||||
|     (while (> pos 0) | ||||
|       (setq head (cons (car lis) | ||||
|                        head) | ||||
|             pos (- pos 1) | ||||
|             lis (cdr lis))) | ||||
|     (cons (reverse head) | ||||
|           lis))) | ||||
|  | ||||
| (defun lcs-finish (M+N V_l vl V_r vr) | ||||
|   "Finalize the LCS algorithm. | ||||
| Should be used only by `lcs-with-positions'." | ||||
|   (let ((maxl 0) | ||||
|         (r '())) | ||||
|     (lcs-for i (- M+N) M+N 1 | ||||
|       (when (> (funcall vl i) | ||||
|                maxl) | ||||
|         (setq maxl (funcall vl i) | ||||
|               r (funcall vr i)))) | ||||
|     (list maxl (reverse r)))) | ||||
|  | ||||
| (defun lcs-with-positions (a-ls b-ls &optional equalp) | ||||
|   "Return the longest common subsequence (LCS) of A-LS and B-LS. | ||||
| EQUALP can be any procedure which returns non-nil when two | ||||
| elements should be considered equal." | ||||
|   (let* ((A (vconcat a-ls)) | ||||
|          (B (vconcat b-ls)) | ||||
|          (N (length A)) | ||||
|          (M (length B)) | ||||
|          (M+N (+ M N)) | ||||
|          (V_d (make-vector (+ 1 (* 2 M+N)) | ||||
|                            0)) | ||||
|          (V_r (make-vector (+ 1 (* 2 M+N)) | ||||
|                            nil)) | ||||
|          (V_l (make-vector (+ 1 (* 2 M+N)) | ||||
|                            0)) | ||||
|          (vd (lambda (i &optional x) | ||||
|                (if x | ||||
|                    (aset V_d (+ i M+N) x) | ||||
|                  (aref V_d (+ i M+N))))) | ||||
|          (vr (lambda (i &optional x) | ||||
|                (if x | ||||
|                    (aset V_r (+ i M+N) x) | ||||
|                  (aref V_r (+ i M+N))))) | ||||
|          (vl (lambda (i &optional x) | ||||
|                (if x | ||||
|                    (aset V_l (+ i M+N) x) | ||||
|                  (aref V_l (+ i M+N)))))) | ||||
|     (when (not equalp) | ||||
|       (setq equalp 'equal)) | ||||
|     (catch 'return | ||||
|       (if (= M+N 0) | ||||
|           (throw 'return '(0 ())) | ||||
|         (lcs-for d 0 M+N 1 | ||||
|           (lcs-for k (- d) d 2 | ||||
|             (let ((x nil) | ||||
|                   (y nil) | ||||
|                   (l nil) | ||||
|                   (r nil)) | ||||
|               (if (or (= k (- d)) | ||||
|                       (and (not (= k d)) | ||||
|                            (< (funcall vd (- k 1)) | ||||
|                               (funcall vd (+ k 1))))) | ||||
|                   (setq x (funcall vd (+ k 1)) | ||||
|                         l (funcall vl (+ k 1)) | ||||
|                         r (funcall vr (+ k 1))) | ||||
|                 (setq x (+ 1 (funcall vd (- k 1))) | ||||
|                       l (funcall vl (- k 1)) | ||||
|                       r (funcall vr (- k 1)))) | ||||
|               (setq y (- x k)) | ||||
|               (while (and (< x N) | ||||
|                           (< y M) | ||||
|                           (funcall equalp (aref A x) (aref B y))) | ||||
|                 (setq r (cons (list (aref A x) x y) | ||||
|                               r) | ||||
|                       x (+ x 1) | ||||
|                       y (+ y 1) | ||||
|                       l (+ l 1))) | ||||
|               (funcall vd k x) | ||||
|               (funcall vr k r) | ||||
|               (funcall vl k l) | ||||
|               (when (and (>= x N) | ||||
|                          (>= y M)) | ||||
|                 (throw 'return(lcs-finish M+N V_l vl V_r vr))))))) | ||||
|       (error "Can't happen")))) | ||||
|  | ||||
| (defun lcs-unified-diff (a b &optional equalp) | ||||
|   "Return a unified diff of the lists A and B. | ||||
| EQUALP should can be a procedure that returns non-nil when two | ||||
| elements of A and B should be considered equal. It's `equal' by | ||||
| default." | ||||
|   (let ((common (cadr (lcs-with-positions a b equalp))) | ||||
|         (a a) | ||||
|         (a-pos 0) | ||||
|         (b b) | ||||
|         (b-pos 0) | ||||
|         (diff '())) | ||||
|     (while common | ||||
|       (let* ((elt (car common)) | ||||
|              (a-off (nth 1 elt)) | ||||
|              (a-skip (- a-off a-pos)) | ||||
|              (b-off (nth 2 elt)) | ||||
|              (b-skip (- b-off b-pos)) | ||||
|              (a-split (lcs-split-at a a-skip)) | ||||
|              (a-head (car a-split)) | ||||
|              (a-tail (cdr a-split)) | ||||
|              (b-split (lcs-split-at b b-skip)) | ||||
|              (b-head (car b-split)) | ||||
|              (b-tail (cdr b-split))) | ||||
|         (setq diff (append diff | ||||
|                            (mapcar (lambda (a) | ||||
|                                      `(- ,a)) | ||||
|                                    a-head) | ||||
|                            (mapcar (lambda (b) | ||||
|                                      `(+ ,b)) | ||||
|                                    b-head) | ||||
|                            `((! ,(car elt)))) | ||||
|  | ||||
|               common (cdr common) | ||||
|               a (cdr a-tail) | ||||
|               a-pos (+ a-off 1) | ||||
|               b (cdr b-tail) | ||||
|               b-pos (+ b-off 1)))) | ||||
|     (append diff | ||||
|             (mapcar (lambda (a) | ||||
|                       `(- ,a)) | ||||
|                     a) | ||||
|             (mapcar (lambda (b) | ||||
|                       `(+ ,b)) | ||||
|                     b)))) | ||||
|  | ||||
| (provide 'lcs) | ||||
| ;;; lcs.el ends here | ||||
							
								
								
									
										115
									
								
								elpa/circe-20160608.1315/lui-autopaste.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								elpa/circe-20160608.1315/lui-autopaste.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,115 @@ | ||||
| ;;; lui-autopaste.el --- Extension for lui for long text input | ||||
|  | ||||
| ;; Copyright (C) 2012  Jorgen Schaefer <forcer@forcix.cx> | ||||
|  | ||||
| ;; Author: Jorgen Schaefer <forcer@forcix.cx> | ||||
|  | ||||
| ;; This file is part of Lui. | ||||
|  | ||||
| ;; This program is free software; you can redistribute it and/or | ||||
| ;; modify it under the terms of the GNU General Public License | ||||
| ;; as published by the Free Software Foundation; either version 3 | ||||
| ;; of the License, or (at your option) any later version. | ||||
|  | ||||
| ;; This program is distributed in the hope that it will be useful, | ||||
| ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| ;; GNU General Public License for more details. | ||||
|  | ||||
| ;; You should have received a copy of the GNU General Public License | ||||
| ;; along with this program. If not, see <http://www.gnu.org/licenses/>. | ||||
|  | ||||
| ;;; Commentary: | ||||
|  | ||||
| ;; This extension for lui will intercept long input and replace it by | ||||
| ;; an URL to a paste service. | ||||
|  | ||||
| ;; What is considered "long" is defined by `lui-autopaste-lines'. You | ||||
| ;; can configure which paste service to use by changing | ||||
| ;; `lui-autopaste-function'. | ||||
|  | ||||
| ;; Run `enable-lui-autopaste' to enable this. | ||||
|  | ||||
| ;;; Code: | ||||
|  | ||||
| (defgroup lui-autopaste nil | ||||
|   "The Lui autopaste extension." | ||||
|   :prefix "lui-autopaste-" | ||||
|   :group 'lui) | ||||
|  | ||||
| (defcustom lui-autopaste-lines 3 | ||||
|   "Starting at this number of lines, Lui will ask to paste the input." | ||||
|   :type 'integer | ||||
|   :group 'lui-autopaste) | ||||
|  | ||||
| (defcustom lui-autopaste-function 'lui-autopaste-service-ixio | ||||
|   "Which paste service to use. | ||||
|  | ||||
| This function will be called with some text as its only argument, | ||||
| and is expected to return an URL to view the contents." | ||||
|   :type '(choice (const :tag "ix.io" lui-autopaste-service-ixio) | ||||
|                  (const :tag "ptpb.pw" lui-autopaste-service-ptpb-pw)) | ||||
|   :group 'lui-autopaste) | ||||
|  | ||||
| ;;;###autoload | ||||
| (defun enable-lui-autopaste () | ||||
|   "Enable the lui autopaste feature. | ||||
|  | ||||
| If you enter more than `lui-autopaste-lines' at once, Lui will | ||||
| ask if you would prefer to use a paste service instead. If you | ||||
| agree, Lui will paste your input to `lui-autopaste-function' and | ||||
| replace it with the resulting URL." | ||||
|   (interactive) | ||||
|   (add-hook 'lui-pre-input-hook 'lui-autopaste)) | ||||
|  | ||||
| ;;;###autoload | ||||
| (defun disable-lui-autopaste () | ||||
|   "Disable the lui autopaste feature." | ||||
|   (interactive) | ||||
|   (remove-hook 'lui-pre-input-hook 'lui-autopaste)) | ||||
|  | ||||
| (defun lui-autopaste () | ||||
|   "Check if the lui input is too large. If so, paste it instead." | ||||
|   (when (and (>= (count-lines (point-min) (point-max)) | ||||
|                  lui-autopaste-lines) | ||||
|              (y-or-n-p "That's pretty long, would you like to use a paste service instead? ")) | ||||
|     (let ((url (funcall lui-autopaste-function | ||||
|                         (buffer-substring (point-min) | ||||
|                                           (point-max))))) | ||||
|       (delete-region (point-min) (point-max)) | ||||
|       (insert url)))) | ||||
|  | ||||
| (defun lui-autopaste-service-ptpb-pw (text) | ||||
|   "Paste TEXT to ptpb.pw and return the paste url." | ||||
|   (let ((url-request-method "POST") | ||||
|         (url-request-extra-headers | ||||
|          '(("Content-Type" . "application/x-www-form-urlencoded"))) | ||||
|         (url-request-data (format "c=%s" (url-hexify-string text))) | ||||
|         (url-http-attempt-keepalives nil)) | ||||
|     (let ((buf (url-retrieve-synchronously "https://ptpb.pw/"))) | ||||
|       (unwind-protect | ||||
|           (with-current-buffer buf | ||||
|             (goto-char (point-min)) | ||||
|             (if (re-search-forward "^url: \\(.*\\)" nil t) | ||||
|                 (match-string 1) | ||||
|               (error "Error during pasting to ptpb.pw"))) | ||||
|         (kill-buffer buf))))) | ||||
|  | ||||
| (defun lui-autopaste-service-ixio (text) | ||||
|   "Paste TEXT to ix.io and return the paste url." | ||||
|   (let ((url-request-method "POST") | ||||
|         (url-request-extra-headers | ||||
|          '(("Content-Type" . "application/x-www-form-urlencoded"))) | ||||
|         (url-request-data (format "f:1=%s" (url-hexify-string text))) | ||||
|         (url-http-attempt-keepalives nil)) | ||||
|     (let ((buf (url-retrieve-synchronously "http://ix.io/"))) | ||||
|       (unwind-protect | ||||
|           (with-current-buffer buf | ||||
|             (goto-char (point-min)) | ||||
|             (if (re-search-forward "\n\n" nil t) | ||||
|                 (buffer-substring (point) (point-at-eol)) | ||||
|               (error "Error during pasting to ix.io"))) | ||||
|         (kill-buffer buf))))) | ||||
|  | ||||
| (provide 'lui-autopaste) | ||||
| ;;; lui-autopaste.el ends here | ||||
							
								
								
									
										198
									
								
								elpa/circe-20160608.1315/lui-format.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										198
									
								
								elpa/circe-20160608.1315/lui-format.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,198 @@ | ||||
| ;;; lui-format.el --- A formatting function for use with Lui | ||||
|  | ||||
| ;; Copyright (C) 2005, 2012  Jorgen Schaefer | ||||
|  | ||||
| ;; Author: Jorgen Schaefer <forcer@forcix.cx> | ||||
|  | ||||
| ;; This file is part of Lui. | ||||
|  | ||||
| ;; This program is free software: you can redistribute it and/or modify | ||||
| ;; it under the terms of the GNU General Public License as published by | ||||
| ;; the Free Software Foundation, either version 3 of the License, or | ||||
| ;; (at your option) any later version. | ||||
|  | ||||
| ;; This program is distributed in the hope that it will be useful, | ||||
| ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| ;; GNU General Public License for more details. | ||||
|  | ||||
| ;; You should have received a copy of the GNU General Public License | ||||
| ;; along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  | ||||
| ;;; Commentary: | ||||
|  | ||||
| ;; An improved formatting function using named parameters. | ||||
| ;; | ||||
| ;; See the docstring of `lui-format' for more details. | ||||
| ;; | ||||
| ;; Most of the design is borrowed from Python's string.format. | ||||
|  | ||||
| ;;; Code: | ||||
|  | ||||
| (require 'lui) | ||||
|  | ||||
| (defun lui-display (format not-tracked-p &rest keywords) | ||||
|   "Display a formatted string in the current Lui interface. | ||||
|  | ||||
| The string is formatted using FORMAT and `lui-format'. | ||||
|  | ||||
| If NOT-TRACKED-P is given, the inserted string won't trigger | ||||
| tracking. See `lui-insert' for a description. | ||||
|  | ||||
| KEYWORDS are the keyword arguments passed to `lui-format'. | ||||
|  | ||||
| See `lui-format' for a full description of the arguments." | ||||
|   (lui-insert (lui-format format keywords) | ||||
|               not-tracked-p)) | ||||
|  | ||||
| (defun lui-format (format &rest keywords) | ||||
|   "Display FORMAT formatted with KEYWORDS. | ||||
| FORMAT should be a symbol whose value is taken. If the value is a | ||||
| procedure, the keyword list is passed as a single argument to it, | ||||
| and it should return the formatted string. If the value is a | ||||
| string, it is formatted according to the rules below. | ||||
|  | ||||
| KEYWORDS is a plist of keywords and strings, or symbols and | ||||
| strings. They are used as format arguments. | ||||
|  | ||||
| The string is taken verbatim, unless there is are opening or | ||||
| closing braces. | ||||
|  | ||||
| Double opening or closing braces are replaced by single | ||||
| occurrences of those characters. Otherwise, the contents between | ||||
| opening and closing braces is a format description and replaced | ||||
| by a formatted string. | ||||
|  | ||||
| The string between opening and closing braces is taken as a name | ||||
| of a keyword argument, and replaced by that argument's value. If | ||||
| there is a colon in the string, the keyword name is the part | ||||
| before the colon. The part after the colon is used to format the | ||||
| argument using standard `format' | ||||
|  | ||||
| Example: | ||||
|  | ||||
|   (lui-format \"Hello {foo:.1f}\" :foo 3.1415) | ||||
|  | ||||
| is equivalent to | ||||
|  | ||||
|   (format \"Hello %.1f\" 3.1415) | ||||
|  | ||||
| If the name is either a number, a number followed by a dash, or | ||||
| two numbers with a dash in between them, this is taken as a | ||||
| special name that is looked up in the list given using the list | ||||
| argument to the :indexed-args keyword. | ||||
|  | ||||
| {1} refers to the second element (element 1) | ||||
| {1-} refers to the second and all following elements | ||||
| {1-3} refers to the second through fourth element | ||||
|  | ||||
| If more than one element is selected, the elements are separated | ||||
| by a single space character. | ||||
|  | ||||
| All named arguments receive a property of `lui-format-argument' | ||||
| with the respective name as value. The whole string receives a | ||||
| `lui-format' property with FORMAT as a value, and a | ||||
| `lui-keywords' argument with KEYWORDS as a value." | ||||
|   ;; If it's only a single argument, that argument is a list. | ||||
|   (when (not (cdr keywords)) | ||||
|     (setq keywords (car keywords))) | ||||
|   (cond | ||||
|    ((functionp format) | ||||
|     (apply format keywords)) | ||||
|    ((and (symbolp format) | ||||
|          (functionp (symbol-value format))) | ||||
|     (apply (symbol-value format) keywords)) | ||||
|    (t | ||||
|     (let* ((format-string (if (symbolp format) | ||||
|                               (symbol-value format) | ||||
|                             format)) | ||||
|            (plist (mapcar (lambda (entry) | ||||
|                             (if (keywordp entry) | ||||
|                                 ;; Keyword -> symbol | ||||
|                                 (intern (substring (symbol-name entry) | ||||
|                                                    1)) | ||||
|                               entry)) | ||||
|                           keywords))) | ||||
|       (propertize (lui-format-internal format-string plist) | ||||
|                   'lui-format format | ||||
|                   'lui-keywords keywords))))) | ||||
|  | ||||
| (defun lui-format-internal (fmt keywords) | ||||
|   "Internal function for `lui-format'. | ||||
|  | ||||
| FMT is the format string and KEYWORDS is the symbol-based plist. | ||||
|  | ||||
| See `lui-format'." | ||||
|   (with-temp-buffer | ||||
|     (insert fmt) | ||||
|     (goto-char (point-min)) | ||||
|     (while (re-search-forward "{{\\|}}\\|{\\([^}]*\\)}" nil t) | ||||
|       (cond | ||||
|        ((string-equal (match-string 0) "3.1") | ||||
|         (replace-match "{")) | ||||
|        ((string-equal (match-string 0) "}}") | ||||
|         (replace-match "}")) | ||||
|        (t ;; (match-string 1) | ||||
|         (replace-match (save-match-data | ||||
|                          (lui-format-single (match-string 1) keywords)) | ||||
|                        t t)))) | ||||
|     (buffer-string))) | ||||
|  | ||||
| (defun lui-format-single (specifier keywords) | ||||
|   "Format a single braced SPECIFIER according to KEYWORDS. | ||||
| See `lui-format' for details. | ||||
|  | ||||
| This adds `lui-format-argument' as necessary." | ||||
|   (let* ((split (split-string specifier ":")) | ||||
|          (identifier (car split)) | ||||
|          (format (cadr split))) | ||||
|     (when (not format) | ||||
|       (setq format "s")) | ||||
|     (propertize (format (concat "%" format) | ||||
|                         (lui-format-lookup identifier keywords)) | ||||
|                 'lui-format-argument (intern identifier)))) | ||||
|  | ||||
| (defun lui-format-lookup (identifier keywords) | ||||
|   "Lookup the format IDENTIFIER in KEYWORDS. | ||||
|  | ||||
| See `lui-format' for details." | ||||
|   (cond | ||||
|    ((string-match "^\\([0-9]+\\)\\(-\\([0-9]+\\)?\\)?$" identifier) | ||||
|     (let ((from (match-string 1 identifier)) | ||||
|           (rangep (match-string 2 identifier)) | ||||
|           (to (match-string 3 identifier)) | ||||
|           (indexed-args (plist-get keywords 'indexed-args))) | ||||
|       (if rangep | ||||
|           (mapconcat (lambda (element) | ||||
|                        (if (stringp element) | ||||
|                            element | ||||
|                          (format "%s" element))) | ||||
|                      (lui-sublist indexed-args | ||||
|                                   (string-to-number from) | ||||
|                                   (when to (string-to-number to))) | ||||
|                      " ") | ||||
|         (or (nth (string-to-number from) | ||||
|                  indexed-args) | ||||
|             "")))) | ||||
|    (t | ||||
|     (or (plist-get keywords (intern identifier)) | ||||
|         (error "Unknown keyword argument %S" identifier))))) | ||||
|  | ||||
| (defun lui-sublist (list from &optional to) | ||||
|   "Return the sublist from LIST starting at FROM and ending at TO." | ||||
|   (if (not to) | ||||
|       (nthcdr from list) | ||||
|     (let ((from-list (nthcdr from list)) | ||||
|           (i (- to from)) | ||||
|           (to-list nil)) | ||||
|       (while (>= i 0) | ||||
|         (when (null from-list) | ||||
|           (error "Argument out of range: %S" to)) | ||||
|         (setq to-list (cons (car from-list) | ||||
|                             to-list) | ||||
|               i (- i 1) | ||||
|               from-list (cdr from-list))) | ||||
|       (nreverse to-list)))) | ||||
|  | ||||
| (provide 'lui-format) | ||||
| ;;; lui-format.el ends here | ||||
							
								
								
									
										182
									
								
								elpa/circe-20160608.1315/lui-irc-colors.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										182
									
								
								elpa/circe-20160608.1315/lui-irc-colors.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,182 @@ | ||||
| ;;; lui-irc-colors.el --- Add IRC color support to LUI | ||||
|  | ||||
| ;; Copyright (C) 2005  Jorgen Schaefer | ||||
|  | ||||
| ;; Author: Jorgen Schaefer <forcer@forcix.cx> | ||||
|  | ||||
| ;; This file is part of Lui. | ||||
|  | ||||
| ;; This program is free software; you can redistribute it and/or | ||||
| ;; modify it under the terms of the GNU General Public License | ||||
| ;; as published by the Free Software Foundation; either version 3 | ||||
| ;; of the License, or (at your option) any later version. | ||||
|  | ||||
| ;; This program is distributed in the hope that it will be useful, | ||||
| ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| ;; GNU General Public License for more details. | ||||
|  | ||||
| ;; You should have received a copy of the GNU General Public License | ||||
| ;; along with this program; if not, write to the Free Software | ||||
| ;; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||||
| ;; 02110-1301  USA | ||||
|  | ||||
| ;;; Commentary: | ||||
|  | ||||
| ;; This tells LUI how to display IRC colors: | ||||
| ;; ^B - Bold | ||||
| ;; ^_ - Underline | ||||
| ;; ^V - Inverse | ||||
| ;; ^] - Italic | ||||
| ;; ^O - Return to normal | ||||
| ;; ^C1,2 - Colors | ||||
|  | ||||
| ;; The colors are documented at http://www.mirc.co.uk/help/color.txt | ||||
|  | ||||
| ;;; Code: | ||||
|  | ||||
| (require 'lui) | ||||
|  | ||||
| (defgroup lui-irc-colors nil | ||||
|   "LUI IRC colors faces." | ||||
|   :group 'circe) | ||||
|  | ||||
| (defface lui-irc-colors-inverse-face | ||||
|   '((t (:inverse-video t))) | ||||
|   "Face used for inverse video." | ||||
|   :group 'lui-irc-colors) | ||||
|  | ||||
| (defun lui-irc-defface (face property on-dark on-light rest doc) | ||||
|   (custom-declare-face | ||||
|    face | ||||
|    `((((type graphic) (class color) (background dark)) | ||||
|       (,property ,on-dark)) | ||||
|      (((type graphic) (class color) (background light)) | ||||
|       (,property ,on-light)) | ||||
|      (t (,property ,rest))) | ||||
|    doc | ||||
|    :group 'lui-irc-colors)) | ||||
|  | ||||
| (defun lui-irc-defface-pair (number on-dark on-light rest name) | ||||
|   (lui-irc-defface | ||||
|    (intern (format "lui-irc-colors-fg-%d-face" number)) | ||||
|    :foreground | ||||
|    on-dark on-light rest | ||||
|    (concat "Face used for foreground IRC color " | ||||
| 	   (number-to-string number) " (" name ").")) | ||||
|   (lui-irc-defface | ||||
|    (intern (format "lui-irc-colors-bg-%d-face" number)) | ||||
|    :background | ||||
|    on-light on-dark rest | ||||
|    (concat "Face used for background IRC color " | ||||
| 	   (number-to-string number) " (" name ")."))) | ||||
|  | ||||
| (defun lui-irc-defface-bulk (colors) | ||||
|   (dotimes (n (length colors)) | ||||
|     (apply 'lui-irc-defface-pair n (nth n colors)))) | ||||
|  | ||||
| (lui-irc-defface-bulk | ||||
|  '(("#ffffff" "#585858" "white"    "white") | ||||
|    ("#a5a5a5" "#000000" "black"    "black") | ||||
|    ("#9b9bff" "#0000ff" "blue4"    "blue") | ||||
|    ("#40eb51" "#006600" "green4"   "green") | ||||
|    ("#ff9696" "#b60000" "red"      "red") | ||||
|    ("#d19999" "#8f3d3d" "red4"     "brown") | ||||
|    ("#d68fff" "#9c009c" "magenta4" "purple") | ||||
|    ("#ffb812" "#7a4f00" "yellow4"  "orange") | ||||
|    ("#ffff00" "#5c5c00" "yellow"   "yellow") | ||||
|    ("#80ff95" "#286338" "green"    "light green") | ||||
|    ("#00b8b8" "#006078" "cyan4"    "teal") | ||||
|    ("#00ffff" "#006363" "cyan"     "light cyan") | ||||
|    ("#a8aeff" "#3f568c" "blue"     "light blue") | ||||
|    ("#ff8bff" "#853885" "magenta"  "pink") | ||||
|    ("#cfcfcf" "#171717" "dimgray"  "grey") | ||||
|    ("#e6e6e6" "#303030" "gray"     "light grey"))) | ||||
|  | ||||
| (defvar lui-irc-colors-regex | ||||
|   "\\(\x02\\|\x1F\\|\x16\\|\x1D\\|\x0F\\|\x03\\)" | ||||
|   "A regular expression matching IRC control codes.") | ||||
|  | ||||
| ;;;###autoload | ||||
| (defun enable-lui-irc-colors () | ||||
|   "Enable IRC color interpretation for Lui." | ||||
|   (interactive) | ||||
|   (add-hook 'lui-pre-output-hook 'lui-irc-colors)) | ||||
|  | ||||
| (defun disable-lui-irc-colors () | ||||
|   "Disable IRC color interpretation for Lui." | ||||
|   (interactive) | ||||
|   (remove-hook 'lui-pre-output-hook 'lui-irc-colors)) | ||||
|  | ||||
| (defun lui-irc-colors () | ||||
|   "Add color faces for IRC colors. | ||||
| This is an appropriate function for `lui-pre-output-hook'." | ||||
|   (goto-char (point-min)) | ||||
|   (let ((start (point)) | ||||
|         (boldp nil) | ||||
|         (inversep nil) | ||||
|         (italicp nil) | ||||
|         (underlinep nil) | ||||
|         (fg nil) | ||||
|         (bg nil)) | ||||
|     (while (re-search-forward lui-irc-colors-regex nil t) | ||||
|       (lui-irc-propertize start (point) | ||||
|                           boldp inversep italicp underlinep | ||||
|                           fg bg) | ||||
|       (let ((code (match-string 1))) | ||||
|         (replace-match "") | ||||
|         (setq start (point)) | ||||
|         (cond | ||||
|          ((string= code "") | ||||
|           (setq boldp (not boldp))) | ||||
|          ((string= code "") | ||||
|           (setq inversep (not inversep))) | ||||
|          ((string= code "") | ||||
|           (setq italicp (not italicp))) | ||||
|          ((string= code "") | ||||
|           (setq underlinep (not underlinep))) | ||||
|          ((string= code "") | ||||
|           (setq boldp nil | ||||
|                 inversep nil | ||||
|                 italicp nil | ||||
|                 underlinep nil | ||||
|                 fg nil | ||||
|                 bg nil)) | ||||
|          ((string= code "") | ||||
|           (if (looking-at "\\([0-9][0-9]?\\)\\(,\\([0-9][0-9]?\\)\\)?") | ||||
|               (progn | ||||
|                 (setq fg (string-to-number (match-string 1)) | ||||
|                       bg (if (match-string 2) | ||||
|                              (string-to-number (match-string 3)) | ||||
|                            bg)) | ||||
|                 (setq fg (if (and fg (not (= fg 99))) (mod fg 16) nil) | ||||
|                       bg (if (and bg (not (= bg 99))) (mod bg 16) nil)) | ||||
|                 (replace-match "")) | ||||
|             (setq fg nil | ||||
|                   bg nil))) | ||||
|          (t | ||||
|           (error "lui-irc-colors: Can't happen!"))))) | ||||
|     (lui-irc-propertize (point) (point-max) | ||||
|                         boldp inversep italicp underlinep fg bg))) | ||||
|  | ||||
| (defun lui-irc-propertize (start end boldp inversep italicp underlinep fg bg) | ||||
|   "Propertize the region between START and END." | ||||
|   (let ((faces (append (and boldp '(bold)) | ||||
|                        (and inversep '(lui-irc-colors-inverse-face)) | ||||
|                        (and italicp '(italic)) | ||||
|                        (and underlinep '(underline)) | ||||
|                        (and fg (list (lui-irc-colors-face 'fg fg))) | ||||
|                        (and bg (list (lui-irc-colors-face 'bg bg)))))) | ||||
|     (when faces | ||||
|       (add-face-text-property start end faces)))) | ||||
|  | ||||
| (defun lui-irc-colors-face (type n) | ||||
|   "Return a face appropriate for face number N. | ||||
| TYPE is either 'fg or 'bg." | ||||
|   (if (and (<= 0 n) | ||||
|            (<= n 15)) | ||||
|       (intern (format "lui-irc-colors-%s-%s-face" type n)) | ||||
|     'default-face)) | ||||
|  | ||||
| (provide 'lui-irc-colors) | ||||
| ;;; lui-irc-colors.el ends here | ||||
							
								
								
									
										201
									
								
								elpa/circe-20160608.1315/lui-logging.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										201
									
								
								elpa/circe-20160608.1315/lui-logging.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,201 @@ | ||||
| ;;; lui-logging.el --- Logging support for lui | ||||
|  | ||||
| ;; Copyright (C) 2006  Jorgen Schaefer, | ||||
| ;;               2012  Anthony Martinez | ||||
|  | ||||
| ;; Author: Anthony Martinez <pi+circe@pihost.us> | ||||
|  | ||||
| ;; This file is part of Lui. | ||||
|  | ||||
| ;; This program is free software; you can redistribute it and/or | ||||
| ;; modify it under the terms of the GNU General Public License | ||||
| ;; as published by the Free Software Foundation; either version 3 | ||||
| ;; of the License, or (at your option) any later version. | ||||
|  | ||||
| ;; This program is distributed in the hope that it will be useful, | ||||
| ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| ;; GNU General Public License for more details. | ||||
|  | ||||
| ;; You should have received a copy of the GNU General Public License | ||||
| ;; along with this program; if not, write to the Free Software | ||||
| ;; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||||
| ;; 02110-1301  USA | ||||
|  | ||||
| ;;; Commentary: | ||||
|  | ||||
| ;; This lui module enables logging. Lui applications can change the | ||||
| ;; values of `lui-logging-format-arguments' to provide further | ||||
| ;; possibilities of customizing `lui-logging-file-format' for users. | ||||
|  | ||||
| ;;; Code: | ||||
|  | ||||
| (require 'lui-format) | ||||
| (require 'url-util) | ||||
|  | ||||
| (defgroup lui-logging nil | ||||
|   "Logging support." | ||||
|   :prefix "lui-logging-" | ||||
|   :group 'lui) | ||||
|  | ||||
| (defcustom lui-logging-format "[%T] {text}" | ||||
|   "The format used for log file entries. | ||||
| This is first passed through `format-time-string' and then through | ||||
| `lui-format'. The following format strings exist: | ||||
|  | ||||
|   {text} - the text to be logged" | ||||
|   :type 'string | ||||
|   :group 'lui-logging) | ||||
|  | ||||
| (defcustom lui-logging-directory "~/.logs" | ||||
|   "The directory where log files are stored." | ||||
|   :type 'directory | ||||
|   :group 'lui-logging) | ||||
|  | ||||
| (defcustom lui-logging-file-format "{buffer}_%Y-%m-%d.txt" | ||||
|   "The format to be used for the log file name. | ||||
| This is first passed through `format-time-string', and then | ||||
| through `lui-format'. Possible lui format strings are: | ||||
|  | ||||
|   {buffer} - the buffer name where the logging happened. | ||||
|  | ||||
| Lui applications can provide further format strings. See | ||||
| `lui-logging-format-arguments' in the appropriate buffer." | ||||
|   :type 'string | ||||
|   :group 'lui-logging) | ||||
|  | ||||
| (defcustom lui-logging-flush-delay 0 | ||||
|   "The number of seconds to delay writing newly-received messages | ||||
| to disk. This can increase performance/decrease IO-wait at the | ||||
| cost of a little bit of safety." | ||||
|   :type 'integer | ||||
|   :group 'lui-logging) | ||||
|  | ||||
| (defvar lui-logging-format-arguments nil | ||||
|   "A list of arguments to be passed to `lui-format'. | ||||
| This can be used to extend the formatting possibilities of the | ||||
| file name for lui applications.") | ||||
| (make-variable-buffer-local 'lui-logging-format-arguments) | ||||
|  | ||||
| (defvar lui-logging-file-name-unreserved-chars | ||||
|   ;; All but '/' is fine actually, but also omit '%' because otherwise there's | ||||
|   ;; ambiguity between one introduced by encoding and a literal one. | ||||
|   '(?! ?\" ?# ?$ ?& ?` ?\( ?\) ?* ?+ ?,?: ?\; ?< ?= ?> ?? ?@?\[ ?\\ ?\] ?^ ?` | ||||
|        ?\{ ?| ?\}) | ||||
|   "A list of characters that should not be percent-encoded by | ||||
| `url-hexify-string' while generating a logging file name.") | ||||
|  | ||||
| (defvar lui-pending-logs | ||||
|   (make-hash-table :test 'equal) | ||||
|   "Storage for log messages awaiting write. It is structured as a | ||||
| hash table mapping filenames to a list-of-strings, which serves as | ||||
| a queue.") | ||||
|  | ||||
| (defvar lui-logging-timer nil | ||||
|   "The timer used to flush lui-logged buffers") | ||||
|  | ||||
| (defun lui-logging-delayed-p () | ||||
|   (> lui-logging-flush-delay 0)) | ||||
|  | ||||
| (defun enable-lui-logging () | ||||
|   "Enable lui logging for this buffer. Also create the log | ||||
| file's directory, should it not exist." | ||||
|   (interactive) | ||||
|   (add-hook 'lui-pre-output-hook 'lui-logging | ||||
|             nil t)) | ||||
|  | ||||
| (defun disable-lui-logging () | ||||
|   "Disable lui logging for this buffer, and flush any pending | ||||
| logs to disk." | ||||
|   (interactive) | ||||
|   (remove-hook 'lui-pre-output-hook 'lui-logging t) | ||||
|   (lui-logging-flush)) | ||||
|  | ||||
| (defun enable-lui-logging-globally () | ||||
|   "Enable lui logging for all Lui buffers. | ||||
|  | ||||
| This affects current as well as future buffers." | ||||
|   (interactive) | ||||
|   (add-hook 'lui-mode-hook 'enable-lui-logging) | ||||
|   (dolist (buf (buffer-list)) | ||||
|     (with-current-buffer buf | ||||
|       (when lui-input-marker | ||||
|         (enable-lui-logging))))) | ||||
|  | ||||
| (defun disable-lui-logging-globally () | ||||
|   "Disable logging in all future Lui buffers. | ||||
|  | ||||
| This affects current as well as future buffers." | ||||
|   (interactive) | ||||
|   (remove-hook 'lui-mode-hook 'enable-lui-logging) | ||||
|   (dolist (buf (buffer-list)) | ||||
|     (with-current-buffer buf | ||||
|       (when lui-input-marker | ||||
|         (disable-lui-logging))))) | ||||
|  | ||||
| (defun lui-logging-file-name () | ||||
|   "Create the name of the log file based on `lui-logging-file-format'." | ||||
|   (let* ((time-formatted (format-time-string lui-logging-file-format)) | ||||
|          (buffer (let ((url-unreserved-chars | ||||
|                         (append url-unreserved-chars | ||||
|                                 lui-logging-file-name-unreserved-chars)) | ||||
|                        (downcased (downcase (buffer-name (current-buffer))))) | ||||
|                    (url-hexify-string downcased))) | ||||
|          (filename (apply 'lui-format | ||||
|                           time-formatted | ||||
|                           :buffer buffer | ||||
|                           lui-logging-format-arguments))) | ||||
|     (concat lui-logging-directory "/" filename))) | ||||
|  | ||||
| (defun lui-logging-flush () | ||||
|   "Flush out the lui-logging queue, and clear the timer set by | ||||
| `lui-logging'." | ||||
|   (maphash #'lui-logging-flush-file lui-pending-logs) | ||||
|   (clrhash lui-pending-logs) | ||||
|   (cancel-timer lui-logging-timer) | ||||
|   (setq lui-logging-timer nil)) | ||||
|  | ||||
| (defun lui-logging-write-to-log (file-name content) | ||||
|   "Actually perform a write to the logfile." | ||||
|   (let ((coding-system-for-write 'raw-text) | ||||
|         (dir (file-name-directory file-name))) | ||||
|     (when (not (file-directory-p dir)) | ||||
|       (make-directory dir t)) | ||||
|     (write-region content nil file-name t 'nomessage))) | ||||
|  | ||||
| (defun lui-logging-flush-file (file-name queue) | ||||
|   "Consume the logging queue and write the content to the log | ||||
| file." | ||||
|   (let ((content (apply #'concat (nreverse queue)))) | ||||
|     (lui-logging-write-to-log file-name content))) | ||||
|  | ||||
| (defun lui-logging-format-string (text) | ||||
|   "Generate a string to be either directly written or enqueued." | ||||
|   (substring-no-properties | ||||
|    (lui-format | ||||
|     (format-time-string lui-logging-format) | ||||
|     :text text))) | ||||
|  | ||||
| (defun lui-logging-enqueue (file-name text) | ||||
|   "Given a filename, push text onto its queue, and tickle the | ||||
| timer, if necessary." | ||||
|   (puthash file-name | ||||
|            (cons text (gethash file-name lui-pending-logs)) | ||||
|            lui-pending-logs) | ||||
|   (when (null lui-logging-timer) | ||||
|     (setq lui-logging-timer | ||||
|           (run-with-timer lui-logging-flush-delay nil | ||||
|                           #'lui-logging-flush)))) | ||||
|  | ||||
| (defun lui-logging () | ||||
|   "If output-queueing is enabled, append the to-be-logged string | ||||
| to the output queue. Otherwise, write directly to the logfile. | ||||
| This should be added to `lui-pre-output-hook' by way of | ||||
| `enable-lui-logging'." | ||||
|   (let ((text (lui-logging-format-string (buffer-string)))) | ||||
|     (if (lui-logging-delayed-p) | ||||
|         (lui-logging-enqueue (lui-logging-file-name) text) | ||||
|       (lui-logging-write-to-log (lui-logging-file-name) text)))) | ||||
|  | ||||
| (provide 'lui-logging) | ||||
| ;;; lui-logging.el ends here | ||||
							
								
								
									
										110
									
								
								elpa/circe-20160608.1315/lui-track-bar.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										110
									
								
								elpa/circe-20160608.1315/lui-track-bar.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,110 @@ | ||||
| ;;; lui-track-bar.el --- Provides a bar to track the last read position | ||||
|  | ||||
| ;; Copyright (C) 2016 Vasilij Schneidermann <v.schneidermann@gmail.com> | ||||
|  | ||||
| ;; Author: Vasilij Schneidermann <v.schneidermann@gmail.com> | ||||
|  | ||||
| ;; This file is part of LUI. | ||||
|  | ||||
| ;; This program is free software; you can redistribute it and/or | ||||
| ;; modify it under the terms of the GNU General Public License | ||||
| ;; as published by the Free Software Foundation; either version 3 | ||||
| ;; of the License, or (at your option) any later version. | ||||
|  | ||||
| ;; This program is distributed in the hope that it will be useful, | ||||
| ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| ;; GNU General Public License for more details. | ||||
|  | ||||
| ;; You should have received a copy of the GNU General Public License | ||||
| ;; along with this program; if not, write to the Free Software | ||||
| ;; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||||
| ;; 02110-1301  USA | ||||
|  | ||||
| ;;; Commentary: | ||||
|  | ||||
| ;; This allows you to track where you've last left off a buffer. | ||||
|  | ||||
| ;; Use (enable-lui-track-bar) to enable this mode globally. You can | ||||
| ;; customize `lui-track-bar-behavior' to change when the track bar | ||||
| ;; moves. You can also use M-x lui-track-bar-move to move the track | ||||
| ;; bar manually. | ||||
|  | ||||
| ;;; Code: | ||||
|  | ||||
| (require 'lui) | ||||
| (require 'tracking) | ||||
|  | ||||
| (defgroup lui-track-bar nil | ||||
|   "Last read position tracking for LUI" | ||||
|   :prefix "lui-track-bar-" | ||||
|   :group 'lui) | ||||
|  | ||||
| (defcustom lui-track-bar-behavior 'before-switch-to-buffer | ||||
|   "When to move the track bar. | ||||
|  | ||||
| The following values are possible. | ||||
|  | ||||
| before-switch-to-buffer (default) | ||||
|   Move the bar to the bottom of the buffer when switching away | ||||
|   from a buffer. | ||||
|  | ||||
| before-tracking-next-buffer | ||||
|   Move the bar when switching to the next buffer using | ||||
|   \\[tracking-next-buffer]. | ||||
|  | ||||
| after-send | ||||
|   Move the bar after sending a message." | ||||
|   :type '(choice (const :tag "Before switching buffers" | ||||
|                         before-switch-to-buffer) | ||||
|                  (const :tag "Before tracking switch" | ||||
|                         before-tracking-next-buffer) | ||||
|                  (const :tag "After sending" | ||||
|                         after-send)) | ||||
|   :group 'lui-track-bar) | ||||
|  | ||||
| (defface lui-track-bar | ||||
|   '((((type graphic) (background light)) | ||||
|      :inherit default :background "dim gray" :height 0.1) | ||||
|     (((type graphic) (background dark)) | ||||
|      :inherit default :background "light gray" :height 0.1) | ||||
|     (((type tty)) | ||||
|      :inherit (font-lock-comment-face default) :underline t)) | ||||
|   "Track bar face" | ||||
|   :group 'lui-track-bar) | ||||
|  | ||||
| (defvar lui-track-bar-overlay nil) | ||||
| (make-variable-buffer-local 'lui-track-bar-overlay) | ||||
|  | ||||
| ;;;###autoload | ||||
| (defun enable-lui-track-bar () | ||||
|   "Enable a bar in Lui buffers that shows where you stopped reading." | ||||
|   (interactive) | ||||
|   (defadvice switch-to-buffer (before lui-track-bar activate) | ||||
|     (when (and (eq lui-track-bar-behavior 'before-switch-to-buffer) | ||||
|                ;; Do not move the bar if the buffer is displayed still | ||||
|                (<= (length (get-buffer-window-list (current-buffer))) | ||||
|                    1)) | ||||
|       (lui-track-bar-move))) | ||||
|   (defadvice tracking-next-buffer (before lui-track-bar activate) | ||||
|     (when (eq lui-track-bar-behavior 'before-tracking-next-buffer) | ||||
|       (lui-track-bar-move))) | ||||
|   (add-hook 'lui-pre-input-hook 'lui-track-bar--move-pre-input)) | ||||
|  | ||||
| (defun lui-track-bar--move-pre-input () | ||||
|   (when (eq lui-track-bar-behavior 'after-send) | ||||
|     (lui-track-bar-move))) | ||||
|  | ||||
| (defun lui-track-bar-move () | ||||
|   "Move the track bar down." | ||||
|   (interactive) | ||||
|   (when (derived-mode-p 'lui-mode) | ||||
|     (when (not lui-track-bar-overlay) | ||||
|       (setq lui-track-bar-overlay (make-overlay (point-min) (point-min))) | ||||
|       (overlay-put lui-track-bar-overlay 'after-string | ||||
|                    (propertize "\n" 'face 'lui-track-bar))) | ||||
|     (move-overlay lui-track-bar-overlay | ||||
|                   lui-output-marker lui-output-marker))) | ||||
|  | ||||
| (provide 'lui-track-bar) | ||||
| ;;; lui-track-bar.el ends here | ||||
							
								
								
									
										1353
									
								
								elpa/circe-20160608.1315/lui.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1353
									
								
								elpa/circe-20160608.1315/lui.el
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										194
									
								
								elpa/circe-20160608.1315/make-tls-process.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										194
									
								
								elpa/circe-20160608.1315/make-tls-process.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,194 @@ | ||||
| ;;; make-tls-process.el --- A non-blocking TLS connection function | ||||
|  | ||||
| ;; Copyright (C) 2015  Jorgen Schaefer <contact@jorgenschaefer.de> | ||||
|  | ||||
| ;; Author: Jorgen Schaefer <contact@jorgenschaefer.de> | ||||
| ;; URL: https://github.com/jorgenschaefer/circe | ||||
|  | ||||
| ;; This program is free software; you can redistribute it and/or | ||||
| ;; modify it under the terms of the GNU General Public License | ||||
| ;; as published by the Free Software Foundation; either version 3 | ||||
| ;; of the License, or (at your option) any later version. | ||||
|  | ||||
| ;; This program is distributed in the hope that it will be useful, | ||||
| ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| ;; GNU General Public License for more details. | ||||
|  | ||||
| ;; You should have received a copy of the GNU General Public License | ||||
| ;; along with this program. If not, see <http://www.gnu.org/licenses/>. | ||||
|  | ||||
| ;;; Commentary: | ||||
|  | ||||
| ;; A `make-tls-process' function like `make-network-process', in | ||||
| ;; particular supporting non-blocking connects. | ||||
|  | ||||
| ;;; Code: | ||||
|  | ||||
| (require 'tls) | ||||
|  | ||||
| (defcustom tls-connection-command | ||||
|   (if (executable-find "gnutls-cli") | ||||
|       "gnutls-cli --insecure -p %p %h" | ||||
|     "openssl s_client -connect %h:%p -no_ssl2 -ign_eof") | ||||
|   "The command to use to create a TLS connection. | ||||
|  | ||||
| %h is replaced with server hostname, %p with port to connect to. | ||||
| The program should read input on stdin and write output to | ||||
| stdout. | ||||
|  | ||||
| Also see `tls-success' for what the program should output after | ||||
| successful negotiation." | ||||
|   :group 'tls | ||||
|   :type 'string) | ||||
|  | ||||
| (defvar tls-debug-output nil | ||||
|   "Non-nil if you want to see lots of debug messages.") | ||||
|  | ||||
| (defun tls--debug (format-string &rest args) | ||||
|   "Display a message if debug output is enabled. | ||||
|  | ||||
| If `tls-debug-output' is non-nil, this acts like `message'. | ||||
| Otherwise, it's a no-op." | ||||
|   (when tls-debug-output | ||||
|     (apply #'message format-string args))) | ||||
|  | ||||
| (defun make-tls-process (&rest args) | ||||
|   "Create a TLS client process. | ||||
|  | ||||
| A TLS network process is a command process that runs a command | ||||
| line program like gnutls or openssl, not a full network process. | ||||
| Network communication should work as usual, but the sentinel | ||||
| might receive process-specific events. | ||||
|  | ||||
| Different from a process sentinel, but like a network sentinel, | ||||
| the sentinel is called with an event \"open\\n\" when the | ||||
| connection is established. | ||||
|  | ||||
| This function uses `tls-connection-command' to connect to a | ||||
| server. | ||||
|  | ||||
| Do NOT use `set-process-filter' or `set-process-sentinel' on the | ||||
| return value of this function. The connection setup uses special | ||||
| sentinels and filters to be deal with the program output used | ||||
| here. Use the :sentinel and :filter keyword arguments to set them | ||||
| once the connection is fully established. | ||||
|  | ||||
| Arguments are specified as keyword/argument pairs, similar to | ||||
| `make-network-process'. The following arguments are defined: | ||||
|  | ||||
| :name NAME -- NAME is name for process.  It is modified if necessary | ||||
| to make it unique. | ||||
|  | ||||
| :buffer BUFFER -- BUFFER is the buffer (or buffer-name) to associate | ||||
| with the process.  Process output goes at end of that buffer, unless | ||||
| you specify an output stream or filter function to handle the output. | ||||
| BUFFER may be also nil, meaning that this process is not associated | ||||
| with any buffer. | ||||
|  | ||||
| :host HOST -- HOST is name of the host to connect to, or its IP | ||||
| address.  The symbol `local' specifies the local host.  If specified | ||||
| for a server process, it must be a valid name or address for the local | ||||
| host, and only clients connecting to that address will be accepted. | ||||
|  | ||||
| :service SERVICE -- SERVICE is name of the service desired, or an | ||||
| integer specifying a port number to connect to. If SERVICE is t, | ||||
| a random port number is selected for the server. (If Emacs was | ||||
| compiled with getaddrinfo, a port number can also be specified as | ||||
| a string, e.g. \"80\", as well as an integer. This is not | ||||
| portable.) | ||||
|  | ||||
| :coding CODING -- If CODING is a symbol, it specifies the coding | ||||
| system used for both reading and writing for this process.  If CODING | ||||
| is a cons (DECODING . ENCODING), DECODING is used for reading, and | ||||
| ENCODING is used for writing. | ||||
|  | ||||
| :noquery BOOL -- Query the user unless BOOL is non-nil, and process is | ||||
| running when Emacs is exited. | ||||
|  | ||||
| :filter FILTER -- Install FILTER as the process filter. | ||||
|  | ||||
| :sentinel SENTINEL -- Install SENTINEL as the process sentinel. | ||||
|  | ||||
| :plist PLIST -- Install PLIST as the new process's initial plist." | ||||
|   (let* ((name (plist-get args :name)) | ||||
|          (host (plist-get args :host)) | ||||
|          (service (plist-get args :service)) | ||||
|          (proc (tls--start-process name tls-connection-command host service))) | ||||
|     (process-put proc :tls-args args) | ||||
|     (set-process-sentinel proc #'tls--sentinel) | ||||
|     (set-process-filter proc #'tls--filter) | ||||
|     proc)) | ||||
|  | ||||
| (defun tls--sentinel (proc event) | ||||
|   "The default sentinel for TLS connections. | ||||
|  | ||||
| Try the next command in the list, or fail if there are none | ||||
| left." | ||||
|   (tls--debug "tls--sentinel %S %S" | ||||
|               (process-status proc) | ||||
|               event) | ||||
|   (tls--debug "Failed TLS output: %s" | ||||
|               (process-get proc :tls-data)) | ||||
|   (if (eq (process-status proc) | ||||
|           'exit) | ||||
|       (let ((sentinel (plist-get (process-get proc :tls-args) | ||||
|                                  :sentinel))) | ||||
|         (when sentinel | ||||
|           (funcall sentinel proc (format "failed with %s\n" event)))) | ||||
|     (error "Unexpected event in tls sentinel: %S" event))) | ||||
|  | ||||
| (defun tls--filter (proc data) | ||||
|   "The default filter for TLS connections. | ||||
|  | ||||
| We wait until both `tls-success' and `tls-end-of-info' have been | ||||
| received. Once that happens, we are done and we can switch over | ||||
| to the real connection." | ||||
|   (let ((data (concat (or (process-get proc :tls-data) | ||||
|                           "") | ||||
|                       data))) | ||||
|     (if (and (string-match tls-success data) | ||||
|              (string-match tls-end-of-info data)) | ||||
|         (let* ((remaining-data (substring data (match-end 0))) | ||||
|                (args (process-get proc :tls-args)) | ||||
|                (buffer (plist-get args :buffer)) | ||||
|                (coding (plist-get args :coding)) | ||||
|                (noquery (plist-get args :noquery)) | ||||
|                (filter (plist-get args :filter)) | ||||
|                (sentinel (plist-get args :sentinel)) | ||||
|                (plist (plist-get args :plist))) | ||||
|           (set-process-plist proc plist) | ||||
|           (set-process-sentinel proc sentinel) | ||||
|           (set-process-filter proc filter) | ||||
|           (set-process-buffer proc buffer) | ||||
|           (if (consp coding) | ||||
|               (set-process-coding-system proc (car coding) (cdr coding)) | ||||
|             (set-process-coding-system proc coding coding)) | ||||
|           (set-process-query-on-exit-flag proc (not noquery)) | ||||
|           (when sentinel | ||||
|             (funcall sentinel proc "open\n")) | ||||
|           (when (and (not (equal remaining-data "")) | ||||
|                      filter) | ||||
|             (funcall filter proc remaining-data))) | ||||
|       (process-put proc :tls-data data)))) | ||||
|  | ||||
| (defun tls--start-process (name cmd host port) | ||||
|   "Start a single process for network communication. | ||||
|  | ||||
| This code is mostly taken from tls.el." | ||||
|   (let ((process-connection-type tls-process-connection-type) | ||||
|         (formatted-cmd | ||||
|          (format-spec | ||||
|           cmd | ||||
|           (format-spec-make | ||||
|            ?h host | ||||
|            ?p (if (integerp port) | ||||
|                   (int-to-string port) | ||||
|                 port))))) | ||||
|     (tls--debug "TLS starting process: %s" formatted-cmd) | ||||
|     (start-process name nil | ||||
|                    shell-file-name shell-command-switch | ||||
|                    formatted-cmd))) | ||||
|  | ||||
| (provide 'make-tls-process) | ||||
| ;;; make-tls-process.el ends here | ||||
							
								
								
									
										223
									
								
								elpa/circe-20160608.1315/shorten.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										223
									
								
								elpa/circe-20160608.1315/shorten.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,223 @@ | ||||
| ;;; shorten.el --- component-wise string shortener | ||||
|  | ||||
| ;; Copyright (C) 2013  John J Foerch <jjfoerch@earthlink.net> | ||||
|  | ||||
| ;; Keywords: extensions | ||||
| ;; Author: John J Foerch <jjfoerch@earthlink.net> | ||||
| ;; URL: https://github.com/jorgenschaefer/circe/blob/master/shorten.el | ||||
|  | ||||
| ;; This program is free software: you can redistribute it and/or modify | ||||
| ;; it under the terms of the GNU General Public License as published by | ||||
| ;; the Free Software Foundation, either version 3 of the License, or | ||||
| ;; (at your option) any later version. | ||||
|  | ||||
| ;; This program is distributed in the hope that it will be useful, | ||||
| ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| ;; GNU General Public License for more details. | ||||
|  | ||||
| ;; You should have received a copy of the GNU General Public License | ||||
| ;; along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  | ||||
| ;;; Commentary: | ||||
|  | ||||
| ;; This is a component-wise string shortener, meaning that, given a list | ||||
| ;; of strings, it breaks each string into parts, then computes shortest | ||||
| ;; prefix of each part with respect to others of the same 'depth', such | ||||
| ;; that when joined back together, the shortened form of the whole string | ||||
| ;; remains unique within the resulting list.  Many styles of shortening | ||||
| ;; are made possible via three functions that the caller may provide: the | ||||
| ;; split function, the join function, and the validate-component function. | ||||
| ;; | ||||
| ;; Strings are broken with the value of `shorten-split-function' (a | ||||
| ;; procedure string->list), and shortened components are rejoined with the | ||||
| ;; value of `shorten-join-function' (a procedure list->string[*]).  The | ||||
| ;; default split and join functions break the string on word boundaries, | ||||
| ;; and rejoin on the empty string.  Potential shortened forms of | ||||
| ;; components are tested with `shorten-validate-component-function'; its | ||||
| ;; default value passes only if its argument contains at least one | ||||
| ;; word-constituent character (regexp \w), meaning that by default, | ||||
| ;; components consisting entirely of non-word characters will not be | ||||
| ;; shortened, and components that start with non-word characters will only | ||||
| ;; be shortened so much that they have at least one word-constituent | ||||
| ;; character in them. | ||||
| ;; | ||||
| ;; The main entry point is `shorten-strings', which takes a list of strings | ||||
| ;; as its argument and returns an alist ((STRING . SHORTENED-STRING) ...). | ||||
| ;; | ||||
| ;; [*] Also takes a second argument; see docstring of | ||||
| ;; `shorten-join-function'. | ||||
|  | ||||
| ;;; History: | ||||
|  | ||||
| ;; - Version 0.1 (March 7, 2013): initial release | ||||
|  | ||||
| ;;; Code: | ||||
|  | ||||
| ;; Tree utils | ||||
| ;; | ||||
| (defsubst shorten-make-tree-root () | ||||
|   (cons nil nil)) | ||||
|  | ||||
| (defsubst shorten-tree-make-entry (token short full) | ||||
|   (list token short full nil)) | ||||
|  | ||||
| (defsubst shorten-tree-token (entry) | ||||
|   (car entry)) | ||||
|  | ||||
| (defsubst shorten-tree-fullname (entry) | ||||
|   (nth 2 entry)) | ||||
|  | ||||
| (defsubst shorten-tree-descendants (entry) | ||||
|   (nthcdr 3 entry)) | ||||
|  | ||||
| (defsubst shorten-tree-set-shortened (entry short) | ||||
|   (setcar (cdr entry) short)) | ||||
|  | ||||
| (defsubst shorten-tree-set-fullname (entry full) | ||||
|   (setcar (nthcdr 2 entry) full)) | ||||
|  | ||||
| (defsubst shorten-tree-insert (node item) | ||||
|   (when (car node) | ||||
|     (setcdr node (cons (car node) (cdr node)))) | ||||
|   (setcar node item)) | ||||
|  | ||||
|  | ||||
| ;; Caller configuration | ||||
| ;; | ||||
| (defun shorten-split (s) | ||||
|   (split-string s "\\b" t)) | ||||
|  | ||||
| (defun shorten-join (lst &optional tail-count) | ||||
|   (mapconcat #'identity lst "")) | ||||
|  | ||||
| (defun shorten-join-sans-tail (lst tail-count) | ||||
|   "A shorten-join that drops unnecessary tail components." | ||||
|   (shorten-join (butlast lst tail-count))) | ||||
|  | ||||
| (defun shorten-validate-component (str) | ||||
|   (string-match-p "\\w" str)) | ||||
|  | ||||
| (defvar shorten-split-function #'shorten-split | ||||
|   "Value should be a function of string->list that breaks a | ||||
| string into components.  The default breaks on word-boundaries. | ||||
| To get simple prefix shortening, bind this to `list'. | ||||
|  | ||||
| Users should not generally change the global value of this | ||||
| variable; instead, bind it dynamically around calls to | ||||
| `shorten-strings'.") | ||||
|  | ||||
| (defvar shorten-join-function #'shorten-join | ||||
|   "A function that takes a list of components and a tail-count, | ||||
| and returns a joined string.  Tail-count is the number of | ||||
| components on the end of the list that are not needed to uniquify | ||||
| the result, and so may be safely dropped if aggressive shortening | ||||
| is desired.  The default preserves tail components, and joins the | ||||
| list on the empty string. | ||||
|  | ||||
| Users should not generally change the global value of this | ||||
| variable; instead, bind it dynamically around calls to | ||||
| `shorten-strings'.") | ||||
|  | ||||
| (defvar shorten-validate-component-function #'shorten-validate-component | ||||
|   "Predicate that returns t if a proposed shortened form of a | ||||
| single component is acceptable, nil if a longer one should be | ||||
| tried.  The default validates only when the candidate contains at | ||||
| least one word-constituent character, thus strings consisting of | ||||
| punctuation will not be shortened.  For aggressive shortening, | ||||
| bind to a procedure that always returns t. | ||||
|  | ||||
| Users should not generally change the global value of this | ||||
| variable; instead, bind it dynamically around calls to | ||||
| `shorten-strings'.") | ||||
|  | ||||
|  | ||||
| ;; Main procedures | ||||
| ;; | ||||
| (defun shorten-one (str others) | ||||
|   "Return shortest unique prefix of STR among OTHERS, or STR if | ||||
| it cannot be shortened.  If STR is a member of OTHERS (tested | ||||
| with `eq') that entry is ignored.  The value of | ||||
| `shorten-validate-component-function' will be used to validate | ||||
| any prefix." | ||||
|   (let ((max (length str)) | ||||
|         (len 1)) | ||||
|     (or (catch 'return | ||||
|           (while (< len max) | ||||
|             (let ((prefix (substring str 0 len))) | ||||
|               (when (funcall shorten-validate-component-function prefix) | ||||
|                 (when (catch 'return | ||||
|                         (dolist (other others t) | ||||
|                           (when (and (>= (length other) len) | ||||
|                                      (string= (substring other 0 len) prefix) | ||||
|                                      (not (eq other str))) | ||||
|                             (throw 'return nil)))) | ||||
|                   (throw 'return prefix))) | ||||
|               (setq len (1+ len))))) | ||||
|         str))) | ||||
|  | ||||
| (defun shorten-walk-internal (node path tail-count result-out) | ||||
|   (let ((others (mapcar #'car node))) | ||||
|     (setq tail-count (if (cdr node) 0 (1+ tail-count))) | ||||
|     (dolist (entry node) | ||||
|       (let* ((token (shorten-tree-token entry)) | ||||
|              (shortened (shorten-one token others)) | ||||
|              (path (cons shortened path)) | ||||
|              (fullname (shorten-tree-fullname entry)) | ||||
|              (descendants (shorten-tree-descendants entry)) | ||||
|              (have-descendants (not (equal '(nil) descendants)))) | ||||
|         (shorten-tree-set-shortened entry shortened) | ||||
|         ;; if this entry has a fullname, add to result-out | ||||
|         (when fullname | ||||
|           (let ((joined (funcall shorten-join-function | ||||
|                                  (reverse path) | ||||
|                                  (if have-descendants 0 tail-count)))) | ||||
|             (shorten-tree-insert result-out (cons fullname joined)))) | ||||
|         ;; if this entry has descendants, recurse | ||||
|         (when have-descendants | ||||
|           (shorten-walk-internal descendants path | ||||
|                                  (if fullname -1 tail-count) | ||||
|                                  result-out)))))) | ||||
|  | ||||
| (defun shorten-walk (tree) | ||||
|   "Takes a tree of the type made by `shorten-make-tree' and | ||||
| returns an alist ((STRING . SHORTENED-STRING) ...).  Uses | ||||
| `shorten-join-function' to join shortened components back | ||||
| together into SHORTENED-STRING.  See also | ||||
| `shorten-validate-component-function'." | ||||
|   (let ((result-out (shorten-make-tree-root))) | ||||
|     (shorten-walk-internal tree '() -1 result-out) | ||||
|     (if (equal '(nil) result-out) nil result-out))) | ||||
|  | ||||
| (defun shorten-make-tree (strings) | ||||
|   "Takes a list of strings and returns a tree of the type used by | ||||
| `shorten-walk' to generate shortened strings.  Uses | ||||
| `shorten-split-function' to split the strings." | ||||
|   (let ((tree (shorten-make-tree-root))) | ||||
|     (dolist (s strings) | ||||
|       (let ((node tree) | ||||
|             (tokens (funcall shorten-split-function s)) | ||||
|             (entry nil)) | ||||
|         ;; create a path in tree for tokens | ||||
|         (dolist (token tokens) | ||||
|           (setq entry (assoc token node)) | ||||
|           (when (not entry) | ||||
|             (setq entry (shorten-tree-make-entry token nil nil)) | ||||
|             (shorten-tree-insert node entry)) | ||||
|           (setq node (shorten-tree-descendants entry))) | ||||
|         ;; for the last token, set 'fullname' | ||||
|         (shorten-tree-set-fullname entry s))) | ||||
|     (if (equal tree '(nil)) nil tree))) | ||||
|  | ||||
| ;;;###autoload | ||||
| (defun shorten-strings (strings) | ||||
|   "Takes a list of strings and returns an alist ((STRING | ||||
| . SHORTENED-STRING) ...).  Uses `shorten-split-function' to split | ||||
| the strings, and `shorten-join-function' to join shortened | ||||
| components back together into SHORTENED-STRING.  See also | ||||
| `shorten-validate-component-function'." | ||||
|   (shorten-walk (shorten-make-tree strings))) | ||||
|  | ||||
|  | ||||
| (provide 'shorten) | ||||
| ;;; shorten.el ends here | ||||
							
								
								
									
										391
									
								
								elpa/circe-20160608.1315/tracking.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										391
									
								
								elpa/circe-20160608.1315/tracking.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,391 @@ | ||||
| ;;; tracking.el --- Buffer modification tracking | ||||
|  | ||||
| ;; Copyright (C) 2006, 2012 - 2015  Jorgen Schaefer | ||||
|  | ||||
| ;; Author: Jorgen Schaefer <forcer@forcix.cx> | ||||
| ;; URL: https://github.com/jorgenschaefer/circe/wiki/Tracking | ||||
|  | ||||
| ;; This program is free software: you can redistribute it and/or modify | ||||
| ;; it under the terms of the GNU General Public License as published by | ||||
| ;; the Free Software Foundation, either version 3 of the License, or | ||||
| ;; (at your option) any later version. | ||||
|  | ||||
| ;; This program is distributed in the hope that it will be useful, | ||||
| ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| ;; GNU General Public License for more details. | ||||
|  | ||||
| ;; You should have received a copy of the GNU General Public License | ||||
| ;; along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  | ||||
| ;;; Commentary: | ||||
|  | ||||
| ;; tracking.el is a library for other Emacs Lisp programs not useful | ||||
| ;; by itself. | ||||
|  | ||||
| ;; The library provides a way to globally register buffers as being | ||||
| ;; modified and scheduled for user review. The user can cycle through | ||||
| ;; the buffers using C-c C-SPC. This is especially useful for buffers | ||||
| ;; that interact with external sources, such as chat clients and | ||||
| ;; similar programs. | ||||
|  | ||||
| ;;; Code: | ||||
|  | ||||
| (require 'easy-mmode) | ||||
| (require 'shorten) | ||||
| (require 'cl-lib) | ||||
|  | ||||
| ;;; User customization | ||||
| (defgroup tracking nil | ||||
|   "Tracking of buffer activities." | ||||
|   :prefix "tracking-" | ||||
|   :group 'applications) | ||||
|  | ||||
| (defcustom tracking-shorten-buffer-names-p t | ||||
|   "Whether to shorten buffer names in the mode line. | ||||
| A non-nil value will cause tracked buffer names to be shortened | ||||
| as much as possible to stay unambiguous when displaying them in | ||||
| the mode line." | ||||
|   :type 'boolean | ||||
|   :group 'tracking) | ||||
|  | ||||
| (defcustom tracking-frame-behavior 'visible | ||||
|   "How to deal with frams to determine visibility of buffers. | ||||
| This is passed as the second argument to `get-buffer-window', | ||||
| see there for further explanation." | ||||
|   :type '(choice (const :tag "All visible frames" visible) | ||||
|                  (const :tag "Visible and iconified frames" 0) | ||||
|                  (const :tag "All frames" t) | ||||
|                  (const :tag "Selected frame only" nil)) | ||||
|   :group 'tracking) | ||||
|  | ||||
| (defcustom tracking-position 'before-modes | ||||
|   "Where tracked buffers should appear in the mode line. | ||||
|  | ||||
|   'before-modes | ||||
|       Before the mode indicators | ||||
|   'after-modes | ||||
|       After the mode indicators | ||||
|   'end | ||||
|       At the end of the mode line" | ||||
|   :type '(choice (const :tag "Before the Mode Indicators" before-modes) | ||||
|                  (const :tag "Afterthe Mode Indicators" after-modes) | ||||
|                  (const :tag "At the End of the Mode Line" end)) | ||||
|   :group 'tracking) | ||||
|  | ||||
| (defcustom tracking-faces-priorities nil | ||||
|   "A list of faces which should be shown by tracking in the mode line. | ||||
| The first face found in this list is used." | ||||
|   :type '(repeat face) | ||||
|   :group 'tracking) | ||||
|  | ||||
| (defcustom tracking-ignored-buffers nil | ||||
|   "A list of buffers that are never tracked. | ||||
| Each element of this list has one of the following forms: | ||||
|  | ||||
|   regexp - Any buffer matching won't be tracked. | ||||
|   function - Any buffer matching won't be tracked. | ||||
|   (regexp faces ...) - Any buffer matching won't be tracked, | ||||
|       unless it has a face in FACES ... associated with it. | ||||
|       If no faces are given, `tracking-faces-priorities' is | ||||
|       used. | ||||
|   (function faces ...) - As per above, but with a function | ||||
|       as predicate instead of a regexp." | ||||
|   :type '(repeat (choice regexp | ||||
|                          function | ||||
|                          (list (choice regexp function) | ||||
|                                (repeat face)))) | ||||
|   :group 'tracking) | ||||
|  | ||||
| (defcustom tracking-most-recent-first nil | ||||
|   "When non-nil, newly tracked buffers will go to the front of the | ||||
| list, rather than to the end." | ||||
|   :type 'boolean | ||||
|   :group 'tracking) | ||||
|  | ||||
| (defcustom tracking-buffer-added-hook nil | ||||
|   "Hook run when a buffer has some activity. | ||||
|  | ||||
| The functions are run in the context of the buffer. | ||||
|  | ||||
| This can also happen when the buffer is already tracked. Check if the | ||||
| buffer name is in `tracking-buffers' if you want to see if it was | ||||
| added before." | ||||
|   :type 'hook | ||||
|   :group 'tracking) | ||||
|  | ||||
| (defcustom tracking-buffer-removed-hook nil | ||||
|   "Hook run when a buffer becomes active and is removed. | ||||
|  | ||||
| The functions are run in the context of the buffer." | ||||
|   :type 'hook | ||||
|   :group 'tracking) | ||||
|  | ||||
| ;;; Internal variables | ||||
| (defvar tracking-buffers nil | ||||
|   "The list of currently tracked buffers.") | ||||
|  | ||||
| (defvar tracking-mode-line-buffers "" | ||||
|   "The entry to the mode line.") | ||||
| (put 'tracking-mode-line-buffers 'risky-local-variable t) | ||||
|  | ||||
| (defvar tracking-start-buffer nil | ||||
|   "The buffer we started from when cycling through the active buffers.") | ||||
|  | ||||
| (defvar tracking-last-buffer nil | ||||
|   "The buffer we last switched to with `tracking-next-buffer'. | ||||
| When this is not the current buffer when we continue switching, a | ||||
| new `tracking-start-buffer' is created.") | ||||
|  | ||||
| (defvar tracking-mode-map | ||||
|   (let ((map (make-sparse-keymap))) | ||||
|     (define-key map (kbd "C-c C-SPC") 'tracking-next-buffer) | ||||
|     (define-key map (kbd "C-c C-@") 'tracking-next-buffer) | ||||
|     map) | ||||
|   "The keymap used for tracking mode.") | ||||
|  | ||||
| ;;;###autoload | ||||
| (define-minor-mode tracking-mode | ||||
|   "Allow cycling through modified buffers. | ||||
| This mode in itself does not track buffer modification, but | ||||
| provides an API for programs to add buffers as modified (using | ||||
| `tracking-add-buffer'). | ||||
|  | ||||
| Once this mode is active, modified buffers are shown in the mode | ||||
| line. The user can cycle through them using | ||||
| \\[tracking-next-buffer]." | ||||
|   :group 'tracking | ||||
|   :global t | ||||
|   (cond | ||||
|    (tracking-mode | ||||
|     (cond | ||||
|      ((eq tracking-position 'before-modes) | ||||
|       (let ((head nil) | ||||
|             (tail (default-value 'mode-line-format))) | ||||
|         (when (not (memq 'tracking-mode-line-buffers tail)) | ||||
|           (catch 'return | ||||
|             (while tail | ||||
|               (if (not (eq (car tail) | ||||
|                            'mode-line-modes)) | ||||
|                   (setq head (cons (car tail) | ||||
|                                    head) | ||||
|                         tail (cdr tail)) | ||||
|                 (setq-default mode-line-format | ||||
|                               (append (reverse head) | ||||
|                                       '(tracking-mode-line-buffers) | ||||
|                                       tail)) | ||||
|                 (throw 'return t))))))) | ||||
|      ((eq tracking-position 'after-modes) | ||||
|       (add-to-list 'mode-line-misc-info | ||||
|                    'tracking-mode-line-buffers)) | ||||
|      ((eq tracking-position 'end) | ||||
|       (add-to-list 'mode-line-misc-info | ||||
|                    'tracking-mode-line-buffers | ||||
|                    t)) | ||||
|      (t | ||||
|       (error "Invalid value for `tracking-position' (%s)" tracking-position))) | ||||
|     (add-hook 'window-configuration-change-hook | ||||
|               'tracking-remove-visible-buffers)) | ||||
|    (t | ||||
|     (setq mode-line-misc-info (delq 'tracking-mode-line-buffers | ||||
|                                     mode-line-misc-info)) | ||||
|     (setq-default mode-line-format (delq 'tracking-mode-line-buffers | ||||
|                                          (default-value 'mode-line-format))) | ||||
|     (remove-hook 'window-configuration-change-hook | ||||
|                  'tracking-remove-visible-buffers)))) | ||||
|  | ||||
| ;;;###autoload | ||||
| (defun tracking-add-buffer (buffer &optional faces) | ||||
|   "Add BUFFER as being modified with FACES. | ||||
| This does check whether BUFFER is currently visible. | ||||
|  | ||||
| If FACES is given, it lists the faces that might be appropriate | ||||
| for BUFFER in the mode line. The highest-priority face of these | ||||
| and the current face of the buffer, if any, is used. Priority is | ||||
| decided according to `tracking-faces-priorities'." | ||||
|   (when (and (not (get-buffer-window buffer tracking-frame-behavior)) | ||||
|              (not (tracking-ignored-p buffer faces))) | ||||
|     (with-current-buffer buffer | ||||
|       (run-hooks 'tracking-buffer-added-hook)) | ||||
|     (let* ((entry (member (buffer-name buffer) | ||||
|                           tracking-buffers))) | ||||
|       (if entry | ||||
|           (setcar entry (tracking-faces-merge (car entry) | ||||
|                                               faces)) | ||||
|         (setq tracking-buffers | ||||
|               (if tracking-most-recent-first | ||||
|                   (cons (tracking-faces-merge (buffer-name buffer) | ||||
|                                               faces) | ||||
|                         tracking-buffers) | ||||
|                   (nconc tracking-buffers | ||||
|                          (list (tracking-faces-merge (buffer-name buffer) | ||||
|                                                      faces))))))) | ||||
|     (setq tracking-mode-line-buffers (tracking-status)) | ||||
|     (force-mode-line-update t) | ||||
|     )) | ||||
|  | ||||
| ;;;###autoload | ||||
| (defun tracking-remove-buffer (buffer) | ||||
|   "Remove BUFFER from being tracked." | ||||
|   (when (member (buffer-name buffer) | ||||
|                 tracking-buffers) | ||||
|     (with-current-buffer buffer | ||||
|       (run-hooks 'tracking-buffer-removed-hook))) | ||||
|   (setq tracking-buffers (delete (buffer-name buffer) | ||||
|                                  tracking-buffers)) | ||||
|   (setq tracking-mode-line-buffers (tracking-status)) | ||||
|   (sit-for 0) ;; Update mode line | ||||
|   ) | ||||
|  | ||||
| ;;;###autoload | ||||
| (defun tracking-next-buffer () | ||||
|   "Switch to the next active buffer." | ||||
|   (interactive) | ||||
|   (cond | ||||
|    ((and (not tracking-buffers) | ||||
|          tracking-start-buffer) | ||||
|     (let ((buf tracking-start-buffer)) | ||||
|       (setq tracking-start-buffer nil) | ||||
|       (if (buffer-live-p buf) | ||||
|           (switch-to-buffer buf) | ||||
|         (message "Original buffer does not exist anymore") | ||||
|         (ding)))) | ||||
|    ((not tracking-buffers) | ||||
|     nil) | ||||
|    (t | ||||
|     (when (not (eq tracking-last-buffer | ||||
|                    (current-buffer))) | ||||
|       (setq tracking-start-buffer (current-buffer))) | ||||
|     (let ((new (car tracking-buffers))) | ||||
|       (when (buffer-live-p (get-buffer new)) | ||||
|         (with-current-buffer new | ||||
|           (run-hooks 'tracking-buffer-removed-hook))) | ||||
|       (setq tracking-buffers (cdr tracking-buffers) | ||||
|             tracking-mode-line-buffers (tracking-status)) | ||||
|       (if (buffer-live-p (get-buffer new)) | ||||
|           (switch-to-buffer new) | ||||
|         (message "Buffer %s does not exist anymore" new) | ||||
|         (ding) | ||||
|         (setq tracking-mode-line-buffers (tracking-status)))) | ||||
|     (setq tracking-last-buffer (current-buffer)) | ||||
|     ;; Update mode line. See `force-mode-line-update' for the idea for | ||||
|     ;; this code. Using `sit-for' can be quite inefficient for larger | ||||
|     ;; buffers. | ||||
|     (dolist (w (window-list)) | ||||
|       (with-current-buffer (window-buffer w))) | ||||
|     ))) | ||||
|  | ||||
| ;;;###autoload | ||||
| (defun tracking-previous-buffer () | ||||
|   "Switch to the last active buffer." | ||||
|   (interactive) | ||||
|   (when tracking-buffers | ||||
|     (switch-to-buffer (car (last tracking-buffers))))) | ||||
|  | ||||
| (defun tracking-ignored-p (buffer faces) | ||||
|   "Return non-nil when BUFFER with FACES shouldn't be tracked. | ||||
| This uses `tracking-ignored-buffers'.  Actual returned value is | ||||
| the entry from tracking-ignored-buffers that causes this buffer | ||||
| to be ignored." | ||||
|   (catch 'return | ||||
|     (let ((buffer-name (buffer-name buffer))) | ||||
|       (dolist (entry tracking-ignored-buffers) | ||||
|         (cond | ||||
|          ((stringp entry) | ||||
|           (and (string-match entry buffer-name) | ||||
|                (throw 'return entry))) | ||||
|          ((functionp entry) | ||||
|           (and (funcall entry buffer-name) | ||||
|                (throw 'return entry))) | ||||
|          ((or (and (stringp (car entry)) | ||||
|                    (string-match (car entry) buffer-name)) | ||||
|               (and (functionp (car entry)) | ||||
|                    (funcall (car entry) buffer-name))) | ||||
|           (when (not (tracking-any-in (or (cdr entry) | ||||
|                                           tracking-faces-priorities) | ||||
|                                       faces)) | ||||
|             (throw 'return entry)))))) | ||||
|     nil)) | ||||
|  | ||||
| (defun tracking-status () | ||||
|   "Return the current track status. | ||||
|  | ||||
| This returns a list suitable for `mode-line-format'." | ||||
|   (if (not tracking-buffers) | ||||
|       "" | ||||
|     (let* ((buffer-names (cl-remove-if-not #'get-buffer tracking-buffers)) | ||||
|            (shortened-names (tracking-shorten tracking-buffers)) | ||||
|            (result (list " ["))) | ||||
|       (while buffer-names | ||||
|         (push `(:propertize | ||||
|                 ,(car shortened-names) | ||||
|                 face ,(get-text-property 0 'face (car buffer-names)) | ||||
|                 keymap ,(let ((map (make-sparse-keymap))) | ||||
|                           (define-key map [mode-line down-mouse-1] | ||||
|                             `(lambda () | ||||
|                                (interactive) | ||||
|                                (pop-to-buffer ,(car buffer-names)))) | ||||
|                           map) | ||||
|                 mouse-face mode-line-highlight | ||||
|                 help-echo ,(format (concat "New activity in %s\n" | ||||
|                                            "mouse-1: pop to the buffer") | ||||
|                                    (car buffer-names))) | ||||
|               result) | ||||
|         (setq buffer-names (cdr buffer-names) | ||||
|               shortened-names (cdr shortened-names)) | ||||
|         (when buffer-names | ||||
|           (push "," result))) | ||||
|       (push "] " result) | ||||
|       (nreverse result)))) | ||||
|  | ||||
| (defun tracking-remove-visible-buffers () | ||||
|   "Remove visible buffers from the tracked buffers. | ||||
| This is usually called via `window-configuration-changed-hook'." | ||||
|   (interactive) | ||||
|   (dolist (buffer-name tracking-buffers) | ||||
|     (let ((buffer (get-buffer buffer-name))) | ||||
|       (cond | ||||
|        ((not buffer) | ||||
|         (setq tracking-buffers (delete buffer-name tracking-buffers)) | ||||
|         (setq tracking-mode-line-buffers (tracking-status)) | ||||
|         (sit-for 0)) | ||||
|        ((get-buffer-window buffer tracking-frame-behavior) | ||||
|         (tracking-remove-buffer buffer)))))) | ||||
|  | ||||
| ;;; Helper functions | ||||
| (defun tracking-shorten (buffers) | ||||
|   "Shorten BUFFERS according to `tracking-shorten-buffer-names-p'." | ||||
|   (if tracking-shorten-buffer-names-p | ||||
|       (let ((all (shorten-strings (mapcar #'buffer-name (buffer-list))))) | ||||
|         (mapcar (lambda (buffer) | ||||
|                   (let ((short (cdr (assoc buffer all)))) | ||||
|                     (set-text-properties | ||||
|                      0 (length short) | ||||
|                      (text-properties-at 0 buffer) | ||||
|                      short) | ||||
|                     short)) | ||||
|                 buffers)) | ||||
|     buffers)) | ||||
|  | ||||
| (defun tracking-any-in (lista listb) | ||||
|   "Return non-nil when any element in LISTA is in LISTB" | ||||
|   (catch 'return | ||||
|     (dolist (entry lista) | ||||
|       (when (memq entry listb) | ||||
|         (throw 'return t))) | ||||
|     nil)) | ||||
|  | ||||
| (defun tracking-faces-merge (string faces) | ||||
|   "Merge faces into string, adhering to `tracking-faces-priorities'. | ||||
| This returns STRING with the new face." | ||||
|   (let ((faces (cons (get-text-property 0 'face string) | ||||
|                      faces))) | ||||
|     (catch 'return | ||||
|       (dolist (candidate tracking-faces-priorities) | ||||
|         (when (memq candidate faces) | ||||
|           (throw 'return | ||||
|                  (propertize string 'face candidate)))) | ||||
|       string))) | ||||
|  | ||||
| (provide 'tracking) | ||||
| ;;; tracking.el ends here | ||||
							
								
								
									
										26
									
								
								elpa/emojify-20160928.550/data/emoji-sets.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								elpa/emojify-20160928.550/data/emoji-sets.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| { | ||||
|     "emojione-v2-22" : { | ||||
|         "description" : "Emojis provided by Emoji One (version 2), resized to 22px", | ||||
|         "website" : "http://emojione.com", | ||||
|         "url" : "https://github.com/iqbalansari/emacs-emojify/blob/a81cfd11cdd0eb5b6840d2a7fe95a9505195c1a3/emojione-v2-22.tar?raw=true", | ||||
|         "sha256" : "adbe3cf2c776fe7daf375d8e8dbd4c40567a1dbb753dce1d05e61a2f815572d3" | ||||
|     }, | ||||
|     "emojione-v2" : { | ||||
|         "description" : "Emojis provided by Emoji One (version 2)", | ||||
|         "website" : "http://emojione.com", | ||||
|         "url" : "https://github.com/iqbalansari/emacs-emojify/blob/a81cfd11cdd0eb5b6840d2a7fe95a9505195c1a3/emojione-v2.tar?raw=true", | ||||
|         "sha256" : "46c5a600a148897da22d42d36f42ad764868568943e96917c33e0fe44113afef" | ||||
|     }, | ||||
|     "emojione-v2.2.6-22" : { | ||||
|         "description" : "Emojis provided by Emoji One (version 2.2.6), resized to 22px", | ||||
|         "website" : "http://emojione.com", | ||||
|         "url" : "https://github.com/iqbalansari/emacs-emojify/blob/4e91ba8c2b3415cd78f53e7026fc76b9ac935fc3/emojione-v2.2.6-22.tar?raw=true", | ||||
|         "sha256" : "56dede1c77ad690eebc21e00913b9c7525d290f1a936f87aad282014b04bf2a7" | ||||
|     }, | ||||
|     "emojione-v2.2.6" : { | ||||
|         "description" : "Emojis provided by Emoji One (version 2.2.6)", | ||||
|         "website" : "http://emojione.com", | ||||
|         "url" : "https://github.com/iqbalansari/emacs-emojify/blob/4e91ba8c2b3415cd78f53e7026fc76b9ac935fc3/emojione-v2.2.6.tar?raw=true", | ||||
|         "sha256" : "416b5807d9836a7030434710c9b859accce1e2e5c3c0dcae8ef2a0d9483ff2e9" | ||||
|     } | ||||
| } | ||||
							
								
								
									
										31306
									
								
								elpa/emojify-20160928.550/data/emoji.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31306
									
								
								elpa/emojify-20160928.550/data/emoji.json
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										68
									
								
								elpa/emojify-20160928.550/emojify-autoloads.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								elpa/emojify-20160928.550/emojify-autoloads.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,68 @@ | ||||
| ;;; emojify-autoloads.el --- automatically extracted autoloads | ||||
| ;; | ||||
| ;;; Code: | ||||
| (add-to-list 'load-path (directory-file-name (or (file-name-directory #$) (car load-path)))) | ||||
|  | ||||
| ;;;### (autoloads nil "emojify" "emojify.el" (22533 17536 588433 | ||||
| ;;;;;;  374000)) | ||||
| ;;; Generated autoloads from emojify.el | ||||
|  | ||||
| (autoload 'emojify-set-emoji-styles "emojify" "\ | ||||
| Set the type of emojis that should be displayed. | ||||
|  | ||||
| STYLES is the styles emoji styles that should be used, see `emojify-emoji-styles' | ||||
|  | ||||
| \(fn STYLES)" nil nil) | ||||
|  | ||||
| (autoload 'emojify-mode "emojify" "\ | ||||
| Emojify mode | ||||
|  | ||||
| \(fn &optional ARG)" t nil) | ||||
|  | ||||
| (defvar global-emojify-mode nil "\ | ||||
| Non-nil if Global Emojify mode is enabled. | ||||
| See the `global-emojify-mode' command | ||||
| for a description of this minor mode. | ||||
| Setting this variable directly does not take effect; | ||||
| either customize it (see the info node `Easy Customization') | ||||
| or call the function `global-emojify-mode'.") | ||||
|  | ||||
| (custom-autoload 'global-emojify-mode "emojify" nil) | ||||
|  | ||||
| (autoload 'global-emojify-mode "emojify" "\ | ||||
| Toggle Emojify mode in all buffers. | ||||
| With prefix ARG, enable Global Emojify mode if ARG is positive; | ||||
| otherwise, disable it.  If called from Lisp, enable the mode if | ||||
| ARG is omitted or nil. | ||||
|  | ||||
| Emojify mode is enabled in all buffers where | ||||
| `emojify-mode' would do it. | ||||
| See `emojify-mode' for more information on Emojify mode. | ||||
|  | ||||
| \(fn &optional ARG)" t nil) | ||||
|  | ||||
| (autoload 'emojify-apropos-emoji "emojify" "\ | ||||
| Show Emojis that match PATTERN. | ||||
|  | ||||
| \(fn PATTERN)" t nil) | ||||
|  | ||||
| (autoload 'emojify-insert-emoji "emojify" "\ | ||||
| Interactively prompt for Emojis and insert them in the current buffer. | ||||
|  | ||||
| This respects the `emojify-emoji-styles' variable. | ||||
|  | ||||
| \(fn)" t nil) | ||||
|  | ||||
| ;;;*** | ||||
|  | ||||
| ;;;### (autoloads nil nil ("emojify-pkg.el") (22533 17536 554432 | ||||
| ;;;;;;  598000)) | ||||
|  | ||||
| ;;;*** | ||||
|  | ||||
| ;; Local Variables: | ||||
| ;; version-control: never | ||||
| ;; no-byte-compile: t | ||||
| ;; no-update-autoloads: t | ||||
| ;; End: | ||||
| ;;; emojify-autoloads.el ends here | ||||
							
								
								
									
										9
									
								
								elpa/emojify-20160928.550/emojify-pkg.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								elpa/emojify-20160928.550/emojify-pkg.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| (define-package "emojify" "20160928.550" "Display emojis in Emacs" | ||||
|   '((seq "1.11") | ||||
|     (ht "2.0") | ||||
|     (emacs "24.3")) | ||||
|   :url "https://github.com/iqbalansari/emacs-emojify" :keywords | ||||
|   '("multimedia" "convenience")) | ||||
| ;; Local Variables: | ||||
| ;; no-byte-compile: t | ||||
| ;; End: | ||||
							
								
								
									
										1571
									
								
								elpa/emojify-20160928.550/emojify.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1571
									
								
								elpa/emojify-20160928.550/emojify.el
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										22
									
								
								elpa/gntp-20141024.1950/gntp-autoloads.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								elpa/gntp-20141024.1950/gntp-autoloads.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| ;;; gntp-autoloads.el --- automatically extracted autoloads | ||||
| ;; | ||||
| ;;; Code: | ||||
| (add-to-list 'load-path (directory-file-name (or (file-name-directory #$) (car load-path)))) | ||||
|  | ||||
| ;;;### (autoloads nil "gntp" "gntp.el" (22533 17538 230470 839000)) | ||||
| ;;; Generated autoloads from gntp.el | ||||
|  | ||||
| (autoload 'gntp-notify "gntp" "\ | ||||
| Send notification NAME with TITLE, TEXT, PRIORITY and ICON to SERVER:PORT. | ||||
| PORT defaults to `gntp-server-port' | ||||
|  | ||||
| \(fn NAME TITLE TEXT SERVER &optional PORT PRIORITY ICON)" nil nil) | ||||
|  | ||||
| ;;;*** | ||||
|  | ||||
| ;; Local Variables: | ||||
| ;; version-control: never | ||||
| ;; no-byte-compile: t | ||||
| ;; no-update-autoloads: t | ||||
| ;; End: | ||||
| ;;; gntp-autoloads.el ends here | ||||
							
								
								
									
										2
									
								
								elpa/gntp-20141024.1950/gntp-pkg.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								elpa/gntp-20141024.1950/gntp-pkg.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| ;;; -*- no-byte-compile: t -*- | ||||
| (define-package "gntp" "20141024.1950" "Growl Notification Protocol for Emacs" 'nil) | ||||
							
								
								
									
										243
									
								
								elpa/gntp-20141024.1950/gntp.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										243
									
								
								elpa/gntp-20141024.1950/gntp.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,243 @@ | ||||
| ;;; gntp.el --- Growl Notification Protocol for Emacs -*- lexical-binding: t -*- | ||||
|  | ||||
| ;; Author: Engelke Eschner <tekai@gmx.li> | ||||
| ;; Version: 0.1 | ||||
| ;; Package-Version: 20141024.1950 | ||||
| ;; Created: 2013-03-21 | ||||
|  | ||||
| ;; LICENSE | ||||
| ;; Copyright (c) 2013 Engelke Eschner | ||||
| ;; All rights reserved. | ||||
|  | ||||
| ;; Redistribution and use in source and binary forms, with or without | ||||
| ;; modification, are permitted provided that the following conditions | ||||
| ;; are met: | ||||
| ;;     * Redistributions of source code must retain the above copyright | ||||
| ;;       notice, this list of conditions and the following disclaimer. | ||||
| ;;     * Redistributions in binary form must reproduce the above | ||||
| ;;       copyright notice, this list of conditions and the following | ||||
| ;;       disclaimer in the documentation and/or other materials provided | ||||
| ;;       with the distribution. | ||||
| ;;     * Neither the name of the gntp.el nor the names of its | ||||
| ;;       contributors may be used to endorse or promote products derived | ||||
| ;;       from this software without specific prior written permission. | ||||
|  | ||||
| ;; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||||
| ;; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||||
| ;; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||||
| ;; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT | ||||
| ;; HOLDER> BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||||
| ;; EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||||
| ;; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||||
| ;; PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | ||||
| ;; OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||
| ;; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||||
| ;; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  | ||||
|  | ||||
| ;;; Commentary: | ||||
| ;; This package implements the Growl Notification Protocol GNTP | ||||
| ;; described at http://www.growlforwindows.com/gfw/help/gntp.aspx | ||||
| ;; It is incomplete as it only lets you send but not receive | ||||
| ;; notifications. | ||||
|  | ||||
| ;;; Code: | ||||
|  | ||||
| (defgroup gntp nil | ||||
|   "GNTP, send/register growl notifications via GNTP from within emacs." | ||||
|   :group 'external) | ||||
|  | ||||
| (defcustom gntp-application-name "Emacs/gntp.el" | ||||
|   "Name of the application gntp registers itself." | ||||
|   :type '(string)) | ||||
|  | ||||
| (defcustom gntp-application-icon nil | ||||
|   "Icon to display as the application icon. | ||||
| Either a URL or a path to a file." | ||||
|   :type '(string)) | ||||
|  | ||||
| (defcustom gntp-server "localhost" | ||||
|   "Default port of the server. | ||||
| Standard says can't be changed, but port-forwarding etc." | ||||
|   :type '(string)) | ||||
|  | ||||
| (defcustom gntp-server-port 23053 | ||||
|   "Default port of the server. | ||||
| Standard says can't be changed, but port-forwarding etc." | ||||
|   :type '(integer)) | ||||
|  | ||||
| (defcustom gntp-register-alist nil | ||||
|   "Registration item list." | ||||
|   :type '(choice string (const nil))) | ||||
|  | ||||
| (defun gntp-register (&optional notifications server  port) | ||||
|   (interactive) | ||||
|   "Register NOTIFICATIONS at SERVER:PORT. | ||||
| PORT defaults to `gntp-server-port'." | ||||
|   (let ((message (gntp-build-message-register (if notifications notifications gntp-register-alist)))) | ||||
|     (gntp-send message (if server server gntp-server) port))) | ||||
|  | ||||
| ;;;###autoload | ||||
| (defun gntp-notify (name title text server &optional port priority icon) | ||||
|   "Send notification NAME with TITLE, TEXT, PRIORITY and ICON to SERVER:PORT. | ||||
| PORT defaults to `gntp-server-port'" | ||||
|   (let ((message (gntp-build-message-notify name title text priority icon))) | ||||
|     (gntp-send message server port))) | ||||
|  | ||||
| (defun gntp-build-message-register (notifications) | ||||
|   "Build the message to register NOTIFICATIONS types." | ||||
|   (let ((lines (list "GNTP/1.0 REGISTER NONE" | ||||
|                      (format "Application-Name: %s" | ||||
|                              gntp-application-name) | ||||
|                      (format "Notifications-Count: %d" | ||||
|                              (length notifications)))) | ||||
|         (icon-uri (gntp-app-icon-uri)) | ||||
|         (icon-data (gntp-app-icon-data)) | ||||
|         (icons (list))) | ||||
|  | ||||
|     ;; append icon uri | ||||
|     (when icon-uri | ||||
|       (nconc lines (list (format "Application-Icon: %s" icon-uri))) | ||||
|       ;; and data when it exists | ||||
|       (when icon-data | ||||
|         (setq icons (cons icon-data icons)))) | ||||
|  | ||||
|     (dolist (notice notifications) | ||||
|       ;; "For each notification being registered: | ||||
|       ;; Each notification being registered should be seperated by a | ||||
|       ;; blank line, including the first notification | ||||
|       (nconc lines (cons "" (gntp-notification-lines notice))) | ||||
|       ;; c | ||||
|       (let ((icon (gntp-notice-icon-data notice))) | ||||
|         (when icon | ||||
|           (nconc icons (list "" icon))))) | ||||
|  | ||||
|     ;; icon data must come last | ||||
|     (when icons | ||||
|       (nconc lines (cons "" icons))) | ||||
|  | ||||
|     (mapconcat 'identity (remove nil lines) "\r\n"))) | ||||
|  | ||||
| (defun gntp-notification-lines (notice) | ||||
|   "Transform NOTICE into a list of strings." | ||||
|   (let ((display-name (gntp-notice-get notice :display)) | ||||
|         (enabled (gntp-notice-get notice :enabled)) | ||||
|         (icon-uri (gntp-notice-icon-uri notice))) | ||||
|   (list | ||||
|    ;; Required - The name (type) of the notification being registered | ||||
|    (concat "Notification-Name: " (gntp-notice-name notice)) | ||||
|    ;; Optional - The name of the notification that is displayed to | ||||
|    ;; the user (defaults to the same value as Notification-Name) | ||||
|    (when display-name | ||||
|      (concat "Notification-Display-Name: " display-name)) | ||||
|    ;; Optional - Indicates if the notification should be enabled by | ||||
|    ;; default (defaults to False) | ||||
|    (when enabled | ||||
|      "Notification-Enabled: True") | ||||
|    ;; Optional - The default icon to use for notifications of this type | ||||
|    (when icon-uri | ||||
|      (concat "Notification-Icon: " icon-uri))))) | ||||
|  | ||||
| (defun gntp-build-message-notify (name title text &optional priority icon) | ||||
|   "Build a message of type NAME with TITLE and TEXT." | ||||
|  | ||||
|   (format | ||||
|    "GNTP/1.0 NOTIFY NONE\r\n\ | ||||
| Application-Name: %s\r\n\ | ||||
| Notification-Name: %s\r\n\ | ||||
| Notification-Title: %s\r\n\ | ||||
| Notification-Text: %s\r\n\ | ||||
| Notification-Priority: %s\r\n\ | ||||
| Notification-Icon: %s\r\n\ | ||||
| \r\n" | ||||
|           gntp-application-name | ||||
|           (if (symbolp name) (symbol-name name) name) | ||||
|           title | ||||
|           ;; no CRLF in the text to avoid accidentel msg end | ||||
|           (replace-regexp-in-string "\r\n" "\n" text) | ||||
|           (if priority priority "0") | ||||
|           (if icon (gntp-icon-uri icon) ""))) | ||||
|  | ||||
| ;; notice | ||||
| ;;(list name ; everthing else is optional | ||||
| ;;      :display "name to display" | ||||
| ;;      :enabled nil | ||||
| ;;      :icon "url or file") | ||||
|  | ||||
|  | ||||
| (defun gntp-notice-icon-uri (notice) | ||||
|   "Get the icon URI from NOTICE." | ||||
|   (gntp-icon-uri (gntp-notice-get notice :icon))) | ||||
|  | ||||
| (defun gntp-notice-icon-data (notice) | ||||
|   "Get icon data from NOTICE." | ||||
|   (gntp-icon-data (gntp-notice-get notice :icon))) | ||||
|  | ||||
| (defun gntp-app-icon-uri () | ||||
|   "Return the value to be used in the Application-Icon header." | ||||
|   (gntp-icon-uri gntp-application-icon)) | ||||
|  | ||||
| (defun gntp-app-icon-data () | ||||
|   "Return the value to be used in the Application-Icon header." | ||||
|   (gntp-icon-data gntp-application-icon)) | ||||
|  | ||||
| (defun gntp-icon-uri (icon) | ||||
|   "Get the URI of ICON." | ||||
|   (when icon | ||||
|     (cond ((string-equal (substring icon 0 7) "http://") icon) | ||||
|           ((and (file-exists-p icon) (file-readable-p icon)) | ||||
|            (concat "x-growl-resource://" (md5 icon)))))) | ||||
|  | ||||
| (defun gntp-icon-data (icon) | ||||
|   "Get the URI of ICON." | ||||
|   (when (and icon (not (string-equal (substring icon 0 7) "http://")) | ||||
|              (file-exists-p icon) (file-readable-p icon)) | ||||
|     (let ((id (md5 icon)) | ||||
|           (data (gntp-file-string icon))) | ||||
|       (format "Identifier: %s\r\nLength: %d\r\n\r\n%s" | ||||
|               id (length data) data)))) | ||||
|  | ||||
| (defun gntp-notice-name (notice) | ||||
|   "Get the name of NOTICE.  The name must be either a symbol or string." | ||||
|   (let ((name (car notice))) | ||||
|     (if (symbolp name) | ||||
|         (symbol-name name) | ||||
|       name))) | ||||
|  | ||||
| (defun gntp-notice-get (notice property) | ||||
|   "Get PROPERTY from NOTICE." | ||||
|   (plist-get (cdr notice) property)) | ||||
|  | ||||
| (defun gntp-send (message server &optional port) | ||||
|   "Send MESSAGE to SERVER:PORT.  PORT defaults to `gntp-server-port'." | ||||
|   (let ((proc (make-network-process | ||||
|                :name "gntp" | ||||
|                :host server | ||||
|                :server nil | ||||
|                :service (if port port gntp-server-port) | ||||
|                ;;:sentinel 'gntp-sentinel | ||||
|                :filter 'gntp-filter))) | ||||
|     ;; hmm one CRLF too much? | ||||
|     (process-send-string proc (concat message "\r\n\r\n\r\n")))) | ||||
|  | ||||
| (defun gntp-filter (proc string) | ||||
|   "Filter for PROC started by `gntp-send'. | ||||
| Argument STRING reply from the server." | ||||
|   (when (string-equal "GNTP/1.0 -ERROR" (substring string 0 15)) | ||||
|     (error "GNTP: Something went wrong take a look at the reply:\n %s" | ||||
|            string))) | ||||
|  | ||||
| ;; (defun gntp-sentinel (proc msg) | ||||
| ;;   (when (string= msg "connection broken by remote peer\n") | ||||
| ;;     (message (format "client %s has quit" proc)))) | ||||
|  | ||||
|  | ||||
| (defun gntp-file-string (file) | ||||
|   "Read the contents of a FILE and return as a string." | ||||
|   (with-temp-buffer | ||||
|     (insert-file-contents-literally file) | ||||
|     (buffer-string))) | ||||
|  | ||||
| (provide 'gntp) | ||||
|  | ||||
| ;;; gntp.el ends here | ||||
							
								
								
									
										15
									
								
								elpa/ht-20161015.1945/ht-autoloads.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								elpa/ht-20161015.1945/ht-autoloads.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| ;;; ht-autoloads.el --- automatically extracted autoloads | ||||
| ;; | ||||
| ;;; Code: | ||||
| (add-to-list 'load-path (directory-file-name (or (file-name-directory #$) (car load-path)))) | ||||
|  | ||||
| ;;;### (autoloads nil nil ("ht.el") (22533 17534 488385 459000)) | ||||
|  | ||||
| ;;;*** | ||||
|  | ||||
| ;; Local Variables: | ||||
| ;; version-control: never | ||||
| ;; no-byte-compile: t | ||||
| ;; no-update-autoloads: t | ||||
| ;; End: | ||||
| ;;; ht-autoloads.el ends here | ||||
							
								
								
									
										2
									
								
								elpa/ht-20161015.1945/ht-pkg.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								elpa/ht-20161015.1945/ht-pkg.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| ;;; -*- no-byte-compile: t -*- | ||||
| (define-package "ht" "20161015.1945" "The missing hash table library for Emacs" '((dash "2.12.0")) :keywords '("hash table" "hash map" "hash")) | ||||
							
								
								
									
										288
									
								
								elpa/ht-20161015.1945/ht.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										288
									
								
								elpa/ht-20161015.1945/ht.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,288 @@ | ||||
| ;;; ht.el --- The missing hash table library for Emacs | ||||
|  | ||||
| ;; Copyright (C) 2013 Wilfred Hughes | ||||
|  | ||||
| ;; Author: Wilfred Hughes <me@wilfred.me.uk> | ||||
| ;; Version: 2.2 | ||||
| ;; Package-Version: 20161015.1945 | ||||
| ;; Keywords: hash table, hash map, hash | ||||
| ;; Package-Requires: ((dash "2.12.0")) | ||||
|  | ||||
| ;; This program is free software; you can redistribute it and/or modify | ||||
| ;; it under the terms of the GNU General Public License as published by | ||||
| ;; the Free Software Foundation, either version 3 of the License, or | ||||
| ;; (at your option) any later version. | ||||
|  | ||||
| ;; This program is distributed in the hope that it will be useful, | ||||
| ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| ;; GNU General Public License for more details. | ||||
|  | ||||
| ;; You should have received a copy of the GNU General Public License | ||||
| ;; along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  | ||||
| ;;; Commentary: | ||||
|  | ||||
| ;; The missing hash table library for Emacs. | ||||
| ;; | ||||
| ;; See documentation at https://github.com/Wilfred/ht.el | ||||
|  | ||||
| ;;; Code: | ||||
|  | ||||
| (require 'dash) | ||||
|  | ||||
| (defmacro ht (&rest pairs) | ||||
|   "Create a hash table with the key-value pairs given. | ||||
| Keys are compared with `equal'. | ||||
|  | ||||
| \(fn (KEY-1 VALUE-1) (KEY-2 VALUE-2) ...)" | ||||
|   (let* ((table-symbol (make-symbol "ht-temp")) | ||||
|          (assignments | ||||
|           (mapcar | ||||
|            (lambda (pair) `(ht-set! ,table-symbol ,@pair)) | ||||
|            pairs))) | ||||
|     `(let ((,table-symbol (ht-create))) | ||||
|        ,@assignments | ||||
|        ,table-symbol))) | ||||
|  | ||||
| (defun ht-create (&optional test) | ||||
|   "Create an empty hash table. | ||||
|  | ||||
| TEST indicates the function used to compare the hash | ||||
| keys.  Default is `equal'.  It can be `eq', `eql', `equal' or a | ||||
| user-supplied test created via `define-hash-table-test'." | ||||
|   (make-hash-table :test (or test 'equal))) | ||||
|  | ||||
| (defun ht<-alist (alist &optional test) | ||||
|   "Create a hash table with initial values according to ALIST. | ||||
|  | ||||
| TEST indicates the function used to compare the hash | ||||
| keys.  Default is `equal'.  It can be `eq', `eql', `equal' or a | ||||
| user-supplied test created via `define-hash-table-test'." | ||||
|   (let ((h (ht-create test))) | ||||
|     ;; the first key-value pair in an alist gets precedence, so we | ||||
|     ;; start from the end of the list: | ||||
|     (dolist (pair (reverse alist) h) | ||||
|       (let ((key (car pair)) | ||||
|             (value (cdr pair))) | ||||
|         (ht-set! h key value))))) | ||||
|  | ||||
| (defalias 'ht-from-alist 'ht<-alist) | ||||
|  | ||||
| (defun ht<-plist (plist &optional test) | ||||
|   "Create a hash table with initial values according to PLIST. | ||||
|  | ||||
| TEST indicates the function used to compare the hash | ||||
| keys.  Default is `equal'.  It can be `eq', `eql', `equal' or a | ||||
| user-supplied test created via `define-hash-table-test'." | ||||
|   (let ((h (ht-create test))) | ||||
|     (dolist (pair (-partition 2 plist) h) | ||||
|       (let ((key (car pair)) | ||||
|             (value (cadr pair))) | ||||
|         (ht-set! h key value))))) | ||||
|  | ||||
| (defalias 'ht-from-plist 'ht<-plist) | ||||
|  | ||||
| (defun ht-get (table key &optional default) | ||||
|   "Look up KEY in TABLE, and return the matching value. | ||||
| If KEY isn't present, return DEFAULT (nil if not specified)." | ||||
|   (gethash key table default)) | ||||
|  | ||||
| (defun ht-set! (table key value) | ||||
|   "Associate KEY in TABLE with VALUE." | ||||
|   (puthash key value table) | ||||
|   nil) | ||||
|  | ||||
| (defalias 'ht-set 'ht-set!) | ||||
|  | ||||
| (defun ht-update! (table from-table) | ||||
|   "Update TABLE according to every key-value pair in FROM-TABLE." | ||||
|   (maphash | ||||
|    (lambda (key value) (puthash key value table)) | ||||
|    from-table) | ||||
|   nil) | ||||
|  | ||||
| (defalias 'ht-update 'ht-update!) | ||||
|  | ||||
| (defun ht-merge (&rest tables) | ||||
|   "Crete a new tables that includes all the key-value pairs from TABLES. | ||||
| If multiple have tables have the same key, the value in the last | ||||
| table is used." | ||||
|   (let ((merged (ht-create))) | ||||
|     (mapc (lambda (table) (ht-update! merged table)) tables) | ||||
|     merged)) | ||||
|  | ||||
| (defun ht-remove! (table key) | ||||
|   "Remove KEY from TABLE." | ||||
|   (remhash key table)) | ||||
|  | ||||
| (defalias 'ht-remove 'ht-remove!) | ||||
|  | ||||
| (defun ht-clear! (table) | ||||
|   "Remove all keys from TABLE." | ||||
|   (clrhash table) | ||||
|   nil) | ||||
|  | ||||
| (defalias 'ht-clear 'ht-clear!) | ||||
|  | ||||
| (defun ht-map (function table) | ||||
|   "Apply FUNCTION to each key-value pair of TABLE, and make a list of the results. | ||||
| FUNCTION is called with two arguments, KEY and VALUE." | ||||
|   (let (results) | ||||
|     (maphash | ||||
|      (lambda (key value) | ||||
|        (push (funcall function key value) results)) | ||||
|      table) | ||||
|     results)) | ||||
|  | ||||
| (defmacro ht-amap (form table) | ||||
|   "Anaphoric version of `ht-map'. | ||||
| For every key-value pair in TABLE, evaluate FORM with the | ||||
| variables KEY and VALUE bound." | ||||
|   `(ht-map (lambda (key value) ,form) ,table)) | ||||
|  | ||||
| (defun ht-keys (table) | ||||
|   "Return a list of all the keys in TABLE." | ||||
|   (ht-amap key table)) | ||||
|  | ||||
| (defun ht-values (table) | ||||
|   "Return a list of all the values in TABLE." | ||||
|   (ht-amap value table)) | ||||
|  | ||||
| (defun ht-items (table) | ||||
|   "Return a list of two-element lists '(key value) from TABLE." | ||||
|   (ht-amap (list key value) table)) | ||||
|  | ||||
| (defalias 'ht-each 'maphash | ||||
|   "Apply FUNCTION to each key-value pair of TABLE. | ||||
| Returns nil, used for side-effects only.") | ||||
|  | ||||
| (defmacro ht-aeach (form table) | ||||
|   "Anaphoric version of `ht-each'. | ||||
| For every key-value pair in TABLE, evaluate FORM with the | ||||
| variables key and value bound." | ||||
|   `(ht-each (lambda (key value) ,form) ,table)) | ||||
|  | ||||
| (defun ht-select-keys (table keys) | ||||
|   "Return a copy of TABLE with only the specified KEYS." | ||||
|   (let (result) | ||||
|     (setq result (make-hash-table :test (hash-table-test table))) | ||||
|     (dolist (key keys result) | ||||
|       (if (not (equal (gethash key table 'key-not-found) 'key-not-found)) | ||||
|           (puthash key (gethash key table) result))))) | ||||
|  | ||||
| (defun ht->plist (table) | ||||
|   "Return a flat list '(key1 value1 key2 value2...) from TABLE. | ||||
|  | ||||
| Note that hash tables are unordered, so this cannot be an exact | ||||
| inverse of `ht<-plist'.  The following is not guaranteed: | ||||
|  | ||||
| \(let ((data '(a b c d))) | ||||
|   (equalp data | ||||
|           (ht->plist (ht<-plist data))))" | ||||
|   (apply 'append (ht-items table))) | ||||
|  | ||||
| (defalias 'ht-to-plist 'ht->plist) | ||||
|  | ||||
| (defun ht-copy (table) | ||||
|   "Return a shallow copy of TABLE (keys and values are shared)." | ||||
|   (copy-hash-table table)) | ||||
|  | ||||
| (defun ht->alist (table) | ||||
|   "Return a list of two-element lists '(key . value) from TABLE. | ||||
|  | ||||
| Note that hash tables are unordered, so this cannot be an exact | ||||
| inverse of `ht<-alist'.  The following is not guaranteed: | ||||
|  | ||||
| \(let ((data '((a . b) (c . d)))) | ||||
|   (equalp data | ||||
|           (ht->alist (ht<-alist data))))" | ||||
|   (ht-amap (cons key value) table)) | ||||
|  | ||||
| (defalias 'ht-to-alist 'ht->alist) | ||||
|  | ||||
| (defalias 'ht? 'hash-table-p) | ||||
|  | ||||
| (defalias 'ht-p 'hash-table-p) | ||||
|  | ||||
| (defun ht-contains? (table key) | ||||
|   "Return 't if TABLE contains KEY." | ||||
|   (not (eq (ht-get table key 'ht--not-found) 'ht--not-found))) | ||||
|  | ||||
| (defalias 'ht-contains-p 'ht-contains?) | ||||
|  | ||||
| (defun ht-size (table) | ||||
|   "Return the actual number of entries in TABLE." | ||||
|   (hash-table-count table)) | ||||
|  | ||||
| (defun ht-empty? (table) | ||||
|   "Return true if the actual number of entries in TABLE is zero." | ||||
|   (zerop (ht-size table))) | ||||
|  | ||||
| (defun ht-select (function table) | ||||
|   "Return a hash table containing all entries in TABLE for which | ||||
| FUNCTION returns a truthy value. | ||||
|  | ||||
| FUNCTION is called with two arguments, KEY and VALUE." | ||||
|   (let ((results (ht-create))) | ||||
|     (ht-each | ||||
|      (lambda (key value) | ||||
|        (when (funcall function key value) | ||||
|          (ht-set! results key value))) | ||||
|      table) | ||||
|     results)) | ||||
|  | ||||
| (defun ht-reject (function table) | ||||
|   "Return a hash table containing all entries in TABLE for which | ||||
| FUNCTION returns a falsy value. | ||||
|  | ||||
| FUNCTION is called with two arguments, KEY and VALUE." | ||||
|   (let ((results (ht-create))) | ||||
|     (ht-each | ||||
|      (lambda (key value) | ||||
|        (unless (funcall function key value) | ||||
|          (ht-set! results key value))) | ||||
|      table) | ||||
|     results)) | ||||
|  | ||||
| (defun ht-reject! (function table) | ||||
|   "Delete entries from TABLE for which FUNCTION returns a falsy value. | ||||
|  | ||||
| FUNCTION is called with two arguments, KEY and VALUE." | ||||
|   (ht-each | ||||
|    (lambda (key value) | ||||
|      (when (funcall function key value) | ||||
|        (remhash key table))) | ||||
|    table) | ||||
|   nil) | ||||
|  | ||||
| (defalias 'ht-delete-if 'ht-reject!) | ||||
|  | ||||
| (defun ht-find (function table) | ||||
|   "Return (key, value) from TABLE for which FUNCTION returns a truthy value. | ||||
| Return nil otherwise. | ||||
|  | ||||
| FUNCTION is called with two arguments, KEY and VALUE." | ||||
|   (catch 'break | ||||
|     (ht-each | ||||
|      (lambda (key value) | ||||
|        (when (funcall function key value) | ||||
|          (throw 'break (list key value)))) | ||||
|      table))) | ||||
|  | ||||
| (defun ht-equal? (table1 table2) | ||||
|   "Return t if TABLE1 and TABLE2 have the same keys and values. | ||||
| Does not compare equality predicates." | ||||
|   (let ((keys1 (ht-keys table1)) | ||||
|         (keys2 (ht-keys table2)) | ||||
|         (sentinel (make-symbol "ht-sentinel"))) | ||||
|     (and (equal (length keys1) (length keys2)) | ||||
|          (--all? | ||||
|           (equal (ht-get table1 it) | ||||
|                  (ht-get table2 it sentinel)) | ||||
|           keys1)))) | ||||
|  | ||||
| (defalias 'ht-equal-p 'ht-equal?) | ||||
|  | ||||
| (provide 'ht) | ||||
| ;;; ht.el ends here | ||||
							
								
								
									
										15
									
								
								elpa/log4e-20150105.505/log4e-autoloads.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								elpa/log4e-20150105.505/log4e-autoloads.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| ;;; log4e-autoloads.el --- automatically extracted autoloads | ||||
| ;; | ||||
| ;;; Code: | ||||
| (add-to-list 'load-path (directory-file-name (or (file-name-directory #$) (car load-path)))) | ||||
|  | ||||
| ;;;### (autoloads nil nil ("log4e.el") (22533 17537 527454 800000)) | ||||
|  | ||||
| ;;;*** | ||||
|  | ||||
| ;; Local Variables: | ||||
| ;; version-control: never | ||||
| ;; no-byte-compile: t | ||||
| ;; no-update-autoloads: t | ||||
| ;; End: | ||||
| ;;; log4e-autoloads.el ends here | ||||
							
								
								
									
										2
									
								
								elpa/log4e-20150105.505/log4e-pkg.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								elpa/log4e-20150105.505/log4e-pkg.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| ;;; -*- no-byte-compile: t -*- | ||||
| (define-package "log4e" "20150105.505" "provide logging framework for elisp" 'nil :url "https://github.com/aki2o/log4e" :keywords '("log")) | ||||
							
								
								
									
										590
									
								
								elpa/log4e-20150105.505/log4e.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										590
									
								
								elpa/log4e-20150105.505/log4e.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,590 @@ | ||||
| ;;; log4e.el --- provide logging framework for elisp | ||||
|  | ||||
| ;; Copyright (C) 2013  Hiroaki Otsu | ||||
|  | ||||
| ;; Author: Hiroaki Otsu <ootsuhiroaki@gmail.com> | ||||
| ;; Keywords: log | ||||
| ;; Package-Version: 20150105.505 | ||||
| ;; URL: https://github.com/aki2o/log4e | ||||
| ;; Version: 0.3.0 | ||||
|  | ||||
| ;; This program is free software; you can redistribute it and/or modify | ||||
| ;; it under the terms of the GNU General Public License as published by | ||||
| ;; the Free Software Foundation, either version 3 of the License, or | ||||
| ;; (at your option) any later version. | ||||
|  | ||||
| ;; This file is distributed in the hope that it will be useful, | ||||
| ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| ;; GNU General Public License for more details. | ||||
|  | ||||
| ;; You should have received a copy of the GNU General Public License | ||||
| ;; along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  | ||||
| ;;; Commentary: | ||||
| ;;  | ||||
| ;; This extension provides logging framework for elisp. | ||||
|  | ||||
| ;;; Dependency: | ||||
| ;;  | ||||
| ;; Nothing. | ||||
|  | ||||
| ;;; Installation: | ||||
| ;; | ||||
| ;; Put this to your load-path. | ||||
| ;; And put the following lines in your elisp file. | ||||
| ;;  | ||||
| ;; (require 'log4e) | ||||
|  | ||||
| ;;; Configuration: | ||||
| ;;  | ||||
| ;; See <https://github.com/aki2o/log4e/blob/master/README.md> | ||||
| ;; Otherwise, eval following sexp. | ||||
| ;; (describe-function 'log4e:deflogger) | ||||
|  | ||||
| ;;; API: | ||||
| ;;  | ||||
| ;; [EVAL] (autodoc-document-lisp-buffer :type 'command :prefix "log4e:" :docstring t) | ||||
| ;; `log4e:next-log' | ||||
| ;; Move to start of next log on log4e-mode. | ||||
| ;; `log4e:previous-log' | ||||
| ;; Move to start of previous log on log4e-mode. | ||||
| ;; `log4e:insert-start-log-quickly' | ||||
| ;; Insert logging statment for trace level log at start of current function/macro. | ||||
| ;;  | ||||
| ;;  *** END auto-documentation | ||||
| ;;  | ||||
| ;; For detail, see <https://github.com/aki2o/log4e/blob/master/README.md> | ||||
| ;;  | ||||
| ;; [Note] Other than listed above, Those specifications may be changed without notice. | ||||
|  | ||||
| ;;; Tested On: | ||||
| ;;  | ||||
| ;; - Emacs ... GNU Emacs 23.3.1 (i386-mingw-nt5.1.2600) of 2011-08-15 on GNUPACK | ||||
|  | ||||
|  | ||||
| ;; Enjoy!!! | ||||
|  | ||||
|  | ||||
| ;;; Code: | ||||
| (eval-when-compile (require 'cl)) | ||||
| (require 'rx) | ||||
|  | ||||
|  | ||||
| (defconst log4e-log-level-alist '((fatal . 6) | ||||
|                                   (error . 5) | ||||
|                                   (warn  . 4) | ||||
|                                   (info  . 3) | ||||
|                                   (debug . 2) | ||||
|                                   (trace . 1)) | ||||
|   "Alist of log level value.") | ||||
|  | ||||
| (defconst log4e-default-logging-function-name-alist '((fatal . "log-fatal") | ||||
|                                                       (error . "log-error") | ||||
|                                                       (warn  . "log-warn") | ||||
|                                                       (info  . "log-info") | ||||
|                                                       (debug . "log-debug") | ||||
|                                                       (trace . "log-trace")) | ||||
|   "Alist of logging function name at default.") | ||||
|  | ||||
|  | ||||
| (defmacro log4e--def-symmaker (symnm) | ||||
|   `(progn | ||||
|      (defsubst ,(intern (concat "log4e--make-symbol-" symnm)) (prefix) | ||||
|        (intern (concat ,(format "log4e--%s-" symnm) prefix))))) | ||||
|  | ||||
| (log4e--def-symmaker "log-buffer") | ||||
| (log4e--def-symmaker "msg-buffer") | ||||
| (log4e--def-symmaker "log-template") | ||||
| (log4e--def-symmaker "time-template") | ||||
| (log4e--def-symmaker "min-level") | ||||
| (log4e--def-symmaker "max-level") | ||||
| (log4e--def-symmaker "toggle-logging") | ||||
| (log4e--def-symmaker "toggle-debugging") | ||||
| (log4e--def-symmaker "buffer-coding-system") | ||||
| (log4e--def-symmaker "author-mail-address") | ||||
|  | ||||
| (defmacro log4e--def-level-logger (prefix suffix level) | ||||
|   (let ((argform (if suffix | ||||
|                      '(msg &rest msgargs) | ||||
|                    '(level msg &rest msgargs))) | ||||
|         (buff (log4e--make-symbol-log-buffer prefix)) | ||||
|         (codsys (log4e--make-symbol-buffer-coding-system prefix)) | ||||
|         (logtmpl (log4e--make-symbol-log-template prefix)) | ||||
|         (timetmpl (log4e--make-symbol-time-template prefix)) | ||||
|         (minlvl (log4e--make-symbol-min-level prefix)) | ||||
|         (maxlvl (log4e--make-symbol-max-level prefix)) | ||||
|         (logging-p (log4e--make-symbol-toggle-logging prefix))) | ||||
|     `(progn | ||||
|  | ||||
|        ;; Define logging function | ||||
|        (defun ,(intern (concat prefix "--" (or suffix "log"))) ,argform | ||||
|          ,(format "Do logging for %s level log. | ||||
| %sMSG/MSGARGS are passed to `format'." | ||||
|                   (or (eval level) "any") | ||||
|                   (if suffix "" "LEVEL is symbol as a log level in '(trace debug info warn error fatal).\n")) | ||||
|          (let ((log4e--current-msg-buffer ,(log4e--make-symbol-msg-buffer prefix))) | ||||
|            (apply 'log4e--logging ,buff ,codsys ,logtmpl ,timetmpl ,minlvl ,maxlvl ,logging-p ,(if suffix level 'level) msg msgargs))) | ||||
|         | ||||
|        ;; Define logging macro | ||||
|        (defmacro ,(intern (concat prefix "--" (or suffix "log") "*")) ,argform | ||||
|          ,(format "Do logging for %s level log. | ||||
| %sMSG/MSGARGS are passed to `format'. | ||||
| Evaluation of MSGARGS is invoked only if %s level log should be printed." | ||||
|                   (or (eval level) "any") | ||||
|                   (if suffix "" "LEVEL is symbol as a log level in '(trace debug info warn error fatal).\n") | ||||
|                   (or (eval level) "the")) | ||||
|          (let ((prefix ,prefix) | ||||
|                (suffix ,suffix) | ||||
|                (level ',level) | ||||
|                (msg msg) | ||||
|                (msgargs msgargs) | ||||
|                (buff (log4e--make-symbol-log-buffer ,prefix)) | ||||
|                (codsys (log4e--make-symbol-buffer-coding-system ,prefix)) | ||||
|                (logtmpl (log4e--make-symbol-log-template ,prefix)) | ||||
|                (timetmpl (log4e--make-symbol-time-template ,prefix)) | ||||
|                (minlvl (log4e--make-symbol-min-level ,prefix)) | ||||
|                (maxlvl (log4e--make-symbol-max-level ,prefix)) | ||||
|                (logging-p (log4e--make-symbol-toggle-logging ,prefix))) | ||||
|            `(let ((log4e--current-msg-buffer ,(log4e--make-symbol-msg-buffer prefix))) | ||||
|               (when (and ,logging-p | ||||
|                          (log4e--logging-level-p ,minlvl ,maxlvl ,level)) | ||||
|                 (log4e--logging ,buff ,codsys ,logtmpl ,timetmpl ,minlvl ,maxlvl ,logging-p ,(if suffix level 'level) ,msg ,@msgargs))))) | ||||
|         | ||||
|        ))) | ||||
|  | ||||
| (defsubst log4e--logging-level-p (minlevel maxlevel currlevel) | ||||
|   (let ((minlvlvalue (or (assoc-default minlevel log4e-log-level-alist) | ||||
|                          1)) | ||||
|         (maxlvlvalue (or (assoc-default maxlevel log4e-log-level-alist) | ||||
|                          6)) | ||||
|         (currlvlvalue (or (assoc-default currlevel log4e-log-level-alist) | ||||
|                           0))) | ||||
|     (and (>= currlvlvalue minlvlvalue) | ||||
|          (<= currlvlvalue maxlvlvalue)))) | ||||
|  | ||||
| (defsubst log4e--get-or-create-log-buffer (buffnm &optional codesys) | ||||
|   (or (get-buffer buffnm) | ||||
|       (let ((buff (get-buffer-create buffnm))) | ||||
|         (with-current-buffer buff | ||||
|           (log4e-mode) | ||||
|           (when codesys | ||||
|             (setq buffer-file-coding-system codesys))) | ||||
|         buff))) | ||||
|  | ||||
| (defvar log4e--regexp-msg-format | ||||
|   (rx-to-string `(and "%" | ||||
|                       (* (any "+#-0"))        ; flags | ||||
|                       (* (any "0-9"))         ; width | ||||
|                       (? "." (+ (any "0-9"))) ; precision | ||||
|                       (any "a-zA-Z")))) | ||||
|  | ||||
| (defsubst log4e--insert-log (logtmpl timetmpl level msg msgargs propertize-p) | ||||
|   (let ((timetext (format-time-string timetmpl)) | ||||
|         (lvltext (format "%-05s" (upcase (symbol-name level)))) | ||||
|         (buffer-read-only nil)) | ||||
|     (when propertize-p | ||||
|       (put-text-property 0 (length timetext) 'face 'font-lock-doc-face timetext) | ||||
|       (put-text-property 0 (length lvltext) 'face 'font-lock-keyword-face lvltext)) | ||||
|     (let* ((logtext logtmpl) | ||||
|            (logtext (replace-regexp-in-string "%t" timetext logtext)) | ||||
|            (logtext (replace-regexp-in-string "%l" lvltext logtext)) | ||||
|            (logtext (replace-regexp-in-string "%m" msg logtext)) | ||||
|            (begin (point))) | ||||
|       (insert logtext "\n") | ||||
|       (when propertize-p | ||||
|         (put-text-property begin (+ begin 1) 'log4e--level level)) | ||||
|       (loop initially (goto-char begin) | ||||
|             while (and msgargs | ||||
|                        (re-search-forward log4e--regexp-msg-format nil t)) | ||||
|             for currtype = (match-string-no-properties 0) | ||||
|             for currarg = (pop msgargs) | ||||
|             for failfmt = nil | ||||
|             for currtext = (condition-case e | ||||
|                                (format currtype currarg) | ||||
|                              (error (setq failfmt t) | ||||
|                                     (format "=%s=" (error-message-string e)))) | ||||
|             if propertize-p | ||||
|             do (ignore-errors | ||||
|                  (cond (failfmt (put-text-property 0 (length currtext) 'face 'font-lock-warning-face currtext)) | ||||
|                        (t       (put-text-property 0 (length currtext) 'face 'font-lock-string-face currtext)))) | ||||
|             do (replace-match currtext t t)) | ||||
|       (goto-char begin)))) | ||||
|  | ||||
| (defvar log4e--current-msg-buffer nil) | ||||
|  | ||||
| ;; We needs this signature be stay for other compiled plugins using old version | ||||
| (defun log4e--logging (buffnm codsys logtmpl timetmpl minlevel maxlevel logging-p level msg &rest msgargs) | ||||
|   (when (and logging-p | ||||
|              (log4e--logging-level-p minlevel maxlevel level)) | ||||
|     (save-match-data | ||||
|       (with-current-buffer (log4e--get-or-create-log-buffer buffnm codsys) | ||||
|         (goto-char (point-max)) | ||||
|         (let* ((buffer-read-only nil) | ||||
|                (begin (point)) | ||||
|                (currlog (progn | ||||
|                           (log4e--insert-log logtmpl timetmpl level msg msgargs t) | ||||
|                           (goto-char (point-max)) | ||||
|                           (buffer-substring-no-properties begin (point)))) | ||||
|                (msgbuf (or (when (and log4e--current-msg-buffer | ||||
|                                       (not (eq log4e--current-msg-buffer t))) | ||||
|                              (ignore-errors (get-buffer log4e--current-msg-buffer))) | ||||
|                            log4e--current-msg-buffer))) | ||||
|           (when msgbuf | ||||
|             (let ((standard-output (if (buffer-live-p msgbuf) | ||||
|                                        msgbuf | ||||
|                                      standard-output))) | ||||
|               (princ currlog)))) | ||||
|         nil)))) | ||||
|  | ||||
| (defun log4e--get-current-log-line-level () | ||||
|   (save-excursion | ||||
|     (beginning-of-line) | ||||
|     (get-text-property (point) 'log4e--level))) | ||||
|  | ||||
| ;; We needs this signature be stay for other plugins compiled with this old version | ||||
| (defun log4e--clear-log (buffnm) | ||||
|   (with-current-buffer (log4e--get-or-create-log-buffer buffnm) | ||||
|     (setq buffer-read-only nil) | ||||
|     (erase-buffer))) | ||||
|  | ||||
| ;; We needs this signature be stay for other plugins compiled with this old version | ||||
| (defun log4e--open-log (buffnm) | ||||
|   (let* ((buff (get-buffer buffnm))) | ||||
|     (if (not (buffer-live-p buff)) | ||||
|         (message "[Log4E] Not exist log buffer.") | ||||
|       (with-current-buffer buff | ||||
|         (setq buffer-read-only t)) | ||||
|       (pop-to-buffer buff)))) | ||||
|  | ||||
| ;; We needs this signature be stay for other plugins compiled with this old version | ||||
| (defun log4e--open-log-if-debug (buffnm dbg) | ||||
|   (when dbg | ||||
|     (log4e--open-log buffnm))) | ||||
|  | ||||
| ;; (defun log4e--send-report-if-not-debug (buffnm dbg addr prefix) | ||||
| ;;   (let* ((buff (get-buffer buffnm))) | ||||
| ;;     (when (and (not dbg) | ||||
| ;;                (stringp addr) | ||||
| ;;                (buffer-live-p buff)) | ||||
| ;;       (reporter-submit-bug-report addr prefix nil nil nil nil)))) | ||||
|  | ||||
|  | ||||
| (defmacro log4e:deflogger (prefix msgtmpl timetmpl &optional log-function-name-custom-alist) | ||||
|   "Define the functions of logging for your elisp. | ||||
|  | ||||
| Specification: | ||||
|  After eval this, you can use the functions for supporting about logging. They are the following ... | ||||
|  - do logging for each log level. Log level are trace, debug, info, warn, error and fatal. | ||||
|  - set max and min log level. | ||||
|  - switch logging. | ||||
|  - switch debugging. | ||||
|  - open and clear log buffer. | ||||
|  - send bug report for you. | ||||
|  For details, see Functions section. | ||||
|  | ||||
| Argument: | ||||
|  - PREFIX is string as your elisp prefix. | ||||
|  - MSGTMPL is string as format of log. The following words has a special meaning. | ||||
|    - %t ... Replaced with time string. About it, see TIMETMPL argument. | ||||
|    - %l ... Replaced with log level. They are 'TRACE', 'DEBUG', 'INFO', 'WARN', 'ERROR', 'FATAL'. | ||||
|    - %m ... Replaced with log message that passed by you. | ||||
|  - TIMETMPL is string as format of time. This value is passed to `format-time-string'. | ||||
|  - LOG-FUNCTION-NAME-CUSTOM-ALIST is alist as the function name of logging. | ||||
|    - If this value is nil, define the following functions. | ||||
|       yourprefix--log-trace | ||||
|       yourprefix--log-debug | ||||
|       ... | ||||
|       yourprefix--log-fatal | ||||
|    - If you want to custom the name of them, give like the following value. | ||||
|       '((fatal . \"fatal\") | ||||
|         (error . \"error\") | ||||
|         (warn  . \"warn\") | ||||
|         (info  . \"info\") | ||||
|         (debug . \"debug\") | ||||
|         (trace . \"trace\")) | ||||
|      Then, define the following functions. | ||||
|       yourprefix--trace | ||||
|       yourprefix--debug | ||||
|       ... | ||||
|       yourprefix--fatal | ||||
|  | ||||
| Functions: | ||||
|  List all functions defined below. PREFIX is your prefix. | ||||
|  - PREFIX--log-fatal    ... #1 | ||||
|  - PREFIX--log-error    ... #1 | ||||
|  - PREFIX--log-warn     ... #1 | ||||
|  - PREFIX--log-info     ... #1 | ||||
|  - PREFIX--log-debug    ... #1 | ||||
|  - PREFIX--log-trace    ... #1 | ||||
|  - PREFIX--log-fatal*   ... #2 | ||||
|  - PREFIX--log-error*   ... #2 | ||||
|  - PREFIX--log-warn*    ... #2 | ||||
|  - PREFIX--log-info*    ... #2 | ||||
|  - PREFIX--log-debug*   ... #2 | ||||
|  - PREFIX--log-trace*   ... #2 | ||||
|  - PREFIX--log | ||||
|  - PREFIX--log-set-level | ||||
|  - PREFIX--log-enable-logging            ... #3 | ||||
|  - PREFIX--log-disable-logging           ... #3 | ||||
|  - PREFIX--log-enable-messaging          ... #3 | ||||
|  - PREFIX--log-disable-messaging         ... #3 | ||||
|  - PREFIX--log-enable-debugging          ... #3 | ||||
|  - PREFIX--log-disable-debugging         ... #3 | ||||
|  - PREFIX--log-debugging-p | ||||
|  - PREFIX--log-set-coding-system | ||||
|  - PREFIX--log-set-author-mail-address | ||||
|  - PREFIX--log-clear-log                 ... #3 | ||||
|  - PREFIX--log-open-log                  ... #3 | ||||
|  - PREFIX--log-open-log-if-debug | ||||
|  | ||||
|  #1 : You can customize this name | ||||
|  #2 : Name is a #1 name + \"*\" | ||||
|  #3 : This is command | ||||
|  | ||||
| Example: | ||||
| ;; If you develop elisp that has prefix \"hoge\", write and eval the following sexp in your elisp file. | ||||
|  | ||||
|  (require 'log4e) | ||||
|  (log4e:deflogger \"hoge\" \"%t [%l] %m\" \"%H:%M:%S\") | ||||
|  | ||||
| ;; Eval the following | ||||
|  (hoge--log-enable-logging) | ||||
|  | ||||
| ;; Then, write the following | ||||
|  | ||||
|  (defun hoge-do-hoge (hoge) | ||||
|    (if (not (stringp hoge)) | ||||
|        (hoge--log-fatal \"failed do hoge : hoge is '%s'\" hoge) | ||||
|      (hoge--log-debug \"start do hoge about '%s'\" hoge) | ||||
|      (message \"hoge!\") | ||||
|      (hoge--log-info \"done hoge about '%s'\" hoge))) | ||||
|  | ||||
| ;; Eval the following | ||||
|  (hoge-do-hoge \"HOGEGE\") | ||||
|  | ||||
| ;; Do M-x hoge--log-open-log | ||||
| ;; Open the buffer which name is \" *log4e-hoge*\". The buffer string is below | ||||
| 12:34:56 [INFO ] done hoge about 'HOGEGE' | ||||
|  | ||||
| ;; Eval the following | ||||
|  (hoge--log-set-level 'trace) | ||||
|  (hoge-do-hoge \"FUGAGA\") | ||||
|  | ||||
| ;; Do M-x hoge--log-open-log | ||||
| ;; Open the buffer. its string is below | ||||
| 12:34:56 [INFO ] done hoge about 'HOGEGE' | ||||
| 12:35:43 [DEBUG] start do hoge about 'FUGAGA' | ||||
| 12:35:43 [INFO ] done hoge about 'FUGAGA' | ||||
|   | ||||
| " | ||||
|   (declare (indent 0)) | ||||
|   (if (or (not (stringp prefix))   (string= prefix "") | ||||
|           (not (stringp msgtmpl))  (string= msgtmpl "") | ||||
|           (not (stringp timetmpl)) (string= timetmpl "")) | ||||
|       (message "[LOG4E] invalid argument of deflogger") | ||||
|     (let* ((bufsym (log4e--make-symbol-log-buffer prefix)) | ||||
|            (msgbufsym (log4e--make-symbol-msg-buffer prefix)) | ||||
|            (logtmplsym (log4e--make-symbol-log-template prefix)) | ||||
|            (timetmplsym (log4e--make-symbol-time-template prefix)) | ||||
|            (minlvlsym (log4e--make-symbol-min-level prefix)) | ||||
|            (maxlvlsym (log4e--make-symbol-max-level prefix)) | ||||
|            (tglsym (log4e--make-symbol-toggle-logging prefix)) | ||||
|            (dbgsym (log4e--make-symbol-toggle-debugging prefix)) | ||||
|            (codsyssym (log4e--make-symbol-buffer-coding-system prefix)) | ||||
|            (addrsym (log4e--make-symbol-author-mail-address prefix)) | ||||
|            (funcnm-alist (loop with custom-alist = (car (cdr log-function-name-custom-alist)) | ||||
|                                   for lvl in '(fatal error warn info debug trace) | ||||
|                                   for lvlpair = (assq lvl custom-alist) | ||||
|                                   for fname = (or (cdr-safe lvlpair) "") | ||||
|                                   collect (or (if (string-match "\*" fname) | ||||
|                                                   (progn | ||||
|                                                     (message "[LOG4E] ignore %s level name in log-function-name-custom-alist. can't use '*' for the name." lvl) | ||||
|                                                     nil) | ||||
|                                                 lvlpair) | ||||
|                                               (assq lvl log4e-default-logging-function-name-alist))))) | ||||
|       `(progn | ||||
|  | ||||
|          ;; Define variable for prefix | ||||
|          (defvar ,bufsym (format " *log4e-%s*" ,prefix)) | ||||
|          (defvar ,logtmplsym ,msgtmpl) | ||||
|          (defvar ,timetmplsym ,timetmpl) | ||||
|          (defvar ,minlvlsym 'info) | ||||
|          (defvar ,maxlvlsym 'fatal) | ||||
|          (defvar ,tglsym nil) | ||||
|          (defvar ,msgbufsym nil) | ||||
|          (defvar ,dbgsym nil) | ||||
|          (defvar ,codsyssym nil) | ||||
|          (defvar ,addrsym nil) | ||||
|  | ||||
|          ;; Define level set function | ||||
|          (defun ,(intern (concat prefix "--log-set-level")) (minlevel &optional maxlevel) | ||||
|            "Set range for doing logging. | ||||
|  | ||||
| MINLEVEL is symbol of lowest level for doing logging. its default is 'info. | ||||
| MAXLEVEL is symbol of highest level for doing logging. its default is 'fatal." | ||||
|            (setq ,minlvlsym minlevel) | ||||
|            (setq ,maxlvlsym maxlevel)) | ||||
|  | ||||
|          ;; Define logging toggle function | ||||
|          (defun ,(intern (concat prefix "--log-enable-logging")) () | ||||
|            "Enable logging by logging functions." | ||||
|            (interactive) | ||||
|            (setq ,tglsym t)) | ||||
|          (defun ,(intern (concat prefix "--log-disable-logging")) () | ||||
|            "Disable logging by logging functions." | ||||
|            (interactive) | ||||
|            (setq ,tglsym nil)) | ||||
|  | ||||
|          ;; Define messaging toggle function | ||||
|          (defun ,(intern (concat prefix "--log-enable-messaging")) (&optional buffer) | ||||
|            "Enable dump the log into other buffer by logging functions. | ||||
|  | ||||
| BUFFER is a buffer dumped log into. nil means *Messages* buffer." | ||||
|            (interactive) | ||||
|            (setq ,msgbufsym (or buffer t))) | ||||
|          (defun ,(intern (concat prefix "--log-disable-messaging")) () | ||||
|            "Disable dump the log into other buffer by logging functions." | ||||
|            (interactive) | ||||
|            (setq ,msgbufsym nil)) | ||||
|  | ||||
|          ;; Define debugging toggle function | ||||
|          (defun ,(intern (concat prefix "--log-enable-debugging")) () | ||||
|            "Enable debugging and logging. | ||||
|  | ||||
| `PREFIX--log-debugging-p' will return t." | ||||
|            (interactive) | ||||
|            (setq ,tglsym t) | ||||
|            (setq ,dbgsym t)) | ||||
|          (defun ,(intern (concat prefix "--log-disable-debugging")) () | ||||
|            "Disable debugging. | ||||
|  | ||||
| `PREFIX--log-debugging-p' will return nil." | ||||
|            (interactive) | ||||
|            (setq ,dbgsym nil)) | ||||
|          (defun ,(intern (concat prefix "--log-debugging-p")) () | ||||
|            ,dbgsym) | ||||
|  | ||||
|          ;; Define coding system set funtion | ||||
|          (defun ,(intern (concat prefix "--log-set-coding-system")) (coding-system) | ||||
|            "Set charset and linefeed of LOG-BUFFER. | ||||
|  | ||||
| CODING-SYSTEM is symbol for setting to `buffer-file-coding-system'. | ||||
| LOG-BUFFER is a buffer which name is \" *log4e-PREFIX*\"." | ||||
|            (setq ,codsyssym coding-system)) | ||||
|  | ||||
|          ;;          ;; Define author mail set function | ||||
|          ;;          (defun ,(intern (concat prefix "--log-set-author-mail-address")) (before-atmark after-atmark) | ||||
|          ;;            "Set mail address of author for elisp that has PREFIX. This value is used SEND-REPORT. | ||||
|  | ||||
|          ;; BEFORE-ATMARK is string as part of mail address. If your address is \"hoge@example.co.jp\", it is \"hoge\". | ||||
|          ;; AFTER-ATMARK is string as part of mail address. If your address is \"hoge@example.co.jp\", it is \"example.co.jp\". | ||||
|          ;; SEND-REPORT is `PREFIX--log-send-report-if-not-debug'." | ||||
|          ;;            (setq ,addrsym (concat before-atmark "@" after-atmark))) | ||||
|  | ||||
|          ;; Define log buffer handle function | ||||
|          (defun ,(intern (concat prefix "--log-clear-log")) () | ||||
|            "Clear buffer string of buffer which name is \" *log4e-PREFIX*\"." | ||||
|            (interactive) | ||||
|            (log4e--clear-log ,bufsym)) | ||||
|          (defun ,(intern (concat prefix "--log-open-log")) () | ||||
|            "Open buffer which name is \" *log4e-PREFIX*\"." | ||||
|            (interactive) | ||||
|            (log4e--open-log ,bufsym)) | ||||
|          (defun ,(intern (concat prefix "--log-open-log-if-debug")) () | ||||
|            "Open buffer which name is \" *log4e-PREFIX*\" if debugging is enabled." | ||||
|            (log4e--open-log-if-debug ,bufsym ,dbgsym)) | ||||
|  | ||||
|          ;;          ;; Define report send function | ||||
|          ;;          (defun ,(intern (concat prefix "--log-send-report-if-not-debug")) () | ||||
|          ;;            "Send bug report to author if debugging is disabled. | ||||
|  | ||||
|          ;; The author mailaddress is set by `PREFIX--log-set-author-mail-address'. | ||||
|          ;; About the way of sending bug report, see `reporter-submit-bug-report'." | ||||
|          ;;            (log4e--send-report-if-not-debug ,bufsym ,dbgsym ,addrsym ,prefix)) | ||||
|  | ||||
|          ;; Define each level logging function | ||||
|          (log4e--def-level-logger ,prefix nil nil) | ||||
|          (log4e--def-level-logger ,prefix ,(assoc-default 'fatal funcnm-alist) 'fatal) | ||||
|          (log4e--def-level-logger ,prefix ,(assoc-default 'error funcnm-alist) 'error) | ||||
|          (log4e--def-level-logger ,prefix ,(assoc-default 'warn  funcnm-alist) 'warn) | ||||
|          (log4e--def-level-logger ,prefix ,(assoc-default 'info  funcnm-alist) 'info) | ||||
|          (log4e--def-level-logger ,prefix ,(assoc-default 'debug funcnm-alist) 'debug) | ||||
|          (log4e--def-level-logger ,prefix ,(assoc-default 'trace funcnm-alist) 'trace) | ||||
|           | ||||
|          )))) | ||||
|  | ||||
|  | ||||
| (define-derived-mode log4e-mode view-mode "Log4E" | ||||
|   "Major mode for browsing a buffer made by log4e. | ||||
|  | ||||
| \\<log4e-mode-map> | ||||
| \\{log4e-mode-map}" | ||||
|   (define-key log4e-mode-map (kbd "J") 'log4e:next-log) | ||||
|   (define-key log4e-mode-map (kbd "K") 'log4e:previous-log)) | ||||
|  | ||||
| (defun log4e:next-log () | ||||
|   "Move to start of next log on log4e-mode." | ||||
|   (interactive) | ||||
|   (let* ((level)) | ||||
|     (while (and (not level) | ||||
|                 (< (point) (point-max))) | ||||
|       (forward-line 1) | ||||
|       (setq level (log4e--get-current-log-line-level))) | ||||
|     level)) | ||||
|  | ||||
| (defun log4e:previous-log () | ||||
|   "Move to start of previous log on log4e-mode." | ||||
|   (interactive) | ||||
|   (let* ((level)) | ||||
|     (while (and (not level) | ||||
|                 (> (point) (point-min))) | ||||
|       (forward-line -1) | ||||
|       (setq level (log4e--get-current-log-line-level))) | ||||
|     level)) | ||||
|  | ||||
| (defun log4e:insert-start-log-quickly () | ||||
|   "Insert logging statment for trace level log at start of current function/macro." | ||||
|   (interactive) | ||||
|   (let* ((fstartpt (when (re-search-backward "(\\(?:defun\\|defmacro\\|defsubst\\)\\*? +\\([^ ]+\\) +(\\([^)]*\\))" nil t) | ||||
|                      (point))) | ||||
|          (fncnm (when fstartpt (match-string-no-properties 1))) | ||||
|          (argtext (when fstartpt (match-string-no-properties 2))) | ||||
|          (prefix (save-excursion | ||||
|                    (goto-char (point-min)) | ||||
|                    (loop while (re-search-forward "(log4e:deflogger[ \n]+\"\\([^\"]+\\)\"" nil t) | ||||
|                             for prefix = (match-string-no-properties 1) | ||||
|                             for currface = (get-text-property (match-beginning 0) 'face) | ||||
|                             if (not (eq currface 'font-lock-comment-face)) | ||||
|                             return prefix)))) | ||||
|     (when (and fstartpt prefix) | ||||
|       (let* ((fncnm (replace-regexp-in-string (concat "\\`" prefix "[^a-zA-Z0-9]+") "" fncnm)) | ||||
|              (fncnm (replace-regexp-in-string "-" " " fncnm)) | ||||
|              (argtext (replace-regexp-in-string "\n" " " argtext)) | ||||
|              (argtext (replace-regexp-in-string "^ +" "" argtext)) | ||||
|              (argtext (replace-regexp-in-string " +$" "" argtext)) | ||||
|              (args (split-string argtext " +")) | ||||
|              (args (loop for arg in args | ||||
|                             if (and (not (string= arg "")) | ||||
|                                     (not (string-match "\\`&" arg))) | ||||
|                             collect arg)) | ||||
|              (logtext (loop with ret = (format "start %s." fncnm) | ||||
|                                for arg in args | ||||
|                                do (setq ret (concat ret " " arg "[%s]")) | ||||
|                                finally return ret)) | ||||
|              (sexpformat (loop with ret = "(%s--log 'trace \"%s\"" | ||||
|                                   for arg in args | ||||
|                                   do (setq ret (concat ret " %s")) | ||||
|                                   finally return (concat ret ")"))) | ||||
|              (inserttext (apply 'format sexpformat prefix logtext args))) | ||||
|         (forward-char) | ||||
|         (forward-sexp 3) | ||||
|         (when (re-search-forward "\\=[ \n]+\"" nil t) | ||||
|           (forward-char -1) | ||||
|           (forward-sexp)) | ||||
|         (newline-and-indent) | ||||
|         (insert inserttext))))) | ||||
|  | ||||
|  | ||||
| (provide 'log4e) | ||||
| ;;; log4e.el ends here | ||||
							
								
								
									
										45
									
								
								elpa/oauth2-0.11/oauth2-autoloads.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								elpa/oauth2-0.11/oauth2-autoloads.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | ||||
| ;;; oauth2-autoloads.el --- automatically extracted autoloads | ||||
| ;; | ||||
| ;;; Code: | ||||
| (add-to-list 'load-path (directory-file-name (or (file-name-directory #$) (car load-path)))) | ||||
|  | ||||
| ;;;### (autoloads nil "oauth2" "oauth2.el" (22533 17544 732619 192000)) | ||||
| ;;; Generated autoloads from oauth2.el | ||||
|  | ||||
| (autoload 'oauth2-refresh-access "oauth2" "\ | ||||
| Refresh OAuth access TOKEN. | ||||
| TOKEN should be obtained with `oauth2-request-access'. | ||||
|  | ||||
| \(fn TOKEN)" nil nil) | ||||
|  | ||||
| (autoload 'oauth2-auth "oauth2" "\ | ||||
| Authenticate application via OAuth2. | ||||
|  | ||||
| \(fn AUTH-URL TOKEN-URL CLIENT-ID CLIENT-SECRET &optional SCOPE STATE REDIRECT-URI)" nil nil) | ||||
|  | ||||
| (autoload 'oauth2-auth-and-store "oauth2" "\ | ||||
| Request access to a resource and store it using `plstore'. | ||||
|  | ||||
| \(fn AUTH-URL TOKEN-URL RESOURCE-URL CLIENT-ID CLIENT-SECRET &optional REDIRECT-URI)" nil nil) | ||||
|  | ||||
| (autoload 'oauth2-url-retrieve-synchronously "oauth2" "\ | ||||
| Retrieve an URL synchronously using TOKEN to access it. | ||||
| TOKEN can be obtained with `oauth2-auth'. | ||||
|  | ||||
| \(fn TOKEN URL &optional REQUEST-METHOD REQUEST-DATA REQUEST-EXTRA-HEADERS)" nil nil) | ||||
|  | ||||
| (autoload 'oauth2-url-retrieve "oauth2" "\ | ||||
| Retrieve an URL asynchronously using TOKEN to access it. | ||||
| TOKEN can be obtained with `oauth2-auth'.  CALLBACK gets called with CBARGS | ||||
| when finished.  See `url-retrieve'. | ||||
|  | ||||
| \(fn TOKEN URL CALLBACK &optional CBARGS REQUEST-METHOD REQUEST-DATA REQUEST-EXTRA-HEADERS)" nil nil) | ||||
|  | ||||
| ;;;*** | ||||
|  | ||||
| ;; Local Variables: | ||||
| ;; version-control: never | ||||
| ;; no-byte-compile: t | ||||
| ;; no-update-autoloads: t | ||||
| ;; End: | ||||
| ;;; oauth2-autoloads.el ends here | ||||
							
								
								
									
										2
									
								
								elpa/oauth2-0.11/oauth2-pkg.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								elpa/oauth2-0.11/oauth2-pkg.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| ;;; -*- no-byte-compile: t -*- | ||||
| (define-package "oauth2" "0.11" "OAuth 2.0 Authorization Protocol" 'nil :url "http://elpa.gnu.org/packages/oauth2.html" :keywords '("comm")) | ||||
							
								
								
									
										342
									
								
								elpa/oauth2-0.11/oauth2.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										342
									
								
								elpa/oauth2-0.11/oauth2.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,342 @@ | ||||
| ;;; oauth2.el --- OAuth 2.0 Authorization Protocol | ||||
|  | ||||
| ;; Copyright (C) 2011-2016 Free Software Foundation, Inc | ||||
|  | ||||
| ;; Author: Julien Danjou <julien@danjou.info> | ||||
| ;; Version: 0.11 | ||||
| ;; Keywords: comm | ||||
|  | ||||
| ;; 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: | ||||
|  | ||||
| ;; Implementation of the OAuth 2.0 draft. | ||||
| ;; | ||||
| ;; The main entry point is `oauth2-auth-and-store' which will return a token | ||||
| ;; structure.  This token structure can be then used with | ||||
| ;; `oauth2-url-retrieve-synchronously' or `oauth2-url-retrieve' to retrieve | ||||
| ;; any data that need OAuth authentication to be accessed. | ||||
| ;; | ||||
| ;; If the token needs to be refreshed, the code handles it automatically and | ||||
| ;; store the new value of the access token. | ||||
|  | ||||
| ;;; Code: | ||||
|  | ||||
| (eval-when-compile (require 'cl)) | ||||
| (require 'plstore) | ||||
| (require 'json) | ||||
| (require 'url-http) | ||||
|  | ||||
| (defun oauth2-request-authorization (auth-url client-id &optional scope state redirect-uri) | ||||
|   "Request OAuth authorization at AUTH-URL by launching `browse-url'. | ||||
| CLIENT-ID is the client id provided by the provider. | ||||
| It returns the code provided by the service." | ||||
|   (browse-url (concat auth-url | ||||
|                       (if (string-match-p "\?" auth-url) "&" "?") | ||||
|                       "client_id=" (url-hexify-string client-id) | ||||
|                       "&response_type=code" | ||||
|                       "&redirect_uri=" (url-hexify-string (or redirect-uri "urn:ietf:wg:oauth:2.0:oob")) | ||||
|                       (if scope (concat "&scope=" (url-hexify-string scope)) "") | ||||
|                       (if state (concat "&state=" (url-hexify-string state)) ""))) | ||||
|   (read-string "Enter the code your browser displayed: ")) | ||||
|  | ||||
| (defun oauth2-request-access-parse () | ||||
|   "Parse the result of an OAuth request." | ||||
|   (goto-char (point-min)) | ||||
|   (when (search-forward-regexp "^$" nil t) | ||||
|     (json-read))) | ||||
|  | ||||
| (defun oauth2-make-access-request (url data) | ||||
|   "Make an access request to URL using DATA in POST." | ||||
|   (let ((url-request-method "POST") | ||||
|         (url-request-data data) | ||||
|         (url-request-extra-headers | ||||
|          '(("Content-Type" . "application/x-www-form-urlencoded")))) | ||||
|     (with-current-buffer (url-retrieve-synchronously url) | ||||
|       (let ((data (oauth2-request-access-parse))) | ||||
|         (kill-buffer (current-buffer)) | ||||
|         data)))) | ||||
|  | ||||
| (defstruct oauth2-token | ||||
|   plstore | ||||
|   plstore-id | ||||
|   client-id | ||||
|   client-secret | ||||
|   access-token | ||||
|   refresh-token | ||||
|   token-url | ||||
|   access-response) | ||||
|  | ||||
| (defun oauth2-request-access (token-url client-id client-secret code &optional redirect-uri) | ||||
|   "Request OAuth access at TOKEN-URL. | ||||
| The CODE should be obtained with `oauth2-request-authorization'. | ||||
| Return an `oauth2-token' structure." | ||||
|   (when code | ||||
|     (let ((result | ||||
|            (oauth2-make-access-request | ||||
|             token-url | ||||
|             (concat | ||||
|              "client_id=" client-id | ||||
|              "&client_secret=" client-secret | ||||
|              "&code=" code | ||||
|              "&redirect_uri=" (url-hexify-string (or redirect-uri "urn:ietf:wg:oauth:2.0:oob")) | ||||
|              "&grant_type=authorization_code")))) | ||||
|       (make-oauth2-token :client-id client-id | ||||
|                          :client-secret client-secret | ||||
|                          :access-token (cdr (assoc 'access_token result)) | ||||
|                          :refresh-token (cdr (assoc 'refresh_token result)) | ||||
|                          :token-url token-url | ||||
|                          :access-response result)))) | ||||
|  | ||||
| ;;;###autoload | ||||
| (defun oauth2-refresh-access (token) | ||||
|   "Refresh OAuth access TOKEN. | ||||
| TOKEN should be obtained with `oauth2-request-access'." | ||||
|   (setf (oauth2-token-access-token token) | ||||
|         (cdr (assoc 'access_token | ||||
|                     (oauth2-make-access-request | ||||
|                      (oauth2-token-token-url token) | ||||
|                      (concat "client_id=" (oauth2-token-client-id token) | ||||
|                              "&client_secret=" (oauth2-token-client-secret token) | ||||
|                              "&refresh_token=" (oauth2-token-refresh-token token) | ||||
|                              "&grant_type=refresh_token"))))) | ||||
|   ;; If the token has a plstore, update it | ||||
|   (let ((plstore (oauth2-token-plstore token))) | ||||
|     (when plstore | ||||
|       (plstore-put plstore (oauth2-token-plstore-id token) | ||||
|                    nil `(:access-token | ||||
|                          ,(oauth2-token-access-token token) | ||||
|                          :refresh-token | ||||
|                          ,(oauth2-token-refresh-token token) | ||||
|                          :access-response | ||||
|                          ,(oauth2-token-access-response token) | ||||
|                          )) | ||||
|       (plstore-save plstore))) | ||||
|   token) | ||||
|  | ||||
| ;;;###autoload | ||||
| (defun oauth2-auth (auth-url token-url client-id client-secret &optional scope state redirect-uri) | ||||
|   "Authenticate application via OAuth2." | ||||
|   (oauth2-request-access | ||||
|    token-url | ||||
|    client-id | ||||
|    client-secret | ||||
|    (oauth2-request-authorization | ||||
|     auth-url client-id scope state redirect-uri) | ||||
|    redirect-uri)) | ||||
|  | ||||
| (defcustom oauth2-token-file (concat user-emacs-directory "oauth2.plstore") | ||||
|   "File path where store OAuth tokens." | ||||
|   :group 'oauth2 | ||||
|   :type 'file) | ||||
|  | ||||
| (defun oauth2-compute-id (auth-url token-url resource-url) | ||||
|   "Compute an unique id based on URLs. | ||||
| This allows to store the token in an unique way." | ||||
|   (secure-hash 'md5 (concat auth-url token-url resource-url))) | ||||
|  | ||||
| ;;;###autoload | ||||
| (defun oauth2-auth-and-store (auth-url token-url resource-url client-id client-secret &optional redirect-uri) | ||||
|   "Request access to a resource and store it using `plstore'." | ||||
|   ;; We store a MD5 sum of all URL | ||||
|   (let* ((plstore (plstore-open oauth2-token-file)) | ||||
|          (id (oauth2-compute-id auth-url token-url resource-url)) | ||||
|          (plist (cdr (plstore-get plstore id)))) | ||||
|     ;; Check if we found something matching this access | ||||
|     (if plist | ||||
|         ;; We did, return the token object | ||||
|         (make-oauth2-token :plstore plstore | ||||
|                            :plstore-id id | ||||
|                            :client-id client-id | ||||
|                            :client-secret client-secret | ||||
|                            :access-token (plist-get plist :access-token) | ||||
|                            :refresh-token (plist-get plist :refresh-token) | ||||
|                            :token-url token-url | ||||
|                            :access-response (plist-get plist :access-response)) | ||||
|       (let ((token (oauth2-auth auth-url token-url | ||||
|                                 client-id client-secret resource-url nil redirect-uri))) | ||||
|         ;; Set the plstore | ||||
|         (setf (oauth2-token-plstore token) plstore) | ||||
|         (setf (oauth2-token-plstore-id token) id) | ||||
|         (plstore-put plstore id nil `(:access-token | ||||
|                                       ,(oauth2-token-access-token token) | ||||
|                                       :refresh-token | ||||
|                                       ,(oauth2-token-refresh-token token) | ||||
|                                       :access-response | ||||
|                                       ,(oauth2-token-access-response token))) | ||||
|         (plstore-save plstore) | ||||
|         token)))) | ||||
|  | ||||
| (defun oauth2-url-append-access-token (token url) | ||||
|   "Append access token to URL." | ||||
|   (concat url | ||||
|           (if (string-match-p "\?" url) "&" "?") | ||||
|           "access_token=" (oauth2-token-access-token token))) | ||||
|  | ||||
| (defvar oauth--url-advice nil) | ||||
| (defvar oauth--token-data) | ||||
|  | ||||
| (defun oauth2-authz-bearer-header (token) | ||||
|   "Return 'Authoriztions: Bearer' header with TOKEN." | ||||
|   (cons "Authorization" (format "Bearer %s" token))) | ||||
|  | ||||
| (defun oauth2-extra-headers (extra-headers) | ||||
|   "Return EXTRA-HEADERS with 'Authorization: Bearer' added." | ||||
|   (cons (oauth2-authz-bearer-header (oauth2-token-access-token (car oauth--token-data))) | ||||
|         extra-headers)) | ||||
|  | ||||
|  | ||||
| ;; FIXME: We should change URL so that this can be done without an advice. | ||||
| (defadvice url-http-handle-authentication (around oauth-hack activate) | ||||
|   (if (not oauth--url-advice) | ||||
|       ad-do-it | ||||
|     (let ((url-request-method url-http-method) | ||||
|           (url-request-data url-http-data) | ||||
|           (url-request-extra-headers | ||||
|            (oauth2-extra-headers url-http-extra-headers)))) | ||||
|     (oauth2-refresh-access (car oauth--token-data)) | ||||
|     (url-retrieve-internal (cdr oauth--token-data) | ||||
|                url-callback-function | ||||
|                url-callback-arguments) | ||||
|     ;; This is to make `url' think it's done. | ||||
|     (when (boundp 'success) (setq success t)) ;For URL library in Emacs<24.4. | ||||
|     (setq ad-return-value t)))                ;For URL library in Emacs≥24.4. | ||||
|  | ||||
| ;;;###autoload | ||||
| (defun oauth2-url-retrieve-synchronously (token url &optional request-method request-data request-extra-headers) | ||||
|   "Retrieve an URL synchronously using TOKEN to access it. | ||||
| TOKEN can be obtained with `oauth2-auth'." | ||||
|   (let* ((oauth--token-data (cons token url))) | ||||
|     (let ((oauth--url-advice t)         ;Activate our advice. | ||||
|           (url-request-method request-method) | ||||
|           (url-request-data request-data) | ||||
|           (url-request-extra-headers | ||||
|            (oauth2-extra-headers request-extra-headers))) | ||||
|       (url-retrieve-synchronously url)))) | ||||
|  | ||||
| ;;;###autoload | ||||
| (defun oauth2-url-retrieve (token url callback &optional | ||||
|                                   cbargs | ||||
|                                   request-method request-data request-extra-headers) | ||||
|   "Retrieve an URL asynchronously using TOKEN to access it. | ||||
| TOKEN can be obtained with `oauth2-auth'.  CALLBACK gets called with CBARGS | ||||
| when finished.  See `url-retrieve'." | ||||
|   ;; TODO add support for SILENT and INHIBIT-COOKIES.  How to handle this in `url-http-handle-authentication'. | ||||
|   (let* ((oauth--token-data (cons token url))) | ||||
|     (let ((oauth--url-advice t)         ;Activate our advice. | ||||
|           (url-request-method request-method) | ||||
|           (url-request-data request-data) | ||||
|           (url-request-extra-headers | ||||
|            (oauth2-extra-headers request-extra-headers))) | ||||
|       (url-retrieve url callback cbargs)))) | ||||
|  | ||||
| ;;;; ChangeLog: | ||||
|  | ||||
| ;; 2016-07-09  Julien Danjou  <julien@danjou.info> | ||||
| ;;  | ||||
| ;; 	oauth2: send authentication token via Authorization header | ||||
| ;;  | ||||
| ;; 2014-01-28  Rüdiger Sonderfeld  <ruediger@c-plusplus.de> | ||||
| ;;  | ||||
| ;; 	oauth2.el: Add support for async retrieve. | ||||
| ;;  | ||||
| ;; 	* packages/oauth2/oauth2.el (oauth--tokens-need-renew): Remove. | ||||
| ;; 	 (oauth--token-data): New variable. | ||||
| ;; 	 (url-http-handle-authentication): Call `url-retrieve-internal' | ||||
| ;; 	 directly instead of depending on `oauth--tokens-need-renew'. | ||||
| ;; 	 (oauth2-url-retrieve-synchronously): Call `url-retrieve' once. | ||||
| ;; 	 (oauth2-url-retrieve): New function. | ||||
| ;;  | ||||
| ;; 	Signed-off-by: Rüdiger Sonderfeld <ruediger@c-plusplus.de>  | ||||
| ;; 	Signed-off-by: Julien Danjou <julien@danjou.info> | ||||
| ;;  | ||||
| ;; 2013-07-22  Stefan Monnier  <monnier@iro.umontreal.ca> | ||||
| ;;  | ||||
| ;; 	* oauth2.el: Only require CL at compile time and avoid flet. | ||||
| ;; 	(success): Don't defvar. | ||||
| ;; 	(oauth--url-advice, oauth--tokens-need-renew): New dynbind variables. | ||||
| ;; 	(url-http-handle-authentication): Add advice. | ||||
| ;; 	(oauth2-url-retrieve-synchronously): Use the advice instead of flet. | ||||
| ;;  | ||||
| ;; 2013-06-29  Julien Danjou  <julien@danjou.info> | ||||
| ;;  | ||||
| ;; 	oauth2: release 0.9, require url-http | ||||
| ;;  | ||||
| ;; 	This is needed so that the `flet' calls doesn't restore the overriden  | ||||
| ;; 	function to an unbound one. | ||||
| ;;  | ||||
| ;; 	Signed-off-by: Julien Danjou <julien@danjou.info> | ||||
| ;;  | ||||
| ;; 2012-08-01  Julien Danjou  <julien@danjou.info> | ||||
| ;;  | ||||
| ;; 	oauth2: upgrade to 0.8, add missing require on cl | ||||
| ;;  | ||||
| ;; 2012-07-03  Julien Danjou  <julien@danjou.info> | ||||
| ;;  | ||||
| ;; 	oauth2: store access-reponse, bump versino to 0.7 | ||||
| ;;  | ||||
| ;; 2012-06-25  Julien Danjou  <julien@danjou.info> | ||||
| ;;  | ||||
| ;; 	oauth2: add redirect-uri parameter, update to 0.6 | ||||
| ;;  | ||||
| ;; 2012-05-29  Julien Danjou  <julien@danjou.info> | ||||
| ;;  | ||||
| ;; 	* packages/oauth2/oauth2.el: Revert fix URL double escaping, update to | ||||
| ;; 	0.5 | ||||
| ;;  | ||||
| ;; 2012-05-04  Julien Danjou  <julien@danjou.info> | ||||
| ;;  | ||||
| ;; 	* packages/oauth2/oauth2.el: Don't use aget, update to 0.4 | ||||
| ;;  | ||||
| ;; 2012-04-19  Julien Danjou  <julien@danjou.info> | ||||
| ;;  | ||||
| ;; 	* packages/oauth2/oauth2.el: Fix URL double escaping, update to 0.3 | ||||
| ;;  | ||||
| ;; 2011-12-20  Julien Danjou  <julien@danjou.info> | ||||
| ;;  | ||||
| ;; 	oauth2: update version 0.2 | ||||
| ;;  | ||||
| ;; 	* oauth2: update version to 0.2 | ||||
| ;;  | ||||
| ;; 2011-12-20  Julien Danjou  <julien@danjou.info> | ||||
| ;;  | ||||
| ;; 	oauth2: allow to use any HTTP request type | ||||
| ;;  | ||||
| ;; 	* oauth2: allow to use any HTTP request type | ||||
| ;;  | ||||
| ;; 2011-10-08  Julien Danjou  <julien@danjou.info> | ||||
| ;;  | ||||
| ;; 	* oauth2.el: Require json. | ||||
| ;; 	 Fix compilation warning with success variable from url.el. | ||||
| ;;  | ||||
| ;; 2011-09-26  Julien Danjou  <julien@danjou.info> | ||||
| ;;  | ||||
| ;; 	* packages/oauth2/oauth2.el (oauth2-request-authorization): Add missing | ||||
| ;; 	 calls to url-hexify-string. | ||||
| ;;  | ||||
| ;; 2011-09-26  Julien Danjou  <julien@danjou.info> | ||||
| ;;  | ||||
| ;; 	* packages/oauth2/oauth2.el: Reformat to avoid long lines. | ||||
| ;;  | ||||
| ;; 2011-09-23  Julien Danjou  <julien@danjou.info> | ||||
| ;;  | ||||
| ;; 	New package oauth2 | ||||
| ;;  | ||||
|  | ||||
|  | ||||
| (provide 'oauth2) | ||||
|  | ||||
| ;;; oauth2.el ends here | ||||
							
								
								
									
										38
									
								
								elpa/org-jekyll-20130508.239/org-jekyll-autoloads.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								elpa/org-jekyll-20130508.239/org-jekyll-autoloads.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | ||||
| ;;; org-jekyll-autoloads.el --- automatically extracted autoloads | ||||
| ;; | ||||
| ;;; Code: | ||||
| (add-to-list 'load-path (directory-file-name (or (file-name-directory #$) (car load-path)))) | ||||
|  | ||||
| ;;;### (autoloads nil "org-jekyll" "org-jekyll.el" (22533 17557 381907 | ||||
| ;;;;;;  797000)) | ||||
| ;;; Generated autoloads from org-jekyll.el | ||||
|  | ||||
| (autoload 'org-jekyll-export-current-entry "org-jekyll" "\ | ||||
|  | ||||
|  | ||||
| \(fn)" t nil) | ||||
|  | ||||
| (autoload 'org-jekyll-export-blog "org-jekyll" "\ | ||||
| Export all entries in project files that have a :blog: keyword | ||||
| and an :on: datestamp.  Property drawers are exported as | ||||
| front-matters, outline entry title is the exported document | ||||
| title.  | ||||
|  | ||||
| \(fn)" t nil) | ||||
|  | ||||
| (autoload 'org-jekyll-export-project "org-jekyll" "\ | ||||
| Export all entries in project files that have a :blog: keyword | ||||
| and an :on: datestamp.  Property drawers are exported as | ||||
| front-matters, outline entry title is the exported document | ||||
| title.  | ||||
|  | ||||
| \(fn PROJECT-NAME)" t nil) | ||||
|  | ||||
| ;;;*** | ||||
|  | ||||
| ;; Local Variables: | ||||
| ;; version-control: never | ||||
| ;; no-byte-compile: t | ||||
| ;; no-update-autoloads: t | ||||
| ;; End: | ||||
| ;;; org-jekyll-autoloads.el ends here | ||||
							
								
								
									
										2
									
								
								elpa/org-jekyll-20130508.239/org-jekyll-pkg.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								elpa/org-jekyll-20130508.239/org-jekyll-pkg.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| ;;; -*- no-byte-compile: t -*- | ||||
| (define-package "org-jekyll" "20130508.239" "Export jekyll-ready posts form org-mode entries" '((org "8.0")) :url "http://juanreyero.com/open/org-jekyll/" :keywords '("hypermedia")) | ||||
							
								
								
									
										257
									
								
								elpa/org-jekyll-20130508.239/org-jekyll.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										257
									
								
								elpa/org-jekyll-20130508.239/org-jekyll.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,257 @@ | ||||
| ;;; org-jekyll.el --- Export jekyll-ready posts form org-mode entries | ||||
| ;;; | ||||
| ;;; Author: Juan Reyero | ||||
| ;;; Version: 0.4 | ||||
| ;; Package-Version: 20130508.239 | ||||
| ;;; Keywords: hypermedia | ||||
| ;;; Package-Requires: ((org "8.0")) | ||||
| ;;; Homepage: http://juanreyero.com/open/org-jekyll/ | ||||
| ;;; Repository: http://github.com/juanre/org-jekyll | ||||
| ;;; Public clone: git://github.com/juanre/org-jekyll.git | ||||
| ;;; | ||||
| ;;; Commentary: | ||||
| ;;; | ||||
| ;;; Extract subtrees from your org-publish project files that have | ||||
| ;;; a :blog: keyword and an :on: property with a timestamp, and | ||||
| ;;; export them to a subdirectory _posts of your project's publishing | ||||
| ;;; directory in the year-month-day-title.html format that Jekyll | ||||
| ;;; expects.  Properties are passed over as yaml front-matter in the | ||||
| ;;; exported files.  The title of the subtree is the title of the | ||||
| ;;; entry.  The title of the post is a link to the post's page. | ||||
| ;;; | ||||
| ;;; Look at http://orgmode.org/worg/org-tutorials/org-jekyll.html for | ||||
| ;;; more info on how to integrate org-mode with Jekyll, and for the | ||||
| ;;; inspiration of the main function down there. | ||||
| ;;; | ||||
| ;;; Code: | ||||
|  | ||||
| ;;(require 'ox-html) | ||||
|  | ||||
| (defvar org-jekyll-category nil | ||||
|   "Specify a property which, if defined in the entry, is used as | ||||
|   a category: the post is written to category/_posts. Ignored if | ||||
|   nil. Use \"lang\" if you want to send posts in different | ||||
|   languages to different directories.") | ||||
|  | ||||
| (defvar org-jekyll-lang-subdirs nil | ||||
|   "Make it an assoc list indexed by language if you want to | ||||
| bypass the category subdir definition and build blog subdirs per | ||||
| language.") | ||||
|  | ||||
| (defvar org-jekyll-localize-dir nil | ||||
|   "If non-nil and the lang property is set in the entry, | ||||
|    org-jekyll will look for a lang.yml file in this directory and | ||||
|    include it in the front matter of the exported entry.") | ||||
|  | ||||
| (defvar org-jekyll-new-buffers nil | ||||
|   "Buffers created to visit org-publish project files looking for blog posts.") | ||||
|  | ||||
| (defun org-jekyll-publish-dir (project &optional category) | ||||
|   "Where does the project go, by default a :blog-publishing-directory | ||||
|    entry in the org-publish-project-alist." | ||||
|   (princ category) | ||||
|   (if org-jekyll-lang-subdirs | ||||
|       (let ((pdir (plist-get (cdr project) :blog-publishing-directory)) | ||||
|             (langdir (cdr (assoc category org-jekyll-lang-subdirs)))) | ||||
|         (if langdir | ||||
|             (concat pdir (cdr (assoc category org-jekyll-lang-subdirs)) | ||||
|                     "_posts/") | ||||
|           (let ((ppdir (plist-get (cdr project) :blog-publishing-directory))) | ||||
|             (unless ppdir | ||||
|               (setq ppdir (plist-get (cdr project) :publishing-directory))) | ||||
|             (concat ppdir | ||||
|                     (if category (concat category "/") "") | ||||
|                     "_posts/")))) | ||||
|     (let ((pdir (plist-get (cdr project) :blog-publishing-directory))) | ||||
|       (unless pdir | ||||
|         (setq pdir (plist-get (cdr project) :publishing-directory))) | ||||
|       (concat pdir | ||||
|               (if category (concat category "/") "") | ||||
|               "_posts/")))) | ||||
|  | ||||
| (defun org-jekyll-site-root (project) | ||||
|   "Site root, like http://yoursite.com, from which blog | ||||
|   permalinks follow.  Needed to replace entry titles with | ||||
|   permalinks that RSS agregators and google buzz know how to | ||||
|   follow.  Looks for a :site-root entry in the org-publish-project-alist." | ||||
|   (or (plist-get (cdr project) :site-root) | ||||
|       "")) | ||||
|  | ||||
|  | ||||
| (defun org-get-jekyll-file-buffer (file) | ||||
|   "Get a buffer visiting FILE.  If the buffer needs to be | ||||
|   created, add it to the list of buffers which might be released | ||||
|   later.  Copied from org-get-agenda-file-buffer, and modified | ||||
|   the list that holds buffers to release." | ||||
|   (let ((buf (org-find-base-buffer-visiting file))) | ||||
|     (if buf | ||||
|         buf | ||||
|       (progn (setq buf (find-file-noselect file)) | ||||
|              (if buf (push buf org-jekyll-new-buffers)) | ||||
|              buf)))) | ||||
|  | ||||
| (defun org-jekyll-slurp-yaml (fname) | ||||
|   (remove "---" (if (file-exists-p fname) | ||||
|                     (split-string (with-temp-buffer | ||||
|                                     (insert-file-contents fname) | ||||
|                                     (buffer-string)) | ||||
|                                   "\n" t)))) | ||||
|  | ||||
| (defun ensure-directories-exist (fname) | ||||
|   (let ((dir (file-name-directory fname))) | ||||
|     (unless (file-accessible-directory-p dir) | ||||
|       (make-directory dir t))) | ||||
|   fname) | ||||
|  | ||||
| (defun org-jekyll-sanitize-string (str project) | ||||
|   (if (plist-get (cdr project) :jekyll-sanitize-permalinks) | ||||
|       (progn (setq str (downcase str)) | ||||
|              (dolist (c '(("á" . "a") | ||||
|                           ("é" . "e") | ||||
|                           ("í" . "i") | ||||
|                           ("ó" . "o") | ||||
|                           ("ú" . "u") | ||||
|                           ("à" . "a") | ||||
|                           ("è" . "e") | ||||
|                           ("ì" . "i") | ||||
|                           ("ò" . "o") | ||||
|                           ("ù" . "u") | ||||
|                           ("ñ" . "n") | ||||
|                           ("ç" . "s") | ||||
|                           ("\\$" . "S") | ||||
|                           ("€" . "E"))) | ||||
|                (setq str (replace-regexp-in-string (car c) (cdr c) str))) | ||||
|              (replace-regexp-in-string "[^abcdefghijklmnopqrstuvwxyz-]" "" | ||||
|                                        (replace-regexp-in-string " +" "-" str))) | ||||
|     str)) | ||||
|  | ||||
| (defun org-jekyll-export-entry (project) | ||||
|   (let* ((props (org-entry-properties nil 'standard)) | ||||
|          (time (cdr (or (assoc "on" props) | ||||
|                         (assoc "ON" props)))) | ||||
|          (lang (cdr (or (assoc "lang" props) | ||||
|                         (assoc "LANG" props)))) | ||||
|          (category (if org-jekyll-category | ||||
|                        (cdr (assoc org-jekyll-category props)) | ||||
|                      nil)) | ||||
|          (yaml-front-matter (copy-alist props))) | ||||
|     (unless (assoc "layout" yaml-front-matter) | ||||
|       (push '("layout" . "post") yaml-front-matter)) | ||||
|     (when time | ||||
|       (let* ((heading (org-get-heading t)) | ||||
|              (title (replace-regexp-in-string "[:=\(\)\?]" "" | ||||
|                                               (replace-regexp-in-string | ||||
|                                                "[ \t]" "-" heading))) | ||||
|              (str-time (and (string-match "\\([[:digit:]\-]+\\) " time) | ||||
|                             (match-string 1 time))) | ||||
|              (to-file (format "%s-%s.html" str-time | ||||
|                               (org-jekyll-sanitize-string title project))) | ||||
|              (org-buffer (current-buffer)) | ||||
|              (yaml-front-matter (cons (cons "title" heading) | ||||
|                                       yaml-front-matter)) | ||||
|              html) | ||||
|         (org-narrow-to-subtree) | ||||
|         (let ((level (- (org-reduced-level (org-outline-level)) 1)) | ||||
|               (top-level org-html-toplevel-hlevel) | ||||
|               (contents (buffer-substring (point-min) (point-max))) | ||||
|               (site-root (org-jekyll-site-root project))) | ||||
|           ;; Without the promotion the header with which the headline | ||||
|           ;; is exported depends on the level.  With the promotion it | ||||
|           ;; fails when the entry is not visible (ie, within a folded | ||||
|           ;; entry). | ||||
|           (dotimes (n level nil) (org-promote-subtree)) | ||||
|           (setq html | ||||
|                 (replace-regexp-in-string | ||||
|                  (format "<h%d id=\"sec-1\">\\(.+\\)</h%d>" | ||||
|                          top-level top-level) | ||||
|                  (format | ||||
|                   "<h%d id=\"sec-1\"><a href=\"%s{{ page.url }}\">\\1</a></h%d>" | ||||
|                   top-level site-root top-level) | ||||
|                  (with-current-buffer | ||||
|                      (org-html-export-as-html nil t t t | ||||
|                                               '(:tags nil | ||||
|                                                 :table-of-contents nil)) | ||||
|                    (buffer-string)))) | ||||
|           (set-buffer org-buffer) | ||||
|           (delete-region (point-min) (point-max)) | ||||
|           (insert contents) | ||||
|           (save-buffer)) | ||||
|         (widen) | ||||
|         (with-temp-file (ensure-directories-exist | ||||
|                          (expand-file-name | ||||
|                           to-file (org-jekyll-publish-dir project category))) | ||||
|           (when yaml-front-matter | ||||
|             (insert "---\n") | ||||
|             (mapc (lambda (pair) | ||||
|                     (insert (format "%s: %s\n" (car pair) (cdr pair)))) | ||||
|                   yaml-front-matter) | ||||
|             (if (and org-jekyll-localize-dir lang) | ||||
|                 (mapc (lambda (line) | ||||
|                         (insert (format "%s\n" line))) | ||||
|                       (org-jekyll-slurp-yaml (concat org-jekyll-localize-dir | ||||
|                                                      lang ".yml")))) | ||||
|             (insert "---\n\n")) | ||||
|           (insert html)))))) | ||||
|  | ||||
| ; Evtl. needed to keep compiler happy: | ||||
| (declare-function org-publish-get-project-from-filename "org-publish" | ||||
|                   (filename &optional up)) | ||||
|  | ||||
| ;;;###autoload | ||||
| (defun org-jekyll-export-current-entry () | ||||
|   (interactive) | ||||
|   (save-excursion | ||||
|     (let ((project (org-publish-get-project-from-filename buffer-file-name))) | ||||
|       (org-back-to-heading t) | ||||
|       (org-jekyll-export-entry project)))) | ||||
|  | ||||
| ;;;###autoload | ||||
| (defun org-jekyll-export-blog () | ||||
|   "Export all entries in project files that have a :blog: keyword | ||||
| and an :on: datestamp.  Property drawers are exported as | ||||
| front-matters, outline entry title is the exported document | ||||
| title. " | ||||
|   (interactive) | ||||
|   (save-excursion | ||||
|     (setq org-jekyll-new-buffers nil) | ||||
|     (let ((project (org-publish-get-project-from-filename (buffer-file-name)))) | ||||
|      (mapc | ||||
|       (lambda (jfile) | ||||
|         (if (string= (file-name-extension jfile) "org") | ||||
|             (with-current-buffer (org-get-jekyll-file-buffer jfile) | ||||
|               ;; It fails for non-visible entries, CONTENT visibility | ||||
|               ;; mode ensures that all of them are visible. | ||||
|               (message (concat "org-jekyll: publishing " jfile )) | ||||
|               (org-content) | ||||
|               (org-map-entries (lambda () (org-jekyll-export-entry project)) | ||||
|                                "blog|BLOG")))) | ||||
|       (org-publish-get-base-files project))) | ||||
|     (org-release-buffers org-jekyll-new-buffers))) | ||||
|  | ||||
| ;;;###autoload | ||||
| (defun org-jekyll-export-project (project-name) | ||||
|   "Export all entries in project files that have a :blog: keyword | ||||
| and an :on: datestamp.  Property drawers are exported as | ||||
| front-matters, outline entry title is the exported document | ||||
| title. " | ||||
|   (interactive) | ||||
|   (save-excursion | ||||
|     (setq org-jekyll-new-buffers nil) | ||||
|     (let ((project (assoc project-name org-publish-project-alist))) | ||||
|      (mapc | ||||
|       (lambda (jfile) | ||||
|         (if (string= (file-name-extension jfile) (plist-get (cdr project) | ||||
|                                                             :base-extension)) | ||||
|             (with-current-buffer (org-get-jekyll-file-buffer jfile) | ||||
|               ;; It fails for non-visible entries, CONTENT visibility | ||||
|               ;; mode ensures that all of them are visible. | ||||
|               (message (concat "org-jekyll: publishing " jfile )) | ||||
|               (org-content) | ||||
|               (org-map-entries (lambda () (org-jekyll-export-entry project)) | ||||
|                                "blog|BLOG")))) | ||||
|       (org-publish-get-base-files project))) | ||||
|     (org-release-buffers org-jekyll-new-buffers))) | ||||
|  | ||||
| (provide 'org-jekyll) | ||||
|  | ||||
| ;;; org-jekyll.el ends here | ||||
| @@ -0,0 +1,39 @@ | ||||
| ;;; org-random-todo-autoloads.el --- automatically extracted autoloads | ||||
| ;; | ||||
| ;;; Code: | ||||
| (add-to-list 'load-path (directory-file-name (or (file-name-directory #$) (car load-path)))) | ||||
|  | ||||
| ;;;### (autoloads nil "org-random-todo" "org-random-todo.el" (22533 | ||||
| ;;;;;;  17556 331883 840000)) | ||||
| ;;; Generated autoloads from org-random-todo.el | ||||
|  | ||||
| (autoload 'org-random-todo "org-random-todo" "\ | ||||
| Show a random TODO notification from your agenda files. | ||||
| See `org-random-todo-files' to change what files are crawled. | ||||
| Runs `org-random-todo--update-cache' if TODO's are out of date. | ||||
|  | ||||
| \(fn)" t nil) | ||||
|  | ||||
| (defvar org-random-todo-mode nil "\ | ||||
| Non-nil if Org-Random-Todo mode is enabled. | ||||
| See the `org-random-todo-mode' command | ||||
| for a description of this minor mode. | ||||
| Setting this variable directly does not take effect; | ||||
| either customize it (see the info node `Easy Customization') | ||||
| or call the function `org-random-todo-mode'.") | ||||
|  | ||||
| (custom-autoload 'org-random-todo-mode "org-random-todo" nil) | ||||
|  | ||||
| (autoload 'org-random-todo-mode "org-random-todo" "\ | ||||
| Show a random TODO every so often | ||||
|  | ||||
| \(fn &optional ARG)" t nil) | ||||
|  | ||||
| ;;;*** | ||||
|  | ||||
| ;; Local Variables: | ||||
| ;; version-control: never | ||||
| ;; no-byte-compile: t | ||||
| ;; no-update-autoloads: t | ||||
| ;; End: | ||||
| ;;; org-random-todo-autoloads.el ends here | ||||
							
								
								
									
										2
									
								
								elpa/org-random-todo-20160208.426/org-random-todo-pkg.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								elpa/org-random-todo-20160208.426/org-random-todo-pkg.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| ;;; -*- no-byte-compile: t -*- | ||||
| (define-package "org-random-todo" "20160208.426" "notify of random TODO's" '((emacs "24.3") (alert "1.2")) :keywords '("org" "todo" "notification")) | ||||
							
								
								
									
										148
									
								
								elpa/org-random-todo-20160208.426/org-random-todo.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										148
									
								
								elpa/org-random-todo-20160208.426/org-random-todo.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,148 @@ | ||||
| ;;; org-random-todo.el --- notify of random TODO's | ||||
|  | ||||
| ;; Copyright (C) 2013-2016 Kevin Brubeck Unhammer | ||||
|  | ||||
| ;; Author: Kevin Brubeck Unhammer <unhammer@fsfe.org> | ||||
| ;; Version: 0.4.1 | ||||
| ;; Package-Version: 20160208.426 | ||||
| ;; Package-Requires: ((emacs "24.3") (alert "1.2")) | ||||
| ;; Keywords: org todo notification | ||||
|  | ||||
| ;; This file is not part of GNU Emacs. | ||||
|  | ||||
| ;; This program is free software; you can redistribute it and/or modify | ||||
| ;; it under the terms of the GNU General Public License as published by | ||||
| ;; the Free Software Foundation; either version 3 of the License, or | ||||
| ;; (at your option) any later version. | ||||
| ;; | ||||
| ;; This program is distributed in the hope that it will be useful, | ||||
| ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| ;; GNU General Public License for more details. | ||||
| ;; | ||||
| ;; You should have received a copy of the GNU General Public License | ||||
| ;; along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  | ||||
| ;;; Commentary: | ||||
|  | ||||
| ;; Show a random TODO from your org-agenda-files every so often. | ||||
| ;; Requires org-element, which was added fairly recently to org-mode | ||||
| ;; (tested with org-mode version 7.9.3f and later). | ||||
|  | ||||
| ;;; Code: | ||||
|  | ||||
| (require 'org-element) | ||||
| (require 'alert) | ||||
| (require 'cl-lib) | ||||
| (unless (fboundp 'cl-mapcan) (defalias 'cl-mapcan 'mapcan)) | ||||
|  | ||||
| (defvar org-random-todo-files nil | ||||
|   "Files to grab TODO items from. | ||||
| If nil, use `org-agenda-files'.") | ||||
|  | ||||
| (defvar org-random-todo--cache nil) | ||||
|  | ||||
| (defun org-random-todo--update-cache () | ||||
|   "Update the cache of TODO's." | ||||
|   (setq org-random-todo--cache | ||||
| 	(cl-mapcan | ||||
| 	 (lambda (file) | ||||
| 	   (when (file-exists-p file) | ||||
| 	     (with-current-buffer (org-get-agenda-file-buffer file) | ||||
| 	       (org-element-map (org-element-parse-buffer) | ||||
| 				'headline | ||||
| 				(lambda (hl) | ||||
| 				  (when (and (org-element-property :todo-type hl) | ||||
| 					     (not (equal 'done (org-element-property :todo-type hl)))) | ||||
|                                     (cons file hl))))))) | ||||
| 	 (or org-random-todo-files org-agenda-files)))) | ||||
|  | ||||
| (defun org-random-todo--headline-to-msg (elt) | ||||
|   "Create a readable alert-message of this TODO headline. | ||||
| The `ELT' argument is an org element, see `org-element'." | ||||
|   (format "%s: %s" | ||||
|           (org-element-property :todo-keyword elt) | ||||
|           (org-element-property :raw-value elt))) | ||||
|  | ||||
| (defvar org-random-todo--current nil) | ||||
|  | ||||
| (defun org-random-todo-goto-current () | ||||
|   "Go to the file/position of last shown TODO." | ||||
|   (interactive) | ||||
|   (find-file (car org-random-todo--current)) | ||||
|   (goto-char (cdr org-random-todo--current))) | ||||
|  | ||||
| ;;;###autoload | ||||
| (defun org-random-todo () | ||||
|   "Show a random TODO notification from your agenda files. | ||||
| See `org-random-todo-files' to change what files are crawled. | ||||
| Runs `org-random-todo--update-cache' if TODO's are out of date." | ||||
|   (interactive) | ||||
|   (unless (minibufferp)	 ; don't run if minibuffer is asking something | ||||
|     (unless org-random-todo--cache | ||||
|       (org-random-todo--update-cache)) | ||||
|     (with-temp-buffer | ||||
|       (let* ((todo (nth (random (length org-random-todo--cache)) | ||||
|                         org-random-todo--cache)) | ||||
|              (path (car todo)) | ||||
|              (elt (cdr todo))) | ||||
|         (setq org-random-todo--current (cons path (org-element-property :begin elt))) | ||||
|         (alert (org-random-todo--headline-to-msg elt) | ||||
|                :title (file-name-base path) | ||||
|                :severity 'trivial | ||||
|                :mode 'org-mode | ||||
|                :category 'random-todo | ||||
|                :buffer (find-buffer-visiting path)))))) | ||||
|  | ||||
| (defvar org-random-todo-how-often 600 | ||||
|   "Show a message every this many seconds. | ||||
| This happens simply by requiring `org-random-todo', as long as | ||||
| this variable is set to a number.") | ||||
|  | ||||
|  | ||||
| (defvar org-random-todo-cache-idletime 600 | ||||
|   "Update cache after being idle this many seconds. | ||||
| See `org-random-todo--update-cache'; only happens if this variable is | ||||
| a number.") | ||||
|  | ||||
| (defvar org-random-todo--timers nil | ||||
|   "List of timers that need to be cancelled on exiting org-random-todo-mode.") | ||||
|  | ||||
| (defun org-random-todo-unless-idle () | ||||
|   "Only run `org-random-todo' if we're not idle. | ||||
| This is to avoid getting a bunch of notification build-up after | ||||
| e.g. a sleep/resume." | ||||
|   (when (or (not (current-idle-time)) | ||||
|             (< (time-to-seconds (current-idle-time)) | ||||
|                org-random-todo-how-often)) | ||||
|     (org-random-todo))) | ||||
|  | ||||
| (defun org-random-todo--setup () | ||||
|   "Set up idle timers." | ||||
|   (setq org-random-todo--timers | ||||
|         (list | ||||
|          (when (numberp org-random-todo-how-often) | ||||
|            (run-with-timer org-random-todo-how-often | ||||
|                            org-random-todo-how-often | ||||
|                            'org-random-todo-unless-idle)) | ||||
|          (when (numberp org-random-todo-cache-idletime) | ||||
|            (run-with-idle-timer org-random-todo-cache-idletime | ||||
|                                 'on-each-idle | ||||
|                                 'org-random-todo--update-cache))))) | ||||
|  | ||||
| (defun org-random-todo--teardown () | ||||
|   "Remove idle timers." | ||||
|   (mapc #'cancel-timer (cl-remove-if nil org-random-todo--timers)) | ||||
|   (setq org-random-todo--timers nil)) | ||||
|  | ||||
| ;;;###autoload | ||||
| (define-minor-mode org-random-todo-mode | ||||
|   "Show a random TODO every so often" | ||||
|   :global t | ||||
|   (if org-random-todo-mode | ||||
|       (org-random-todo--setup) | ||||
|     (org-random-todo--teardown))) | ||||
|  | ||||
|  | ||||
| (provide 'org-random-todo) | ||||
| ;;; org-random-todo.el ends here | ||||
							
								
								
									
										15
									
								
								elpa/org-rtm-20160214.436/org-rtm-autoloads.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								elpa/org-rtm-20160214.436/org-rtm-autoloads.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| ;;; org-rtm-autoloads.el --- automatically extracted autoloads | ||||
| ;; | ||||
| ;;; Code: | ||||
| (add-to-list 'load-path (directory-file-name (or (file-name-directory #$) (car load-path)))) | ||||
|  | ||||
| ;;;### (autoloads nil nil ("org-rtm.el") (22533 17555 688869 169000)) | ||||
|  | ||||
| ;;;*** | ||||
|  | ||||
| ;; Local Variables: | ||||
| ;; version-control: never | ||||
| ;; no-byte-compile: t | ||||
| ;; no-update-autoloads: t | ||||
| ;; End: | ||||
| ;;; org-rtm-autoloads.el ends here | ||||
							
								
								
									
										2
									
								
								elpa/org-rtm-20160214.436/org-rtm-pkg.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								elpa/org-rtm-20160214.436/org-rtm-pkg.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| ;;; -*- no-byte-compile: t -*- | ||||
| (define-package "org-rtm" "20160214.436" "Simple import/export from rememberthemilk to org-mode" '((rtm "0.1")) :url "https://github.com/pmiddend/org-rtm" :keywords '("outlines" "data")) | ||||
							
								
								
									
										140
									
								
								elpa/org-rtm-20160214.436/org-rtm.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										140
									
								
								elpa/org-rtm-20160214.436/org-rtm.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,140 @@ | ||||
| ;;; org-rtm.el --- Simple import/export from rememberthemilk to org-mode | ||||
| ;; Copyright (c) 2016 Philipp Middendorf | ||||
| ;; Author: Philipp Middendorf <pmidden@secure.mailbox.org> | ||||
| ;; Created: 15 Jan 2016 | ||||
| ;; Version: 0.1 | ||||
| ;; Package-Version: 20160214.436 | ||||
| ;; Package-Requires: ((rtm "0.1")) | ||||
| ;; Keywords: outlines, data | ||||
| ;; Homepage: https://github.com/pmiddend/org-rtm | ||||
|  | ||||
| ;; This product uses the Remember The Milk API but is not endorsed or | ||||
| ;; certified by Remember The Milk | ||||
|  | ||||
| ;; This file is not part of GNU Emacs. | ||||
|  | ||||
| ;; This file is free software; you can redistribute it and/or modify | ||||
| ;; it under the terms of the MIT license (see COPYING). | ||||
|  | ||||
| ;;; Commentary: | ||||
| ;; Simple import/export from rememberthemilk to org-mode | ||||
| ;; | ||||
| ;; The project is hosted at https://github.com/pmiddend/org-rtm | ||||
| ;; The latest version, and all the relevant information can be found there. | ||||
| ;;; Code: | ||||
| (require 'rtm) | ||||
| (require 'org) | ||||
|  | ||||
|  | ||||
| (defgroup org-rtm () | ||||
|   "Retrieve and complete tasks from rememberthemilk.com and convert them to org-mode" | ||||
|   :group 'external | ||||
|   :link '(url-link "https://github.com/pmiddend/org-rtm") | ||||
|   :prefix "org-rtm-") | ||||
|  | ||||
| (defcustom org-rtm-import-file "~/rtm.org" | ||||
|   "Where to export the contents of RTM to when using org-rtm-import." | ||||
|   :group 'org-rtm | ||||
|   :type 'file) | ||||
|  | ||||
| (defcustom org-rtm-complete-after-import nil | ||||
|   "Complete the imported tasks in RTM. | ||||
| It might be a good idea to set this after you verified that  | ||||
| the import process is working well." | ||||
|   :group 'org-rtm | ||||
|   :type 'boolean) | ||||
|  | ||||
| (defun org-rtm-assoc-value (symbol list) | ||||
|   "Get the value behind SYMBOL in an association LIST (not the pair of key/value)." | ||||
|   (cdr (assoc symbol list))) | ||||
|  | ||||
| (defun org-rtm-print-list (rtml) | ||||
|   "Convert an RTM list RTML to an org mode segment (top level, starting with *)." | ||||
|   (progn | ||||
|     (concat | ||||
|      "* " | ||||
|      (org-rtm-assoc-value 'name (car (cdr rtml)))))) | ||||
|  | ||||
| (defun org-rtm-format-note (note) | ||||
|   "Format a single RTM task NOTE." | ||||
|   (nth 2 note)) | ||||
|  | ||||
| (defun org-rtm-format-notes (notes-list) | ||||
|   "Format a list NOTES-LIST of RTM task notes and concatenate to string." | ||||
|   (cond ((equal (length notes-list) 0) "") | ||||
| 	(t (concat "\n" (mapconcat 'org-rtm-format-note notes-list "\n"))))) | ||||
|  | ||||
| (defun org-rtm-format-time-to-org (time-value) | ||||
|   "Convert an ISO date time TIME-VALUE to the org-mode time format.  | ||||
| I didn't find built-in function to accomplish this." | ||||
|   (print (length time-value)) | ||||
|   (format-time-string (cdr org-time-stamp-formats) (date-to-time time-value))) | ||||
|  | ||||
| (defun org-rtm-print-entry (e) | ||||
|   "Format a single RTM task E and output as second level org segment (starting with **)." | ||||
|   (let* | ||||
|       ((topAssocList (cdr e)) | ||||
|        (taskAssocList (car topAssocList)) | ||||
|        (due (org-rtm-assoc-value 'due (car (org-rtm-assoc-value 'task topAssocList)))) | ||||
|        (notes-list (nthcdr 2 (assoc 'notes topAssocList)))) | ||||
|     (progn | ||||
|       (concat | ||||
|        "** TODO " | ||||
|        (org-rtm-assoc-value 'name taskAssocList) | ||||
|        (if (not (or (eq due nil) (string= due ""))) (concat "\nSCHEDULED: " (org-rtm-format-time-to-org due))) | ||||
|        (if (org-rtm-assoc-value 'url taskAssocList) (concat "\n" (org-rtm-assoc-value 'url taskAssocList)) "") | ||||
|        (org-rtm-format-notes notes-list))))) | ||||
|  | ||||
| (defun org-rtm-format-list-entries (list-id) | ||||
|   "Convert a single RTM task list LIST-ID to org mode items." | ||||
|   (mapconcat 'org-rtm-print-entry (nthcdr 2 (car (rtm-tasks-get-list list-id "status:incomplete"))) "\n")) | ||||
|  | ||||
| (defun org-rtm-format-list (list-id list-name) | ||||
|   "Format a single list with LIST-ID and LIST-NAME as a top-level org-mode segment starting with *." | ||||
|   (progn | ||||
|     (concat "* " list-name "\n" (org-rtm-format-list-entries list-id)))) | ||||
|  | ||||
| (defun org-rtm-format-lists () | ||||
|   "Format RTM lists to org mode segments." | ||||
|   (mapconcat (lambda (list) (org-rtm-format-list (org-rtm-assoc-value 'id (nth 1 list)) (org-rtm-assoc-value 'name (nth 1 list)))) (rtm-lists-get-list) "\n")) | ||||
|  | ||||
| (defun org-rtm-complete-items (list-id) | ||||
|   "Complete all items in a given RTM list with LIST-ID (doesn't do any org-mode conversion)." | ||||
|   (mapcar | ||||
|    (lambda (taskseries-w-task) | ||||
|      (rtm-tasks-complete list-id (car taskseries-w-task) (cdr taskseries-w-task))) | ||||
|    (org-rtm-retrieve-taskseries-id-with-task-list list-id))) | ||||
|  | ||||
| (defun org-rtm-retrieve-taskseries-id-with-task-list (list-id) | ||||
|   "Retrieves the taskseries entry for list with LIST-ID." | ||||
|   (mapcar | ||||
|    (lambda (list) | ||||
|      `(,(org-rtm-assoc-value 'id (nth 1 list)) . ,(org-rtm-assoc-value 'id (car (org-rtm-assoc-value 'task (nthcdr 2 list)))))) | ||||
|    (nthcdr 2 (car (rtm-tasks-get-list list-id "status:incomplete"))))) | ||||
|  | ||||
| (defun org-rtm-retrieve-list-ids () | ||||
|   "Retrieve a list of RTM list ids." | ||||
|   (mapcar (lambda (list) (org-rtm-assoc-value 'id (nth 1 list))) (rtm-lists-get-list))) | ||||
|  | ||||
| (defun org-rtm-complete-all-lists () | ||||
|   "Complete all items of RTM all lists." | ||||
|   (mapcar (lambda (list-id) (org-rtm-complete-items list-id)) (org-rtm-retrieve-list-ids))) | ||||
|  | ||||
| (defun org-rtm-import () | ||||
|   "Import RTM tasks to the given import file (overwriting it), then optionally completing the tasks, then opening the file in Emacs." | ||||
|   (interactive) | ||||
|   (message "Starting RTM import...") | ||||
|   (let | ||||
|       ((import-data (org-rtm-format-lists))) | ||||
|     (find-file org-rtm-import-file) | ||||
|     (erase-buffer) | ||||
|     (if | ||||
| 	org-rtm-complete-after-import | ||||
| 	(progn | ||||
| 	  (org-rtm-complete-all-lists) | ||||
| 	  (message "Imported and completed all RTM tasks")) | ||||
|         (message "Imported tasks, not completing RTM tasks because of configuration option")) | ||||
|     (insert import-data))) | ||||
|  | ||||
| (provide 'org-rtm) | ||||
| ;;; org-rtm.el ends here | ||||
							
								
								
									
										15
									
								
								elpa/request-20160822.1659/request-autoloads.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								elpa/request-20160822.1659/request-autoloads.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| ;;; request-autoloads.el --- automatically extracted autoloads | ||||
| ;; | ||||
| ;;; Code: | ||||
| (add-to-list 'load-path (directory-file-name (or (file-name-directory #$) (car load-path)))) | ||||
|  | ||||
| ;;;### (autoloads nil nil ("request.el") (22533 17545 888645 569000)) | ||||
|  | ||||
| ;;;*** | ||||
|  | ||||
| ;; Local Variables: | ||||
| ;; version-control: never | ||||
| ;; no-byte-compile: t | ||||
| ;; no-update-autoloads: t | ||||
| ;; End: | ||||
| ;;; request-autoloads.el ends here | ||||
							
								
								
									
										2
									
								
								elpa/request-20160822.1659/request-pkg.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								elpa/request-20160822.1659/request-pkg.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| ;;; -*- no-byte-compile: t -*- | ||||
| (define-package "request" "20160822.1659" "Compatible layer for URL request in Emacs" '((emacs "24") (cl-lib "0.5"))) | ||||
							
								
								
									
										1297
									
								
								elpa/request-20160822.1659/request.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1297
									
								
								elpa/request-20160822.1659/request.el
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										15
									
								
								elpa/rtm-20160116.927/rtm-autoloads.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								elpa/rtm-20160116.927/rtm-autoloads.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| ;;; rtm-autoloads.el --- automatically extracted autoloads | ||||
| ;; | ||||
| ;;; Code: | ||||
| (add-to-list 'load-path (directory-file-name (or (file-name-directory #$) (car load-path)))) | ||||
|  | ||||
| ;;;### (autoloads nil nil ("rtm.el") (22533 17553 387816 669000)) | ||||
|  | ||||
| ;;;*** | ||||
|  | ||||
| ;; Local Variables: | ||||
| ;; version-control: never | ||||
| ;; no-byte-compile: t | ||||
| ;; no-update-autoloads: t | ||||
| ;; End: | ||||
| ;;; rtm-autoloads.el ends here | ||||
							
								
								
									
										2
									
								
								elpa/rtm-20160116.927/rtm-pkg.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								elpa/rtm-20160116.927/rtm-pkg.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| ;;; -*- no-byte-compile: t -*- | ||||
| (define-package "rtm" "20160116.927" "An elisp implementation of the Remember The Milk API" '((cl-lib "1.0")) :url "https://github.com/pmiddend/emacs-rtm" :keywords '("remember" "the" "milk" "productivity" "todo")) | ||||
							
								
								
									
										697
									
								
								elpa/rtm-20160116.927/rtm.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										697
									
								
								elpa/rtm-20160116.927/rtm.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,697 @@ | ||||
| ;;; rtm.el --- An elisp implementation of the Remember The Milk API | ||||
|  | ||||
| ;; Copyright (C) 2009 Friedrich Delgado Friedrichs | ||||
| ;; uses parts of org-rtm.el Copyright (C) 2008  Avdi Grimm | ||||
| ;; Modified by Philipp Middendorf (pmidden@secure.mailbox.org) 2016 | ||||
|  | ||||
| ;; Author: Friedrich Delgado Friedrichs <frie...@nomaden.org> | ||||
| ;; Created: Oct 18 2009 | ||||
| ;; Version: 0.1 | ||||
| ;; Package-Version: 20160116.927 | ||||
| ;; Package-Requires: ((cl-lib "1.0")) | ||||
| ;; Keywords: remember the milk productivity todo | ||||
| ;; URL: https://github.com/pmiddend/emacs-rtm | ||||
|  | ||||
| ;; This product uses the Remember The Milk API but is not endorsed or | ||||
| ;; certified by Remember The Milk | ||||
|  | ||||
| ;; This file is NOT part of GNU Emacs. | ||||
|  | ||||
| ;; This file is free software; you can redistribute it and/or modify | ||||
| ;; it under the terms of the GNU General Public License as published by | ||||
| ;; the Free Software Foundation; either version 3, or (at your option) | ||||
| ;; any later version. | ||||
|  | ||||
| ;; This file is distributed in the hope that it will be useful, | ||||
| ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
| ;; GNU General Public License for more details. | ||||
|  | ||||
| ;; You should have received a copy of the GNU General Public License | ||||
| ;; along with GNU Emacs; see the file COPYING. If not, write to | ||||
| ;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||||
| ;; Boston, MA 02110-1301, USA. | ||||
|  | ||||
| ;;; Commentary: | ||||
|  | ||||
| ;; Note by Philipp: This file was taken from the simple-rtm repository and | ||||
| ;; has some minor modifications so it doesn't give byte-compilation | ||||
| ;; warnings. | ||||
|  | ||||
| ;;; Code: | ||||
|  | ||||
| (require 'cl-lib) | ||||
| (require 'url-http) | ||||
| (require 'url-util) | ||||
| (require 'xml) | ||||
| (require 'custom) | ||||
|  | ||||
| ;;;; Customisation | ||||
|  | ||||
| (defgroup rtm nil | ||||
|   "Options for emacs lisp integration of Remember The Milk" | ||||
|   :tag "elisp RTM" | ||||
|   :group 'applications) | ||||
|  | ||||
| (defcustom rtm-api-key "d40eb4df08dd52c1930afa9d79dceda0" | ||||
|   "Your own API key for Remember The Milk." | ||||
|   :type 'string :group 'rtm) | ||||
| (defcustom rtm-api-shared-secret "39d8e367fdce977c" | ||||
|   "Your shared secret for your Remember The Milk API Key. | ||||
|  | ||||
| Note that in an open source application it is not easily possible to | ||||
| hide the secret. That's why it's probably the best solution for every | ||||
| user to register their own API key. | ||||
|  | ||||
| See also | ||||
| http://groups.google.com/group/rememberthemilk-api/browse_thread/thread/dcb035f162d4dcc8%3Fpli%3D1 | ||||
|  | ||||
| You can register your own API key and secret under | ||||
| http://www.rememberthemilk.com/services/api/requestkey.rtm | ||||
|  | ||||
| In the description just tell them you're going to use the emacs lisp | ||||
| API Kit" | ||||
|   :type 'string :group 'rtm) | ||||
|  | ||||
| ;;;; constants and variables | ||||
|  | ||||
| (defconst rtm-rest-uri "http://api.rememberthemilk.com/services/rest/" | ||||
|   "Endpoint URL for REST requests. See | ||||
|   http://www.rememberthemilk.com/services/api/request.rest.rtm") | ||||
|  | ||||
| (defconst rtm-auth-uri "http://www.rememberthemilk.com/services/auth/" | ||||
|   "Authentication service URL, see | ||||
|   http://www.rememberthemilk.com/services/api/authentication.rtm") | ||||
|  | ||||
| (defvar rtm-auth-token "" | ||||
|   "Auth token received from RTM Website, after the user authenticated | ||||
|   your app") | ||||
|  | ||||
| (defvar rtm-auth-token-valid nil | ||||
|   "Set to t after the auth token has been validated.") | ||||
|  | ||||
| (defconst rtm-ui-buffer-name "*rtm*" | ||||
|   "Name for the rtm user interface buffer") | ||||
|  | ||||
| (defconst rtm-auth-token-file ".rtm-auth-token" | ||||
|   "Name for storing the auth token for the current session") | ||||
|  | ||||
| (defvar rtm-current-timeline nil | ||||
|   "The current timeline") | ||||
|  | ||||
| (defvar rtm-debug nil | ||||
|   "debug level") | ||||
|  | ||||
| (make-variable-buffer-local 'rtm-auth-token-valid) | ||||
| (put 'rtm-auth-token-valid 'permanent-local t) | ||||
|  | ||||
| ;;;; API wrappers | ||||
| (defmacro def-rtm-method (methodname rtm-method-name call-func result-func | ||||
|                                      result-path &rest parms) | ||||
|   (declare (indent 1)) | ||||
|   `(defun ,methodname ,parms | ||||
|      (,result-func ,result-path | ||||
|                    (,call-func ',rtm-method-name | ||||
|                                ,@(mapcar (lambda (sym) | ||||
|                                            `(cons ,(symbol-name sym) ,sym)) | ||||
|                                          ;; remove lambda keywords | ||||
|                                          (cl-remove-if (lambda (sym) | ||||
|                                                       (or (eq sym '&optional) | ||||
|                                                           (eq sym '&rest))) | ||||
|                                                     parms)))))) | ||||
|  | ||||
| (defmacro def-rtm-macro (macro-name call-func result-func) | ||||
|   (declare (indent 0)) | ||||
|   `(defmacro ,macro-name (methodname rtm-method-name result-path &rest parms) | ||||
|      (declare (indent 1)) | ||||
|      `(def-rtm-method ,methodname ,rtm-method-name ,',call-func | ||||
|                       ,',result-func | ||||
|                       ',result-path ,@parms))) | ||||
|  | ||||
| (def-rtm-macro def-rtm-signed-scalar-method | ||||
|                rtm-call-signed rtm-get-scalar-from-response) | ||||
|  | ||||
| (def-rtm-macro def-rtm-authenticated-scalar-method | ||||
|                rtm-call-authenticated rtm-get-scalar-from-response) | ||||
|  | ||||
| (def-rtm-macro def-rtm-timeline-scalar-method | ||||
|                rtm-call-timeline rtm-get-scalar-from-response) | ||||
|  | ||||
| (def-rtm-macro def-rtm-signed-list-method | ||||
|                rtm-call-signed rtm-get-list-from-response) | ||||
|  | ||||
| (def-rtm-macro def-rtm-authenticated-list-method | ||||
|                rtm-call-authenticated rtm-get-list-from-response) | ||||
|  | ||||
| (def-rtm-macro def-rtm-timeline-list-method | ||||
|                rtm-call-timeline rtm-get-list-from-response) | ||||
|  | ||||
| ;; awfully brief aliases, but those long names mess up indentation | ||||
| ;; recomendation: use only the authenticated aliases, and the long | ||||
| ;; names for those (rarely used) methods that are only signed | ||||
| (defalias 'def-rtm-si-sca 'def-rtm-signed-scalar-method) | ||||
| (defalias 'def-rtm-authenticated-scalar-method 'def-rtm-authenticated-scalar-method) | ||||
| (defalias 'def-rtm-authenticated-scalar-method! 'def-rtm-timeline-scalar-method) | ||||
| (defalias 'def-rtm-si-lis 'def-rtm-signed-list-method) | ||||
| (defalias 'def-rtm-list 'def-rtm-authenticated-list-method) | ||||
| (defalias 'def-rtm-list! 'def-rtm-timeline-list-method) | ||||
|  | ||||
| ;; TODO: I removed the usages of the aliases above - do I have to rewrite | ||||
| ;; these calls as well? | ||||
| (put 'def-rtm-si-sca 'lisp-indent-function 1) | ||||
| (put 'def-rtm-authenticated-scalar-method 'lisp-indent-function 1) | ||||
| (put 'def-rtm-authenticated-scalar-method! 'lisp-indent-function 1) | ||||
| (put 'def-rtm-si-lis 'lisp-indent--function 1) | ||||
| (put 'def-rtm-list 'lisp-indent-function 1) | ||||
| (put 'def-rtm-list! 'lisp-indent-function 1) | ||||
|  | ||||
| ;; note that, for modifying functions, it's mostly better to define | ||||
| ;; them via define-rtm-list!, since you will receive the transaction | ||||
| ;; *and* the result, while a function defined via define-rtm-scalar! | ||||
| ;; will only return the transaction | ||||
|  | ||||
| (defun rtm-call-unsigned (method &rest params) | ||||
|   (let ((request (rtm-construct-request-url rtm-rest-uri | ||||
|                                             (rtm-prepare-params method | ||||
|                                                                 params)))) | ||||
|     (rtm-do-request request))) | ||||
|  | ||||
| (defun rtm-call-signed (method &rest params) | ||||
|   (let* ((unsigned-params (rtm-prepare-params method params)) | ||||
|          (all-params (append-api-sig unsigned-params)) | ||||
|          (request (rtm-construct-request-url rtm-rest-uri | ||||
|                                              all-params))) | ||||
|     (rtm-do-request request))) | ||||
|  | ||||
| (defun rtm-call-authenticated (method &rest params) | ||||
|   (apply #'rtm-call-signed | ||||
|          method | ||||
|          `("auth_token" . ,(rtm-authenticate)) | ||||
|          params)) | ||||
|  | ||||
| (defun rtm-call-timeline (method &rest params) | ||||
|   (apply #'rtm-call-authenticated | ||||
|          method | ||||
|          `("timeline" . ,(rtm-timeline)) | ||||
|          params)) | ||||
|  | ||||
| (defun rtm-get-nodes-from-node-list (node-name node-list) | ||||
|   (cl-remove-if-not (lambda (el) (eq node-name | ||||
|                                   (xml-node-name el))) | ||||
|                  node-list)) | ||||
|  | ||||
| (defun rtm-get-node-content-from-response (node-name response) | ||||
|   (xml-node-children (car (rtm-get-nodes-from-node-list node-name | ||||
|                                            response)))) | ||||
|  | ||||
| (defun rtm-get-list-from-response (path response) | ||||
|   (let ((rst path) | ||||
|         (content response)) | ||||
|     (while rst | ||||
|       (setq content (rtm-get-node-content-from-response (car rst) content)) | ||||
|       (setq rst (cdr rst))) | ||||
|     content)) | ||||
|  | ||||
| (defun rtm-get-scalar-from-response (path response) | ||||
|   (car (rtm-get-list-from-response path response))) | ||||
|  | ||||
| ;;;;; Actual api wrappers from | ||||
| ;; http://www.rememberthemilk.com/services/api/methods/ | ||||
| ;;;;;; auth | ||||
| (def-rtm-signed-scalar-method rtm-auth-check-token rtm.auth.checkToken | ||||
|                               (auth token) auth_token) | ||||
| ;; api call response (without post-processing): | ||||
| ;; ((auth nil | ||||
| ;;        (token nil "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx") | ||||
| ;;        (perms nil "delete") | ||||
| ;;        (user | ||||
| ;;         ((id . "xxxxxxx") | ||||
| ;;          (username . "johndoe") | ||||
| ;;          (fullname . "John Doe"))))) | ||||
| (def-rtm-signed-scalar-method rtm-auth-get-frob rtm.auth.getFrob (frob)) | ||||
| (def-rtm-signed-scalar-method rtm-auth-get-token rtm.auth.getToken | ||||
|                               (auth token) frob) | ||||
| ;; api call response (without post-processing): | ||||
| ;; ((auth nil (token nil "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX") | ||||
| ;; (perms nil "delete") (user (... ... ...)))) | ||||
|  | ||||
| ;;;;;; contacts | ||||
| (def-rtm-timeline-list-method rtm-contacts-add rtm.contacts.add (contact) contact) | ||||
| (def-rtm-timeline-list-method rtm-contacts-delete rtm.contacts.delete () contact_id) | ||||
| (def-rtm-authenticated-list-method rtm-contacts-get-list rtm.contacts.getList (contacts)) | ||||
|  | ||||
| ;;;;;; groups | ||||
| (def-rtm-timeline-list-method rtm-groups-add rtm.groups.add () group) | ||||
| (def-rtm-timeline-list-method rtm-groups-add-contact rtm.groups.addContact () | ||||
|                group_id contact_id) | ||||
| (def-rtm-timeline-list-method rtm-groups-delete rtm.groups.delete () group_id) | ||||
| (def-rtm-authenticated-list-method rtm-groups-get-list rtm.groups.getList ()) | ||||
| (def-rtm-timeline-list-method rtm-groups-remove-contact rtm.groups.removeContact () | ||||
|                group_id contact_id) | ||||
|  | ||||
| ;;;;;; lists | ||||
| (def-rtm-timeline-list-method rtm-lists-add rtm.lists.add () | ||||
|                name &optional filter) | ||||
| (def-rtm-timeline-list-method rtm-lists-archive rtm.lists.archive () | ||||
|                list_id) | ||||
| (def-rtm-timeline-list-method rtm-lists-delete rtm.lists.delete () | ||||
|                list_id) | ||||
| (def-rtm-authenticated-list-method rtm-lists-get-list rtm.lists.getList (lists)) | ||||
| ;; example response (after result function): | ||||
| ;; ((list | ||||
| ;;   ((id . "7781815") | ||||
| ;;    (name . "Inbox") | ||||
| ;;    (deleted . "0") | ||||
| ;;    (locked . "1") | ||||
| ;;    (archived . "0") | ||||
| ;;    (position . "-1") | ||||
| ;;    (smart . "0") | ||||
| ;;    (sort_order . "0"))) | ||||
| ;;  (list | ||||
| ;;   ((id . "7781820") | ||||
| ;;    (name . "All Tasks") | ||||
| ;;    (deleted . "0") | ||||
| ;;    (locked . "0") | ||||
| ;;    (archived . "0") | ||||
| ;;    (position . "0") | ||||
| ;;    (smart . "1") | ||||
| ;;    (sort_order . "0")) | ||||
| ;;   (filter nil)) | ||||
| ;;  (list | ||||
| ;;   ((id . "7781818") | ||||
| ;;    (name . "Work") | ||||
| ;;    (deleted . "0") | ||||
| ;;    (locked . "0") | ||||
| ;;    (archived . "0") | ||||
| ;;    (position . "0") | ||||
| ;;    (smart . "0") | ||||
| ;;    (sort_order . "0"))) | ||||
| ;;  (list | ||||
| ;;   ((id . "7781816") | ||||
| ;;    (name . "Private") | ||||
| ;;    (deleted . "0") | ||||
| ;;    (locked . "0") | ||||
| ;;    (archived . "0") | ||||
| ;;    (position . "0") | ||||
| ;;    (smart . "0") | ||||
| ;;    (sort_order . "0"))) | ||||
| ;;  (list | ||||
| ;;   ((id . "7781819") | ||||
| ;;    (name . "Sent") | ||||
| ;;    (deleted . "0") | ||||
| ;;    (locked . "1") | ||||
| ;;    (archived . "0") | ||||
| ;;    (position . "1") | ||||
| ;;    (smart . "0") | ||||
| ;;    (sort_order . "0")))) | ||||
| (def-rtm-timeline-list-method rtm-lists-set-default-list rtm.lists.setDefaultList () | ||||
|                list_id) | ||||
| (def-rtm-timeline-list-method rtm-lists-set-name rtm.lists.setName () | ||||
|                list_id name) | ||||
| (def-rtm-timeline-list-method rtm-lists-unarchive rtm.lists.unarchive () | ||||
|                list_id) | ||||
|  | ||||
| ;;;;;; locations | ||||
| (def-rtm-authenticated-list-method rtm-locations-get-list rtm.locations.getList (locations)) | ||||
|  | ||||
| ;;;;;; reflection | ||||
| (def-rtm-signed-list-method rtm-reflection-get-methods rtm.reflection.getMethods | ||||
|                             (methods)) | ||||
| (def-rtm-signed-scalar-method rtm-reflection-get-method-info | ||||
|                               rtm.reflection.getMethodInfo () method_name) | ||||
|  | ||||
| ;;;;;; settings | ||||
| (def-rtm-authenticated-list-method rtm-settings-get-list rtm.settings.getList (settings)) | ||||
|  | ||||
| ;;;;;; tasks | ||||
| (def-rtm-timeline-list-method rtm-tasks-add rtm.tasks.add () | ||||
|                name &optional parse list_id) | ||||
|  | ||||
| (def-rtm-timeline-list-method rtm-tasks-add-tags rtm.tasks.addTags () | ||||
|                list_id taskseries_id task_id tags) | ||||
|  | ||||
| (def-rtm-timeline-list-method rtm-tasks-complete rtm.tasks.complete () | ||||
|                list_id taskseries_id task_id) | ||||
|  | ||||
| (def-rtm-timeline-list-method rtm-tasks-delete rtm.tasks.delete () | ||||
|                list_id taskseries_id task_id) | ||||
|  | ||||
| (def-rtm-authenticated-list-method rtm-tasks-get-list rtm.tasks.getList (tasks) | ||||
|               &optional list_id filter last_sync) | ||||
| ;; example response (after result function): | ||||
| ;; ((list | ||||
| ;;   ((id . "7781819"))) | ||||
| ;;  (list | ||||
| ;;   ((id . "7781817"))) | ||||
| ;;  (list | ||||
| ;;   ((id . "7781816")) | ||||
| ;;   (taskseries | ||||
| ;;    ((id . "35272531") | ||||
| ;;     (created . "2009-03-08T20:57:45Z") | ||||
| ;;     (modified . "2009-03-08T21:52:18Z") | ||||
| ;;     (name . "Try Remember The Milk") | ||||
| ;;     (source . "js") | ||||
| ;;     (url . "") | ||||
| ;;     (location_id . "")) | ||||
| ;;    (tags nil) | ||||
| ;;    (participants nil) | ||||
| ;;    (notes nil) | ||||
| ;;    (task | ||||
| ;;     ((id . "49791364") | ||||
| ;;      (due . "2009-03-08T20:57:00Z") | ||||
| ;;      (has_due_time . "1") | ||||
| ;;      (added . "2009-03-08T20:57:45Z") | ||||
| ;;      (completed . "2009-03-08T21:52:16Z") | ||||
| ;;      (deleted . "") | ||||
| ;;      (priority . "1") | ||||
| ;;      (postponed . "0") | ||||
| ;;      (estimate . ""))))) | ||||
| ;;  (list | ||||
| ;;   ((id . "7781818"))) | ||||
| ;;  (list | ||||
| ;;   ((id . "7781820")))) | ||||
|  | ||||
| (def-rtm-timeline-list-method rtm-tasks-move-priority rtm.tasks.movePriority () | ||||
|                list_id taskseries_id task_id direction) | ||||
|  | ||||
| (def-rtm-timeline-list-method rtm-tasks-move-to rtm.tasks.moveTo () | ||||
|                from_list_id to_list_id taskseries_id task_id) | ||||
|  | ||||
| (def-rtm-timeline-list-method rtm-tasks-postpone rtm.tasks.postpone () | ||||
|                list_id taskseries_id task_id) | ||||
|  | ||||
| (def-rtm-timeline-list-method rtm-tasks-remove-tags rtm.tasks.removeTags () | ||||
|                list_id taskseries_id task_id tags) | ||||
|  | ||||
| (def-rtm-timeline-list-method rtm-tasks-set-due-date rtm.tasks.setDueDate () | ||||
|                list_id taskseries_id task_id &optional due has_due_time parse) | ||||
|  | ||||
| (def-rtm-timeline-list-method rtm-tasks-set-estimate rtm.tasks.setEstimate () | ||||
|                list_id taskseries_id task_id &optional estimate) | ||||
|  | ||||
| (def-rtm-timeline-list-method rtm-tasks-set-location rtm.tasks.setLocation () | ||||
|                list_id taskseries_id task_id &optional location_id) | ||||
|  | ||||
| (def-rtm-timeline-list-method rtm-tasks-set-name rtm.tasks.setName () | ||||
|                list_id taskseries_id task_id name) | ||||
|  | ||||
| (def-rtm-timeline-list-method rtm-tasks-set-priority rtm.tasks.setPriority () | ||||
|                list_id taskseries_id task_id &optional priority) | ||||
|  | ||||
| (def-rtm-timeline-list-method rtm-tasks-set-recurrence rtm.tasks.setRecurrence () | ||||
|                list_id taskseries_id task_id &optional repeat) | ||||
|  | ||||
| (def-rtm-timeline-list-method rtm-tasks-set-tags rtm.tasks.setTags () | ||||
|                list_id taskseries_id task_id &optional tags) | ||||
|  | ||||
| (def-rtm-timeline-list-method rtm-tasks-set-url rtm.tasks.setURL () | ||||
|                list_id taskseries_id task_id &optional url) | ||||
|  | ||||
| (def-rtm-timeline-list-method rtm-tasks-uncomplete rtm.tasks.uncomplete () | ||||
|                list_id taskseries_id task_id) | ||||
|  | ||||
| ;;;;;; tasks.notes | ||||
| (def-rtm-timeline-list-method rtm-tasks-notes-add rtm.tasks.notes.add () | ||||
|                list_id taskseries_id task_id note_title note_text) | ||||
|  | ||||
| (def-rtm-timeline-list-method rtm-tasks-notes-delete rtm.tasks.notes.delete () | ||||
|                note_id) | ||||
|  | ||||
| (def-rtm-timeline-list-method rtm-tasks-notes-edit rtm.tasks.notes.edit () | ||||
|                note_id note_title note_text) | ||||
|  | ||||
| ;;;;;; test | ||||
| (defun rtm-test-echo () | ||||
|   (rtm-call-unsigned 'rtm.test.echo)) | ||||
|  | ||||
| (def-rtm-authenticated-list-method rtm-test-login rtm.test.login ()) | ||||
|  | ||||
| ;;;;;; time | ||||
| (def-rtm-signed-list-method rtm-time-convert rtm.time.convert () | ||||
|                             to_timezone &optional from_timezone time) | ||||
|  | ||||
| ;;;;;; timelines | ||||
| (def-rtm-authenticated-scalar-method rtm-timelines-create rtm.timelines.create (timeline)) | ||||
| (defun rtm-timeline () | ||||
|   (unless rtm-current-timeline | ||||
|     (progn | ||||
|       (setq rtm-current-timeline (rtm-timelines-create)))) | ||||
|   rtm-current-timeline) | ||||
|  | ||||
| ;;;;;; timezones | ||||
| (def-rtm-signed-list-method rtm-timezones-get-list rtm.timezones.getList ()) | ||||
|  | ||||
| ;;;;;; transactions | ||||
| (def-rtm-timeline-list-method rtm-transactions-undo rtm.transactions.undo () transaction_id) | ||||
|  | ||||
| ;;;; User authentication | ||||
|  | ||||
| (defun rtm-authenticate () | ||||
|   "Always use this function to call an authenticated method, it's the only one | ||||
| that will update rtm-auth-token" | ||||
|   (setq rtm-auth-token | ||||
|         (let ((auth-token (or (rtm-get-stored-auth-token) | ||||
|                               rtm-auth-token))) | ||||
|           (if (and auth-token | ||||
|                    (rtm-auth-token-valid auth-token)) | ||||
|               auth-token | ||||
|             (rtm-get-new-auth-token)))) | ||||
|   rtm-auth-token) | ||||
|  | ||||
| (defun rtm-auth-token-valid (auth-token) | ||||
|   (if rtm-auth-token-valid | ||||
|       t | ||||
|     (let ((token (ignore-errors (rtm-auth-check-token auth-token)))) | ||||
|       (if (and token | ||||
|                (string-equal auth-token token)) | ||||
|           (setq rtm-auth-token-valid t) | ||||
|         nil)))) | ||||
|  | ||||
| (defun rtm-get-new-auth-token () | ||||
|   (let* ((frob (rtm-auth-get-frob)) | ||||
|          (auth-url (rtm-authentication-url 'delete frob)) | ||||
|          (auth-token nil)) | ||||
|     (while (not auth-token) | ||||
|       (browse-url auth-url) | ||||
|       (rtm-authentication-dialog auth-url) | ||||
|       (setq auth-token | ||||
|             (rtm-auth-get-token frob)) | ||||
|       (if (rtm-auth-token-valid auth-token) | ||||
|           (rtm-store-auth-token auth-token) | ||||
|         (setq auth-token nil))) | ||||
|     auth-token)) | ||||
|  | ||||
| (defun rtm-store-auth-token (auth-token) | ||||
|   (let ((token-file (locate-user-emacs-file rtm-auth-token-file))) | ||||
|     (unless (file-exists-p token-file) | ||||
|       (with-temp-file token-file)) | ||||
|     (set-file-modes token-file #o600) | ||||
|     (with-temp-file token-file | ||||
|       (insert auth-token))) | ||||
|   auth-token) | ||||
|  | ||||
| (defun rtm-get-stored-auth-token () | ||||
|   (let ((token-file (locate-user-emacs-file rtm-auth-token-file))) | ||||
|     (if (file-exists-p token-file) | ||||
|         (if (file-readable-p token-file) | ||||
|             (with-temp-buffer | ||||
|               (insert-file-contents token-file) | ||||
|               (buffer-string)) | ||||
|           (error "Auth token store %s exists, but is not readable." | ||||
|                  token-file)) | ||||
|       nil))) | ||||
|  | ||||
| (defun rtm-authentication-dialog (auth-url) | ||||
|   (let ((rtm-buffer (generate-new-buffer rtm-ui-buffer-name))) | ||||
|     (with-current-buffer rtm-buffer | ||||
|       (insert "Please visit the following url to authenticate this | ||||
| application:\n\n") | ||||
|       (insert-text-button auth-url 'type 'rtm-url) | ||||
|       (display-buffer rtm-buffer) | ||||
|       ;; (redisplay) | ||||
|       (read-from-minibuffer | ||||
|        "Press RETURN if after authentication was granted") | ||||
|       (kill-buffer rtm-buffer)))) | ||||
|  | ||||
| (define-button-type 'rtm-url | ||||
|   'action (lambda (x) | ||||
|             (let ((button (button-at (point)))) | ||||
|               (browse-url | ||||
|                (button-label button)))) | ||||
|   'follow-link t) | ||||
|  | ||||
| (define-button-type 'rtm-button | ||||
|   'follow-link t) | ||||
|  | ||||
| (defun rtm-authentication-url (perms frob) | ||||
|   (let* ((unsigned-params `(("api_key" . ,rtm-api-key) | ||||
|                             ("perms" . ,(maybe-string perms)) | ||||
|                             ("frob" . ,frob))) | ||||
|          (all-params (append-api-sig unsigned-params))) | ||||
|     (rtm-construct-request-url rtm-auth-uri | ||||
|                                all-params))) | ||||
|  | ||||
| ;;;; WebAPI handling | ||||
|  | ||||
| (defun rtm-do-request (request) | ||||
|   (if rtm-debug | ||||
|       (message "request: %s" request)) | ||||
|   (rtm-parse-response (url-retrieve-synchronously request))) | ||||
|  | ||||
| ;; adapted from avdi's code: | ||||
| (defun rtm-api-sig (params) | ||||
|   (let* ((param-copy (cl-copy-list params)) | ||||
|          (sorted-params (sort param-copy | ||||
|                               (lambda (lhs rhs) (string< (car lhs) (car rhs))))) | ||||
|          (joined-params (mapcar (lambda (param) | ||||
|                                   (concat (car param) (cdr param))) | ||||
|                                 sorted-params)) | ||||
|          (params-str (cl-reduce 'concat joined-params)) | ||||
|          (with-secret (concat rtm-api-shared-secret params-str))) | ||||
|     (md5 with-secret))) | ||||
|  | ||||
| (defun rtm-prepare-params (method params) | ||||
|   (rtm-add-method+api method | ||||
|                       (rtm-stringify-params (rtm-weed-empty-params params)))) | ||||
|  | ||||
| (defun rtm-stringify-params (params) | ||||
|   (mapcar #'rtm-stringify-param params)) | ||||
|  | ||||
| (defun rtm-stringify-param (param) | ||||
|   (let* ((name (car param)) | ||||
|          (value (cdr param))) | ||||
|     (cons (rtm-stringify-param-name name) | ||||
|           (rtm-stringify-value value)))) | ||||
|  | ||||
| (defun rtm-stringify-param-name (name) | ||||
|   (cond ((stringp name) | ||||
|          name) | ||||
|         ((symbolp name) | ||||
|          (symbol-name name)))) | ||||
|  | ||||
| ;; note: because we can't really tell between parameter wasn't given | ||||
| ;; and explicitly set as nil (see rtm-weed-empty-params below), you | ||||
| ;; should give 'false rather than nil if you mean false | ||||
| (defun rtm-stringify-value (value) | ||||
|   (cond ((stringp value) | ||||
|          value) | ||||
|         ((eq t value) | ||||
|          "true") | ||||
|         ((null value) | ||||
|          "false") | ||||
|         ((listp value) | ||||
|          (rtm-comma-separated-list value)) | ||||
|         ((symbolp value) | ||||
|          (symbol-name value)) | ||||
|         ((numberp value) | ||||
|          (number-to-string value)))) | ||||
|  | ||||
| (defun rtm-comma-separated-list (lis) | ||||
|   "turn a list into a comma separated string (and flatten it)" | ||||
|   (cl-labels ((comsep (lis first) | ||||
|                  (if (null lis) | ||||
|                      "" | ||||
|                    (concat (if first "" ",") | ||||
|                            (rtm-stringify-value (car lis)) | ||||
|                            (comsep (cdr lis) nil))))) | ||||
|     (comsep lis t))) | ||||
|  | ||||
|  | ||||
| (defun rtm-weed-empty-params (params) | ||||
|   (cl-remove-if (lambda (param) | ||||
|                (and (listp param) | ||||
|                     (not (null param)) | ||||
|                     (null (cdr param)))) | ||||
|              params)) | ||||
|  | ||||
| (defun rtm-add-method+api (method params) | ||||
|   (append `(("method" . ,(maybe-string method)) | ||||
|             ("api_key" . ,rtm-api-key)) | ||||
|           params)) | ||||
|  | ||||
| ;; adapted from avdi's code: | ||||
| (defun rtm-construct-request-url (base-uri params) | ||||
|   "Construct a URL for calling a method from params" | ||||
|   (let* ((param-pairs (mapcar 'rtm-format-param params)) | ||||
|          (query (rtm-join-params param-pairs))) | ||||
|     (string-to-unibyte (concat base-uri "?" query)))) | ||||
|  | ||||
| ;; adapted from avdi's code: | ||||
| (defun rtm-format-param (param) | ||||
|   (let ((key (car param)) | ||||
|         (value (cdr param))) | ||||
|     ;; it's important that we sign the unencoded parameters, but of | ||||
|     ;; course the request must be url-encoded | ||||
|     (concat key "=" (url-hexify-string value)))) | ||||
|  | ||||
| ;; from avdi's code: | ||||
| (defun rtm-join-params (params) | ||||
|   (cl-reduce (lambda (left right) (concat left "&" right)) params)) | ||||
|  | ||||
| ;; adapted from avdi's code: | ||||
| (defun rtm-construct-url (method) | ||||
|   (concat rtm-rest-uri | ||||
|           "?" | ||||
|           "method=" method | ||||
|           "&" | ||||
|           "api_key=" rtm-api-key)) | ||||
|  | ||||
| ;; from avdi's code: | ||||
| ;; TODO Interpret the stat attribute and throw an error if it's not ok | ||||
| (defun rtm-parse-response (response) | ||||
|   (with-current-buffer response | ||||
|     (let* ((node-list (xml-parse-region (point-min) (point-max))) | ||||
|            (rsps (rtm-get-nodes-from-node-list 'rsp node-list))) | ||||
|       (when (> (length rsps) 1) | ||||
|         (warn | ||||
|          "Got more than one <rsp> node in response, please examine! | ||||
| Response:%s" (pp node-list))) | ||||
|       (let* ((rsp (car rsps)) | ||||
|              (children (xml-node-children rsp)) | ||||
|              (stat (rtm-stat rsp))) | ||||
|         (unless stat | ||||
|           (warn "Weird, got no stat attribute in <rsp> node. | ||||
| %s" (pp node-list))) | ||||
|         (if (eq stat 'ok) | ||||
|             children | ||||
|           (let* ((err (car (rtm-get-nodes-from-node-list 'err children))) | ||||
|                  (code (xml-get-attribute err 'code)) | ||||
|                  (msg (xml-get-attribute err 'msg))) | ||||
|             (error "Error in server response: Code: %s\n | ||||
| Message: \"%s\"" code msg))))))) | ||||
|  | ||||
| (defun rtm-stat (rsp) | ||||
|   (let ((stat (xml-get-attribute-or-nil rsp 'stat))) | ||||
|     (if stat | ||||
|         (intern (downcase stat)) | ||||
|       stat))) | ||||
|  | ||||
| ;;; example responses | ||||
| ;; failure: | ||||
| ;; ((rsp | ||||
| ;;   ((stat . "fail")) | ||||
| ;;   (err | ||||
| ;;    ((code . "97") | ||||
| ;;     (msg . "Missing signature"))))) | ||||
| ;; success: | ||||
| ;; rtm.auth.getFrob: | ||||
| ;; ((rsp | ||||
| ;;   ((stat . "ok")) | ||||
| ;;   (frob nil "cce8d04e182212cddd5cdc815e09648fecd18e0e"))) | ||||
| ;; rtm.test.echo: | ||||
| ;; ((rsp ((stat . "ok")) | ||||
| ;;       (api_key nil "00000000000000000000000000000000") | ||||
| ;;       (method nil "rtm.test.echo"))) | ||||
| (defun append-api-sig (unsigned-params) | ||||
|   (let ((api-sig (rtm-api-sig unsigned-params))) | ||||
|     (append unsigned-params | ||||
|             `(("api_sig" . ,api-sig))))) | ||||
|  | ||||
| ;;;; Misc/Helper functions | ||||
| (defun maybe-string (symbol-or-string) | ||||
|   (if (stringp symbol-or-string) symbol-or-string | ||||
|     (symbol-name symbol-or-string))) | ||||
|  | ||||
| (provide 'rtm) | ||||
|  | ||||
| ;;; rtm.el ends here | ||||
							
								
								
									
										49
									
								
								elpa/simple-rtm-20160222.734/simple-rtm-autoloads.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								elpa/simple-rtm-20160222.734/simple-rtm-autoloads.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | ||||
| ;;; simple-rtm-autoloads.el --- automatically extracted autoloads | ||||
| ;; | ||||
| ;;; Code: | ||||
| (add-to-list 'load-path (directory-file-name (or (file-name-directory #$) (car load-path)))) | ||||
|  | ||||
| ;;;### (autoloads nil "simple-rtm" "simple-rtm.el" (22533 17554 588844 | ||||
| ;;;;;;  77000)) | ||||
| ;;; Generated autoloads from simple-rtm.el | ||||
|  (put 'simple-rtm-mode-line-string 'risky-local-variable t) | ||||
|  | ||||
| (autoload 'simple-rtm-mode "simple-rtm" "\ | ||||
| An interactive \"do everything right now\" mode for Remember The Milk | ||||
|  | ||||
| Display all of your lists and tasks in a new buffer or switch to | ||||
| that buffer if it already exists. | ||||
|  | ||||
| Each action will be sent to the Remember The Milk web interface | ||||
| immediately. | ||||
|  | ||||
| \\{simple-rtm-mode-map} | ||||
|  | ||||
| \(fn)" t nil) | ||||
|  | ||||
| (defvar display-simple-rtm-tasks-mode nil "\ | ||||
| Non-nil if Display-Simple-Rtm-Tasks mode is enabled. | ||||
| See the `display-simple-rtm-tasks-mode' command | ||||
| for a description of this minor mode. | ||||
| Setting this variable directly does not take effect; | ||||
| either customize it (see the info node `Easy Customization') | ||||
| or call the function `display-simple-rtm-tasks-mode'.") | ||||
|  | ||||
| (custom-autoload 'display-simple-rtm-tasks-mode "simple-rtm" nil) | ||||
|  | ||||
| (autoload 'display-simple-rtm-tasks-mode "simple-rtm" "\ | ||||
| Display SimpleRTM task statistics in the mode line. | ||||
| The text being displayed in the mode line is controlled by the variables | ||||
| `simple-rtm-mode-line-format'. | ||||
| The mode line will be updated automatically when a task is modified. | ||||
|  | ||||
| \(fn &optional ARG)" t nil) | ||||
|  | ||||
| ;;;*** | ||||
|  | ||||
| ;; Local Variables: | ||||
| ;; version-control: never | ||||
| ;; no-byte-compile: t | ||||
| ;; no-update-autoloads: t | ||||
| ;; End: | ||||
| ;;; simple-rtm-autoloads.el ends here | ||||
							
								
								
									
										2
									
								
								elpa/simple-rtm-20160222.734/simple-rtm-pkg.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								elpa/simple-rtm-20160222.734/simple-rtm-pkg.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| ;;; -*- no-byte-compile: t -*- | ||||
| (define-package "simple-rtm" "20160222.734" "Interactive Emacs mode for Remember The Milk" '((rtm "0.1") (dash "2.0.0")) :keywords '("remember" "the" "milk" "productivity" "todo")) | ||||
							
								
								
									
										1355
									
								
								elpa/simple-rtm-20160222.734/simple-rtm.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1355
									
								
								elpa/simple-rtm-20160222.734/simple-rtm.el
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										47
									
								
								elpa/slack-20160928.2036/slack-autoloads.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								elpa/slack-20160928.2036/slack-autoloads.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,47 @@ | ||||
| ;;; slack-autoloads.el --- automatically extracted autoloads | ||||
| ;; | ||||
| ;;; Code: | ||||
| (add-to-list 'load-path (directory-file-name (or (file-name-directory #$) (car load-path)))) | ||||
|  | ||||
| ;;;### (autoloads nil "slack" "slack.el" (22533 17549 313723 713000)) | ||||
| ;;; Generated autoloads from slack.el | ||||
|  | ||||
| (autoload 'slack-start "slack" "\ | ||||
|  | ||||
|  | ||||
| \(fn &optional TEAM)" t nil) | ||||
|  | ||||
| ;;;*** | ||||
|  | ||||
| ;;;### (autoloads nil "slack-team" "slack-team.el" (22533 17549 403725 | ||||
| ;;;;;;  767000)) | ||||
| ;;; Generated autoloads from slack-team.el | ||||
|  | ||||
| (autoload 'slack-register-team "slack-team" "\ | ||||
| PLIST must contain :name :client-id :client-secret with value. | ||||
| setting :token will reduce your configuration step. | ||||
| you will notified when receive message with channel included in subscribed-chennels. | ||||
| if :default is t and `slack-prefer-current-team' is t, skip selecting team when channels listed. | ||||
| you can change current-team with `slack-change-current-team' | ||||
|  | ||||
| \(fn &rest PLIST)" t nil) | ||||
|  | ||||
| ;;;*** | ||||
|  | ||||
| ;;;### (autoloads nil nil ("slack-bot-message.el" "slack-buffer.el" | ||||
| ;;;;;;  "slack-channel.el" "slack-file.el" "slack-group.el" "slack-im.el" | ||||
| ;;;;;;  "slack-message-editor.el" "slack-message-formatter.el" "slack-message-notification.el" | ||||
| ;;;;;;  "slack-message-reaction.el" "slack-message-sender.el" "slack-message.el" | ||||
| ;;;;;;  "slack-pkg.el" "slack-reaction.el" "slack-reminder.el" "slack-reply.el" | ||||
| ;;;;;;  "slack-request.el" "slack-room.el" "slack-search.el" "slack-user-message.el" | ||||
| ;;;;;;  "slack-user.el" "slack-util.el" "slack-websocket.el") (22533 | ||||
| ;;;;;;  17549 504728 72000)) | ||||
|  | ||||
| ;;;*** | ||||
|  | ||||
| ;; Local Variables: | ||||
| ;; version-control: never | ||||
| ;; no-byte-compile: t | ||||
| ;; no-update-autoloads: t | ||||
| ;; End: | ||||
| ;;; slack-autoloads.el ends here | ||||
							
								
								
									
										89
									
								
								elpa/slack-20160928.2036/slack-bot-message.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								elpa/slack-20160928.2036/slack-bot-message.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,89 @@ | ||||
| ;;; slack-bot-message.el --- bot message class        -*- lexical-binding: t; -*- | ||||
|  | ||||
| ;; Copyright (C) 2015  yuya.minami | ||||
|  | ||||
| ;; Author: yuya.minami <yuya.minami@yuyaminami-no-MacBook-Pro.local> | ||||
| ;; Keywords: | ||||
|  | ||||
| ;; This program is free software; you can redistribute it and/or modify | ||||
| ;; it under the terms of the GNU General Public License as published by | ||||
| ;; the Free Software Foundation, either version 3 of the License, or | ||||
| ;; (at your option) any later version. | ||||
|  | ||||
| ;; This program is distributed in the hope that it will be useful, | ||||
| ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| ;; GNU General Public License for more details. | ||||
|  | ||||
| ;; You should have received a copy of the GNU General Public License | ||||
| ;; along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  | ||||
| ;;; Commentary: | ||||
|  | ||||
| ;; | ||||
|  | ||||
| ;;; Code: | ||||
|  | ||||
| (require 'eieio) | ||||
| (require 'slack-message) | ||||
| (require 'slack-message-formatter) | ||||
|  | ||||
| (defun slack-find-bot (id team) | ||||
|   (with-slots (bots) team | ||||
|     (cl-find-if (lambda (bot) | ||||
|                   (string= id (plist-get bot :id))) | ||||
|                 bots))) | ||||
|  | ||||
| (defmethod slack-bot-name ((m slack-bot-message) team) | ||||
|   (if (slot-boundp m 'bot-id) | ||||
|       (let ((bot (slack-find-bot (oref m bot-id) team))) | ||||
|         (if bot | ||||
|             (plist-get bot :name) | ||||
|           (oref m username))) | ||||
|     (oref m username))) | ||||
|  | ||||
| (defmethod slack-message-to-alert ((m slack-bot-message) team) | ||||
|   (let ((text (if (slot-boundp m 'text) | ||||
|                   (oref m text)))) | ||||
|     (with-slots (attachments) m | ||||
|       (if (and text (< 0 (length text))) | ||||
|           (slack-message-unescape-string text team) | ||||
|         (let ((attachment-string (mapconcat #'slack-attachment-to-alert attachments " "))) | ||||
|           (slack-message-unescape-string attachment-string team)))))) | ||||
|  | ||||
| (defmethod slack-message-sender-name ((m slack-bot-message) team) | ||||
|   (slack-bot-name m team)) | ||||
|  | ||||
| (defmethod slack-attachment-to-string ((a slack-attachment)) | ||||
|   (with-slots (fallback text pretext title title-link) a | ||||
|     (if (and pretext title text) | ||||
|         (mapconcat #'identity | ||||
|                    (cl-remove-if #'null (list pretext title title-link text)) | ||||
|                    "\n") | ||||
|       fallback))) | ||||
|  | ||||
| (defmethod slack-attachment-to-string((a slack-shared-message)) | ||||
|   (with-slots (fallback text author-name ts channel-name color from-url) a | ||||
|     (let* ((header-property '(:weight bold)) | ||||
|            (footer-property '(:height 0.8)) | ||||
|            (pad-property '(:weight ultra-bold)) | ||||
|            (pad (propertize "|" 'face pad-property)) | ||||
|            (header (concat pad "\t" | ||||
|                            (propertize author-name 'face header-property))) | ||||
|            (body (format "%s\t%s" pad (mapconcat #'identity | ||||
|                                                  (split-string text "\n") | ||||
|                                                  (format "\n\t%s\t" pad)))) | ||||
|            (footer (concat pad "\t" | ||||
|                            (propertize | ||||
|                             (format "%s %s" channel-name (slack-message-time-to-string ts)) | ||||
|                             'face footer-property)))) | ||||
|       (format "\t%s\n \t%s\n \t%s" | ||||
|               header | ||||
|               body | ||||
|               footer)))) | ||||
|  | ||||
| (defmethod slack-attachment-to-alert ((a slack-attachment)) | ||||
|   (oref a fallback)) | ||||
|  | ||||
| (provide 'slack-bot-message) | ||||
| ;;; slack-bot-message.el ends here | ||||
							
								
								
									
										327
									
								
								elpa/slack-20160928.2036/slack-buffer.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										327
									
								
								elpa/slack-20160928.2036/slack-buffer.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,327 @@ | ||||
| ;;; slack-buffer.el --- slack buffer                  -*- lexical-binding: t; -*- | ||||
|  | ||||
| ;; Copyright (C) 2015  南優也 | ||||
|  | ||||
| ;; Author: 南優也 <yuyaminami@minamiyuunari-no-MacBook-Pro.local> | ||||
| ;; Keywords: | ||||
|  | ||||
| ;; This program is free software; you can redistribute it and/or modify | ||||
| ;; it under the terms of the GNU General Public License as published by | ||||
| ;; the Free Software Foundation, either version 3 of the License, or | ||||
| ;; (at your option) any later version. | ||||
|  | ||||
| ;; This program is distributed in the hope that it will be useful, | ||||
| ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| ;; GNU General Public License for more details. | ||||
|  | ||||
| ;; You should have received a copy of the GNU General Public License | ||||
| ;; along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  | ||||
| ;;; Commentary: | ||||
|  | ||||
| ;; | ||||
|  | ||||
| ;;; Code: | ||||
|  | ||||
| (require 'eieio) | ||||
| (require 'lui) | ||||
| (require 'slack-room) | ||||
|  | ||||
| (defvar lui-prompt-string "> ") | ||||
|  | ||||
| (defvar slack-mode-map | ||||
|   (let ((map (make-sparse-keymap))) | ||||
|     ;; (define-key map (kbd "C-s C-r") #'slack-room-update-messages) | ||||
|     ;; (define-key map (kbd "C-s C-b") #'slack-message-write-another-buffer) | ||||
|     map)) | ||||
|  | ||||
| (define-derived-mode slack-mode lui-mode "Slack" | ||||
|   "" | ||||
|   (lui-set-prompt lui-prompt-string) | ||||
|   (setq lui-input-function 'slack-message--send)) | ||||
|  | ||||
| (define-derived-mode slack-info-mode lui-mode "Slack Info" | ||||
|   "" | ||||
|   (lui-set-prompt lui-prompt-string)) | ||||
|  | ||||
| (defvar slack-current-room-id) | ||||
| (defvar slack-current-team-id) | ||||
| (defvar slack-current-message nil) | ||||
| (defcustom slack-buffer-emojify nil | ||||
|   "Show emoji with `emojify' if true." | ||||
|   :group 'slack) | ||||
|  | ||||
| (defmacro slack-buffer-widen (&rest body) | ||||
|   `(save-excursion | ||||
|      (save-restriction | ||||
|        (widen) | ||||
|        ,@body))) | ||||
|  | ||||
| (defun slack-get-buffer-create (room) | ||||
|   (let* ((buf-name (slack-room-buffer-name room)) | ||||
|          (buffer (get-buffer buf-name))) | ||||
|     (unless buffer | ||||
|       (setq buffer (generate-new-buffer buf-name)) | ||||
|       (with-current-buffer buffer | ||||
|         (slack-mode) | ||||
|         (slack-buffer-insert-previous-link room) | ||||
|         (add-hook 'kill-buffer-hook 'slack-reset-room-last-read nil t) | ||||
|         (add-hook 'lui-pre-output-hook 'slack-buffer-add-last-ts-property nil t) | ||||
|         (add-hook 'lui-post-output-hook 'slack-buffer-add-ts-property nil t))) | ||||
|     buffer)) | ||||
|  | ||||
| (defmethod slack-buffer-set-current-room-id ((room slack-room)) | ||||
|   (set (make-local-variable 'slack-current-room-id) (oref room id))) | ||||
|  | ||||
| (defun slack-buffer-set-current-team-id (team) | ||||
|   (set (make-local-variable 'slack-current-team-id) (oref team id))) | ||||
|  | ||||
| (defun slack-buffer-enable-emojify () | ||||
|   (if slack-buffer-emojify | ||||
|       (let ((emojify (require 'emojify nil t))) | ||||
|         (unless emojify | ||||
|           (error "Emojify is not installed")) | ||||
|         (emojify-mode t)))) | ||||
|  | ||||
| (defun slack-buffer-goto (ts) | ||||
|   (let ((point (slack-buffer-ts-eq (point-min) (point-max) ts))) | ||||
|     (when point | ||||
|       (goto-char point)))) | ||||
|  | ||||
| (defmethod slack-buffer-insert-previous-link ((room slack-room)) | ||||
|   (let ((oldest (slack-room-prev-link-info room))) | ||||
|     (if oldest | ||||
|         (slack-buffer-widen | ||||
|          (let ((inhibit-read-only t)) | ||||
|            (goto-char (point-min)) | ||||
|            (insert | ||||
|             (concat | ||||
|              (propertize "(load more message)" | ||||
|                          'face '(:underline t) | ||||
|                          'oldest oldest | ||||
|                          'keymap (let ((map (make-sparse-keymap))) | ||||
|                                    (define-key map (kbd "RET") | ||||
|                                      #'slack-room-load-prev-messages) | ||||
|                                    map)) | ||||
|              "\n\n")) | ||||
|            (set-marker lui-output-marker (point))))))) | ||||
|  | ||||
| (defmethod slack-buffer-insert-prev-messages ((room slack-room) team oldest-ts) | ||||
|   (slack-buffer-widen | ||||
|    (let ((messages (slack-room-prev-messages room oldest-ts))) | ||||
|      (if messages | ||||
|          (progn | ||||
|            (slack-buffer-insert-previous-link room) | ||||
|            (cl-loop for m in messages | ||||
|                     do (slack-buffer-insert m team t))) | ||||
|        (set-marker lui-output-marker (point-min)) | ||||
|        (lui-insert "(no more messages)\n")) | ||||
|      (slack-buffer-recover-lui-output-marker)))) | ||||
|  | ||||
| (cl-defun slack-buffer-create (room team | ||||
|                                     &key | ||||
|                                     (insert-func | ||||
|                                      #'slack-buffer-insert-messages) | ||||
|                                     (type 'message)) | ||||
|   (cl-labels | ||||
|       ((get-buffer (type room) | ||||
|                    (cl-ecase type | ||||
|                      (message (slack-get-buffer-create room)) | ||||
|                      (info (slack-get-info-buffer-create room))))) | ||||
|     (let* ((buffer (get-buffer type room))) | ||||
|       (with-current-buffer buffer | ||||
|         (if insert-func | ||||
|             (funcall insert-func room team)) | ||||
|         (slack-buffer-set-current-room-id room) | ||||
|         (slack-buffer-set-current-team-id team) | ||||
|         (slack-buffer-enable-emojify)) | ||||
|       buffer))) | ||||
|  | ||||
| (defun slack-buffer-add-last-ts-property () | ||||
|   (when slack-current-message | ||||
|     (add-text-properties | ||||
|      (point-min) (point-max) | ||||
|      `(slack-last-ts ,lui-time-stamp-last)))) | ||||
|  | ||||
| (defun slack-buffer-add-ts-property () | ||||
|   (when slack-current-message | ||||
|     (add-text-properties | ||||
|      (point-min) (point-max) | ||||
|      `(ts ,(oref slack-current-message ts))))) | ||||
|  | ||||
| (defun slack-buffer-insert (message team &optional not-tracked-p) | ||||
|   (let ((lui-time-stamp-time (slack-message-time-stamp message)) | ||||
|         (beg lui-input-marker) | ||||
|         (inhibit-read-only t)) | ||||
|     (let ((slack-current-message message)) | ||||
|       (lui-insert (slack-message-to-string message team) not-tracked-p)))) | ||||
|  | ||||
| (defun slack-buffer-insert-messages (room team) | ||||
|   (let* ((sorted (slack-room-sorted-messages room)) | ||||
|          (messages (slack-room-latest-messages room sorted))) | ||||
|     (if messages | ||||
|         (progn | ||||
|           ;; (slack-buffer-insert-previous-link room) | ||||
|           (cl-loop for m in messages | ||||
|                    do (slack-buffer-insert m team t)) | ||||
|           (let ((latest-message (car (last messages)))) | ||||
|             (slack-room-update-last-read room latest-message) | ||||
|             (slack-room-update-mark room team latest-message))) | ||||
|       (unless (eq 0 (oref room unread-count-display)) | ||||
|         (let ((latest-message (car (last sorted)))) | ||||
|           (slack-room-update-mark room team latest-message)))))) | ||||
|  | ||||
| (defun slack-buffer-show-typing-p (buffer) | ||||
|   (cl-case slack-typing-visibility | ||||
|     ('frame (slack-buffer-in-current-frame buffer)) | ||||
|     ('buffer (slack-buffer-current-p buffer)) | ||||
|     ('never nil))) | ||||
|  | ||||
| (defun slack-buffer-current-p (buffer) | ||||
|   (if buffer | ||||
|       (string= (buffer-name buffer) | ||||
|                (buffer-name (current-buffer))))) | ||||
|  | ||||
| (defun slack-buffer-in-current-frame (buffer) | ||||
|   (if buffer | ||||
|       (cl-member (buffer-name buffer) | ||||
|                  (mapcar #'buffer-name | ||||
|                          (mapcar #'window-buffer (window-list))) | ||||
|                  :test #'string=))) | ||||
|  | ||||
| (cl-defun slack-buffer-update (room msg team &key replace) | ||||
|   (let* ((buf-name (slack-room-buffer-name room)) | ||||
|          (buffer (get-buffer buf-name))) | ||||
|     (if buffer | ||||
|         (progn | ||||
|           (if (slack-buffer-in-current-frame buffer) | ||||
|               (slack-room-update-mark room team msg) | ||||
|             (slack-room-inc-unread-count room)) | ||||
|           (if replace | ||||
|               (slack-buffer-replace buffer msg) | ||||
|             (with-current-buffer buffer | ||||
|               (slack-room-update-last-read room msg) | ||||
|               (slack-buffer-insert msg team)))) | ||||
|       (slack-room-inc-unread-count room)))) | ||||
|  | ||||
| (defmacro slack-buffer-goto-char (find-point &rest else) | ||||
|   `(let* ((cur-point (point)) | ||||
|           (ts (get-text-property cur-point 'ts))) | ||||
|      (let ((next-point ,find-point)) | ||||
|        (if next-point | ||||
|            (goto-char next-point) | ||||
|          (if (< 0 (length ',else)) | ||||
|              ,@else))))) | ||||
|  | ||||
| (defun slack-buffer-goto-next-message () | ||||
|   (interactive) | ||||
|   (slack-buffer-goto-char | ||||
|    (slack-buffer-next-point cur-point (point-max) ts) | ||||
|    (slack-buffer-goto-first-message))) | ||||
|  | ||||
| (defun slack-buffer-goto-prev-message () | ||||
|   (interactive) | ||||
|   (slack-buffer-goto-char | ||||
|    (slack-buffer-prev-point cur-point (point-min) ts) | ||||
|    (slack-buffer-goto-last-message))) | ||||
|  | ||||
| (defun slack-buffer-goto-first-message () | ||||
|   (interactive) | ||||
|   (goto-char | ||||
|    (slack-buffer-next-point (point-min) (point-max) "0"))) | ||||
|  | ||||
| (defun slack-buffer-goto-last-message () | ||||
|   (interactive) | ||||
|   (goto-char | ||||
|    (slack-buffer-prev-point (point-max) (point-min) (format-time-string "%s")))) | ||||
|  | ||||
| (defun slack-buffer-header-p (point) | ||||
|   (let ((face (get-text-property point 'face))) | ||||
|     (string= (format "%s" face) "slack-message-output-header"))) | ||||
|  | ||||
| (defun slack-buffer-next-point (start end ts) | ||||
|   (cl-loop for i from start to end | ||||
|            if (and (string< ts | ||||
|                             (get-text-property i 'ts)) | ||||
|                    (slack-buffer-header-p i)) | ||||
|            return i)) | ||||
|  | ||||
| (defun slack-buffer-prev-point (start end ts) | ||||
|   (cl-loop for i from start downto end | ||||
|            if (and (string< (get-text-property i 'ts) | ||||
|                             ts) | ||||
|                    (slack-buffer-header-p i)) | ||||
|            return i)) | ||||
|  | ||||
| (defun slack-buffer-ts-eq (start end ts) | ||||
|   (if (and start end) | ||||
|       (cl-loop for i from start to end | ||||
|                if (string= (get-text-property i 'ts) | ||||
|                            ts) | ||||
|                return i))) | ||||
|  | ||||
| (defun slack-buffer-ts-not-eq (start end ts) | ||||
|   (if (and start end) | ||||
|       (cl-loop for i from start to end | ||||
|                if (not (string= (get-text-property i 'ts) | ||||
|                                 ts)) | ||||
|                return i))) | ||||
|  | ||||
| (defun slack-buffer-replace (buffer msg) | ||||
|   (with-current-buffer buffer | ||||
|     (slack-buffer-widen | ||||
|      (let* ((cur-point (point)) | ||||
|             (ts (oref msg ts)) | ||||
|             (beg (slack-buffer-ts-eq (point-min) (point-max) ts)) | ||||
|             (end (slack-buffer-ts-not-eq beg (point-max) ts))) | ||||
|        (if (and beg end) | ||||
|            (let ((inhibit-read-only t) | ||||
|                  (lui-time-stamp-last (get-text-property beg 'slack-last-ts))) | ||||
|              (delete-region beg end) | ||||
|              (set-marker lui-output-marker beg) | ||||
|              (slack-buffer-insert msg | ||||
|                                   (slack-team-find slack-current-team-id)) | ||||
|  | ||||
|              (slack-buffer-recover-lui-output-marker) | ||||
|              (slack-buffer-goto ts))))))) | ||||
|  | ||||
| (defun slack-buffer-recover-lui-output-marker () | ||||
|   (set-marker lui-output-marker (- (marker-position | ||||
|                                     lui-input-marker) | ||||
|  | ||||
|                                    (length lui-prompt-string)))) | ||||
|  | ||||
| (defun slack-get-info-buffer-create (room) | ||||
|   (let* ((buf-name (slack-room-buffer-name room)) | ||||
|          (buffer (get-buffer buf-name))) | ||||
|     (unless buffer | ||||
|       (setq buffer (generate-new-buffer buf-name)) | ||||
|       (with-current-buffer buffer | ||||
|         (slack-info-mode) | ||||
|         (slack-buffer-insert-previous-link room) | ||||
|         (add-hook 'kill-buffer-hook 'slack-reset-room-last-read nil t) | ||||
|         (add-hook 'lui-pre-output-hook 'slack-buffer-add-last-ts-property nil t) | ||||
|         (add-hook 'lui-post-output-hook 'slack-buffer-add-ts-property nil t))) | ||||
|     buffer)) | ||||
|  | ||||
| (defun slack-buffer-create-info (buf-name insert-func) | ||||
|   (let ((buf (slack-get-info-buffer-create buf-name))) | ||||
|     (with-current-buffer buf | ||||
|       (setq buffer-read-only nil) | ||||
|       (erase-buffer) | ||||
|       (goto-char (point-min)) | ||||
|       (funcall insert-func) | ||||
|       (goto-char (point-max)) | ||||
|       (setq buffer-read-only t) | ||||
|       (slack-buffer-enable-emojify)) | ||||
|     buf)) | ||||
|  | ||||
| (defun slack-reset-room-last-read () | ||||
|   (let ((room (slack-room-find slack-current-room-id | ||||
|                                (slack-team-find slack-current-team-id)))) | ||||
|     (slack-room-update-last-read room | ||||
|                                  (slack-message "msg" :ts "0")))) | ||||
|  | ||||
| (provide 'slack-buffer) | ||||
| ;;; slack-buffer.el ends here | ||||
							
								
								
									
										236
									
								
								elpa/slack-20160928.2036/slack-channel.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										236
									
								
								elpa/slack-20160928.2036/slack-channel.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,236 @@ | ||||
| ;;; slack-channel.el ---slack channel implement      -*- lexical-binding: t; -*- | ||||
|  | ||||
| ;; Copyright (C) 2015  yuya.minami | ||||
|  | ||||
| ;; Author: yuya.minami <yuya.minami@yuyaminami-no-MacBook-Pro.local> | ||||
| ;; Keywords: | ||||
|  | ||||
| ;; This program is free software; you can redistribute it and/or modify | ||||
| ;; it under the terms of the GNU General Public License as published by | ||||
| ;; the Free Software Foundation, either version 3 of the License, or | ||||
| ;; (at your option) any later version. | ||||
|  | ||||
| ;; This program is distributed in the hope that it will be useful, | ||||
| ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| ;; GNU General Public License for more details. | ||||
|  | ||||
| ;; You should have received a copy of the GNU General Public License | ||||
| ;; along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  | ||||
| ;;; Commentary: | ||||
|  | ||||
| ;; | ||||
|  | ||||
| ;;; Code: | ||||
|  | ||||
| (require 'eieio) | ||||
| (require 'slack-group) | ||||
| (require 'slack-buffer) | ||||
| (require 'slack-util) | ||||
|  | ||||
| (defvar slack-buffer-function) | ||||
|  | ||||
| (defconst slack-channel-history-url "https://slack.com/api/channels.history") | ||||
| (defconst slack-channel-list-url "https://slack.com/api/channels.list") | ||||
| (defconst slack-channel-buffer-name "*Slack - Channel*") | ||||
| (defconst slack-channel-update-mark-url "https://slack.com/api/channels.mark") | ||||
| (defconst slack-create-channel-url "https://slack.com/api/channels.create") | ||||
| (defconst slack-channel-rename-url "https://slack.com/api/channels.rename") | ||||
| (defconst slack-channel-invite-url "https://slack.com/api/channels.invite") | ||||
| (defconst slack-channel-leave-url "https://slack.com/api/channels.leave") | ||||
| (defconst slack-channel-join-url "https://slack.com/api/channels.join") | ||||
| (defconst slack-channel-info-url "https://slack.com/api/channels.info") | ||||
| (defconst slack-channel-archive-url "https://slack.com/api/channels.archive") | ||||
| (defconst slack-channel-unarchive-url "https://slack.com/api/channels.unarchive") | ||||
|  | ||||
| (defclass slack-channel (slack-group) | ||||
|   ((is-member :initarg :is_member) | ||||
|    (num-members :initarg :num_members))) | ||||
|  | ||||
| (defmethod slack-room-buffer-name ((room slack-channel)) | ||||
|   (concat slack-channel-buffer-name | ||||
|           " : " | ||||
|           (slack-room-name-with-team-name room))) | ||||
|  | ||||
| (defun slack-channel-names (team &optional filter) | ||||
|   (with-slots (channels) team | ||||
|     (slack-room-names channels filter))) | ||||
|  | ||||
| (defmethod slack-room-member-p ((room slack-channel)) | ||||
|   (oref room is-member)) | ||||
|  | ||||
| (defun slack-channel-select () | ||||
|   (interactive) | ||||
|   (let ((team (slack-team-select))) | ||||
|     (slack-room-select | ||||
|      (cl-loop for team in (list team) | ||||
|               for channels = (oref team channels) | ||||
|               nconc channels)))) | ||||
|  | ||||
| (defun slack-channel-list-update () | ||||
|   (interactive) | ||||
|   (let ((team (slack-team-select))) | ||||
|     (cl-labels ((on-list-update | ||||
|                  (&key data &allow-other-keys) | ||||
|                  (slack-request-handle-error | ||||
|                   (data "slack-channel-list-update") | ||||
|                   (oset team channels | ||||
|                         (mapcar #'(lambda (d) | ||||
|                                     (slack-room-create d team 'slack-channel)) | ||||
|                                 (plist-get data :channels))) | ||||
|                   (message "Slack Channel List Updated")))) | ||||
|       (slack-room-list-update slack-channel-list-url | ||||
|                               #'on-list-update | ||||
|                               team | ||||
|                               :sync nil)))) | ||||
|  | ||||
| (defmethod slack-room-update-mark-url ((_room slack-channel)) | ||||
|   slack-channel-update-mark-url) | ||||
|  | ||||
| (defun slack-create-channel () | ||||
|   (interactive) | ||||
|   (let ((team (slack-team-select))) | ||||
|     (cl-labels | ||||
|         ((on-create-channel (&key data &allow-other-keys) | ||||
|                             (slack-request-handle-error | ||||
|                              (data "slack-channel-create")))) | ||||
|       (slack-create-room slack-create-channel-url | ||||
|                          team | ||||
|                          #'on-create-channel)))) | ||||
|  | ||||
| (defun slack-channel-rename () | ||||
|   (interactive) | ||||
|   (slack-room-rename slack-channel-rename-url | ||||
|                      #'slack-channel-names)) | ||||
|  | ||||
| (defun slack-channel-invite () | ||||
|   (interactive) | ||||
|   (slack-room-invite slack-channel-invite-url | ||||
|                      #'slack-channel-names)) | ||||
|  | ||||
| (defun slack-channel-leave () | ||||
|   (interactive) | ||||
|   (let* ((team (slack-team-select)) | ||||
|          (channel (slack-current-room-or-select | ||||
|                    #'(lambda () | ||||
|                        (slack-channel-names | ||||
|                         team | ||||
|                         #'(lambda (channels) | ||||
|                             (cl-remove-if-not #'slack-room-member-p | ||||
|                                               channels))))))) | ||||
|     (cl-labels | ||||
|         ((on-channel-leave (&key data &allow-other-keys) | ||||
|                            (slack-request-handle-error | ||||
|                             (data "slack-channel-leave") | ||||
|                             (oset channel is-member nil) | ||||
|                             (message "Left Channel: %s" | ||||
|                                      (slack-room-name channel))))) | ||||
|       (slack-room-request-with-id slack-channel-leave-url | ||||
|                                   (oref channel id) | ||||
|                                   team | ||||
|                                   #'on-channel-leave)))) | ||||
|  | ||||
| (defun slack-channel-join () | ||||
|   (interactive) | ||||
|   (cl-labels | ||||
|       ((filter-channel (channels) | ||||
|                        (cl-remove-if | ||||
|                         #'(lambda (c) | ||||
|                             (or (slack-room-member-p c) | ||||
|                                 (slack-room-archived-p c))) | ||||
|                         channels))) | ||||
|     (let* ((team (slack-team-select)) | ||||
|            (channel (slack-current-room-or-select | ||||
|                      #'(lambda () | ||||
|                          (slack-channel-names team | ||||
|                           #'filter-channel))))) | ||||
|       (cl-labels | ||||
|           ((on-channel-join (&key data &allow-other-keys) | ||||
|                             (slack-request-handle-error | ||||
|                              (data "slack-channel-join")))) | ||||
|         (slack-request | ||||
|          slack-channel-join-url | ||||
|          team | ||||
|          :params (list (cons "name" (slack-room-name channel))) | ||||
|          :sync nil | ||||
|          :success #'on-channel-join)))) | ||||
|   ) | ||||
|  | ||||
| (defun slack-channel-create-from-info (id team) | ||||
|   (cl-labels | ||||
|       ((on-create-from-info | ||||
|         (&key data &allow-other-keys) | ||||
|         (slack-request-handle-error | ||||
|          (data "slack-channel-create-from-info") | ||||
|          (let* ((c-data (plist-get data :channel)) | ||||
|                 (latest (plist-get c-data :latest))) | ||||
|            (if latest | ||||
|                (plist-put c-data :latest | ||||
|                           (slack-message-create latest))) | ||||
|            (if (plist-get c-data :is_channel) | ||||
|                (let ((channel | ||||
|                       (slack-room-create c-data team 'slack-channel))) | ||||
|                  (with-slots (channels) team | ||||
|                    (push channel channels)) | ||||
|                  (message "Channel: %s created" | ||||
|                           (slack-room-name-with-team-name channel)))))))) | ||||
|     (slack-channel-fetch-info id team #'on-create-from-info))) | ||||
|  | ||||
| (defun slack-channel-fetch-info (id team success) | ||||
|   (slack-request | ||||
|    slack-channel-info-url | ||||
|    team | ||||
|    :sync nil | ||||
|    :params (list (cons "channel" id)) | ||||
|    :success success)) | ||||
|  | ||||
| (defun slack-channel-archive () | ||||
|   (interactive) | ||||
|   (let* ((team (slack-team-select)) | ||||
|          (channel (slack-current-room-or-select | ||||
|                    #'(lambda () | ||||
|                        (slack-channel-names | ||||
|                         team | ||||
|                         #'(lambda (channels) | ||||
|                             (cl-remove-if #'slack-room-archived-p | ||||
|                                           channels))))))) | ||||
|     (cl-labels | ||||
|         ((on-channel-archive (&key data &allow-other-keys) | ||||
|                              (slack-request-handle-error | ||||
|                               (data "slack-channel-archive")))) | ||||
|       (slack-room-request-with-id slack-channel-archive-url | ||||
|                                   (oref channel id) | ||||
|                                   team | ||||
|                                   #'on-channel-archive)))) | ||||
|  | ||||
| (defun slack-channel-unarchive () | ||||
|   (interactive) | ||||
|   (let* ((team (slack-team-select)) | ||||
|          (channel (slack-current-room-or-select | ||||
|                    #'(lambda () | ||||
|                        (slack-channel-names | ||||
|                         team | ||||
|                         #'(lambda (channels) | ||||
|                             (cl-remove-if-not #'slack-room-archived-p | ||||
|                                               channels))))))) | ||||
|     (cl-labels | ||||
|         ((on-channel-unarchive (&key data &allow-other-keys) | ||||
|                                (slack-request-handle-error | ||||
|                                 (data "slack-channel-unarchive")))) | ||||
|       (slack-room-request-with-id slack-channel-unarchive-url | ||||
|                                   (oref channel id) | ||||
|                                   team | ||||
|                                   #'on-channel-unarchive)))) | ||||
|  | ||||
| (defmethod slack-room-history-url ((_room slack-channel)) | ||||
|   slack-channel-history-url) | ||||
|  | ||||
| (defmethod slack-room-subscribedp ((room slack-channel) team) | ||||
|   (with-slots (subscribed-channels) team | ||||
|     (let ((name (slack-room-name room))) | ||||
|       (and name | ||||
|            (memq (intern name) subscribed-channels))))) | ||||
|  | ||||
| (provide 'slack-channel) | ||||
| ;;; slack-channel.el ends here | ||||
							
								
								
									
										244
									
								
								elpa/slack-20160928.2036/slack-file.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										244
									
								
								elpa/slack-20160928.2036/slack-file.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,244 @@ | ||||
| ;;; slack-file.el ---  handle files                  -*- lexical-binding: t; -*- | ||||
|  | ||||
| ;; Copyright (C) 2016  南優也 | ||||
|  | ||||
| ;; Author: 南優也 <yuyaminami@minamiyuunari-no-MacBook-Pro.local> | ||||
| ;; Keywords: | ||||
|  | ||||
| ;; This program is free software; you can redistribute it and/or modify | ||||
| ;; it under the terms of the GNU General Public License as published by | ||||
| ;; the Free Software Foundation, either version 3 of the License, or | ||||
| ;; (at your option) any later version. | ||||
|  | ||||
| ;; This program is distributed in the hope that it will be useful, | ||||
| ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| ;; GNU General Public License for more details. | ||||
|  | ||||
| ;; You should have received a copy of the GNU General Public License | ||||
| ;; along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  | ||||
| ;;; Commentary: | ||||
|  | ||||
| ;; | ||||
|  | ||||
| ;;; Code: | ||||
|  | ||||
| (require 'eieio) | ||||
| (require 'slack-room) | ||||
|  | ||||
| (defconst slack-file-list-url "https://slack.com/api/files.list") | ||||
| (defconst slack-file-upload-url "https://slack.com/api/files.upload") | ||||
| (defconst slack-file-delete-url "https://slack.com/api/files.delete") | ||||
|  | ||||
| (defclass slack-file (slack-message) | ||||
|   ((id :initarg :id) | ||||
|    (created :initarg :created) | ||||
|    (name :initarg :name) | ||||
|    (size :initarg :size) | ||||
|    (public :initarg :public) | ||||
|    (filetype :initarg :filetype) | ||||
|    (user :initarg :user) | ||||
|    (preview :initarg :preview) | ||||
|    (initial-comment :initarg :initial_comment :initform nil) | ||||
|    (permalink :initarg :permalink) | ||||
|    (channels :initarg :channels :type list) | ||||
|    (groups :initarg :groups :type list) | ||||
|    (ims :initarg :ims :type list) | ||||
|    (username :initarg :username))) | ||||
|  | ||||
| (defclass slack-file-room (slack-room) ()) | ||||
|  | ||||
| (defun slack-file-room-obj (team) | ||||
|   (with-slots (file-room) team | ||||
|     (if file-room | ||||
|         file-room | ||||
|       (setq file-room (slack-file-room "file-room" | ||||
|                                        :name "Files" | ||||
|                                        :id "F" | ||||
|                                        :team-id (oref team id) | ||||
|                                        :created (format-time-string "%s") | ||||
|                                        :last_read "0" | ||||
|                                        :latest nil | ||||
|                                        :unread_count 0 | ||||
|                                        :unread_count_display 0 | ||||
|                                        :messages '()))))) | ||||
|  | ||||
| (defun slack-file-create (payload) | ||||
|   (plist-put payload :channels (append (plist-get payload :channels) nil)) | ||||
|   (plist-put payload :groups (append (plist-get payload :groups) nil)) | ||||
|   (plist-put payload :ims (append (plist-get payload :ims) nil)) | ||||
|   (plist-put payload :reactions (append (plist-get payload :reactions) nil)) | ||||
|   (plist-put payload :pinned_to (append (plist-get payload :pinned_to) nil)) | ||||
|   (plist-put payload :ts (number-to-string (plist-get payload :timestamp))) | ||||
|   (let ((file (apply #'slack-file "file" | ||||
|                      (slack-collect-slots 'slack-file payload)))) | ||||
|     (oset file reactions | ||||
|           (mapcar #'slack-reaction-create (plist-get payload :reactions))) | ||||
|     file)) | ||||
|  | ||||
| (defmethod slack-message-equal ((f slack-file) other) | ||||
|   (string= (oref f id) (oref other id))) | ||||
|  | ||||
| (defmethod slack-file-pushnew ((f slack-file) team) | ||||
|   (let ((room (slack-file-room-obj team))) | ||||
|     (with-slots (messages) room | ||||
|       (cl-pushnew f messages | ||||
|                   :test #'slack-message-equal)))) | ||||
|  | ||||
| (defmethod slack-message-body ((file slack-file) team) | ||||
|   (with-slots (initial-comment) file | ||||
|     (let ((body (plist-get initial-comment :comment))) | ||||
|       (slack-message-unescape-string body team)))) | ||||
|  | ||||
| (defmethod slack-message-to-string ((file slack-file) team) | ||||
|   (with-slots (ts name size filetype permalink user initial-comment reactions) | ||||
|       file | ||||
|     (let* ((header (slack-user-name user team)) | ||||
|            (body (format "name: %s\nsize: %s\ntype: %s\n%s\n" | ||||
|                          name size filetype permalink)) | ||||
|            (reactions-str (slack-message-reactions-to-string | ||||
|                            reactions))) | ||||
|       (slack-message-put-header-property header) | ||||
|       (slack-message-put-text-property body) | ||||
|       (slack-message-put-reactions-property reactions-str) | ||||
|       (let ((message | ||||
|              (concat header "\n" body | ||||
|                      (if initial-comment | ||||
|                          (format "comment: %s\n%s\n" | ||||
|                                  (slack-user-name | ||||
|                                   (plist-get initial-comment :user) | ||||
|                                   team) | ||||
|                                  (slack-message-body file team))) | ||||
|                      (if reactions-str | ||||
|                          (concat "\n" reactions-str "\n"))))) | ||||
|         (put-text-property 0 (length message) 'ts ts message) | ||||
|         message)))) | ||||
|  | ||||
| (defmethod slack-room-update-mark ((_room slack-file-room) _team _msg)) | ||||
|  | ||||
| (defun slack-file-create-buffer (team) | ||||
|   (funcall slack-buffer-function | ||||
|            (slack-buffer-create (slack-file-room-obj team) | ||||
|                                 team | ||||
|                                 :type 'info))) | ||||
|  | ||||
| (defun slack-file-list () | ||||
|   (interactive) | ||||
|   (let* ((team (slack-team-select)) | ||||
|          (room (slack-file-room-obj team))) | ||||
|     (with-slots (messages) room | ||||
|       (if messages | ||||
|           (slack-file-create-buffer team) | ||||
|         (slack-room-history room team nil | ||||
|                             #'(lambda () | ||||
|                                 (slack-file-create-buffer team))))))) | ||||
|  | ||||
| (defmethod slack-room-history ((room slack-file-room) team | ||||
|                                &optional | ||||
|                                oldest | ||||
|                                after-success | ||||
|                                async) | ||||
|   (cl-labels | ||||
|       ((on-file-list | ||||
|         (&key data &allow-other-keys) | ||||
|         (slack-request-handle-error | ||||
|          (data "slack-file-list") | ||||
|          (let ((files (cl-loop for e across (plist-get data :files) | ||||
|                                collect (slack-file-create e)))) | ||||
|            (if oldest | ||||
|                (slack-room-set-prev-messages room files) | ||||
|              (slack-room-update-last-read room | ||||
|                                           (make-instance 'slack-message | ||||
|                                                          :ts "0")) | ||||
|              (slack-room-set-messages room files))) | ||||
|          (if after-success | ||||
|              (funcall after-success))))) | ||||
|     (slack-request | ||||
|      slack-file-list-url | ||||
|      team | ||||
|      :params (list (if oldest | ||||
|                        (cons "ts_to" oldest))) | ||||
|      :success #'on-file-list | ||||
|      :sync (if async nil t)))) | ||||
|  | ||||
| (defun slack-file-upload () | ||||
|   (interactive) | ||||
|   (cl-labels | ||||
|       ((on-file-upload (&key data &allow-other-keys) | ||||
|                        (slack-request-handle-error | ||||
|                         (data "slack-file-upload"))) | ||||
|        (select-channels (channels acc) | ||||
|                         (let ((selected (completing-read "Select Channel: " | ||||
|                                                          channels nil t))) | ||||
|                           (if (< 0 (length selected)) | ||||
|                               (select-channels channels (push selected acc)) | ||||
|                             acc))) | ||||
|        (channel-id (selected channels) | ||||
|                    (oref (cdr (cl-assoc selected channels :test #'string=)) | ||||
|                          id))) | ||||
|     (let* ((team (slack-team-select)) | ||||
|            (channels (slack-room-names | ||||
|                       (append (oref team ims) | ||||
|                               (oref team channels) | ||||
|                               (oref team groups)))) | ||||
|            (target-channels (select-channels channels '())) | ||||
|            (channel-ids (mapconcat #'(lambda (selected) | ||||
|                                        (channel-id selected channels)) | ||||
|                                    (cl-delete-if #'null target-channels) | ||||
|                                    ",")) | ||||
|            (buf (find-file-noselect | ||||
|                  (car (find-file-read-args | ||||
|                        "Select File: " | ||||
|                        (confirm-nonexistent-file-or-buffer))))) | ||||
|            (filename (read-from-minibuffer "Filename: " | ||||
|                                            (file-name-nondirectory | ||||
|                                             (buffer-file-name buf)))) | ||||
|            (filetype (read-from-minibuffer "Filetype: " | ||||
|                                            (file-name-extension | ||||
|                                             (buffer-file-name buf)))) | ||||
|            (initial-comment (read-from-minibuffer "Message: "))) | ||||
|       (slack-request | ||||
|        slack-file-upload-url | ||||
|        team | ||||
|        :type "POST" | ||||
|        :params (list (cons "filename" filename) | ||||
|                      (cons "channels" channel-ids) | ||||
|                      (cons "filetype" filetype) | ||||
|                      (if initial-comment | ||||
|                          (cons "initial_comment" initial-comment))) | ||||
|        :files (list (cons "file" buf)) | ||||
|        :headers (list (cons "Content-Type" "multipart/form-data")) | ||||
|        :success #'on-file-upload | ||||
|        :sync nil)))) | ||||
|  | ||||
| (defun slack-file-delete () | ||||
|   (interactive) | ||||
|   (cl-labels | ||||
|       ((on-file-delete (&key data &allow-other-keys) | ||||
|                        (slack-request-handle-error | ||||
|                         (data "slack-file-delete")))) | ||||
|     (let* ((team (slack-team-select)) | ||||
|            (files (oref (slack-file-room-obj team) messages)) | ||||
|            (your-files (cl-remove-if #'(lambda (f) | ||||
|                                          (not (string= (oref f user) | ||||
|                                                        (oref team self-id)))) | ||||
|                                      files)) | ||||
|            (candidates (mapcar #'(lambda (f) | ||||
|                                    (cons (concat | ||||
|                                           (slack-message-time-to-string (oref f ts)) | ||||
|                                           " " | ||||
|                                           (oref f name)) | ||||
|                                          f)) | ||||
|                                your-files)) | ||||
|            (selected (completing-read "Select File: " candidates)) | ||||
|            (deleting-file (cdr (cl-assoc selected candidates :test #'string=)))) | ||||
|       (slack-request | ||||
|        slack-file-delete-url | ||||
|        team | ||||
|        :params (list (cons "file" (oref deleting-file id))) | ||||
|        :sync nil | ||||
|        :success #'on-file-delete)))) | ||||
|  | ||||
| (provide 'slack-file) | ||||
| ;;; slack-file.el ends here | ||||
							
								
								
									
										192
									
								
								elpa/slack-20160928.2036/slack-group.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										192
									
								
								elpa/slack-20160928.2036/slack-group.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,192 @@ | ||||
| ;;; slack-group.el --- slack private group interface  -*- lexical-binding: t; -*- | ||||
|  | ||||
| ;; Copyright (C) 2015  Yuya Minami | ||||
|  | ||||
| ;; Author: Yuya Minami | ||||
| ;; Keywords: | ||||
|  | ||||
| ;; This program is free software; you can redistribute it and/or modify | ||||
| ;; it under the terms of the GNU General Public License as published by | ||||
| ;; the Free Software Foundation, either version 3 of the License, or | ||||
| ;; (at your option) any later version. | ||||
|  | ||||
| ;; This program is distributed in the hope that it will be useful, | ||||
| ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| ;; GNU General Public License for more details. | ||||
|  | ||||
| ;; You should have received a copy of the GNU General Public License | ||||
| ;; along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  | ||||
| ;;; Commentary: | ||||
|  | ||||
| ;; | ||||
|  | ||||
| ;;; Code: | ||||
|  | ||||
| (require 'eieio) | ||||
| (require 'slack-room) | ||||
| (require 'slack-util) | ||||
| (require 'slack-buffer) | ||||
|  | ||||
| (defconst slack--group-open-url "https://slack.com/api/groups.open") | ||||
| (defconst slack-group-history-url "https://slack.com/api/groups.history") | ||||
| (defconst slack-group-buffer-name "*Slack - Private Group*") | ||||
| (defconst slack-group-list-url "https://slack.com/api/groups.list") | ||||
| (defconst slack-group-update-mark-url "https://slack.com/api/groups.mark") | ||||
| (defconst slack-create-group-url "https://slack.com/api/groups.create") | ||||
| (defconst slack-group-rename-url "https://slack.com/api/groups.rename") | ||||
| (defconst slack-group-invite-url "https://slack.com/api/groups.invite") | ||||
| (defconst slack-group-leave-url "https://slack.com/api/groups.leave") | ||||
| (defconst slack-group-archive-url "https://slack.com/api/groups.archive") | ||||
| (defconst slack-group-unarchive-url "https://slack.com/api/groups.unarchive") | ||||
|  | ||||
| (defvar slack-buffer-function) | ||||
|  | ||||
| (defclass slack-group (slack-room) | ||||
|   ((name :initarg :name :type string) | ||||
|    (is-group :initarg :is_group) | ||||
|    (creator :initarg :creator) | ||||
|    (is-archived :initarg :is_archived) | ||||
|    (is-mpim :initarg :is_mpim) | ||||
|    (members :initarg :members :type list) | ||||
|    (topic :initarg :topic) | ||||
|    (unread-count-display :initarg :unread_count_display :initform 0 :type integer) | ||||
|    (purpose :initarg :purpose))) | ||||
|  | ||||
| (defun slack-group-names (team &optional filter) | ||||
|   (with-slots (groups) team | ||||
|     (slack-room-names groups filter))) | ||||
|  | ||||
| (defmethod slack-room-subscribedp ((room slack-group) team) | ||||
|   (with-slots (subscribed-channels) team | ||||
|     (let ((name (slack-room-name room))) | ||||
|       (and name | ||||
|            (memq (intern name) subscribed-channels))))) | ||||
|  | ||||
| (defmethod slack-room-buffer-name ((room slack-group)) | ||||
|   (concat slack-group-buffer-name | ||||
|           " : " | ||||
|           (slack-room-name-with-team-name room))) | ||||
|  | ||||
| (defun slack-group-select () | ||||
|   (interactive) | ||||
|   (let ((team (slack-team-select))) | ||||
|     (slack-room-select | ||||
|      (cl-loop for team in (list team) | ||||
|               for groups = (oref team groups) | ||||
|               nconc groups)))) | ||||
|  | ||||
| (defun slack-group-list-update () | ||||
|   (interactive) | ||||
|   (let ((team (slack-team-select))) | ||||
|     (cl-labels ((on-list-update | ||||
|                  (&key data &allow-other-keys) | ||||
|                  (slack-request-handle-error | ||||
|                   (data "slack-group-list-update") | ||||
|                   (with-slots (groups) team | ||||
|                     (setq groups | ||||
|                           (mapcar #'(lambda (g) | ||||
|                                       (slack-room-create g team 'slack-group)) | ||||
|                                   (plist-get data :groups)))) | ||||
|                   (message "Slack Group List Updated")))) | ||||
|       (slack-room-list-update slack-group-list-url | ||||
|                               #'on-list-update | ||||
|                               :sync nil)))) | ||||
|  | ||||
|  | ||||
| (defmethod slack-room-update-mark-url ((_room slack-group)) | ||||
|   slack-group-update-mark-url) | ||||
|  | ||||
| (defun slack-create-group () | ||||
|   (interactive) | ||||
|   (let ((team (slack-team-select))) | ||||
|     (cl-labels | ||||
|         ((on-create-group (&key data &allow-other-keys) | ||||
|                           (slack-request-handle-error | ||||
|                            (data "slack-create-group")))) | ||||
|       (slack-create-room slack-create-group-url | ||||
|                          team | ||||
|                          #'on-create-group)))) | ||||
|  | ||||
| (defun slack-group-rename () | ||||
|   (interactive) | ||||
|   (slack-room-rename slack-group-rename-url | ||||
|                      #'slack-group-names)) | ||||
|  | ||||
| (defun slack-group-invite () | ||||
|   (interactive) | ||||
|   (slack-room-invite slack-group-invite-url | ||||
|                      #'slack-group-names)) | ||||
|  | ||||
| (defun slack-group-leave () | ||||
|   (interactive) | ||||
|   (let* ((team (slack-team-select)) | ||||
|          (group (slack-current-room-or-select | ||||
|                  #'(lambda () | ||||
|                      (slack-group-names team))))) | ||||
|     (cl-labels | ||||
|         ((on-group-leave | ||||
|           (&key data &allow-other-keys) | ||||
|           (slack-request-handle-error | ||||
|            (data "slack-group-leave") | ||||
|            (with-slots (groups) team | ||||
|              (setq groups | ||||
|                    (cl-delete-if #'(lambda (g) | ||||
|                                      (slack-room-equal-p group g)) | ||||
|                                  groups))) | ||||
|            (message "Left Group: %s" | ||||
|                     (slack-room-name-with-team-name group))))) | ||||
|       (slack-room-request-with-id slack-group-leave-url | ||||
|                                   (oref group id) | ||||
|                                   team | ||||
|                                   #'on-group-leave)))) | ||||
|  | ||||
| (defmethod slack-room-archived-p ((room slack-group)) | ||||
|   (oref room is-archived)) | ||||
|  | ||||
| (defun slack-group-archive () | ||||
|   (interactive) | ||||
|   (let* ((team (slack-team-select)) | ||||
|          (group (slack-current-room-or-select | ||||
|                  #'(lambda () | ||||
|                      (slack-group-names | ||||
|                       team | ||||
|                       #'(lambda (groups) | ||||
|                           (cl-remove-if #'slack-room-archived-p | ||||
|                                         groups))))))) | ||||
|     (cl-labels | ||||
|         ((on-group-archive (&key data &allow-other-keys) | ||||
|                            (slack-request-handle-error | ||||
|                             (data "slack-group-archive")))) | ||||
|       (slack-room-request-with-id slack-group-archive-url | ||||
|                                   (oref group id) | ||||
|                                   team | ||||
|                                   #'on-group-archive)))) | ||||
|  | ||||
| (defun slack-group-unarchive () | ||||
|   (interactive) | ||||
|   (let* ((team (slack-team-select)) | ||||
|          (group (slack-current-room-or-select | ||||
|                  #'(lambda () | ||||
|                      (slack-group-names | ||||
|                       team | ||||
|                       #'(lambda (groups) | ||||
|                           (cl-remove-if-not #'slack-room-archived-p | ||||
|                                             groups))))))) | ||||
|     (cl-labels | ||||
|         ((on-group-unarchive (&key _data &allow-other-keys) | ||||
|                              (data "slack-group-unarchive"))) | ||||
|       (slack-room-request-with-id slack-group-unarchive-url | ||||
|                                   (oref group id) | ||||
|                                   team | ||||
|                                   #'on-group-unarchive)))) | ||||
|  | ||||
| (defmethod slack-mpim-p ((room slack-group)) | ||||
|   (oref room is-mpim)) | ||||
|  | ||||
| (defmethod slack-room-history-url ((_room slack-group)) | ||||
|   slack-group-history-url) | ||||
|  | ||||
| (provide 'slack-group) | ||||
| ;;; slack-group.el ends here | ||||
							
								
								
									
										184
									
								
								elpa/slack-20160928.2036/slack-im.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										184
									
								
								elpa/slack-20160928.2036/slack-im.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,184 @@ | ||||
| ;;; slack-im.el ---slack direct message interface    -*- lexical-binding: t; -*- | ||||
|  | ||||
| ;; Copyright (C) 2015  南優也 | ||||
|  | ||||
| ;; Author: 南優也 <yuyaminami@minamiyuunari-no-MacBook-Pro.local> | ||||
| ;; Keywords: | ||||
|  | ||||
| ;; This program is free software; you can redistribute it and/or modify | ||||
| ;; it under the terms of the GNU General Public License as published by | ||||
| ;; the Free Software Foundation, either version 3 of the License, or | ||||
| ;; (at your option) any later version. | ||||
|  | ||||
| ;; This program is distributed in the hope that it will be useful, | ||||
| ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| ;; GNU General Public License for more details. | ||||
|  | ||||
| ;; You should have received a copy of the GNU General Public License | ||||
| ;; along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  | ||||
| ;;; Commentary: | ||||
|  | ||||
| ;; | ||||
|  | ||||
| ;;; Code: | ||||
|  | ||||
| (require 'eieio) | ||||
| (require 'slack-util) | ||||
| (require 'slack-room) | ||||
| (require 'slack-buffer) | ||||
| (require 'slack-user) | ||||
|  | ||||
| (defvar slack-buffer-function) | ||||
|  | ||||
| (defconst slack-im-history-url "https://slack.com/api/im.history") | ||||
| (defconst slack-im-buffer-name "*Slack - Direct Messages*") | ||||
| (defconst slack-user-list-url "https://slack.com/api/users.list") | ||||
| (defconst slack-im-list-url "https://slack.com/api/im.list") | ||||
| (defconst slack-im-close-url "https://slack.com/api/im.close") | ||||
| (defconst slack-im-open-url "https://slack.com/api/im.open") | ||||
| (defconst slack-im-update-mark-url "https://slack.com/api/im.mark") | ||||
|  | ||||
| (defclass slack-im (slack-room) | ||||
|   ((user :initarg :user) | ||||
|    (is-open :initarg :is_open :initform nil))) | ||||
|  | ||||
| (defmethod slack-room-open-p ((room slack-im)) | ||||
|   (oref room is-open)) | ||||
|  | ||||
| (defmethod slack-room-name-with-team-name ((room slack-im)) | ||||
|   (with-slots (team-id user) room | ||||
|     (let* ((team (slack-team-find team-id)) | ||||
|            (user-name (slack-user-name user team))) | ||||
|       (format "%s - %s" (oref team name) user-name)))) | ||||
|  | ||||
| (defmethod slack-im-user-presence ((room slack-im)) | ||||
|   (with-slots ((user-id user) team-id) room | ||||
|     (let* ((team (slack-team-find team-id)) | ||||
|            (user (slack-user-find user-id team))) | ||||
|       (slack-user-presence-to-string user)))) | ||||
|  | ||||
| (defmethod slack-room-name ((room slack-im)) | ||||
|   (with-slots (user team-id) room | ||||
|     (slack-user-name user (slack-team-find team-id)))) | ||||
|  | ||||
| (defun slack-im-user-name (im team) | ||||
|   (with-slots (user) im | ||||
|     (slack-user-name user team))) | ||||
|  | ||||
| (defun slack-im-names (team) | ||||
|   (with-slots (ims) team | ||||
|     (mapcar #'(lambda (im) (cons (slack-im-user-name im team) im)) | ||||
|             ims))) | ||||
|  | ||||
| (defmethod slack-room-buffer-name ((room slack-im)) | ||||
|   (concat slack-im-buffer-name | ||||
|           " : " | ||||
|           (slack-room-name-with-team-name room))) | ||||
|  | ||||
| (defun slack-im-select () | ||||
|   (interactive) | ||||
|   (let ((team (slack-team-select))) | ||||
|     (slack-room-select | ||||
|      (cl-loop for team in (list team) | ||||
|               for ims = (cl-remove-if #'(lambda (im) (not (oref im is-open))) | ||||
|                                       (oref team ims)) | ||||
|               nconc ims)))) | ||||
|  | ||||
| (defun slack-user-equal-p (a b) | ||||
|   (string= (plist-get a :id) (plist-get b :id))) | ||||
|  | ||||
| (defun slack-user-pushnew (user team) | ||||
|   (with-slots (users) team | ||||
|     (cl-pushnew user users :test #'slack-user-equal-p))) | ||||
|  | ||||
| (defun slack-im-update-room-list (users team) | ||||
|   (cl-labels ((on-update-room-list | ||||
|                (&key data &allow-other-keys) | ||||
|                (slack-request-handle-error | ||||
|                 (data "slack-im-update-room-list") | ||||
|                 (mapc #'(lambda (u) (slack-user-pushnew u team)) | ||||
|                       (append users nil)) | ||||
|                 (oset team ims | ||||
|                       (mapcar #'(lambda (d) | ||||
|                                   (slack-room-create d team 'slack-im)) | ||||
|                               (plist-get data :ims))) | ||||
|                 (message "Slack Im List Updated")))) | ||||
|     (slack-room-list-update slack-im-list-url | ||||
|                             #'on-update-room-list | ||||
|                             team | ||||
|                             :sync nil))) | ||||
|  | ||||
| (defun slack-im-list-update () | ||||
|   (interactive) | ||||
|   (let ((team (slack-team-select))) | ||||
|     (slack-request | ||||
|      slack-user-list-url | ||||
|      team | ||||
|      :success (cl-function (lambda (&key data &allow-other-keys) | ||||
|                              (slack-request-handle-error (data "slack-im-list-update") | ||||
|                                                          (let ((users (plist-get data :members))) | ||||
|                                                            (slack-im-update-room-list users team))))) | ||||
|      :sync nil))) | ||||
|  | ||||
| (defmethod slack-room-update-mark-url ((_room slack-im)) | ||||
|   slack-im-update-mark-url) | ||||
|  | ||||
| (defmethod slack-room-history-url ((_room slack-im)) | ||||
|   slack-im-history-url) | ||||
|  | ||||
| (defun slack-im-close () | ||||
|   (interactive) | ||||
|   (let* ((team (slack-team-select)) | ||||
|          (alist (cl-remove-if #'(lambda (im-names) | ||||
|                                   (not (oref (cdr im-names) is-open))) | ||||
|                               (slack-im-names team)))) | ||||
|     (slack-select-from-list | ||||
|      (alist "Select User: ") | ||||
|      (cl-labels | ||||
|          ((on-success | ||||
|            (&key data &allow-other-keys) | ||||
|            (slack-request-handle-error | ||||
|             (data "slack-im-close") | ||||
|             (if (plist-get data :already_closed) | ||||
|                 (let ((im (slack-room-find (oref selected id) team))) | ||||
|                   (oset im is-open nil) | ||||
|                   (message "Direct Message Channel with %s Already Closed" | ||||
|                            (slack-user-name (oref im user) team))))))) | ||||
|        (slack-request | ||||
|         slack-im-close-url | ||||
|         team | ||||
|         :type "POST" | ||||
|         :params (list (cons "channel" (oref selected id))) | ||||
|         :success #'on-success | ||||
|         :sync nil))))) | ||||
|  | ||||
| (defun slack-im-open () | ||||
|   (interactive) | ||||
|   (let* ((team (slack-team-select)) | ||||
|          (alist (cl-remove-if #'(lambda (im-names) | ||||
|                                   (oref (cdr im-names) is-open)) | ||||
|                               (slack-im-names team)))) | ||||
|     (slack-select-from-list | ||||
|      (alist "Select User: ") | ||||
|      (cl-labels | ||||
|          ((on-success | ||||
|            (&key data &allow-other-keys) | ||||
|            (slack-request-handle-error | ||||
|             (data "slack-im-open") | ||||
|             (if (plist-get data :already_open) | ||||
|                 (let ((im (slack-room-find (oref selected id) team))) | ||||
|                   (oset im is-open t) | ||||
|                   (message "Direct Message Channel with %s Already Open" | ||||
|                            (slack-user-name (oref im user) team))))))) | ||||
|        (slack-request | ||||
|         slack-im-open-url | ||||
|         team | ||||
|         :type "POST" | ||||
|         :params (list (cons "user" (oref selected user))) | ||||
|         :success #'on-success | ||||
|         :sync nil))))) | ||||
|  | ||||
| (provide 'slack-im) | ||||
| ;;; slack-im.el ends here | ||||
							
								
								
									
										141
									
								
								elpa/slack-20160928.2036/slack-message-editor.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										141
									
								
								elpa/slack-20160928.2036/slack-message-editor.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,141 @@ | ||||
| ;;; slack-message-editor.el ---  edit message interface  -*- lexical-binding: t; -*- | ||||
|  | ||||
| ;; Copyright (C) 2015  南優也 | ||||
|  | ||||
| ;; Author: 南優也 <yuyaminami@minamiyuunari-no-MacBook-Pro.local> | ||||
| ;; Keywords: | ||||
|  | ||||
| ;; This program is free software; you can redistribute it and/or modify | ||||
| ;; it under the terms of the GNU General Public License as published by | ||||
| ;; the Free Software Foundation, either version 3 of the License, or | ||||
| ;; (at your option) any later version. | ||||
|  | ||||
| ;; This program is distributed in the hope that it will be useful, | ||||
| ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| ;; GNU General Public License for more details. | ||||
|  | ||||
| ;; You should have received a copy of the GNU General Public License | ||||
| ;; along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  | ||||
| ;;; Commentary: | ||||
|  | ||||
| ;; | ||||
|  | ||||
| ;;; Code: | ||||
| (require 'slack-message-sender) | ||||
|  | ||||
| (defconst slack-message-edit-url "https://slack.com/api/chat.update") | ||||
| (defconst slack-message-edit-buffer-name "*Slack - Edit message*") | ||||
| (defconst slack-message-write-buffer-name "*Slack - Write message*") | ||||
| (defvar slack-buffer-function) | ||||
| (defvar slack-target-ts) | ||||
| (make-local-variable 'slack-target-ts) | ||||
| (defvar slack-message-edit-buffer-type) | ||||
| (make-local-variable 'slack-message-edit-buffer-type) | ||||
| (defvar slack-current-room-id) | ||||
| (defvar slack-current-team-id) | ||||
|  | ||||
| (defvar slack-edit-message-mode-map | ||||
|   (let ((keymap (make-sparse-keymap))) | ||||
|     (define-key keymap (kbd "C-s C-m") #'slack-message-embed-mention) | ||||
|     (define-key keymap (kbd "C-s C-c") #'slack-message-embed-channel) | ||||
|     (define-key keymap (kbd "C-c C-k") #'slack-message-cancel-edit) | ||||
|     (define-key keymap (kbd "C-c C-c") #'slack-message-send-from-buffer) | ||||
|     keymap)) | ||||
|  | ||||
| (define-derived-mode slack-edit-message-mode fundamental-mode "Slack Edit Msg" | ||||
|   "" | ||||
|   (slack-buffer-enable-emojify)) | ||||
|  | ||||
|  | ||||
| (defun slack-message-write-another-buffer () | ||||
|   (interactive) | ||||
|   (let* ((team (slack-team-find slack-current-team-id)) | ||||
|          (target-room (if (boundp 'slack-current-room-id) | ||||
|                           (slack-room-find slack-current-room-id | ||||
|                                            team) | ||||
|                         (slack-message-read-room team))) | ||||
|          (buf (get-buffer-create slack-message-write-buffer-name))) | ||||
|     (with-current-buffer buf | ||||
|       (slack-message-setup-edit-buf target-room 'new | ||||
|                                     :team team)) | ||||
|     (funcall slack-buffer-function buf))) | ||||
|  | ||||
| (defun slack-message-edit () | ||||
|   (interactive) | ||||
|   (let* ((team (slack-team-find slack-current-team-id)) | ||||
|          (room (slack-room-find slack-current-room-id | ||||
|                                 team)) | ||||
|          (target (thing-at-point 'word)) | ||||
|          (ts (get-text-property 0 'ts target)) | ||||
|          (msg (slack-room-find-message room ts))) | ||||
|     (unless msg | ||||
|       (error "Can't find original message")) | ||||
|     (unless (string= (oref team self-id) (oref msg user)) | ||||
|       (error "Cant't edit other user's message")) | ||||
|     (slack-message-edit-text msg room))) | ||||
|  | ||||
| (defun slack-message-edit-text (msg room) | ||||
|   (let ((buf (get-buffer-create slack-message-edit-buffer-name)) | ||||
|         (team (slack-team-find slack-current-team-id))) | ||||
|     (with-current-buffer buf | ||||
|       (slack-edit-message-mode) | ||||
|       (slack-message-setup-edit-buf room 'edit | ||||
|                                     :ts (oref msg ts) | ||||
|                                     :team team) | ||||
|       (insert (oref msg text))) | ||||
|     (funcall slack-buffer-function buf))) | ||||
|  | ||||
| (cl-defun slack-message-setup-edit-buf (room buf-type &key ts team) | ||||
|   (slack-edit-message-mode) | ||||
|   (setq buffer-read-only nil) | ||||
|   (erase-buffer) | ||||
|   (if (and (eq buf-type 'edit) ts) | ||||
|       (set (make-local-variable 'slack-target-ts) ts)) | ||||
|   (set (make-local-variable 'slack-message-edit-buffer-type) buf-type) | ||||
|   (slack-buffer-set-current-room-id room) | ||||
|   (slack-buffer-set-current-team-id team) | ||||
|   (message "C-c C-c to send edited msg")) | ||||
|  | ||||
| (defun slack-message-cancel-edit () | ||||
|   (interactive) | ||||
|   (let* ((team (slack-team-find slack-current-team-id)) | ||||
|          (room (slack-room-find slack-current-room-id | ||||
|                                 team))) | ||||
|     (erase-buffer) | ||||
|     (delete-window) | ||||
|     (slack-room-make-buffer-with-room room team))) | ||||
|  | ||||
| (defun slack-message-send-from-buffer () | ||||
|   (interactive) | ||||
|   (let ((buf-string (buffer-substring (point-min) (point-max)))) | ||||
|     (cl-case slack-message-edit-buffer-type | ||||
|       ('edit | ||||
|        (let* ((team (slack-team-find slack-current-team-id)) | ||||
|               (room (slack-room-find slack-current-room-id | ||||
|                                      team))) | ||||
|          (slack-message--edit (oref room id) | ||||
|                               team | ||||
|                               slack-target-ts | ||||
|                               buf-string))) | ||||
|       ('new (slack-message--send buf-string))) | ||||
|     (kill-buffer) | ||||
|     (delete-window))) | ||||
|  | ||||
| (defun slack-message--edit (channel team ts text) | ||||
|   (cl-labels ((on-edit (&key data &allow-other-keys) | ||||
|                        (slack-request-handle-error | ||||
|                         (data "slack-message--edit")))) | ||||
|     (slack-request | ||||
|      slack-message-edit-url | ||||
|      team | ||||
|      :type "POST" | ||||
|      :sync nil | ||||
|      :params (list (cons "channel" channel) | ||||
|                    (cons "ts" ts) | ||||
|                    (cons "text" text)) | ||||
|      :success #'on-edit))) | ||||
|  | ||||
| (provide 'slack-message-editor) | ||||
| ;;; slack-message-editor.el ends here | ||||
							
								
								
									
										182
									
								
								elpa/slack-20160928.2036/slack-message-formatter.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										182
									
								
								elpa/slack-20160928.2036/slack-message-formatter.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,182 @@ | ||||
| ;;; slack-message-formatter.el --- format message text  -*- lexical-binding: t; -*- | ||||
|  | ||||
| ;; Copyright (C) 2015  yuya.minami | ||||
|  | ||||
| ;; Author: yuya.minami <yuya.minami@yuyaminami-no-MacBook-Pro.local> | ||||
| ;; Keywords: | ||||
|  | ||||
| ;; This program is free software; you can redistribute it and/or modify | ||||
| ;; it under the terms of the GNU General Public License as published by | ||||
| ;; the Free Software Foundation, either version 3 of the License, or | ||||
| ;; (at your option) any later version. | ||||
|  | ||||
| ;; This program is distributed in the hope that it will be useful, | ||||
| ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| ;; GNU General Public License for more details. | ||||
|  | ||||
| ;; You should have received a copy of the GNU General Public License | ||||
| ;; along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  | ||||
| ;;; Commentary: | ||||
|  | ||||
| ;; | ||||
|  | ||||
| ;;; Code: | ||||
|  | ||||
| (require 'eieio) | ||||
| (require 'slack-user) | ||||
| (require 'slack-room) | ||||
|  | ||||
| (defface slack-message-output-text | ||||
|   '((t (:weight normal :height 0.9))) | ||||
|   "Face used to text message." | ||||
|   :group 'slack) | ||||
|  | ||||
| (defface slack-message-output-header | ||||
|   '((t (:foreground "#FFA000" | ||||
|                     :weight bold | ||||
|                     :height 1.0 | ||||
|                     :underline t))) | ||||
|   "Face used to text message." | ||||
|   :group 'slack) | ||||
|  | ||||
| (defface slack-message-output-reaction | ||||
|   '((t (:overline t))) | ||||
|   "Face used to reactions." | ||||
|   :group 'slack) | ||||
|  | ||||
| (defface slack-message-deleted-face | ||||
|   '((t (:strike-through t))) | ||||
|   "Face used to deleted message." | ||||
|   :group 'slack) | ||||
|  | ||||
| (defun slack-message-put-header-property (header) | ||||
|   (if header | ||||
|       (propertize header 'face 'slack-message-output-header))) | ||||
|  | ||||
| (defun slack-message-put-text-property (text) | ||||
|   (if text | ||||
|       (propertize text 'face 'slack-message-output-text))) | ||||
|  | ||||
| (defun slack-message-put-reactions-property (text) | ||||
|   (if text | ||||
|       (propertize text 'face 'slack-message-output-reaction))) | ||||
|  | ||||
| (defun slack-message-put-hard (text) | ||||
|   (if text | ||||
|       (propertize text 'hard t))) | ||||
|  | ||||
| (defun slack-message-put-deleted-property (text) | ||||
|   (if text | ||||
|       (propertize text 'face 'slack-message-deleted-face))) | ||||
|  | ||||
| (defmethod slack-message-propertize ((m slack-message) text) | ||||
|   text) | ||||
|  | ||||
| (defun slack-message-time-to-string (ts) | ||||
|   (if ts | ||||
|       (format-time-string "%Y-%m-%d %H:%M:%S" | ||||
|                           (seconds-to-time (string-to-number ts))))) | ||||
|  | ||||
| (defun slack-message-reactions-to-string (reactions) | ||||
|   (if reactions | ||||
|       (concat "\n" (mapconcat #'slack-reaction-to-string reactions " ")))) | ||||
|  | ||||
| (defmethod slack-message-header ((m slack-message) team) | ||||
|   (slack-message-sender-name m team)) | ||||
|  | ||||
| (defun slack-format-message (header body attachment-body reactions) | ||||
|   (let ((messages (list header body attachment-body reactions))) | ||||
|     (concat (mapconcat #'identity | ||||
|                (cl-remove-if #'(lambda (e) (< (length e) 1)) messages) | ||||
|                "\n") | ||||
|             "\n"))) | ||||
|  | ||||
| (defmethod slack-message-to-string ((m slack-message) team) | ||||
|   (let ((text (if (slot-boundp m 'text) | ||||
|                   (oref m text)))) | ||||
|     (let* ((header (slack-message-put-header-property | ||||
|                     (slack-message-header m team))) | ||||
|            (row-body (slack-message-body m team)) | ||||
|            (attachment-body (slack-message-attachment-body m team)) | ||||
|            (body (if (oref m deleted-at) | ||||
|                      (slack-message-put-deleted-property row-body) | ||||
|                    (slack-message-put-text-property row-body))) | ||||
|            (reactions-str | ||||
|             (slack-message-put-reactions-property | ||||
|              (slack-message-reactions-to-string (oref m reactions))))) | ||||
|       (slack-message-propertize | ||||
|        m (slack-format-message header body attachment-body reactions-str))))) | ||||
|  | ||||
| (defmethod slack-message-body ((m slack-message) team) | ||||
|   (with-slots (text) m | ||||
|     (slack-message-unescape-string text team))) | ||||
|  | ||||
| (defmethod slack-message-attachment-body ((m slack-message) team) | ||||
|   (with-slots (attachments) m | ||||
|     (let ((body (mapconcat #'slack-attachment-to-string attachments "\n"))) | ||||
|       (if (< 0 (length body)) | ||||
|           (slack-message-unescape-string body team))))) | ||||
|  | ||||
| (defmethod slack-message-to-alert ((m slack-message) team) | ||||
|   (with-slots (text) m | ||||
|     (slack-message-unescape-string text team))) | ||||
|  | ||||
| (defun slack-message-unescape-string (text team) | ||||
|   (when text | ||||
|     (let* ((and-unescpaed | ||||
|             (replace-regexp-in-string "&" "&" text)) | ||||
|            (lt-unescaped | ||||
|             (replace-regexp-in-string "<" "<" and-unescpaed)) | ||||
|            (gt-unescaped | ||||
|             (replace-regexp-in-string ">" ">" lt-unescaped))) | ||||
|       (slack-message-unescape-command | ||||
|        (slack-message-unescape-user-id | ||||
|         (slack-message-unescape-channel gt-unescaped) | ||||
|         team))))) | ||||
|  | ||||
| (defun slack-message-unescape-user-id (text team) | ||||
|   (let ((user-regexp "<@\\(U.*?\\)>")) | ||||
|     (cl-labels ((unescape-user-id | ||||
|                  (text) | ||||
|                  (concat "@" (or | ||||
|                               (slack-message-replace-user-name text) | ||||
|                               (slack-user-name (match-string 1 text) team) | ||||
|                               (match-string 1 text))))) | ||||
|       (replace-regexp-in-string user-regexp | ||||
|                                 #'unescape-user-id | ||||
|                                 text t)))) | ||||
|  | ||||
| (defun slack-message-replace-user-name (text) | ||||
|   (let ((user-name-regexp "<@U.*?|\\(.*?\\)>")) | ||||
|     (cl-labels ((replace-user-id-with-name (text) | ||||
|                                            (match-string 1 text))) | ||||
|       (if (string-match-p user-name-regexp text) | ||||
|           (replace-regexp-in-string user-name-regexp | ||||
|                                     #'replace-user-id-with-name | ||||
|                                     text))))) | ||||
|  | ||||
| (defun slack-message-unescape-command (text) | ||||
|   (let ((command-regexp "<!\\(.*?\\)>")) | ||||
|     (cl-labels ((unescape-command | ||||
|                  (text) | ||||
|                  (concat "@" (match-string 1 text)))) | ||||
|       (replace-regexp-in-string command-regexp | ||||
|                                 #'unescape-command | ||||
|                                 text)))) | ||||
|  | ||||
| (defun slack-message-unescape-channel (text) | ||||
|   (let ((channel-regexp "<#\\(C.*?\\)|\\(.*?\\)>")) | ||||
|     (cl-labels ((unescape-channel | ||||
|                  (text) | ||||
|                  (concat "#" (or (match-string 2 text) | ||||
|                                  (slack-room-find | ||||
|                                   (match-string 1 text)) | ||||
|                                  (match-string 1 text))))) | ||||
|       (replace-regexp-in-string channel-regexp | ||||
|                                 #'unescape-channel | ||||
|                                 text t)))) | ||||
|  | ||||
| (provide 'slack-message-formatter) | ||||
| ;;; slack-message-formatter.el ends here | ||||
							
								
								
									
										79
									
								
								elpa/slack-20160928.2036/slack-message-notification.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								elpa/slack-20160928.2036/slack-message-notification.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,79 @@ | ||||
| ;;; slack-message-notification.el --- message notification  -*- lexical-binding: t; -*- | ||||
|  | ||||
| ;; Copyright (C) 2015  yuya.minami | ||||
|  | ||||
| ;; Author: yuya.minami <yuya.minami@yuyaminami-no-MacBook-Pro.local> | ||||
| ;; Keywords: | ||||
|  | ||||
| ;; This program is free software; you can redistribute it and/or modify | ||||
| ;; it under the terms of the GNU General Public License as published by | ||||
| ;; the Free Software Foundation, either version 3 of the License, or | ||||
| ;; (at your option) any later version. | ||||
|  | ||||
| ;; This program is distributed in the hope that it will be useful, | ||||
| ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| ;; GNU General Public License for more details. | ||||
|  | ||||
| ;; You should have received a copy of the GNU General Public License | ||||
| ;; along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  | ||||
| ;;; Commentary: | ||||
|  | ||||
| ;; | ||||
|  | ||||
| ;;; Code: | ||||
| (require 'eieio) | ||||
| (require 'slack-room) | ||||
| (require 'slack-message) | ||||
| (require 'slack-message-formatter) | ||||
| (require 'slack-buffer) | ||||
| (require 'slack-im) | ||||
| (require 'alert) | ||||
|  | ||||
| (defvar alert-default-style) | ||||
|  | ||||
| (defcustom slack-message-custom-notifier nil | ||||
|   "Custom notification function.\ntake 3 Arguments.\n(lambda (MESSAGE ROOM TEAM) ...)." | ||||
|   :group 'slack) | ||||
|  | ||||
| (defun slack-message-notify (message room team) | ||||
|   (if slack-message-custom-notifier | ||||
|       (funcall slack-message-custom-notifier message room team) | ||||
|     (slack-message-notify-alert message room team))) | ||||
|  | ||||
| (defun slack-message-notify-alert (message room team) | ||||
|   (if (and (not (slack-message-minep message team)) | ||||
|            (or (slack-im-p room) | ||||
|                (and (slack-group-p room) (slack-mpim-p room)) | ||||
|                (slack-room-subscribedp room team) | ||||
|                (string-match (format "@%s" (plist-get (oref team self) :name)) | ||||
|                              (slack-message-body message team)))) | ||||
|       (let ((team-name (oref team name)) | ||||
|             (room-name (slack-room-name room)) | ||||
|             (text (slack-message-to-alert message team)) | ||||
|             (user-name (slack-message-sender-name message team))) | ||||
|         (if (and (eq alert-default-style 'notifier) | ||||
|                  (slack-im-p room) | ||||
|                  (or (eq (aref text 0) ?\[) | ||||
|                      (eq (aref text 0) ?\{) | ||||
|                      (eq (aref text 0) ?\<) | ||||
|                      (eq (aref text 0) ?\())) | ||||
|             (setq text (concat "\\" text))) | ||||
|         (alert (if (slack-im-p room) text (format "%s: %s" user-name text)) | ||||
|                :title (if (slack-im-p room) | ||||
|                           (format "%s - %s" team-name room-name) | ||||
|                         (format "%s - #%s" team-name room-name)) | ||||
|                :category 'slack)))) | ||||
|  | ||||
| (defmethod slack-message-sender-equalp ((_m slack-message) _sender-id) | ||||
|   nil) | ||||
|  | ||||
| (defmethod slack-message-minep ((m slack-message) team) | ||||
|   (if team | ||||
|       (with-slots (self-id) team | ||||
|         (slack-message-sender-equalp m self-id)) | ||||
|     (slack-message-sender-equalp m (oref team self-id)))) | ||||
|  | ||||
| (provide 'slack-message-notification) | ||||
| ;;; slack-message-notification.el ends here | ||||
							
								
								
									
										155
									
								
								elpa/slack-20160928.2036/slack-message-reaction.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										155
									
								
								elpa/slack-20160928.2036/slack-message-reaction.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,155 @@ | ||||
| ;;; slack-message-reaction.el --- adding, removing reaction from message  -*- lexical-binding: t; -*- | ||||
|  | ||||
| ;; Copyright (C) 2015  yuya.minami | ||||
|  | ||||
| ;; Author: yuya.minami <yuya.minami@yuyaminami-no-MacBook-Pro.local> | ||||
| ;; Keywords: | ||||
|  | ||||
| ;; This program is free software; you can redistribute it and/or modify | ||||
| ;; it under the terms of the GNU General Public License as published by | ||||
| ;; the Free Software Foundation, either version 3 of the License, or | ||||
| ;; (at your option) any later version. | ||||
|  | ||||
| ;; This program is distributed in the hope that it will be useful, | ||||
| ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| ;; GNU General Public License for more details. | ||||
|  | ||||
| ;; You should have received a copy of the GNU General Public License | ||||
| ;; along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  | ||||
| ;;; Commentary: | ||||
|  | ||||
| ;; | ||||
|  | ||||
| ;;; Code: | ||||
|  | ||||
| (require 'slack-message) | ||||
| (require 'slack-reaction) | ||||
| (require 'slack-room) | ||||
|  | ||||
| (defconst slack-message-reaction-add-url "https://slack.com/api/reactions.add") | ||||
| (defconst slack-message-reaction-remove-url "https://slack.com/api/reactions.remove") | ||||
| (defvar slack-current-team-id) | ||||
| (defvar slack-current-room-id) | ||||
| (defvar slack-emojify-comp-list) | ||||
| (defcustom slack-invalid-emojis '("^:flag_" "tone[[:digit:]]:$" "-" "^[^:].*[^:]$" "\\Ca") | ||||
|   "Invalid emoji regex. Slack server treated some emojis as Invalid." | ||||
|   :group 'slack) | ||||
|  | ||||
| (defun slack-message-reaction-load-emojify-comp-list () | ||||
|   (if (and (bound-and-true-p emojify-emojis) | ||||
|            (not (bound-and-true-p slack-emojify-comp-list))) | ||||
|       (setq slack-emojify-comp-list | ||||
|             (let ((invalid-regex (mapconcat #'identity | ||||
|                                             slack-invalid-emojis | ||||
|                                             "\\|"))) | ||||
|               (cl-remove-if (lambda (s) (string-match invalid-regex s)) | ||||
|                             (hash-table-keys emojify-emojis)))))) | ||||
|  | ||||
| (defun slack-message-add-reaction () | ||||
|   (interactive) | ||||
|   (let* ((word (thing-at-point 'word)) | ||||
|          (ts (get-text-property 0 'ts word)) | ||||
|          (reaction (slack-message-reaction-input)) | ||||
|          (team (slack-team-find slack-current-team-id)) | ||||
|          (room (slack-room-find slack-current-room-id | ||||
|                                 team))) | ||||
|     (slack-message-reaction-add reaction ts room team))) | ||||
|  | ||||
| (defun slack-message-remove-reaction () | ||||
|   (interactive) | ||||
|   (let* ((team (slack-team-find slack-current-team-id)) | ||||
|          (room (slack-room-find slack-current-room-id | ||||
|                                 team)) | ||||
|          (word (thing-at-point 'word)) | ||||
|          (ts (get-text-property 0 'ts word)) | ||||
|          (msg (slack-room-find-message room ts)) | ||||
|          (reactions (oref msg reactions)) | ||||
|          (reaction (slack-message-reaction-select reactions))) | ||||
|     (slack-message-reaction-remove reaction ts room team))) | ||||
|  | ||||
| (defun slack-message-show-reaction-users () | ||||
|   (interactive) | ||||
|   (let* ((team (slack-team-find slack-current-team-id)) | ||||
|          (reaction (ignore-errors (get-text-property (point) 'reaction)))) | ||||
|     (if reaction | ||||
|         (let ((user-names (slack-reaction-user-names reaction team))) | ||||
|           (message "reacted users: %s" (mapconcat #'identity user-names ", "))) | ||||
|       (message "Can't get reaction:")))) | ||||
|  | ||||
| (defun slack-message-reaction-select (reactions) | ||||
|   (let ((list (mapcar #'(lambda (r) | ||||
|                           (cons (oref r name) | ||||
|                                 (oref r name))) | ||||
|                       reactions))) | ||||
|     (slack-select-from-list | ||||
|      (list "Select Reaction: ") | ||||
|      selected))) | ||||
|  | ||||
| (defun slack-message-reaction-input () | ||||
|   (slack-message-reaction-load-emojify-comp-list) | ||||
|   (let ((reaction (if (bound-and-true-p slack-emojify-comp-list) | ||||
|                       (completing-read "Select Emoji: " slack-emojify-comp-list) | ||||
|                     (read-from-minibuffer "Emoji: ")))) | ||||
|     (if (and (string-prefix-p ":" reaction) | ||||
|              (string-suffix-p ":" reaction)) | ||||
|         (substring reaction 1 -1) | ||||
|       reaction))) | ||||
|  | ||||
| (defun slack-message-reaction-add (reaction ts room team) | ||||
|   (cl-labels ((on-reaction-add | ||||
|                (&key data &allow-other-keys) | ||||
|                (slack-request-handle-error | ||||
|                 (data "slack-message-reaction-add")))) | ||||
|     (slack-request | ||||
|      slack-message-reaction-add-url | ||||
|      team | ||||
|      :type "POST" | ||||
|      :sync nil | ||||
|      :params (list (cons "channel" (oref room id)) | ||||
|                    (cons "timestamp" ts) | ||||
|                    (cons "name" reaction)) | ||||
|      :success #'on-reaction-add))) | ||||
|  | ||||
| (defun slack-message-reaction-remove (reaction ts room team) | ||||
|   (cl-labels ((on-reaction-remove | ||||
|                (&key data &allow-other-keys) | ||||
|                (slack-request-handle-error | ||||
|                 (data "slack-message-reaction-remove")))) | ||||
|     (slack-request | ||||
|      slack-message-reaction-remove-url | ||||
|      team | ||||
|      :type "POST" | ||||
|      :sync nil | ||||
|      :params (list (cons "channel" (oref room id)) | ||||
|                    (cons "timestamp" ts) | ||||
|                    (cons "name" reaction)) | ||||
|      :success #'on-reaction-remove))) | ||||
|  | ||||
| (cl-defmacro slack-message-find-reaction ((m reaction) &body body) | ||||
|   `(let ((same-reaction (cl-find-if #'(lambda (r) (slack-reaction-equalp r ,reaction)) | ||||
|                                     (oref ,m reactions)))) | ||||
|      ,@body)) | ||||
|  | ||||
| (defmethod slack-message-append-reaction ((m slack-message) reaction) | ||||
|   (slack-message-find-reaction | ||||
|    (m reaction) | ||||
|    (if same-reaction | ||||
|        (slack-reaction-join same-reaction reaction) | ||||
|      (push reaction (oref m reactions))))) | ||||
|  | ||||
| (defmethod slack-message-pop-reaction ((m slack-message) reaction) | ||||
|   (slack-message-find-reaction | ||||
|    (m reaction) | ||||
|    (if same-reaction | ||||
|        (if (eq 1 (oref same-reaction count)) | ||||
|            (with-slots (reactions) m | ||||
|              (setq reactions | ||||
|                    (cl-delete-if #'(lambda (r) | ||||
|                                      (slack-reaction-equalp same-reaction r)) | ||||
|                                  reactions))) | ||||
|          (cl-decf (oref same-reaction count)))))) | ||||
|  | ||||
| (provide 'slack-message-reaction) | ||||
| ;;; slack-message-reaction.el ends here | ||||
							
								
								
									
										170
									
								
								elpa/slack-20160928.2036/slack-message-sender.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										170
									
								
								elpa/slack-20160928.2036/slack-message-sender.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,170 @@ | ||||
| ;;; slack-message-sender.el --- slack message concern message sending  -*- lexical-binding: t; -*- | ||||
|  | ||||
| ;; Copyright (C) 2015  yuya.minami | ||||
|  | ||||
| ;; Author: yuya.minami <yuya.minami@yuyaminami-no-MacBook-Pro.local> | ||||
| ;; Keywords: | ||||
|  | ||||
| ;; This program is free software; you can redistribute it and/or modify | ||||
| ;; it under the terms of the GNU General Public License as published by | ||||
| ;; the Free Software Foundation, either version 3 of the License, or | ||||
| ;; (at your option) any later version. | ||||
|  | ||||
| ;; This program is distributed in the hope that it will be useful, | ||||
| ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| ;; GNU General Public License for more details. | ||||
|  | ||||
| ;; You should have received a copy of the GNU General Public License | ||||
| ;; along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  | ||||
| ;;; Commentary: | ||||
|  | ||||
| ;; | ||||
|  | ||||
| ;;; Code: | ||||
|  | ||||
| (require 'eieio) | ||||
| (require 'json) | ||||
| (require 'slack-websocket) | ||||
| (require 'slack-im) | ||||
| (require 'slack-group) | ||||
| (require 'slack-message) | ||||
| (require 'slack-channel) | ||||
|  | ||||
| (defvar slack-message-minibuffer-local-map nil) | ||||
| (defvar slack-buffer-function) | ||||
|  | ||||
| (defun slack-message-send () | ||||
|   (interactive) | ||||
|   (slack-message--send (slack-message-read-from-minibuffer))) | ||||
|  | ||||
| (defun slack-message-inc-id (team) | ||||
|   (with-slots (message-id) team | ||||
|     (if (eq message-id (1- most-positive-fixnum)) | ||||
|         (setq message-id 1) | ||||
|       (cl-incf message-id)))) | ||||
|  | ||||
| (defun slack-escape-message (message) | ||||
|   "Escape '<,' '>' & '&' in MESSAGE." | ||||
|   (replace-regexp-in-string | ||||
|    ">" ">" | ||||
|    (replace-regexp-in-string | ||||
|     "<" "<" | ||||
|     (replace-regexp-in-string "&" "&" message)))) | ||||
|  | ||||
| (defun slack-link-users (message team) | ||||
|   "Add links to all references to valid users in MESSAGE." | ||||
|   (replace-regexp-in-string | ||||
|    "@\\<\\([A-Za-z0-9.-_]+\\)" | ||||
|    #'(lambda (text) | ||||
|        (let* ((username (match-string 1 text)) | ||||
|               (id (slack-user-get-id username team))) | ||||
|          (if id | ||||
|              (format "<@%s|%s>" id username) | ||||
|            (cond | ||||
|             ((string= username "here") "<!here|here>") | ||||
|             ((find username '("channel" "group") :test #'string=) "<!channel>") | ||||
|             ((string= username "everyone") "<!everyone>") | ||||
|             (t text))))) | ||||
|    message t)) | ||||
|  | ||||
| (defun slack-link-channels (message team) | ||||
|   "Add links to all references to valid channels in MESSAGE." | ||||
|   (let ((channel-ids | ||||
|          (mapcar #'(lambda (x) | ||||
|                      (let ((channel (cdr x))) | ||||
|                        (cons (slack-room-name channel) (slot-value channel 'id)))) | ||||
|                  (slack-channel-names team)))) | ||||
|     (replace-regexp-in-string | ||||
|      "#\\<\\([A-Za-z0-9.-_]+\\)" | ||||
|      #'(lambda (text) | ||||
|          (let* ((channel (match-string 1 text)) | ||||
|                 (id (cdr (assoc channel channel-ids)))) | ||||
|            (if id | ||||
|                (format "<#%s|%s>" id channel) | ||||
|              text))) | ||||
|      message t))) | ||||
|  | ||||
| (defun slack-message--send (message) | ||||
|   (if slack-current-team-id | ||||
|       (let* ((team (slack-team-find slack-current-team-id)) | ||||
|              (message (slack-link-channels | ||||
|                        (slack-link-users | ||||
|                         (slack-escape-message message) | ||||
|                         team) | ||||
|                        team))) | ||||
|         (slack-message-inc-id team) | ||||
|         (with-slots (message-id sent-message self-id) team | ||||
|           (let* ((m (list :id message-id | ||||
|                           :channel (slack-message-get-room-id) | ||||
|                           :type "message" | ||||
|                           :user self-id | ||||
|                           :text message)) | ||||
|                  (json (json-encode m)) | ||||
|                  (obj (slack-message-create m))) | ||||
|             (slack-ws-send json team) | ||||
|             (puthash message-id obj sent-message)))) | ||||
|     (error "Call from Slack Buffer"))) | ||||
|  | ||||
| (defun slack-message-get-room-id () | ||||
|   (if (and (boundp 'slack-current-room-id) | ||||
|            (boundp 'slack-current-team-id)) | ||||
|       (oref (slack-room-find slack-current-room-id | ||||
|                              (slack-team-find slack-current-team-id)) | ||||
|             id) | ||||
|     (oref (slack-message-read-room (slack-team-select)) id))) | ||||
|  | ||||
| (defun slack-message-read-room (team) | ||||
|   (let* ((list (slack-message-room-list team)) | ||||
|          (choices (mapcar #'car list)) | ||||
|          (room-name (slack-message-read-room-list "Select Room: " choices)) | ||||
|          (room (cdr (cl-assoc room-name list :test #'string=)))) | ||||
|     room)) | ||||
|  | ||||
| (defun slack-message-read-room-list (prompt choices) | ||||
|   (let ((completion-ignore-case t)) | ||||
|     (completing-read (format "%s" prompt) | ||||
|                      choices nil t nil nil choices))) | ||||
|  | ||||
| (defun slack-message-room-list (team) | ||||
|   (append (slack-group-names team) | ||||
|           (slack-im-names team) | ||||
|           (slack-channel-names team))) | ||||
|  | ||||
| (defun slack-message-read-from-minibuffer () | ||||
|   (let ((prompt "Message: ")) | ||||
|     (slack-message-setup-minibuffer-keymap) | ||||
|     (read-from-minibuffer | ||||
|      prompt | ||||
|      nil | ||||
|      slack-message-minibuffer-local-map))) | ||||
|  | ||||
| (defun slack-message-setup-minibuffer-keymap () | ||||
|   (unless slack-message-minibuffer-local-map | ||||
|     (setq slack-message-minibuffer-local-map | ||||
|           (let ((map (make-sparse-keymap))) | ||||
|             (define-key map (kbd "RET") 'newline) | ||||
|             (set-keymap-parent map minibuffer-local-map) | ||||
|             map)))) | ||||
|  | ||||
| (defun slack-message-embed-channel () | ||||
|   (interactive) | ||||
|   (let ((team (slack-team-select))) | ||||
|     (let* ((alist (slack-channel-names team))) | ||||
|       (slack-select-from-list | ||||
|        (alist "Select Channel: ") | ||||
|        (insert (concat "#" (slack-room-name selected))))))) | ||||
|  | ||||
| (defun slack-message-embed-mention () | ||||
|   (interactive) | ||||
|   (let ((team (slack-team-select))) | ||||
|     (let* ((pre-defined (list (list "here" :name "here") | ||||
|                               (list "channel" :name "channel"))) | ||||
|            (alist (append pre-defined (slack-user-names team)))) | ||||
|       (slack-select-from-list | ||||
|        (alist "Select User: ") | ||||
|        (insert (concat "@" (plist-get selected :name))))))) | ||||
|  | ||||
| (provide 'slack-message-sender) | ||||
| ;;; slack-message-sender.el ends here | ||||
							
								
								
									
										295
									
								
								elpa/slack-20160928.2036/slack-message.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										295
									
								
								elpa/slack-20160928.2036/slack-message.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,295 @@ | ||||
| ;;; slack-message.el --- slack-message                -*- lexical-binding: t; -*- | ||||
|  | ||||
| ;; Copyright (C) 2015  yuya.minami | ||||
|  | ||||
| ;; Author: yuya.minami <yuya.minami@yuyaminami-no-MacBook-Pro.local> | ||||
| ;; Keywords: | ||||
|  | ||||
| ;; This program is free software; you can redistribute it and/or modify | ||||
| ;; it under the terms of the GNU General Public License as published by | ||||
| ;; the Free Software Foundation, either version 3 of the License, or | ||||
| ;; (at your option) any later version. | ||||
|  | ||||
| ;; This program is distributed in the hope that it will be useful, | ||||
| ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| ;; GNU General Public License for more details. | ||||
|  | ||||
| ;; You should have received a copy of the GNU General Public License | ||||
| ;; along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  | ||||
| ;;; Commentary: | ||||
|  | ||||
| ;; | ||||
|  | ||||
| ;;; Code: | ||||
|  | ||||
| (require 'eieio) | ||||
| (require 'slack-util) | ||||
| (require 'slack-reaction) | ||||
|  | ||||
| (defvar slack-current-room-id) | ||||
| (defvar slack-current-team-id) | ||||
| (defconst slack-message-pins-add-url "https://slack.com/api/pins.add") | ||||
| (defconst slack-message-pins-remove-url "https://slack.com/api/pins.remove") | ||||
| (defconst slack-message-delete-url "https://slack.com/api/chat.delete") | ||||
|  | ||||
| (defclass slack-message () | ||||
|   ((type :initarg :type :type string) | ||||
|    (subtype :initarg :subtype) | ||||
|    (channel :initarg :channel :initform nil) | ||||
|    (ts :initarg :ts :type string :initform "") | ||||
|    (text :initarg :text :type (or null string) :initform nil) | ||||
|    (item-type :initarg :item_type) | ||||
|    (attachments :initarg :attachments :type (or null list) :initform nil) | ||||
|    (reactions :initarg :reactions :type (or null list)) | ||||
|    (is-starred :initarg :is_starred :type boolean) | ||||
|    (pinned-to :initarg :pinned_to :type (or null list)) | ||||
|    (edited-at :initarg :edited-at :initform nil) | ||||
|    (deleted-at :initarg :deleted-at :initform nil))) | ||||
|  | ||||
| (defclass slack-file-message (slack-message) | ||||
|   ((file :initarg :file) | ||||
|    ;; (bot-id :initarg :bot_id :type (or null string)) | ||||
|    ;; (username :initarg :username) | ||||
|    ;; (display-as-bot :initarg :display_as_bot) | ||||
|    (upload :initarg :upload) | ||||
|    (user :initarg :user :initform nil))) | ||||
|  | ||||
| (defclass slack-reply (slack-message) | ||||
|   ((user :initarg :user :initform nil) | ||||
|    (reply-to :initarg :reply_to :type integer) | ||||
|    (id :initarg :id :type integer))) | ||||
|  | ||||
| (defclass slack-user-message (slack-message) | ||||
|   ((user :initarg :user :type string) | ||||
|    (edited :initarg :edited) | ||||
|    (id :initarg :id) | ||||
|    (inviter :initarg :inviter))) | ||||
|  | ||||
| (defclass slack-bot-message (slack-message) | ||||
|   ((bot-id :initarg :bot_id :type string) | ||||
|    (username :initarg :username :type string :initform "") | ||||
|    (icons :initarg :icons))) | ||||
|  | ||||
| (defclass slack-attachment () | ||||
|   ((fallback :initarg :fallback :initform nil) | ||||
|    (title :initarg :title :initform nil) | ||||
|    (title-link :initarg :title_link :initform nil) | ||||
|    (pretext :initarg :pretext :initform nil) | ||||
|    (text :initarg :text :initform nil) | ||||
|    (author-name :initarg :author_name) | ||||
|    (author-link :initarg :author_link) | ||||
|    (author-icon :initarg :author_icon) | ||||
|    (fields :initarg :fields :type (or null list)) | ||||
|    (image-url :initarg :image_url) | ||||
|    (thumb-url :initarg :thumb_url) | ||||
|    (is-share :initarg :is_share :initform nil))) | ||||
|  | ||||
| (defclass slack-shared-message (slack-attachment) | ||||
|   ((ts :initarg :ts :initform nil) | ||||
|    (color :initarg :color :initform nil) | ||||
|    (channel-id :initarg :channel_id :initform nil) | ||||
|    (channel-name :initarg :channel_name :initform nil) | ||||
|    (from-url :initarg :from_url :initform nil))) | ||||
|  | ||||
| (defgeneric slack-message-sender-name  (slack-message team)) | ||||
| (defgeneric slack-message-to-string (slack-message)) | ||||
| (defgeneric slack-message-to-alert (slack-message)) | ||||
|  | ||||
| (defgeneric slack-room-buffer-name (room)) | ||||
|  | ||||
| (defun slack-room-find (id team) | ||||
|   (if (and id team) | ||||
|       (cl-labels ((find-room (room) | ||||
|                              (string= id (oref room id)))) | ||||
|         (cond | ||||
|          ((string-prefix-p "F" id) (slack-file-room-obj team)) | ||||
|          ((string-prefix-p "C" id) (cl-find-if #'find-room | ||||
|                                                (oref team channels))) | ||||
|          ((string-prefix-p "G" id) (cl-find-if #'find-room | ||||
|                                                (oref team groups))) | ||||
|          ((string-prefix-p "D" id) (cl-find-if #'find-room | ||||
|                                                (oref team ims))) | ||||
|          ((string-prefix-p "Q" id) (cl-find-if #'find-room | ||||
|                                                (oref team search-results))))))) | ||||
|  | ||||
| (defun slack-reaction-create (payload) | ||||
|   (apply #'slack-reaction "reaction" | ||||
|          (slack-collect-slots 'slack-reaction payload))) | ||||
|  | ||||
| (defmethod slack-message-set-reactions ((m slack-message) payload) | ||||
|   (let ((reactions (plist-get payload :reactions))) | ||||
|     (if (< 0 (length reactions)) | ||||
|         (oset m reactions (mapcar #'slack-reaction-create reactions)))) | ||||
|   m) | ||||
|  | ||||
| (defun slack-attachment-create (payload) | ||||
|   (plist-put payload :fields | ||||
|              (append (plist-get payload :fields) nil)) | ||||
|   (if (plist-get payload :is_share) | ||||
|       (apply #'slack-shared-message "shared-attachment" | ||||
|              (slack-collect-slots 'slack-shared-message payload)) | ||||
|     (apply #'slack-attachment "attachment" | ||||
|            (slack-collect-slots 'slack-attachment payload)))) | ||||
|  | ||||
| (defmethod slack-message-set-attachments ((m slack-message) payload) | ||||
|   (let ((attachments (plist-get payload :attachments))) | ||||
|     (if (< 0 (length attachments)) | ||||
|         (oset m attachments | ||||
|               (mapcar #'slack-attachment-create attachments)))) | ||||
|   m) | ||||
|  | ||||
| (cl-defun slack-message-create (payload &key room) | ||||
|   (when payload | ||||
|     (plist-put payload :reactions (append (plist-get payload :reactions) nil)) | ||||
|     (plist-put payload :attachments (append (plist-get payload :attachments) nil)) | ||||
|     (plist-put payload :pinned_to (append (plist-get payload :pinned_to) nil)) | ||||
|     (if room | ||||
|         (plist-put payload :channel (oref room id))) | ||||
|     (cl-labels ((create | ||||
|                  (m) | ||||
|                  (let ((subtype (plist-get m :subtype))) | ||||
|                    (cond | ||||
|                     ((plist-member m :reply_to) | ||||
|                      (apply #'slack-reply "reply" | ||||
|                             (slack-collect-slots 'slack-reply m))) | ||||
|                     ((and subtype (string-prefix-p "file" subtype)) | ||||
|                      (apply #'slack-file-message "file-msg" | ||||
|                             (slack-collect-slots 'slack-file-message m))) | ||||
|                     ((plist-member m :user) | ||||
|                      (apply #'slack-user-message "user-msg" | ||||
|                             (slack-collect-slots 'slack-user-message m))) | ||||
|                     ((and subtype (string= "bot_message" subtype)) | ||||
|                      (apply #'slack-bot-message "bot-msg" | ||||
|                             (slack-collect-slots 'slack-bot-message m))))))) | ||||
|       (let ((message (create payload))) | ||||
|         (when message | ||||
|           (slack-message-set-attachments message payload) | ||||
|           (slack-message-set-reactions message payload)))))) | ||||
|  | ||||
| (defmethod slack-message-equal ((m slack-message) n) | ||||
|   (string= (oref m ts) (oref n ts))) | ||||
|  | ||||
| (defmethod slack-message-update ((m slack-message) team &optional replace no-notify) | ||||
|   (cl-labels | ||||
|       ((push-message-to (room msg) | ||||
|                         (with-slots (messages) room | ||||
|                           (when (< 0 (length messages)) | ||||
|                             (cl-pushnew msg messages | ||||
|                                         :test #'slack-message-equal)) | ||||
|                           (update-latest room msg))) | ||||
|        (update-latest (room msg) | ||||
|                       (with-slots (latest) room | ||||
|                         (if (or (null latest) | ||||
|                                 (string< (oref latest ts) (oref msg ts))) | ||||
|                             (setq latest msg))))) | ||||
|     (with-slots (channel) m | ||||
|       (let ((room (slack-room-find channel team))) | ||||
|         (when room | ||||
|           (push-message-to room m) | ||||
|           (slack-buffer-update room m team :replace replace) | ||||
|           (unless no-notify | ||||
|             (slack-message-notify m room team))))))) | ||||
|  | ||||
|  | ||||
| (defun slack-message-edited (payload team) | ||||
|   (let* ((edited-message (slack-decode (plist-get payload :message))) | ||||
|          (room (slack-room-find (plist-get payload :channel) team)) | ||||
|          (message (slack-room-find-message room | ||||
|                                            (plist-get edited-message :ts))) | ||||
|          (edited-info (plist-get edited-message :edited))) | ||||
|     (if message | ||||
|         (progn | ||||
|           (with-slots (text edited-at attachments) message | ||||
|             (setq text (plist-get edited-message :text)) | ||||
|             (setq edited-at (plist-get edited-info :ts)) | ||||
|             (if (plist-get edited-message :attachments) | ||||
|                 (setq attachments | ||||
|                       (mapcar #'slack-attachment-create | ||||
|                               (plist-get edited-message :attachments))))) | ||||
|           (slack-message-update message team t))))) | ||||
|  | ||||
| (defmethod slack-message-sender-name ((m slack-message) team) | ||||
|   (slack-user-name (oref m user) team)) | ||||
|  | ||||
| (defun slack-message-pins-add () | ||||
|   (interactive) | ||||
|   (slack-message-pins-request slack-message-pins-add-url)) | ||||
|  | ||||
| (defun slack-message-pins-remove () | ||||
|   (interactive) | ||||
|   (slack-message-pins-request slack-message-pins-remove-url)) | ||||
|  | ||||
| (defun slack-message-pins-request (url) | ||||
|   (unless (and (bound-and-true-p slack-current-team-id) | ||||
|                (bound-and-true-p slack-current-room-id)) | ||||
|     (error "Call From Slack Room Buffer")) | ||||
|   (let* ((team (slack-team-find slack-current-team-id)) | ||||
|          (room (slack-room-find slack-current-room-id | ||||
|                                 team)) | ||||
|          (word (thing-at-point 'word)) | ||||
|          (ts (ignore-errors (get-text-property 0 'ts word)))) | ||||
|     (unless ts | ||||
|       (error "Call From Slack Room Buffer")) | ||||
|     (cl-labels ((on-pins-add | ||||
|                  (&key data &allow-other-keys) | ||||
|                  (slack-request-handle-error | ||||
|                   (data "slack-message-pins-request")))) | ||||
|       (slack-request | ||||
|        url | ||||
|        team | ||||
|        :params (list (cons "channel" (oref room id)) | ||||
|                      (cons "timestamp" ts)) | ||||
|        :success #'on-pins-add | ||||
|        :sync nil)))) | ||||
|  | ||||
| (defun slack-message-time-stamp (message) | ||||
|   (seconds-to-time (string-to-number (oref message ts)))) | ||||
|  | ||||
| (defun slack-message-delete () | ||||
|   (interactive) | ||||
|   (unless (and (boundp 'slack-current-team-id) | ||||
|                (boundp 'slack-current-room-id)) | ||||
|     (error "Call From Slack Room Buffer")) | ||||
|   (let* ((team (slack-team-find slack-current-team-id)) | ||||
|          (channel (slack-room-find slack-current-room-id | ||||
|                                    team)) | ||||
|          (ts (ignore-errors (get-text-property (point) 'ts)))) | ||||
|     (unless ts | ||||
|       (error "Call With Cursor On Message")) | ||||
|     (let ((message (slack-room-find-message channel ts))) | ||||
|       (when message | ||||
|         (cl-labels | ||||
|             ((on-delete | ||||
|               (&key data &allow-other-keys) | ||||
|               (slack-request-handle-error | ||||
|                (data "slack-message-delete")))) | ||||
|           (if (yes-or-no-p "Are you sure you want to delete this message?") | ||||
|               (slack-request | ||||
|                slack-message-delete-url | ||||
|                team | ||||
|                :type "POST" | ||||
|                :params (list (cons "ts" (oref message ts)) | ||||
|                              (cons "channel" (oref channel id))) | ||||
|                :success #'on-delete | ||||
|                :sync nil) | ||||
|             (message "Canceled"))))))) | ||||
|  | ||||
| (defun slack-message-deleted (payload team) | ||||
|   (let* ((channel-id (plist-get payload :channel)) | ||||
|          (ts (plist-get payload :deleted_ts)) | ||||
|          (deleted-ts (plist-get payload :ts)) | ||||
|          (channel (slack-room-find channel-id team)) | ||||
|          (message (slack-room-find-message channel ts))) | ||||
|     (when message | ||||
|       (oset message deleted-at deleted-ts) | ||||
|       (alert "message deleted" | ||||
|              :title (format "\\[%s] from %s" | ||||
|                             (slack-room-name-with-team-name channel) | ||||
|                             (slack-message-sender-name message team)) | ||||
|              :category 'slack) | ||||
|       (slack-buffer-update channel message team :replace t)))) | ||||
|  | ||||
| (provide 'slack-message) | ||||
| ;;; slack-message.el ends here | ||||
							
								
								
									
										11
									
								
								elpa/slack-20160928.2036/slack-pkg.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								elpa/slack-20160928.2036/slack-pkg.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| (define-package "slack" "20160928.2036" "Slack client for Emacs" | ||||
|   '((websocket "1.5") | ||||
|     (request "0.2.0") | ||||
|     (oauth2 "0.10") | ||||
|     (circe "2.2") | ||||
|     (alert "1.2") | ||||
|     (emojify "0.2")) | ||||
|   :url "https://github.com/yuya373/emacs-slack") | ||||
| ;; Local Variables: | ||||
| ;; no-byte-compile: t | ||||
| ;; End: | ||||
							
								
								
									
										66
									
								
								elpa/slack-20160928.2036/slack-reaction.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								elpa/slack-20160928.2036/slack-reaction.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,66 @@ | ||||
| ;;; slack-reaction.el ---  deal with reactions       -*- lexical-binding: t; -*- | ||||
|  | ||||
| ;; Copyright (C) 2015  yuya.minami | ||||
|  | ||||
| ;; Author: yuya.minami <yuya.minami@yuyaminami-no-MacBook-Pro.local> | ||||
| ;; Keywords: | ||||
|  | ||||
| ;; This program is free software; you can redistribute it and/or modify | ||||
| ;; it under the terms of the GNU General Public License as published by | ||||
| ;; the Free Software Foundation, either version 3 of the License, or | ||||
| ;; (at your option) any later version. | ||||
|  | ||||
| ;; This program is distributed in the hope that it will be useful, | ||||
| ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| ;; GNU General Public License for more details. | ||||
|  | ||||
| ;; You should have received a copy of the GNU General Public License | ||||
| ;; along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  | ||||
| ;;; Commentary: | ||||
|  | ||||
| ;; | ||||
|  | ||||
| ;;; Code: | ||||
|  | ||||
| (require 'eieio) | ||||
|  | ||||
| (defclass slack-reaction () | ||||
|   ((name :initarg :name :type string) | ||||
|    (count :initarg :count :type integer) | ||||
|    (users :initarg :users :initform ()))) | ||||
|  | ||||
| (defmethod slack-reaction-join ((r slack-reaction) other) | ||||
|   (if (string= (oref r name) (oref other name)) | ||||
|       (progn | ||||
|         (cl-incf (oref r count)) | ||||
|         (oset r users (nconc (oref other users) (oref r users))) | ||||
|         r))) | ||||
|  | ||||
| (defmethod slack-reaction-user-names ((r slack-reaction) team) | ||||
|   (with-slots (users) r | ||||
|     (mapcar #'(lambda (u) (slack-user-name u team)) | ||||
|             users))) | ||||
|  | ||||
| (defmethod slack-reaction-equalp ((r slack-reaction) other) | ||||
|   (string= (oref r name) (oref other name))) | ||||
|  | ||||
| (defmethod slack-reaction-to-string ((r slack-reaction)) | ||||
|   (let ((text (format ":%s:: %d" (oref r name) (oref r count)))) | ||||
|     (put-text-property 0 (length text) 'reaction r text) | ||||
|     text)) | ||||
|  | ||||
| (defun slack-reaction-notify (payload team) | ||||
|   (let* ((user-id (plist-get payload :user)) | ||||
|          (room (slack-room-find (plist-get (plist-get payload :item) :channel) | ||||
|                                 team)) | ||||
|          (reaction (plist-get payload :reaction)) | ||||
|          (msg (slack-user-message "msg" | ||||
|                                   :text (format "added reaction %s" reaction) | ||||
|                                   :user user-id))) | ||||
|     (slack-message-notify msg room team))) | ||||
|  | ||||
| (provide 'slack-reaction) | ||||
| ;;; slack-reaction.el ends here | ||||
|  | ||||
							
								
								
									
										264
									
								
								elpa/slack-20160928.2036/slack-reminder.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										264
									
								
								elpa/slack-20160928.2036/slack-reminder.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,264 @@ | ||||
| ;;; slack-reminder.el ---                            -*- lexical-binding: t; -*- | ||||
|  | ||||
| ;; Copyright (C) 2016  南優也 | ||||
|  | ||||
| ;; Author: 南優也 <yuyaminami@minamiyuuya-no-MacBook.local> | ||||
| ;; Keywords: | ||||
|  | ||||
| ;; This program is free software; you can redistribute it and/or modify | ||||
| ;; it under the terms of the GNU General Public License as published by | ||||
| ;; the Free Software Foundation, either version 3 of the License, or | ||||
| ;; (at your option) any later version. | ||||
|  | ||||
| ;; This program is distributed in the hope that it will be useful, | ||||
| ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| ;; GNU General Public License for more details. | ||||
|  | ||||
| ;; You should have received a copy of the GNU General Public License | ||||
| ;; along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  | ||||
| ;;; Commentary: | ||||
|  | ||||
| ;; | ||||
|  | ||||
| ;;; Code: | ||||
|  | ||||
| (require 'eieio) | ||||
| (require 'slack-team) | ||||
|  | ||||
| (defconst slack-reminder-list-url "https://slack.com/api/reminders.list") | ||||
| (defconst slack-reminder-add-url "https://slack.com/api/reminders.add") | ||||
| (defconst slack-reminder-delete-url "https://slack.com/api/reminders.delete") | ||||
| (defconst slack-reminder-complete-url "https://slack.com/api/reminders.complete") | ||||
| (defconst slack-reminder-info-url "https://slack.com/api/reminders.info") | ||||
|  | ||||
| (defclass slack-reminder-base () | ||||
|   ((id :initarg :id :type string) | ||||
|    (creator :initarg :creator :type string) | ||||
|    (user :initarg :user :type string) | ||||
|    (text :initarg :text :type string))) | ||||
|  | ||||
| (defclass slack-recurring-reminder (slack-reminder-base) | ||||
|   ()) | ||||
|  | ||||
| (defclass slack-reminder (slack-reminder-base) | ||||
|   ((time :initarg :time :type integer) | ||||
|    (complete-ts :initarg :complete_ts :type integer))) | ||||
|  | ||||
| (defmethod slack-reminder-user ((r slack-reminder-base) team) | ||||
|   (slack-user-find (oref r user) team)) | ||||
|  | ||||
| (defmethod slack-reminder-creator ((r slack-reminder-base) team) | ||||
|   (slack-user-find (oref r creator) team)) | ||||
|  | ||||
| (defmethod slack-team-add-reminder ((team slack-team) reminder) | ||||
|   (with-slots (reminders) team | ||||
|     (cl-pushnew reminder reminders | ||||
|                 :test #'(lambda (a b) (string= (oref a id) (oref b id)))))) | ||||
|  | ||||
| (defmethod slack-reminder-completedp ((r slack-reminder)) | ||||
|   (not (eq 0 (oref r complete-ts)))) | ||||
|  | ||||
| (defmethod slack-reminder-completedp ((_r slack-recurring-reminder)) | ||||
|   nil) | ||||
|  | ||||
| (defun slack-reminder-create (payload) | ||||
|   (let ((klass (if (eq :json-false (plist-get payload :recurring)) | ||||
|                    'slack-reminder | ||||
|                  'slack-recurring-reminder))) | ||||
|     (apply #'make-instance klass | ||||
|            (slack-collect-slots klass payload)))) | ||||
|  | ||||
| (defun slack-reminder-add () | ||||
|   (interactive) | ||||
|   (let* ((team (slack-team-select)) | ||||
|          (user (slack-select-from-list | ||||
|                 ((slack-user-names team) "Select Target User: "))) | ||||
|          (time (read-from-minibuffer | ||||
|                 "Time (Ex. \"in 15 minutes,\" or \"every Thursday\"): ")) | ||||
|          (text (read-from-minibuffer "Text: "))) | ||||
|     (cl-labels | ||||
|         ((on-reminder-add (&key data &allow-other-keys) | ||||
|                           (slack-request-handle-error | ||||
|                            (data "slack-reminder-add") | ||||
|                            (let ((reminder (slack-reminder-create | ||||
|                                             (slack-decode | ||||
|                                              (plist-get data :reminder))))) | ||||
|                              (slack-team-add-reminder team reminder) | ||||
|                              (message "Reminder Created!"))))) | ||||
|       (slack-request | ||||
|        slack-reminder-add-url | ||||
|        team | ||||
|        :sync nil | ||||
|        :params (list (cons "text" text) | ||||
|                      (cons "time" time) | ||||
|                      (and user (cons "user" (plist-get user :id)))) | ||||
|        :success #'on-reminder-add)))) | ||||
|  | ||||
| (defmethod slack-reminder-to-body ((r slack-reminder)) | ||||
|   (with-slots (text time complete-ts) r | ||||
|     (let ((time-str (format "Remind At: %s" | ||||
|                             (slack-message-time-to-string | ||||
|                              (number-to-string time)))) | ||||
|           (completed (format "Completed: %s" | ||||
|                              (if (eq complete-ts 0) | ||||
|                                  "Not Yet" | ||||
|                                (slack-message-time-to-string | ||||
|                                 (number-to-string complete-ts)))))) | ||||
|       (format "%s\n%s\n\n%s" time-str completed text)))) | ||||
|  | ||||
| (defmethod slack-reminder-to-body ((r slack-recurring-reminder)) | ||||
|   (oref r text)) | ||||
|  | ||||
| (defmethod slack-reminder-to-string ((r slack-reminder-base) team) | ||||
|   (with-slots (creator user) r | ||||
|     (let* ((header (slack-message-put-header-property | ||||
|                     (format "From: %s To: %s" | ||||
|                             (slack-user-name creator team) | ||||
|                             (slack-user-name user team)))) | ||||
|            (body (slack-reminder-to-body r))) | ||||
|       (format "%s\n%s\n\n" header body)))) | ||||
|  | ||||
| (defmethod slack-create-reminder-buffer ((team slack-team)) | ||||
|   (let* ((buf-name "*Slack - Reminders*") | ||||
|          (buf (get-buffer-create buf-name))) | ||||
|     (with-current-buffer buf | ||||
|       (setq buffer-read-only nil) | ||||
|       (erase-buffer) | ||||
|       (goto-char (point-min)) | ||||
|       (with-slots (reminders) team | ||||
|         (cl-loop for reminder in reminders | ||||
|                  do (insert (slack-reminder-to-string reminder team)))) | ||||
|       (setq buffer-read-only t)) | ||||
|     buf)) | ||||
|  | ||||
| (defmethod slack-reminder-sort-key ((r slack-reminder)) | ||||
|   (oref r time)) | ||||
|  | ||||
| (defmethod slack-reminder-sort-key ((r slack-recurring-reminder)) | ||||
|   0) | ||||
|  | ||||
| (defun slack-reminder-sort (team) | ||||
|   (with-slots (reminders) team | ||||
|     (setq reminders | ||||
|           (cl-sort reminders #'< | ||||
|                    :key #'(lambda (r) (slack-reminder-sort-key r)))))) | ||||
|  | ||||
| (defun slack-reminder-list () | ||||
|   (interactive) | ||||
|   (let ((team (slack-team-select))) | ||||
|     (cl-labels | ||||
|         ((on-reminder-list | ||||
|           (&key data &allow-other-keys) | ||||
|           (slack-request-handle-error | ||||
|            (data "slack-reminder-list") | ||||
|            (oset team reminders | ||||
|                  (cl-loop | ||||
|                   for payload in (slack-decode | ||||
|                                   (append (plist-get data :reminders) | ||||
|                                           nil)) | ||||
|                   collect (slack-reminder-create payload))) | ||||
|            (slack-reminder-sort team) | ||||
|            (if (< 0 (length (oref team reminders))) | ||||
|                (funcall | ||||
|                 slack-buffer-function | ||||
|                 (slack-create-reminder-buffer team)) | ||||
|              (message "No Reminders!"))))) | ||||
|       (slack-request | ||||
|        slack-reminder-list-url | ||||
|        team | ||||
|        :sync nil | ||||
|        :success #'on-reminder-list)))) | ||||
|  | ||||
| (defmethod slack-reminders-alist ((team slack-team) &optional filter) | ||||
|   (cl-labels ((text (r) | ||||
|                     (with-slots (creator user text) r | ||||
|                       (format "Creator: %s Target: %s Content: %s" | ||||
|                               (slack-user-name creator team) | ||||
|                               (slack-user-name user team) | ||||
|                               text)))) | ||||
|     (with-slots (reminders) team | ||||
|       (mapcar #'(lambda (r) (cons (text r) r)) | ||||
|               (if filter | ||||
|                   (cl-remove-if-not #'(lambda (r) (funcall filter r)) | ||||
|                                     reminders) | ||||
|                 reminders))))) | ||||
|  | ||||
| (defmethod slack-team-delete-reminder ((team slack-team) r) | ||||
|   (with-slots (reminders) team | ||||
|     (setq reminders | ||||
|           (cl-remove-if #'(lambda (e) | ||||
|                             (string= (oref e id) (oref r id))) | ||||
|                         reminders)))) | ||||
|  | ||||
| (defun slack-reminder-select (team &optional filter) | ||||
|   (slack-select-from-list | ||||
|    ((slack-reminders-alist team filter) "Select: "))) | ||||
|  | ||||
| (defun slack-reminder-delete () | ||||
|   (interactive) | ||||
|   (let* ((team (slack-team-select)) | ||||
|          (reminder (slack-reminder-select team))) | ||||
|     (cl-labels | ||||
|         ((on-reminder-delete (&key data &allow-other-keys) | ||||
|                              (slack-request-handle-error | ||||
|                               (data "slack-reminder-delete") | ||||
|                               (slack-team-delete-reminder team reminder) | ||||
|                               (message "Reminder Deleted!")))) | ||||
|       (slack-request | ||||
|        slack-reminder-delete-url | ||||
|        team | ||||
|        :sync nil | ||||
|        :params (list (cons "reminder" (oref reminder id))) | ||||
|        :success #'on-reminder-delete)))) | ||||
|  | ||||
| (defmethod slack-reminder-info ((r slack-reminder-base) team callback) | ||||
|   (cl-labels | ||||
|       ((on-reminder-info (&key data &allow-other-keys) | ||||
|                          (slack-request-handle-error | ||||
|                           (data "slack-reminder-info") | ||||
|                           (let ((reminder (slack-reminder-create | ||||
|                                            (plist-get (slack-decode data) | ||||
|                                                       :reminder)))) | ||||
|                             (funcall callback reminder))))) | ||||
|     (slack-request | ||||
|      slack-reminder-info-url | ||||
|      team | ||||
|      :sync nil | ||||
|      :params (list (cons "reminder" (oref r id))) | ||||
|      :success #'on-reminder-info))) | ||||
|  | ||||
| (defmethod slack-reminder-refresh ((r slack-reminder-base) team) | ||||
|   (slack-reminder-info | ||||
|    r team | ||||
|    #'(lambda (reminder) | ||||
|        (with-slots (reminders) team | ||||
|          (setq reminders | ||||
|                (cl-remove-if #'(lambda (e) (string= (oref e id) | ||||
|                                                     (oref reminder id))) | ||||
|                              reminders)) | ||||
|          (push reminder reminders)) | ||||
|        (message "Reminder Updated!")))) | ||||
|  | ||||
| (defun slack-reminder-complete () | ||||
|   (interactive) | ||||
|   (let* ((team (slack-team-select)) | ||||
|          (reminder (slack-reminder-select | ||||
|                     team | ||||
|                     #'(lambda (r) | ||||
|                         (not (slack-reminder-completedp r)))))) | ||||
|     (cl-labels | ||||
|         ((on-reminder-complete (&key data &allow-other-keys) | ||||
|                                (slack-request-handle-error | ||||
|                                 (data "slack-reminder-complete") | ||||
|                                 (slack-reminder-refresh reminder team)))) | ||||
|       (slack-request | ||||
|        slack-reminder-complete-url | ||||
|        team | ||||
|        :sync nil | ||||
|        :params (list (cons "reminder" (oref reminder id))) | ||||
|        :success #'on-reminder-complete)))) | ||||
|  | ||||
| (provide 'slack-reminder) | ||||
| ;;; slack-reminder.el ends here | ||||
							
								
								
									
										49
									
								
								elpa/slack-20160928.2036/slack-reply.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								elpa/slack-20160928.2036/slack-reply.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | ||||
| ;;; slack-reply.el ---handle reply from slack        -*- lexical-binding: t; -*- | ||||
|  | ||||
| ;; Copyright (C) 2015  yuya.minami | ||||
|  | ||||
| ;; Author: yuya.minami <yuya.minami@yuyaminami-no-MacBook-Pro.local> | ||||
| ;; Keywords: | ||||
|  | ||||
| ;; This program is free software; you can redistribute it and/or modify | ||||
| ;; it under the terms of the GNU General Public License as published by | ||||
| ;; the Free Software Foundation, either version 3 of the License, or | ||||
| ;; (at your option) any later version. | ||||
|  | ||||
| ;; This program is distributed in the hope that it will be useful, | ||||
| ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| ;; GNU General Public License for more details. | ||||
|  | ||||
| ;; You should have received a copy of the GNU General Public License | ||||
| ;; along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  | ||||
| ;;; Commentary: | ||||
|  | ||||
| ;; | ||||
|  | ||||
| ;;; Code: | ||||
| (require 'eieio) | ||||
| (require 'slack-message) | ||||
|  | ||||
| (defmethod slack-message-handle-reply ((m slack-reply) team) | ||||
|   (with-slots (reply-to) m | ||||
|     (let ((sent-msg (slack-message-find-sent m team))) | ||||
|       (if sent-msg | ||||
|           (progn | ||||
|             (oset sent-msg ts (oref m ts)) | ||||
|             (slack-message-update sent-msg team)))))) | ||||
|  | ||||
| (defmethod slack-message-find-sent ((m slack-reply) team) | ||||
|   (with-slots (reply-to) m | ||||
|     (with-slots (sent-message) team | ||||
|       (let ((found (gethash reply-to sent-message))) | ||||
|         (remhash reply-to sent-message) | ||||
|         found)))) | ||||
|  | ||||
| (defmethod slack-message-sender-equalp ((m slack-reply) sender-id) | ||||
|   (string= (oref m user) sender-id)) | ||||
|  | ||||
|  | ||||
| (provide 'slack-reply) | ||||
| ;;; slack-reply.el ends here | ||||
							
								
								
									
										80
									
								
								elpa/slack-20160928.2036/slack-request.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								elpa/slack-20160928.2036/slack-request.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,80 @@ | ||||
| ;;; slack-request.el ---slack request function       -*- lexical-binding: t; -*- | ||||
|  | ||||
| ;; Copyright (C) 2015  南優也 | ||||
|  | ||||
| ;; Author: 南優也 <yuyaminami@minamiyuunari-no-MacBook-Pro.local> | ||||
| ;; Keywords: | ||||
|  | ||||
| ;; This program is free software; you can redistribute it and/or modify | ||||
| ;; it under the terms of the GNU General Public License as published by | ||||
| ;; the Free Software Foundation, either version 3 of the License, or | ||||
| ;; (at your option) any later version. | ||||
|  | ||||
| ;; This program is distributed in the hope that it will be useful, | ||||
| ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| ;; GNU General Public License for more details. | ||||
|  | ||||
| ;; You should have received a copy of the GNU General Public License | ||||
| ;; along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  | ||||
| ;;; Commentary: | ||||
|  | ||||
| ;; | ||||
|  | ||||
| ;;; Code: | ||||
|  | ||||
| (require 'json) | ||||
| (require 'request) | ||||
|  | ||||
| (defcustom slack-request-timeout 5 | ||||
|   "Request Timeout in seconds." | ||||
|   :group 'slack) | ||||
|  | ||||
| (defun slack-parse-to-hash () | ||||
|   (let ((json-object-type 'hash-table)) | ||||
|     (let ((res (json-read-from-string (buffer-string)))) | ||||
|       res))) | ||||
|  | ||||
| (defun slack-parse-to-plist () | ||||
|   (let ((json-object-type 'plist)) | ||||
|     (json-read))) | ||||
|  | ||||
| (defun slack-request-parse-payload (payload) | ||||
|   (let ((json-object-type 'plist)) | ||||
|     (json-read-from-string payload))) | ||||
|  | ||||
| (cl-defun slack-request (url team &key | ||||
|                              (type "GET") | ||||
|                              (success) | ||||
|                              (error nil) | ||||
|                              (params nil) | ||||
|                              (parser #'slack-parse-to-plist) | ||||
|                              (sync t) | ||||
|                              (files nil) | ||||
|                              (headers nil) | ||||
|                              (timeout slack-request-timeout)) | ||||
|   (request | ||||
|    url | ||||
|    :type type | ||||
|    :sync sync | ||||
|    :params (cons (cons "token" (oref team token)) | ||||
|                  params) | ||||
|    :files files | ||||
|    :headers headers | ||||
|    :parser parser | ||||
|    :success success | ||||
|    :error error | ||||
|    :timeout timeout)) | ||||
|  | ||||
| (cl-defmacro slack-request-handle-error ((data req-name) &body body) | ||||
|   "Bind error to e if present in DATA." | ||||
|   `(if (eq (plist-get ,data :ok) :json-false) | ||||
|        (message "Failed to request %s: %s" | ||||
|                 ,req-name | ||||
|                 (plist-get ,data :error)) | ||||
|      (progn | ||||
|        ,@body))) | ||||
|  | ||||
| (provide 'slack-request) | ||||
| ;;; slack-request.el ends here | ||||
							
								
								
									
										472
									
								
								elpa/slack-20160928.2036/slack-room.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										472
									
								
								elpa/slack-20160928.2036/slack-room.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,472 @@ | ||||
| ;;; slack-room.el --- slack generic room interface    -*- lexical-binding: t; -*- | ||||
|  | ||||
| ;; Copyright (C) 2015  南優也 | ||||
|  | ||||
| ;; Author: 南優也 <yuyaminami@minamiyuunari-no-MacBook-Pro.local> | ||||
| ;; Keywords: | ||||
|  | ||||
| ;; This program is free software; you can redistribute it and/or modify | ||||
| ;; it under the terms of the GNU General Public License as published by | ||||
| ;; the Free Software Foundation, either version 3 of the License, or | ||||
| ;; (at your option) any later version. | ||||
|  | ||||
| ;; This program is distributed in the hope that it will be useful, | ||||
| ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| ;; GNU General Public License for more details. | ||||
|  | ||||
| ;; You should have received a copy of the GNU General Public License | ||||
| ;; along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  | ||||
| ;;; Commentary: | ||||
|  | ||||
| ;; | ||||
|  | ||||
| ;;; Code: | ||||
|  | ||||
| (require 'eieio) | ||||
| (require 'slack-request) | ||||
| (require 'slack-message) | ||||
|  | ||||
| (defvar slack-current-room-id) | ||||
| (defvar slack-current-team-id) | ||||
| (defvar slack-buffer-function) | ||||
| (defconst slack-room-pins-list-url "https://slack.com/api/pins.list") | ||||
|  | ||||
| (defclass slack-room () | ||||
|   ((name :initarg :name :type string) | ||||
|    (id :initarg :id) | ||||
|    (created :initarg :created) | ||||
|    (has-pins :initarg :has_pins) | ||||
|    (last-read :initarg :last_read :type string :initform "0") | ||||
|    (latest :initarg :latest) | ||||
|    (oldest :initarg :oldest) | ||||
|    (unread-count :initarg :unread_count) | ||||
|    (unread-count-display :initarg :unread_count_display :initform 0 :type integer) | ||||
|    (messages :initarg :messages :initform ()) | ||||
|    (team-id :initarg :team-id))) | ||||
|  | ||||
| (defgeneric slack-room-name (room)) | ||||
| (defgeneric slack-room-history (room team &optional oldest after-success sync)) | ||||
| (defgeneric slack-room-update-mark-url (room)) | ||||
|  | ||||
| (defun slack-room-create (payload team class) | ||||
|   (cl-labels | ||||
|       ((prepare (p) | ||||
|                 (plist-put p :members | ||||
|                            (append (plist-get p :members) nil)) | ||||
|                 (plist-put p :latest | ||||
|                            (slack-message-create (plist-get p :latest))) | ||||
|                 (plist-put p :team-id (oref team id)) | ||||
|                 p)) | ||||
|     (let ((attributes (slack-collect-slots class (prepare payload)))) | ||||
|       (apply #'make-instance class attributes)))) | ||||
|  | ||||
| (defmethod slack-room-subscribedp ((_room slack-room) _team) | ||||
|   nil) | ||||
|  | ||||
| (defmethod slack-room-buffer-name ((room slack-room)) | ||||
|   (concat "*Slack*" | ||||
|           " : " | ||||
|           (slack-room-name-with-team-name room))) | ||||
|  | ||||
| (cl-defmacro slack-room-request-update (room team url latest after-success sync) | ||||
|   `(cl-labels | ||||
|        ((on-request-update | ||||
|          (&key data &allow-other-keys) | ||||
|          (slack-request-handle-error | ||||
|           (data "slack-room-request-update") | ||||
|           (let* ((datum (plist-get data :messages)) | ||||
|                  (messages | ||||
|                   (cl-loop for data across datum | ||||
|                            collect (slack-message-create data :room ,room)))) | ||||
|             (if ,latest | ||||
|                 (slack-room-set-prev-messages ,room messages) | ||||
|               (slack-room-set-messages ,room messages) | ||||
|               (slack-room-update-last-read | ||||
|                room | ||||
|                (make-instance 'slack-message :ts "0"))) | ||||
|             (if (and ,after-success | ||||
|                      (functionp ,after-success)) | ||||
|                 (funcall ,after-success)))))) | ||||
|      (slack-request | ||||
|       ,url | ||||
|       ,team | ||||
|       :params (list (cons "channel" (oref ,room id)) | ||||
|                     (if ,latest | ||||
|                         (cons "latest" ,latest))) | ||||
|       :success #'on-request-update | ||||
|       :sync (if ,sync t nil)))) | ||||
|  | ||||
| (cl-defun slack-room-make-buffer-with-room (room team &key update) | ||||
|   (with-slots (messages latest) room | ||||
|     (if (or update (< (length messages) 1)) | ||||
|         (slack-room-history room team)) | ||||
|     (funcall slack-buffer-function | ||||
|              (slack-buffer-create room team)))) | ||||
|  | ||||
| (cl-defmacro slack-select-from-list ((alist prompt) &body body) | ||||
|   "Bind candidates from selected." | ||||
|   (let ((key (cl-gensym))) | ||||
|     `(let* ((,key (let ((completion-ignore-case t)) | ||||
|                     (completing-read (format "%s" ,prompt) | ||||
|                                      ,alist nil t))) | ||||
|             (selected (cdr (cl-assoc ,key ,alist :test #'string=)))) | ||||
|        ,@body | ||||
|        selected))) | ||||
|  | ||||
| (defun slack-room-select (rooms) | ||||
|   (let* ((alist (slack-room-names | ||||
|                  rooms | ||||
|                  #'(lambda (rs) | ||||
|                      (cl-remove-if #'(lambda (r) | ||||
|                                        (or (not (slack-room-member-p r)) | ||||
|                                            (slack-room-archived-p r) | ||||
|                                            (not (slack-room-open-p r)))) | ||||
|                                    rs))))) | ||||
|     (slack-select-from-list | ||||
|      (alist "Select Channel: ") | ||||
|      (slack-room-make-buffer-with-room | ||||
|       selected | ||||
|       (slack-team-find (oref selected team-id)) | ||||
|       :update nil)))) | ||||
|  | ||||
| (cl-defun slack-room-list-update (url success team &key (sync t)) | ||||
|   (slack-request | ||||
|    url | ||||
|    team | ||||
|    :success success | ||||
|    :sync sync)) | ||||
|  | ||||
| (defun slack-room-update-messages () | ||||
|   (interactive) | ||||
|   (unless (and (boundp 'slack-current-room-id) | ||||
|                (boundp 'slack-current-team-id)) | ||||
|     (error "Call From Slack Room Buffer")) | ||||
|   (let* ((team (slack-team-find slack-current-team-id)) | ||||
|          (room (slack-room-find slack-current-room-id team)) | ||||
|          (cur-point (point))) | ||||
|     (slack-room-history room team) | ||||
|     (slack-buffer-create | ||||
|      room team :insert-func | ||||
|      #'(lambda (room team) | ||||
|          (slack-buffer-widen | ||||
|           (let ((inhibit-read-only t)) | ||||
|             (delete-region (point-min) (marker-position lui-output-marker)))) | ||||
|          (slack-buffer-insert-previous-link room) | ||||
|          (slack-buffer-insert-messages room team) | ||||
|          (goto-char cur-point))))) | ||||
|  | ||||
| (defmethod slack-room-render-prev-messages ((room slack-room) team | ||||
|                                             oldest ts) | ||||
|   (slack-buffer-create | ||||
|    room team | ||||
|    :insert-func | ||||
|    #'(lambda (room team) | ||||
|        (slack-buffer-widen | ||||
|         (let ((inhibit-read-only t) | ||||
|               (loading-message-end | ||||
|                (slack-buffer-ts-eq (point-min) (point-max) oldest))) | ||||
|           (delete-region (point-min) loading-message-end) | ||||
|           (slack-buffer-insert-prev-messages room team oldest))) | ||||
|        (slack-buffer-goto ts)))) | ||||
|  | ||||
| (defmethod slack-room-prev-link-info ((room slack-room)) | ||||
|   (with-slots (oldest) room | ||||
|     (if oldest | ||||
|         (oref oldest ts)))) | ||||
|  | ||||
| (defun slack-room-load-prev-messages () | ||||
|   (interactive) | ||||
|   (let* ((cur-point (point)) | ||||
|          (ts (get-text-property (next-single-property-change cur-point 'ts) | ||||
|                                 'ts)) | ||||
|          (oldest (ignore-errors (get-text-property 0 'oldest | ||||
|                                                    (thing-at-point 'line)))) | ||||
|          (current-team (slack-team-find slack-current-team-id)) | ||||
|          (current-room (slack-room-find slack-current-room-id | ||||
|                                         current-team))) | ||||
|     (slack-room-history current-room | ||||
|                         current-team | ||||
|                         oldest | ||||
|                         #'(lambda () | ||||
|                             (slack-room-render-prev-messages current-room | ||||
|                                                              current-team | ||||
|                                                              oldest ts))))) | ||||
|  | ||||
| (defun slack-room-find-message (room ts) | ||||
|   (cl-find-if #'(lambda (m) (string= ts (oref m ts))) | ||||
|               (oref room messages) | ||||
|               :from-end t)) | ||||
|  | ||||
| (defmethod slack-room-name-with-team-name ((room slack-room)) | ||||
|   (with-slots (team-id name) room | ||||
|     (let ((team (slack-team-find team-id))) | ||||
|       (format "%s - %s" (oref team name) name)))) | ||||
|  | ||||
| (defmacro slack-room-names (rooms &optional filter) | ||||
|   `(cl-labels | ||||
|        ((latest-ts (room) | ||||
|                    (with-slots (latest) room | ||||
|                      (if latest (oref latest ts) "0"))) | ||||
|         (unread-count (room) | ||||
|                       (with-slots (unread-count-display) room | ||||
|                         (if (< 0 unread-count-display) | ||||
|                             (concat "(" | ||||
|                                     (number-to-string unread-count-display) | ||||
|                                     ")") | ||||
|                           ""))) | ||||
|         (sort-rooms (rooms) | ||||
|                     (nreverse | ||||
|                      (cl-sort rooms #'string< | ||||
|                               :key #'(lambda (name-with-room) (latest-ts (cdr name-with-room)))))) | ||||
|         (build-label (room) | ||||
|                      (concat (im-presence room) | ||||
|                              (format "%s %s" | ||||
|                                      (slack-room-name-with-team-name room) | ||||
|                                      (unread-count room)))) | ||||
|         (im-presence (room) | ||||
|                      (if (object-of-class-p room 'slack-im) | ||||
|                          (slack-im-user-presence room) | ||||
|                        "  ")) | ||||
|         (build-cons (room) | ||||
|                     (cons (build-label room) room))) | ||||
|      (sort-rooms | ||||
|       (cl-loop for room in (if ,filter | ||||
|                                (funcall ,filter ,rooms) | ||||
|                              ,rooms) | ||||
|                collect (cons (build-label room) room))))) | ||||
|  | ||||
| (defmethod slack-room-name ((room slack-room)) | ||||
|   (oref room name)) | ||||
|  | ||||
| (defmethod slack-room-update-last-read ((room slack-room) msg) | ||||
|   (with-slots (ts) msg | ||||
|     (oset room last-read ts))) | ||||
|  | ||||
| (defmethod slack-room-latest-messages ((room slack-room) messages) | ||||
|   (with-slots (last-read) room | ||||
|     (cl-remove-if #'(lambda (m) | ||||
|                       (or (string< (oref m ts) last-read) | ||||
|                           (string= (oref m ts) last-read))) | ||||
|                   messages))) | ||||
|  | ||||
| (defun slack-room-sort-messages (messages) | ||||
|   (cl-sort messages | ||||
|            #'string< | ||||
|            :key #'(lambda (m) (oref m ts)))) | ||||
|  | ||||
| (defmethod slack-room-sorted-messages ((room slack-room)) | ||||
|   (with-slots (messages) room | ||||
|     (slack-room-sort-messages (copy-sequence messages)))) | ||||
|  | ||||
| (defmethod slack-room-set-prev-messages ((room slack-room) prev-messages) | ||||
|   (slack-room-set-messages | ||||
|    room | ||||
|    (cl-delete-duplicates (append (oref room messages) | ||||
|                                  prev-messages) | ||||
|                          :test #'slack-message-equal))) | ||||
|  | ||||
| (defmethod slack-room-set-messages ((room slack-room) m) | ||||
|   (let ((sorted (slack-room-sort-messages m))) | ||||
|     (oset room oldest (car sorted)) | ||||
|     (oset room messages sorted) | ||||
|     (oset room latest (car (last sorted))))) | ||||
|  | ||||
| (defmethod slack-room-prev-messages ((room slack-room) from) | ||||
|   (with-slots (messages) room | ||||
|     (cl-remove-if #'(lambda (m) | ||||
|                       (or (string< from (oref m ts)) | ||||
|                           (string= from (oref m ts)))) | ||||
|                   (slack-room-sort-messages (copy-sequence messages))))) | ||||
|  | ||||
| (defmethod slack-room-update-mark ((room slack-room) team msg) | ||||
|   (cl-labels ((on-update-mark (&key data &allow-other-keys) | ||||
|                               (slack-request-handle-error | ||||
|                                (data "slack-room-update-mark")))) | ||||
|     (with-slots (ts) msg | ||||
|       (with-slots (id) room | ||||
|         (slack-request | ||||
|          (slack-room-update-mark-url room) | ||||
|          team | ||||
|          :type "POST" | ||||
|          :params (list (cons "channel"  id) | ||||
|                        (cons "ts"  ts)) | ||||
|          :success #'on-update-mark | ||||
|          :sync nil))))) | ||||
|  | ||||
| (defun slack-room-pins-list () | ||||
|   (interactive) | ||||
|   (unless (and (bound-and-true-p slack-current-room-id) | ||||
|                (bound-and-true-p slack-current-team-id)) | ||||
|     (error "Call from slack room buffer")) | ||||
|   (let* ((team (slack-team-find slack-current-team-id)) | ||||
|          (room (slack-room-find slack-current-room-id | ||||
|                                 team)) | ||||
|          (channel (oref room id))) | ||||
|     (cl-labels ((on-pins-list (&key data &allow-other-keys) | ||||
|                               (slack-request-handle-error | ||||
|                                (data "slack-room-pins-list") | ||||
|                                (slack-room-on-pins-list | ||||
|                                 (plist-get data :items) | ||||
|                                 room team)))) | ||||
|       (slack-request | ||||
|        slack-room-pins-list-url | ||||
|        team | ||||
|        :params (list (cons "channel" channel)) | ||||
|        :success #'on-pins-list | ||||
|        :sync nil)))) | ||||
|  | ||||
| (defun slack-room-on-pins-list (items room team) | ||||
|   (cl-labels ((buffer-name (room) | ||||
|                            (concat "*Slack - Pinned Items*" | ||||
|                                    " : " | ||||
|                                    (slack-room-name-with-team-name room)))) | ||||
|     (let* ((messages (mapcar #'slack-message-create | ||||
|                              (mapcar #'(lambda (i) | ||||
|                                          (plist-get i :message)) | ||||
|                                      items))) | ||||
|            (buf-header (propertize "Pinned Items" | ||||
|                                    'face '(:underline | ||||
|                                            t | ||||
|                                            :weight bold)))) | ||||
|       (funcall slack-buffer-function | ||||
|                (slack-buffer-create-info | ||||
|                 (buffer-name room) | ||||
|                 #'(lambda () | ||||
|                     (insert buf-header) | ||||
|                     (insert "\n\n") | ||||
|                     (mapc #'(lambda (m) (insert | ||||
|                                          (slack-message-to-string m))) | ||||
|                           messages))) | ||||
|                team)))) | ||||
|  | ||||
| (defun slack-select-rooms () | ||||
|   (interactive) | ||||
|   (let ((team (slack-team-select))) | ||||
|     (slack-room-select | ||||
|      (cl-loop for team in (list team) | ||||
|               append (with-slots (groups ims channels) team | ||||
|                        (append ims groups channels)))))) | ||||
|  | ||||
| (defun slack-create-room (url team success) | ||||
|   (slack-request | ||||
|    url | ||||
|    team | ||||
|    :type "POST" | ||||
|    :params (list (cons "name" (read-from-minibuffer "Name: "))) | ||||
|    :success success | ||||
|    :sync nil)) | ||||
|  | ||||
| (defun slack-room-rename (url room-alist-func) | ||||
|   (cl-labels | ||||
|       ((on-rename-success (&key data &allow-other-keys) | ||||
|                           (slack-request-handle-error | ||||
|                            (data "slack-room-rename")))) | ||||
|     (let* ((team (slack-team-select)) | ||||
|            (room-alist (funcall room-alist-func team)) | ||||
|            (room (slack-select-from-list | ||||
|                   (room-alist "Select Channel: "))) | ||||
|            (name (read-from-minibuffer "New Name: "))) | ||||
|       (slack-request | ||||
|        url | ||||
|        team | ||||
|        :params (list (cons "channel" (oref room id)) | ||||
|                      (cons "name" name)) | ||||
|        :success #'on-rename-success | ||||
|        :sync nil)))) | ||||
|  | ||||
| (defmacro slack-current-room-or-select (room-alist-func) | ||||
|   `(if (and (boundp 'slack-current-room-id) | ||||
|             (boundp 'slack-current-team-id)) | ||||
|        (slack-room-find slack-current-room-id | ||||
|                         (slack-team-find slack-current-team-id)) | ||||
|      (let* ((room-alist (funcall ,room-alist-func))) | ||||
|        (slack-select-from-list | ||||
|         (room-alist "Select Channel: "))))) | ||||
|  | ||||
| (defmacro slack-room-invite (url room-alist-func) | ||||
|   `(cl-labels | ||||
|        ((on-group-invite (&key data &allow-other-keys) | ||||
|                          (slack-request-handle-error | ||||
|                           (data "slack-room-invite") | ||||
|                           (if (plist-get data :already_in_group) | ||||
|                               (message "User already in group") | ||||
|                             (message "Invited!"))))) | ||||
|      (let* ((team (slack-team-select)) | ||||
|             (room (slack-current-room-or-select | ||||
|                    #'(lambda () | ||||
|                        (funcall ,room-alist-func team | ||||
|                                 #'(lambda (rooms) | ||||
|                                     (cl-remove-if #'slack-room-archived-p | ||||
|                                                   rooms)))))) | ||||
|             (user-id (plist-get (slack-select-from-list | ||||
|                                  ((slack-user-names team) | ||||
|                                   "Select User: ")) :id))) | ||||
|        (slack-request | ||||
|         ,url | ||||
|         team | ||||
|         :params (list (cons "channel" (oref room id)) | ||||
|                       (cons "user" user-id)) | ||||
|         :success #'on-group-invite | ||||
|         :sync nil)))) | ||||
|  | ||||
| (defmethod slack-room-member-p ((_room slack-room)) | ||||
|   t) | ||||
|  | ||||
| (defmethod slack-room-archived-p ((_room slack-room)) | ||||
|   nil) | ||||
|  | ||||
| (defmethod slack-room-open-p ((_room slack-room)) | ||||
|   t) | ||||
|  | ||||
| (defmethod slack-room-equal-p ((room slack-room) other) | ||||
|   (with-slots (id) room | ||||
|     (with-slots ((other-id id)) other | ||||
|       (string= id other-id)))) | ||||
|  | ||||
| (defun slack-room-deleted (id team) | ||||
|   (let ((room (slack-room-find id team))) | ||||
|     (cond | ||||
|      ((object-of-class-p room 'slack-channel) | ||||
|       (with-slots (channels) team | ||||
|         (setq channels (cl-delete-if #'(lambda (c) (slack-room-equal-p room c)) | ||||
|                                      channels))) | ||||
|       (message "Channel: %s deleted" | ||||
|                (slack-room-name-with-team-name room)))))) | ||||
|  | ||||
| (cl-defun slack-room-request-with-id (url id team success) | ||||
|   (slack-request | ||||
|    url | ||||
|    team | ||||
|    :params (list (cons "channel" id)) | ||||
|    :success success | ||||
|    :sync nil)) | ||||
|  | ||||
| (defmethod slack-room-history ((room slack-room) team | ||||
|                                &optional | ||||
|                                oldest | ||||
|                                after-success | ||||
|                                async) | ||||
|   (slack-room-request-update room | ||||
|                              team | ||||
|                              (slack-room-history-url room) | ||||
|                              oldest | ||||
|                              after-success | ||||
|                              (if async nil t))) | ||||
|  | ||||
| (defmethod slack-room-inc-unread-count ((room slack-room)) | ||||
|   (cl-incf (oref room unread-count-display))) | ||||
|  | ||||
| (defun slack-room-find-by-name (name team) | ||||
|   (cl-labels | ||||
|       ((find-by-name (rooms name) | ||||
|                      (cl-find-if #'(lambda (e) (string= name | ||||
|                                                         (slack-room-name e))) | ||||
|                                  rooms))) | ||||
|     (or (find-by-name (oref team groups) name) | ||||
|         (find-by-name (oref team channels) name) | ||||
|         (find-by-name (oref team ims) name)))) | ||||
|  | ||||
| (provide 'slack-room) | ||||
| ;;; slack-room.el ends here | ||||
							
								
								
									
										459
									
								
								elpa/slack-20160928.2036/slack-search.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										459
									
								
								elpa/slack-20160928.2036/slack-search.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,459 @@ | ||||
| ;;; slack-search.el ---                              -*- lexical-binding: t; -*- | ||||
|  | ||||
| ;; Copyright (C) 2016  南優也 | ||||
|  | ||||
| ;; Author: 南優也 <yuyaminami@minamiyuunari-no-MacBook-Pro.local> | ||||
| ;; Keywords: | ||||
|  | ||||
| ;; This program is free software; you can redistribute it and/or modify | ||||
| ;; it under the terms of the GNU General Public License as published by | ||||
| ;; the Free Software Foundation, either version 3 of the License, or | ||||
| ;; (at your option) any later version. | ||||
|  | ||||
| ;; This program is distributed in the hope that it will be useful, | ||||
| ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| ;; GNU General Public License for more details. | ||||
|  | ||||
| ;; You should have received a copy of the GNU General Public License | ||||
| ;; along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  | ||||
| ;;; Commentary: | ||||
|  | ||||
| ;; | ||||
|  | ||||
| ;;; Code: | ||||
|  | ||||
| (require 'eieio) | ||||
| (require 'slack-room) | ||||
|  | ||||
| (defclass slack-search-result (slack-room) | ||||
|   ((type :initarg :type :type symbol) | ||||
|    (query :initarg :query :type string) | ||||
|    (per-page :initarg :per-page :type integer) | ||||
|    (total-page :initarg :total-page :type integer) | ||||
|    (current-page :initarg :current-page :type integer) | ||||
|    (total-messages :initarg :total-messages :type integer) | ||||
|    (sort :initarg :sort :type string) | ||||
|    (sort-dir :initarg :sort-dir :type string) | ||||
|    (last-channel-id :initarg :last-channel-id :type string :initform ""))) | ||||
|  | ||||
| (defclass slack-file-search-result (slack-search-result) ()) | ||||
|  | ||||
| (defclass slack-search-message () | ||||
|   ((user-id :initarg :user-id :type string) | ||||
|    (username :initarg :username :type string) | ||||
|    (ts :initarg :ts :type string) | ||||
|    (text :initarg :text :type string) | ||||
|    (previous-2 :initarg :previous-2) | ||||
|    (previous :initarg :previous) | ||||
|    (next :initarg :next) | ||||
|    (next-2 :initarg :next-2) | ||||
|    (info :initarg :info))) | ||||
|  | ||||
| (defclass slack-search-message-info () | ||||
|   ((channel-id :initarg :channel-id :type string) | ||||
|    (channel-name :initarg :channel-name :type string) | ||||
|    (permalink :initarg :permalink :type string :initform "") | ||||
|    (result-id :initarg :result-id :type string))) | ||||
|  | ||||
| (defun slack-search-result-id (type query sort sort-dir) | ||||
|   (format "Q%s%s%s%s" type query sort sort-dir)) | ||||
|  | ||||
| (defun slack-search-create-message-info (payload) | ||||
|   (let ((channel (plist-get payload :channel))) | ||||
|     (make-instance 'slack-search-message-info | ||||
|                    :channel-id (plist-get channel :id) | ||||
|                    :channel-name (plist-get channel :name) | ||||
|                    :permalink (plist-get payload :permalink)))) | ||||
|  | ||||
| (defmethod slack-search-create-message ((room slack-search-result) payload) | ||||
|   (cl-labels ((create-message | ||||
|                (params info) | ||||
|                (let ((previous-2 (if (plist-get params :previous_2) | ||||
|                                      (create-message (plist-get params :previous_2) | ||||
|                                                      info))) | ||||
|                      (previous (if (plist-get params :previous) | ||||
|                                    (create-message (plist-get params :previous) | ||||
|                                                    info))) | ||||
|                      (next (if (plist-get params :next) | ||||
|                                (create-message (plist-get params :next) | ||||
|                                                info))) | ||||
|                      (next-2 (if (plist-get params :next_2) | ||||
|                                  (create-message (plist-get params :next_2) | ||||
|                                                  info)))) | ||||
|                  (make-instance 'slack-search-message | ||||
|                                 :info info | ||||
|                                 :user-id (plist-get params :user) | ||||
|                                 :username (plist-get params :username) | ||||
|                                 :text (plist-get params :text) | ||||
|                                 :ts (plist-get params :ts) | ||||
|                                 :previous-2 previous-2 | ||||
|                                 :previous previous | ||||
|                                 :next next | ||||
|                                 :next-2 next-2))) | ||||
|               (create-info | ||||
|                (params result) | ||||
|                (let ((channel (plist-get params :channel))) | ||||
|                  (make-instance 'slack-search-message-info | ||||
|                                 :result-id (oref result id) | ||||
|                                 :channel-id (plist-get channel :id) | ||||
|                                 :channel-name (plist-get channel :name) | ||||
|                                 :permalink (plist-get params :permalink))))) | ||||
|     (let ((info (create-info payload room))) | ||||
|       (create-message payload info)))) | ||||
|  | ||||
| (defmethod slack-search-create-message ((_room slack-file-search-result) payload) | ||||
|   (slack-file-create payload)) | ||||
|  | ||||
| (defun slack-create-search-result (plist team type) | ||||
|   (let* ((result (cl-case type | ||||
|                    ('message (apply #'make-instance 'slack-search-result | ||||
|                                     (slack-collect-slots 'slack-search-result | ||||
|                                                          plist))) | ||||
|                    ('file (apply #'make-instance 'slack-file-search-result | ||||
|                                  (slack-collect-slots 'slack-file-search-result | ||||
|                                                       plist))))) | ||||
|          (result-messages (cl-loop | ||||
|                            for message in (plist-get plist :messages) | ||||
|                            collect (slack-search-create-message result message)))) | ||||
|     (slack-room-set-messages result result-messages) | ||||
|     (with-slots (search-results) team | ||||
|       (setq search-results | ||||
|             (cl-remove-if #'(lambda (other) | ||||
|                               (slack-room-equal-p result other)) | ||||
|                           search-results)) | ||||
|       (push result search-results)) | ||||
|     result)) | ||||
|  | ||||
| (defun slack-search-create-result-params (data team type sort sort-dir) | ||||
|   (let* ((messages (cl-case type | ||||
|                      ('message (plist-get data :messages)) | ||||
|                      ('file (plist-get data :files)))) | ||||
|          (paging (plist-get messages :paging)) | ||||
|          (query (plist-get data :query)) | ||||
|          (plist (list :type type | ||||
|                       :team-id (oref team id) | ||||
|                       :id (slack-search-result-id | ||||
|                            type query sort sort-dir) | ||||
|                       :sort sort | ||||
|                       :sort-dir sort-dir | ||||
|                       :query query | ||||
|                       :per-page (plist-get paging :count) | ||||
|                       :total-page (plist-get paging :pages) | ||||
|                       :current-page (plist-get paging :page) | ||||
|                       :total-messages (plist-get paging :total) | ||||
|                       :messages | ||||
|                       (append (plist-get messages :matches) | ||||
|                               nil)))) | ||||
|  | ||||
|     plist)) | ||||
|  | ||||
| (defun slack-search-query-params () | ||||
|   (let ((team (slack-team-select)) | ||||
|         (query (read-from-minibuffer "Query: ")) | ||||
|         (sort (completing-read "Sort: " `("score" "timestamp") | ||||
|                                nil t)) | ||||
|         (sort-dir (completing-read "Direction: " `("desc" "asc") | ||||
|                                    nil t))) | ||||
|     (list team query sort sort-dir))) | ||||
|  | ||||
| (defun slack-search-pushnew (search-result team) | ||||
|   (cl-pushnew search-result (oref team search-results) | ||||
|               :test #'slack-room-equal-p)) | ||||
|  | ||||
| (defun slack-search-from-messages () | ||||
|   (interactive) | ||||
|   (cl-destructuring-bind (team query sort sort-dir) (slack-search-query-params) | ||||
|     (let ((type 'message)) | ||||
|       (cl-labels | ||||
|           ((on-search | ||||
|             (&key data &allow-other-keys) | ||||
|             (slack-request-handle-error | ||||
|              (data "slack-search-from-messages") | ||||
|              (let* ((params (slack-search-create-result-params | ||||
|                              data team type sort sort-dir)) | ||||
|                     (search-result (slack-create-search-result params team 'message))) | ||||
|                (slack-search-pushnew search-result team) | ||||
|                (funcall slack-buffer-function | ||||
|                         (slack-buffer-create search-result | ||||
|                                              team :type 'info)))))) | ||||
|         (let ((same-search (slack-room-find (slack-search-result-id | ||||
|                                              type query sort sort-dir) | ||||
|                                             team))) | ||||
|           (if same-search | ||||
|               (progn | ||||
|                 (message "Same Query Already Exist") | ||||
|                 (funcall slack-buffer-function | ||||
|                          (slack-buffer-create same-search | ||||
|                                               team | ||||
|                                               :type 'info))) | ||||
|             (slack-search-request-message team | ||||
|                                           query | ||||
|                                           sort | ||||
|                                           sort-dir | ||||
|                                           #'on-search))))) | ||||
|     )) | ||||
|  | ||||
| (defun slack-search-from-files () | ||||
|   (interactive) | ||||
|   (cl-destructuring-bind (team query sort sort-dir) (slack-search-query-params) | ||||
|     (let ((type 'file)) | ||||
|       (cl-labels | ||||
|           ((on-search | ||||
|             (&key data &allow-other-keys) | ||||
|             (slack-request-handle-error | ||||
|              (data "slack-search-from-files") | ||||
|              (let* ((params (slack-search-create-result-params | ||||
|                              data team type sort sort-dir)) | ||||
|                     (search-result (slack-create-search-result params team 'file))) | ||||
|                (slack-search-pushnew search-result team) | ||||
|                (funcall slack-buffer-function | ||||
|                         (slack-buffer-create search-result | ||||
|                                              team :type 'info)))))) | ||||
|         (let ((same-search (slack-room-find (slack-search-result-id type query | ||||
|                                                                     sort sort-dir) | ||||
|                                             team))) | ||||
|           (if same-search | ||||
|               (progn | ||||
|                 (message "Same Query Already Exist") | ||||
|                 (funcall slack-buffer-function | ||||
|                          (slack-buffer-create same-search | ||||
|                                               team | ||||
|                                               :type 'info))) | ||||
|             (slack-search-request-file team | ||||
|                                        query | ||||
|                                        sort | ||||
|                                        sort-dir | ||||
|                                        #'on-search))))))) | ||||
|  | ||||
| (cl-defun slack-search-request-message (team query sort sort-dir success | ||||
|                                              &optional | ||||
|                                              (page 1) | ||||
|                                              (async t)) | ||||
|   (slack-search-request team query sort sort-dir success page async | ||||
|                         "https://slack.com/api/search.messages")) | ||||
|  | ||||
| (cl-defun slack-search-request-file (team query sort sort-dir success | ||||
|                                           &optional | ||||
|                                           (page 1) | ||||
|                                           (async t)) | ||||
|   (slack-search-request team query sort sort-dir success page async | ||||
|                         "https://slack.com/api/search.files")) | ||||
|  | ||||
| (defun slack-search-request (team query sort sort-dir success page async url) | ||||
|   (if (< 0 (length query)) | ||||
|       (slack-request | ||||
|        url | ||||
|        team | ||||
|        :type "POST" | ||||
|        :params (list (cons "query" query) | ||||
|                      (cons "sort" sort) | ||||
|                      (cons "sort_dir" sort-dir) | ||||
|                      (cons "page" (number-to-string page))) | ||||
|        :success success | ||||
|        :sync (not async)))) | ||||
|  | ||||
| (defun slack-search-alist (team) | ||||
|   (with-slots (search-results) team | ||||
|     (cl-loop for s in search-results | ||||
|              collect (cons (slack-room-buffer-name s) s)))) | ||||
|  | ||||
| (defun slack-search-select () | ||||
|   (interactive) | ||||
|   (let* ((team (slack-team-select)) | ||||
|          (alist (slack-search-alist team))) | ||||
|     (slack-select-from-list | ||||
|      (alist "Select Search: ") | ||||
|      (funcall slack-buffer-function | ||||
|               (slack-buffer-create selected | ||||
|                                    team | ||||
|                                    :type 'info))))) | ||||
|  | ||||
| ;; protocols | ||||
| (defmethod slack-room-update-mark ((_room slack-search-result) _team _msg)) | ||||
| (defmethod slack-room-sorted-messages ((room slack-search-result)) | ||||
|   (copy-sequence (oref room messages))) | ||||
|  | ||||
| (defmethod slack-room-update-last-read ((room slack-search-result) msg) | ||||
|   (if (not (slot-exists-p msg 'info)) | ||||
|       (progn | ||||
|         (oset room last-read (oref msg ts)) | ||||
|         (oset room last-channel-id "")) | ||||
|     (with-slots (ts info) msg | ||||
|       (with-slots (channel-id) info | ||||
|         (oset room last-read ts) | ||||
|         (oset room last-channel-id channel-id))))) | ||||
|  | ||||
| (defmethod slack-search-get-index ((_search-result slack-file-search-result) | ||||
|                                    messages last-read &optional _last-chanel-id) | ||||
|   (cl-loop for i from 0 upto (1- (length messages)) | ||||
|            for m = (nth i messages) | ||||
|            if (string= (oref m ts) last-read) | ||||
|            return i)) | ||||
|  | ||||
| (defmethod slack-search-get-index ((_search-result slack-search-result) | ||||
|                                    messages last-read &optional last-channel-id) | ||||
|   (cl-loop for i from 0 upto (1- (length messages)) | ||||
|            for m = (nth i messages) | ||||
|            if (and (string= (oref m ts) last-read) | ||||
|                    (string= (oref (oref m info) channel-id) | ||||
|                             last-channel-id)) | ||||
|            return i)) | ||||
|  | ||||
| (defmethod slack-room-latest-messages ((room slack-search-result) messages) | ||||
|   (with-slots (type last-read last-channel-id) room | ||||
|     (let* ((r-messages (reverse messages)) | ||||
|            (nth (slack-search-get-index room r-messages | ||||
|                                         last-read last-channel-id))) | ||||
|       (if nth | ||||
|           (nreverse | ||||
|            (nthcdr (1+ nth) r-messages)) | ||||
|         (copy-sequence messages))))) | ||||
|  | ||||
| (defmethod slack-room-prev-messages ((room slack-file-search-result) oldest) | ||||
|   (let* ((messages (reverse (oref room messages))) | ||||
|          (nth (slack-search-get-index room messages oldest))) | ||||
|     (if nth | ||||
|         (nreverse (nthcdr (1+ nth) messages))))) | ||||
|  | ||||
| (defmethod slack-room-prev-messages ((room slack-search-result) param) | ||||
|   (let* ((oldest (car param)) | ||||
|          (channel-id (cdr param)) | ||||
|          (messages (reverse (oref room messages))) | ||||
|          (nth (slack-search-get-index room messages | ||||
|                                       oldest channel-id))) | ||||
|     (if nth | ||||
|         (nreverse (nthcdr (1+ nth) messages))))) | ||||
|  | ||||
| (defmethod slack-room-render-prev-messages ((room slack-search-result) | ||||
|                                             team oldest ts) | ||||
|   (slack-buffer-create | ||||
|    room team | ||||
|    :insert-func | ||||
|    #'(lambda (room team) | ||||
|        (slack-buffer-widen | ||||
|         (let* ((inhibit-read-only t) | ||||
|                (oldest-ts (if (listp oldest) (car oldest) oldest)) | ||||
|                (loading-message-end (slack-buffer-ts-eq (point-min) | ||||
|                                                         (point-max) | ||||
|                                                         oldest-ts))) | ||||
|           (delete-region (point-min) loading-message-end) | ||||
|           (slack-buffer-insert-prev-messages room team oldest))) | ||||
|        (slack-buffer-goto ts)) | ||||
|    :type 'info)) | ||||
|  | ||||
| (defmethod slack-buffer-insert-prev-messages ((room slack-search-result) team oldest) | ||||
|   (slack-buffer-widen | ||||
|    (let ((messages (slack-room-prev-messages room oldest))) | ||||
|      (if messages | ||||
|          (progn | ||||
|            (slack-buffer-insert-previous-link room) | ||||
|            (cl-loop for m in messages | ||||
|                     do (slack-buffer-insert m team t))) | ||||
|        (set-marker lui-output-marker (point-min)) | ||||
|        (lui-insert "(no more messages)\n")) | ||||
|      (slack-buffer-recover-lui-output-marker)))) | ||||
|  | ||||
| (defmethod slack-room-prev-link-info ((room slack-file-search-result)) | ||||
|   (with-slots (oldest) room | ||||
|     (oref oldest ts))) | ||||
|  | ||||
| (defmethod slack-room-prev-link-info ((room slack-search-result)) | ||||
|   (with-slots (oldest) room | ||||
|     (with-slots (info ts) oldest | ||||
|       (cons ts (oref info channel-id))))) | ||||
|  | ||||
| (defmethod slack-message-equal ((m slack-search-message) n) | ||||
|   (with-slots ((m-info info) (m-ts ts)) m | ||||
|     (with-slots ((m-channel-id channel-id)) m-info | ||||
|       (with-slots ((n-info info) (n-ts ts)) n | ||||
|         (with-slots ((n-channel-id channel-id)) n-info | ||||
|           (and (string= m-channel-id n-channel-id) | ||||
|                (string= m-ts n-ts))))))) | ||||
|  | ||||
| (defmethod slack-room-buffer-name ((room slack-search-result)) | ||||
|   (with-slots (query sort sort-dir team-id type) room | ||||
|     (let ((team (slack-team-find team-id))) | ||||
|       (format "%s - %s Query: %s Sort: %s Order: %s" | ||||
|               (oref team name) | ||||
|               (eieio-object-class room) | ||||
|               query sort sort-dir)))) | ||||
|  | ||||
| (defmethod slack-message-to-string ((message slack-search-message) team) | ||||
|   (with-slots (info text username) message | ||||
|     (with-slots (channel-id permalink) info | ||||
|       (let* ((header (format "%s" username)) | ||||
|              (channel (slack-room-find channel-id team)) | ||||
|              (body (slack-message-unescape-string | ||||
|                     (format "%s\n\n------------\nChanel: %s\nPermalink: %s" | ||||
|                             text | ||||
|                             (slack-room-name channel) | ||||
|                             permalink) | ||||
|                     team))) | ||||
|         (slack-message-put-header-property header) | ||||
|         (slack-message-put-text-property body) | ||||
|         (format "%s\n%s\n" header body))))) | ||||
|  | ||||
| (defmethod slack-room-set-prev-messages ((room slack-search-result) prev) | ||||
|   (slack-room-set-messages room (nreverse | ||||
|                                  (nconc (nreverse prev) (oref room messages))))) | ||||
|  | ||||
| (defmethod slack-room-set-messages ((room slack-search-result) messages) | ||||
|   (let ((msgs (nreverse messages))) | ||||
|     (oset room messages msgs) | ||||
|     (oset room latest (car (last msgs))) | ||||
|     (oset room oldest (car msgs)))) | ||||
|  | ||||
| (defmethod slack-room-history ((room slack-search-result) team | ||||
|                                &optional | ||||
|                                oldest after-success async) | ||||
|   (cl-labels | ||||
|       ((on-history | ||||
|         (&key data &allow-other-keys) | ||||
|         (slack-request-handle-error | ||||
|          (data "slack-room-history") | ||||
|          (let* ((matches (cl-case (eieio-object-class room) | ||||
|                            ('slack-search-result (plist-get data :messages)) | ||||
|                            ('slack-file-search-result (plist-get data :files)))) | ||||
|                 (messages (cl-loop | ||||
|                            for match across (plist-get matches :matches) | ||||
|                            collect (slack-search-create-message room match)))) | ||||
|            (oset room current-page | ||||
|                  (plist-get (plist-get matches :paging) :page)) | ||||
|            (if oldest | ||||
|                (slack-room-set-prev-messages room messages) | ||||
|              (let ((init-msg (make-instance 'slack-search-message | ||||
|                                             :ts "0" :info | ||||
|                                             (make-instance 'slack-search-message-info | ||||
|                                                            :channel-id "")))) | ||||
|                (slack-room-update-last-read room init-msg)) | ||||
|              (slack-room-set-messages room messages)) | ||||
|            (if after-success | ||||
|                (funcall after-success)))))) | ||||
|     (let* ((current-page (oref room current-page)) | ||||
|            (total-page (oref room total-page)) | ||||
|            (next-page (if oldest | ||||
|                           (1+ current-page) | ||||
|                         1))) | ||||
|       (with-slots (query sort sort-dir) room | ||||
|         (cl-case (eieio-object-class room) | ||||
|           ('slack-search-result | ||||
|            (slack-search-request-message team | ||||
|                                          query | ||||
|                                          sort | ||||
|                                          sort-dir | ||||
|                                          #'on-history | ||||
|                                          next-page | ||||
|                                          async)) | ||||
|           ('slack-file-search-result | ||||
|            (slack-search-request-file team | ||||
|                                       query | ||||
|                                       sort | ||||
|                                       sort-dir | ||||
|                                       #'on-history | ||||
|                                       next-page | ||||
|                                       async))))))) | ||||
|  | ||||
| (provide 'slack-search) | ||||
| ;;; slack-search.el ends here | ||||
							
								
								
									
										202
									
								
								elpa/slack-20160928.2036/slack-team.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										202
									
								
								elpa/slack-20160928.2036/slack-team.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,202 @@ | ||||
| ;;; slack-team.el ---  team class                    -*- lexical-binding: t; -*- | ||||
|  | ||||
| ;; Copyright (C) 2016  南優也 | ||||
|  | ||||
| ;; Author: 南優也 <yuyaminami@minamiyuunari-no-MacBook-Pro.local> | ||||
| ;; Keywords: | ||||
|  | ||||
| ;; This program is free software; you can redistribute it and/or modify | ||||
| ;; it under the terms of the GNU General Public License as published by | ||||
| ;; the Free Software Foundation, either version 3 of the License, or | ||||
| ;; (at your option) any later version. | ||||
|  | ||||
| ;; This program is distributed in the hope that it will be useful, | ||||
| ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| ;; GNU General Public License for more details. | ||||
|  | ||||
| ;; You should have received a copy of the GNU General Public License | ||||
| ;; along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  | ||||
| ;;; Commentary: | ||||
|  | ||||
| ;; | ||||
|  | ||||
| ;;; Code: | ||||
| (require 'eieio) | ||||
| (require 'slack-util) | ||||
|  | ||||
| (defvar slack-teams nil) | ||||
| (defvar slack-current-team nil) | ||||
| (defcustom slack-prefer-current-team nil | ||||
|   "If set to t, using `slack-current-team' for interactive function. | ||||
| use `slack-change-current-team' to change `slack-current-team'" | ||||
|   :group 'slack) | ||||
|  | ||||
| (defclass slack-team () | ||||
|   ((id :initarg :id) | ||||
|    (token :initarg :token :initform nil) | ||||
|    (client-id :initarg :client-id) | ||||
|    (client-secret :initarg :client-secret) | ||||
|    (name :initarg :name :initform nil) | ||||
|    (domain :initarg :domain) | ||||
|    (self :initarg :self) | ||||
|    (self-id :initarg :self-id) | ||||
|    (self-name :initarg :self-name) | ||||
|    (channels :initarg :channels) | ||||
|    (groups :initarg :groups) | ||||
|    (ims :initarg :ims) | ||||
|    (file-room :initform nil) | ||||
|    (search-results :initform nil) | ||||
|    (users :initarg :users) | ||||
|    (bots :initarg :bots) | ||||
|    (ws-url :initarg :ws-url) | ||||
|    (ws-conn :initarg :ws-conn :initform nil) | ||||
|    (ping-timer :initform nil) | ||||
|    (check-ping-timeout-timer :initform nil) | ||||
|    (check-ping-timeout-sec :initarg :check-ping-timeout-sec | ||||
|                            :initform 20) | ||||
|    (reconnect-auto :initarg :reconnect-auto :initform t) | ||||
|    (reconnect-timer :initform nil) | ||||
|    (reconnect-after-sec :initform 10) | ||||
|    (reconnect-count :initform 0) | ||||
|    (reconnect-count-max :initform 360) | ||||
|    (last-pong :initform nil) | ||||
|    (waiting-send :initform nil) | ||||
|    (sent-message :initform (make-hash-table)) | ||||
|    (message-id :initform 0) | ||||
|    (connected :initform nil) | ||||
|    (subscribed-channels :initarg :subscribed-channels | ||||
|                         :type list :initform nil) | ||||
|    (typing :initform nil) | ||||
|    (typing-timer :initform nil) | ||||
|    (reminders :initform nil :type list) | ||||
|    (ping-check-timers :initform (slack-ws-init-ping-check-timers)))) | ||||
|  | ||||
| (defun slack-team-find (id) | ||||
|   (cl-find-if #'(lambda (team) (string= id (oref team id))) | ||||
|               slack-teams)) | ||||
|  | ||||
| (defmethod slack-team-disconnect ((team slack-team)) | ||||
|   (slack-ws-close team)) | ||||
|  | ||||
| (defmethod slack-team-equalp ((team slack-team) other) | ||||
|   (with-slots (client-id) team | ||||
|     (string= client-id (oref other client-id)))) | ||||
|  | ||||
| (defmethod slack-team-name ((team slack-team)) | ||||
|   (oref team name)) | ||||
|  | ||||
| ;;;###autoload | ||||
| (defun slack-register-team (&rest plist) | ||||
|   "PLIST must contain :name :client-id :client-secret with value. | ||||
| setting :token will reduce your configuration step. | ||||
| you will notified when receive message with channel included in subscribed-chennels. | ||||
| if :default is t and `slack-prefer-current-team' is t, skip selecting team when channels listed. | ||||
| you can change current-team with `slack-change-current-team'" | ||||
|   (interactive | ||||
|    (let ((name (read-from-minibuffer "Team Name: ")) | ||||
|          (client-id (read-from-minibuffer "Client Id: ")) | ||||
|          (client-secret (read-from-minibuffer "Cliend Secret: ")) | ||||
|          (token (read-from-minibuffer "Token: "))) | ||||
|      (list :name name :client-id client-id :client-secret client-secret | ||||
|            :token token))) | ||||
|   (cl-labels ((same-client-id | ||||
|                (client-id) | ||||
|                (cl-find-if #'(lambda (team) | ||||
|                                (string= client-id (oref team client-id))) | ||||
|                            slack-teams)) | ||||
|               (missing (plist) | ||||
|                        (cl-remove-if | ||||
|                         #'null | ||||
|                         (mapcar #'(lambda (key) | ||||
|                                     (unless (plist-member plist key) | ||||
|                                       key)) | ||||
|                                 '(:name :client-id :client-secret))))) | ||||
|     (let ((missing (missing plist))) | ||||
|       (if missing | ||||
|           (error "Missing Keyword: %s" missing))) | ||||
|     (let ((team (apply #'slack-team "team" | ||||
|                        (slack-collect-slots 'slack-team plist)))) | ||||
|       (let ((same-team (cl-find-if | ||||
|                         #'(lambda (o) (slack-team-equalp team o)) | ||||
|                         slack-teams))) | ||||
|         (if same-team | ||||
|             (progn | ||||
|               (slack-team-disconnect same-team) | ||||
|               (slack-start team)))) | ||||
|  | ||||
|       (setq slack-teams | ||||
|             (cons team | ||||
|                   (cl-remove-if #'(lambda (other) | ||||
|                                     (slack-team-equalp team other)) | ||||
|                                 slack-teams))) | ||||
|       (if (plist-get plist :default) | ||||
|           (setq slack-current-team team))))) | ||||
|  | ||||
| (defun slack-team-find-by-name (name) | ||||
|   (if name | ||||
|       (cl-find-if #'(lambda (team) (string= name (oref team name))) | ||||
|                   slack-teams))) | ||||
|  | ||||
| (cl-defun slack-team-select (&optional no-default) | ||||
|   (cl-labels ((select-team () | ||||
|                            (slack-team-find-by-name | ||||
|                             (completing-read | ||||
|                              "Select Team: " | ||||
|                              (mapcar #'(lambda (team) (oref team name)) | ||||
|                                      (slack-team-connected-list)))))) | ||||
|     (let ((team (if (and slack-prefer-current-team | ||||
|                          slack-current-team | ||||
|                          (not no-default)) | ||||
|                     slack-current-team | ||||
|                   (select-team)))) | ||||
|       ;; (if (and slack-prefer-current-team | ||||
|       ;;          (not slack-current-team) | ||||
|       ;;          (not no-default)) | ||||
|       ;;     (if (yes-or-no-p (format "Set %s to current-team?" | ||||
|       ;;                              (oref team name))) | ||||
|       ;;         (setq slack-current-team team))) | ||||
|       team))) | ||||
|  | ||||
| (defmethod slack-team-connectedp ((team slack-team)) | ||||
|   (oref team connected)) | ||||
|  | ||||
| (defun slack-team-connected-list () | ||||
|   (cl-remove-if #'null | ||||
|                 (mapcar #'(lambda (team) | ||||
|                             (if (slack-team-connectedp team) team)) | ||||
|                         slack-teams))) | ||||
|  | ||||
| (defun slack-change-current-team () | ||||
|   (interactive) | ||||
|   (let ((team (slack-team-find-by-name | ||||
|                (completing-read | ||||
|                 "Select Team: " | ||||
|                 (mapcar #'(lambda (team) (oref team name)) | ||||
|                         slack-teams))))) | ||||
|     (setq slack-current-team team) | ||||
|     (message "Set slack-current-team to %s" (or (and team (oref team name)) | ||||
|                                                 "nil")) | ||||
|     (if team | ||||
|         (slack-team-connect team)))) | ||||
|  | ||||
| (defmethod slack-team-connect ((team slack-team)) | ||||
|   (unless (slack-team-connectedp team) | ||||
|     (slack-start team))) | ||||
|  | ||||
| (defun slack-team-delete () | ||||
|   (interactive) | ||||
|   (let ((selected (slack-team-select t))) | ||||
|     (if (yes-or-no-p (format "Delete %s from `slack-teams'?" | ||||
|                              (oref selected name))) | ||||
|         (progn | ||||
|           (setq slack-teams | ||||
|                 (cl-remove-if #'(lambda (team) | ||||
|                                   (slack-team-equalp selected team)) | ||||
|                               slack-teams)) | ||||
|           (slack-team-disconnect selected) | ||||
|           (message "Delete %s from `slack-teams'" (oref selected name)))))) | ||||
|  | ||||
| (provide 'slack-team) | ||||
| ;;; slack-team.el ends here | ||||
							
								
								
									
										36
									
								
								elpa/slack-20160928.2036/slack-user-message.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								elpa/slack-20160928.2036/slack-user-message.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | ||||
| ;;; package --- Summary | ||||
| ;;; Commentary: | ||||
|  | ||||
| ;;; Code: | ||||
|  | ||||
| (require 'eieio) | ||||
| (require 'slack-message-formatter) | ||||
| (require 'slack-message-reaction) | ||||
| (require 'slack-message-editor) | ||||
|  | ||||
| (defvar slack-user-message-keymap | ||||
|   (let ((keymap (make-sparse-keymap))) | ||||
|     keymap)) | ||||
|  | ||||
| (defmethod slack-message-sender-equalp ((m slack-user-message) sender-id) | ||||
|   (string= (oref m user) sender-id)) | ||||
|  | ||||
| (defmethod slack-message-header ((m slack-user-message) team) | ||||
|   (with-slots (ts edited-at deleted-at) m | ||||
|     (let* ((name (slack-message-sender-name m team)) | ||||
|            (time (slack-message-time-to-string ts)) | ||||
|            (edited-at (slack-message-time-to-string edited-at)) | ||||
|            (deleted-at (slack-message-time-to-string deleted-at)) | ||||
|            (header (format "%s" name))) | ||||
|       (if deleted-at | ||||
|           (format "%s deleted_at: %s" header deleted-at) | ||||
|         (if edited-at | ||||
|             (format "%s edited_at: %s" header edited-at) | ||||
|           header))))) | ||||
|  | ||||
| (defmethod slack-message-propertize ((m slack-user-message) text) | ||||
|   (put-text-property 0 (length text) 'keymap slack-user-message-keymap text) | ||||
|   text) | ||||
|  | ||||
| (provide 'slack-user-message) | ||||
| ;;; slack-user-message.el ends here | ||||
							
								
								
									
										63
									
								
								elpa/slack-20160928.2036/slack-user.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								elpa/slack-20160928.2036/slack-user.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,63 @@ | ||||
| ;;; slack-user.el ---slack user interface            -*- lexical-binding: t; -*- | ||||
|  | ||||
| ;; Copyright (C) 2015  南優也 | ||||
|  | ||||
| ;; Author: 南優也 <yuyaminami@minamiyuunari-no-MacBook-Pro.local> | ||||
| ;; Keywords: | ||||
|  | ||||
| ;; This program is free software; you can redistribute it and/or modify | ||||
| ;; it under the terms of the GNU General Public License as published by | ||||
| ;; the Free Software Foundation, either version 3 of the License, or | ||||
| ;; (at your option) any later version. | ||||
|  | ||||
| ;; This program is distributed in the hope that it will be useful, | ||||
| ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| ;; GNU General Public License for more details. | ||||
|  | ||||
| ;; You should have received a copy of the GNU General Public License | ||||
| ;; along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  | ||||
| ;;; Commentary: | ||||
|  | ||||
| ;; | ||||
|  | ||||
| ;;; Code: | ||||
|  | ||||
| (require 'slack-request) | ||||
| (require 'slack-room) | ||||
|  | ||||
| (defun slack-user-find (id team) | ||||
|   (with-slots (users) team | ||||
|     (cl-find-if (lambda (user) | ||||
|                   (string= id (plist-get user :id))) | ||||
|                 users))) | ||||
|  | ||||
| (defun slack-user-find-by-name (name team) | ||||
|   (with-slots (users) team | ||||
|     (cl-find-if (lambda (user) | ||||
|                   (string= name (plist-get user :name))) | ||||
|                 users))) | ||||
|  | ||||
| (defun slack-user-get-id (name team) | ||||
|   (let ((user (slack-user-find-by-name name team))) | ||||
|     (if user | ||||
|         (plist-get user :id)))) | ||||
|  | ||||
| (defun slack-user-name (id team) | ||||
|   (let ((user (slack-user-find id team))) | ||||
|     (if user | ||||
|         (plist-get user :name)))) | ||||
|  | ||||
| (defun slack-user-names (team) | ||||
|   (with-slots (users) team | ||||
|     (mapcar (lambda (u) (cons (plist-get u :name) u)) | ||||
|             users))) | ||||
|  | ||||
| (defun slack-user-presence-to-string (user) | ||||
|   (if (string= (plist-get user :presence) "active") | ||||
|       "* " | ||||
|     "  ")) | ||||
|  | ||||
| (provide 'slack-user) | ||||
| ;;; slack-user.el ends here | ||||
							
								
								
									
										88
									
								
								elpa/slack-20160928.2036/slack-util.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								elpa/slack-20160928.2036/slack-util.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,88 @@ | ||||
| ;;; slack-util.el ---utility functions               -*- lexical-binding: t; -*- | ||||
|  | ||||
| ;; Copyright (C) 2015  yuya.minami | ||||
|  | ||||
| ;; Author: yuya.minami <yuya.minami@yuyaminami-no-MacBook-Pro.local> | ||||
| ;; Keywords: | ||||
|  | ||||
| ;; This program is free software; you can redistribute it and/or modify | ||||
| ;; it under the terms of the GNU General Public License as published by | ||||
| ;; the Free Software Foundation, either version 3 of the License, or | ||||
| ;; (at your option) any later version. | ||||
|  | ||||
| ;; This program is distributed in the hope that it will be useful, | ||||
| ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| ;; GNU General Public License for more details. | ||||
|  | ||||
| ;; You should have received a copy of the GNU General Public License | ||||
| ;; along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  | ||||
| ;;; Commentary: | ||||
|  | ||||
| ;; | ||||
|  | ||||
| ;;; Code: | ||||
|  | ||||
| (require 'eieio) | ||||
|  | ||||
| (defun slack-seq-to-list (seq) | ||||
|   (if (listp seq) seq (append seq nil))) | ||||
|  | ||||
| (defun slack-decode (seq) | ||||
|   (cl-loop for e in (slack-seq-to-list seq) | ||||
|            collect (if (stringp e) | ||||
|                        (decode-coding-string e 'utf-8) | ||||
|                      e))) | ||||
|  | ||||
| (defun slack-class-have-slot-p (class slot) | ||||
|   (and (symbolp slot) | ||||
|        (let* ((stripped (substring (symbol-name slot) 1)) | ||||
|               (replaced (replace-regexp-in-string "_" "-" | ||||
|                                                   stripped)) | ||||
|               (symbolized (intern replaced))) | ||||
|          (slot-exists-p class symbolized)))) | ||||
|  | ||||
| (defun slack-collect-slots (class seq) | ||||
|   (let ((plist (slack-seq-to-list seq))) | ||||
|     (cl-loop for p in plist | ||||
|              if (and (slack-class-have-slot-p class p) | ||||
|                      (plist-member plist p)) | ||||
|              nconc (let ((value (plist-get plist p))) | ||||
|                      (list p (if (stringp value) | ||||
|                                  (decode-coding-string value 'utf-8) | ||||
|                                (if (eq :json-false value) | ||||
|                                    nil | ||||
|                                  value))))))) | ||||
|  | ||||
| (defun company-slack-backend (command &optional arg &rest ignored) | ||||
|   "Completion backend for slack chats.  It currently understands | ||||
| @USER; adding #CHANNEL should be a simple matter of programming." | ||||
|   (interactive (list 'interactive)) | ||||
|   (cl-labels | ||||
|       ((prefix-type (str) (cond | ||||
|                            ((string-prefix-p "@" str) 'user) | ||||
|                            ((string-prefix-p "#" str) 'channel))) | ||||
|        (content (str) (substring str 1 nil))) | ||||
|     (cl-case command | ||||
|       (interactive (company-begin-backend 'company-slack-backend)) | ||||
|       (prefix (when (cl-find major-mode '(slack-mode | ||||
|                                           slack-edit-message-mode)) | ||||
|                 (company-grab-line "\\(\\W\\|^\\)\\(@\\w*\\|#\\w*\\)" | ||||
|                                    2))) | ||||
|       (candidates (let ((content (content arg))) | ||||
|                     (cl-case (prefix-type arg) | ||||
|                       (user | ||||
|                        (cl-loop for user in (oref slack-current-team users) | ||||
|                                 if (string-prefix-p content | ||||
|                                                     (plist-get user :name)) | ||||
|                                 collect (concat "@" (plist-get user :name)))) | ||||
|                       (channel | ||||
|                        (cl-loop for team in (oref slack-current-team channels) | ||||
|                                 if (string-prefix-p content | ||||
|                                                     (oref team name)) | ||||
|                                 collect (concat "#" (oref team name))))))) | ||||
|       ))) | ||||
|  | ||||
| (provide 'slack-util) | ||||
| ;;; slack-util.el ends here | ||||
							
								
								
									
										510
									
								
								elpa/slack-20160928.2036/slack-websocket.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										510
									
								
								elpa/slack-20160928.2036/slack-websocket.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,510 @@ | ||||
| ;;; slack-websocket.el --- slack websocket interface  -*- lexical-binding: t; -*- | ||||
|  | ||||
| ;; Copyright (C) 2015  南優也 | ||||
|  | ||||
| ;; Author: 南優也 <yuyaminami@minamiyuunari-no-MacBook-Pro.local> | ||||
| ;; Keywords: | ||||
|  | ||||
| ;; This program is free software; you can redistribute it and/or modify | ||||
| ;; it under the terms of the GNU General Public License as published by | ||||
| ;; the Free Software Foundation, either version 3 of the License, or | ||||
| ;; (at your option) any later version. | ||||
|  | ||||
| ;; This program is distributed in the hope that it will be useful, | ||||
| ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| ;; GNU General Public License for more details. | ||||
|  | ||||
| ;; You should have received a copy of the GNU General Public License | ||||
| ;; along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  | ||||
| ;;; Commentary: | ||||
|  | ||||
| ;; | ||||
|  | ||||
| ;;; Code: | ||||
| (require 'websocket) | ||||
| (require 'slack-request) | ||||
| (require 'slack-message) | ||||
| (require 'slack-reply) | ||||
|  | ||||
| (defclass slack-typing () | ||||
|   ((room :initarg :room :initform nil) | ||||
|    (limit :initarg :limit :initform nil) | ||||
|    (users :initarg :users :initform nil))) | ||||
|  | ||||
| (defclass slack-typing-user () | ||||
|   ((limit :initarg :limit :initform nil) | ||||
|    (user-name :initarg :user-name :initform nil))) | ||||
|  | ||||
| (defun slack-ws-open (team) | ||||
|   (with-slots (ws-url ws-conn reconnect-count) team | ||||
|     (unless ws-conn | ||||
|       (setq ws-conn | ||||
|             (websocket-open | ||||
|              ws-url | ||||
|              :on-message | ||||
|              #'(lambda (websocket frame) | ||||
|                  (slack-ws-on-message websocket frame team)))) | ||||
|       (setq reconnect-count 0)))) | ||||
|  | ||||
| (defun slack-ws-close (&optional team) | ||||
|   (interactive) | ||||
|   (unless team | ||||
|     (setq team slack-teams)) | ||||
|   (cl-labels | ||||
|       ((close (team) | ||||
|               (let ((team-name (oref team name))) | ||||
|                 (with-slots (connected ws-conn last-pong) team | ||||
|                   (if ws-conn | ||||
|                       (progn | ||||
|                         (websocket-close ws-conn) | ||||
|                         (setq ws-conn nil) | ||||
|                         (setq connected nil) | ||||
|                         (slack-ws-cancel-ping-timer team) | ||||
|                         (slack-ws-cancel-ping-check-timers team) | ||||
|                         (message "Slack Websocket Closed - %s" team-name)) | ||||
|                     (message "Slack Websocket is not open - %s" team-name)))))) | ||||
|     (if (listp team) | ||||
|         (mapc #'close team) | ||||
|       (close team)))) | ||||
|  | ||||
|  | ||||
| (defun slack-ws-send (payload team) | ||||
|   (with-slots (waiting-send ws-conn) team | ||||
|     (push payload waiting-send) | ||||
|     (condition-case _e | ||||
|         (progn | ||||
|           (websocket-send-text ws-conn payload) | ||||
|           (setq waiting-send | ||||
|                 (cl-remove-if #'(lambda (p) (string= payload p)) | ||||
|                               waiting-send))) | ||||
|       (websocket-closed (slack-ws-reconnect team)) | ||||
|       (websocket-illegal-frame (message "Sent illegal frame.") | ||||
|                                (slack-ws-close team)) | ||||
|       (error (slack-ws-reconnect team))))) | ||||
|  | ||||
| (defun slack-ws-resend (team) | ||||
|   (with-slots (waiting-send) team | ||||
|     (let ((candidate waiting-send)) | ||||
|       (setq waiting-send nil) | ||||
|       (cl-loop for msg in candidate | ||||
|                do (sleep-for 1) (slack-ws-send msg team))))) | ||||
|  | ||||
|  | ||||
| (defun slack-ws-on-message (_websocket frame team) | ||||
|   ;; (message "%s" (slack-request-parse-payload | ||||
|   ;;                (websocket-frame-payload frame))) | ||||
|   (when (websocket-frame-completep frame) | ||||
|     (let* ((payload (slack-request-parse-payload | ||||
|                      (websocket-frame-payload frame))) | ||||
|            (decoded-payload (slack-decode payload)) | ||||
|            (type (plist-get decoded-payload :type))) | ||||
|       ;; (message "%s" decoded-payload) | ||||
|       (condition-case err | ||||
|           (cond | ||||
|            ((string= type "pong") | ||||
|             (slack-ws-handle-pong decoded-payload team)) | ||||
|            ((string= type "hello") | ||||
|             (slack-ws-cancel-reconnect-timer team) | ||||
|             (slack-cancel-notify-adandon-reconnect) | ||||
|             (slack-ws-set-ping-timer team) | ||||
|             (slack-ws-resend team) | ||||
|             (message "Slack Websocket Is Ready! - %s" | ||||
|                      (oref team name))) | ||||
|            ((plist-get decoded-payload :reply_to) | ||||
|             (slack-ws-handle-reply decoded-payload team)) | ||||
|            ((string= type "message") | ||||
|             (slack-ws-handle-message decoded-payload team)) | ||||
|            ((string= type "reaction_added") | ||||
|             (slack-ws-handle-reaction-added decoded-payload team)) | ||||
|            ((string= type "reaction_removed") | ||||
|             (slack-ws-handle-reaction-removed decoded-payload team)) | ||||
|            ((string= type "channel_created") | ||||
|             (slack-ws-handle-channel-created decoded-payload team)) | ||||
|            ((or (string= type "channel_archive") | ||||
|                 (string= type "group_archive")) | ||||
|             (slack-ws-handle-room-archive decoded-payload team)) | ||||
|            ((or (string= type "channel_unarchive") | ||||
|                 (string= type "group_unarchive")) | ||||
|             (slack-ws-handle-room-unarchive decoded-payload team)) | ||||
|            ((string= type "channel_deleted") | ||||
|             (slack-ws-handle-channel-deleted decoded-payload team)) | ||||
|            ((or (string= type "channel_rename") | ||||
|                 (string= type "group_rename")) | ||||
|             (slack-ws-handle-room-rename decoded-payload team)) | ||||
|            ((or (string= type "channel_joined") | ||||
|                 (string= type "group_joined")) | ||||
|             (slack-ws-handle-room-joined decoded-payload team)) | ||||
|            ((string= type "presence_change") | ||||
|             (slack-ws-handle-presence-change decoded-payload team)) | ||||
|            ((or (string= type "bot_added") | ||||
|                 (string= type "bot_changed")) | ||||
|             (slack-ws-handle-bot decoded-payload team)) | ||||
|            ((or (string= type "file_deleted") | ||||
|                 (string= type "file_unshared")) | ||||
|             (slack-ws-handle-file-deleted decoded-payload team)) | ||||
|            ((or (string= type "im_marked") | ||||
|                 (string= type "channel_marked") | ||||
|                 (string= type "group_marked")) | ||||
|             (slack-ws-handle-room-marked decoded-payload team)) | ||||
|            ((string= type "im_open") | ||||
|             (slack-ws-handle-im-open decoded-payload team)) | ||||
|            ((string= type "im_close") | ||||
|             (slack-ws-handle-im-close decoded-payload team)) | ||||
|            ((string= type "team_join") | ||||
|             (slack-ws-handle-team-join decoded-payload team)) | ||||
|            ((string= type "user_typing") | ||||
|             (slack-ws-handle-user-typing decoded-payload team))) | ||||
|         (error (progn | ||||
|                  (warn "%s payload: %s" err decoded-payload) | ||||
|                  (signal (car err) (cdr err)))))))) | ||||
|  | ||||
| (defun slack-user-typing (team) | ||||
|   (with-slots (typing typing-timer) team | ||||
|     (with-slots (limit users room) typing | ||||
|       (let ((current (float-time))) | ||||
|         (if (and typing-timer (timerp typing-timer) | ||||
|                  (< limit current)) | ||||
|             (progn | ||||
|               (cancel-timer typing-timer) | ||||
|               (setq typing-timer nil) | ||||
|               (setq typing nil)) | ||||
|           (if (slack-buffer-show-typing-p | ||||
|                (get-buffer (slack-room-buffer-name room))) | ||||
|               (let ((team-name (slack-team-name team)) | ||||
|                     (room-name (slack-room-name room)) | ||||
|                     (visible-users (cl-remove-if | ||||
|                                     #'(lambda (u) (< (oref u limit) current)) | ||||
|                                     users))) | ||||
|                 (message "Slack [%s - %s] %s is typing..." | ||||
|                          team-name room-name | ||||
|                          (mapconcat #'(lambda (u) (oref u user-name)) | ||||
|                                     visible-users | ||||
|                                     ", "))))))))) | ||||
|  | ||||
| (defun slack-ws-handle-user-typing (payload team) | ||||
|   (let* ((user (slack-user-name (plist-get payload :user) team)) | ||||
|          (room (slack-room-find (plist-get payload :channel) team))) | ||||
|     (if (slack-buffer-show-typing-p | ||||
|          (get-buffer (slack-room-buffer-name room))) | ||||
|         (let ((limit (+ 3 (float-time)))) | ||||
|           (with-slots (typing typing-timer) team | ||||
|             (if (and typing (equal room (oref typing room))) | ||||
|                 (with-slots ((typing-limit limit) | ||||
|                              (typing-room room) users) typing | ||||
|                   (setq typing-limit limit) | ||||
|                   (let ((typing-user (make-instance 'slack-typing-user | ||||
|                                                     :limit limit | ||||
|                                                     :user-name user))) | ||||
|                     (setq users | ||||
|                           (cons typing-user | ||||
|                                 (cl-remove-if #'(lambda (u) | ||||
|                                                   (string= (oref u user-name) | ||||
|                                                            user)) | ||||
|                                               users)))))) | ||||
|             (unless typing | ||||
|               (let ((new-typing (make-instance 'slack-typing | ||||
|                                                :room room :limit limit)) | ||||
|                     (typing-user (make-instance 'slack-typing-user | ||||
|                                                 :limit limit :user-name user))) | ||||
|                 (oset new-typing users (list typing-user)) | ||||
|                 (setq typing new-typing)) | ||||
|               (setq typing-timer | ||||
|                     (run-with-timer t 1 #'slack-user-typing team)))))))) | ||||
|  | ||||
| (defun slack-ws-handle-team-join (payload team) | ||||
|   (let ((user (slack-decode (plist-get payload :user)))) | ||||
|     (with-slots (users) team | ||||
|       (setq users | ||||
|             (cons user | ||||
|                   (cl-remove-if #'(lambda (u) | ||||
|                                     (string= (plist-get u :id) | ||||
|                                              (plist-get user :id))) | ||||
|                                 users)))) | ||||
|     (message "User %s Joind Team: %s" | ||||
|              (plist-get (slack-user-find (plist-get user :id) | ||||
|                                          team) | ||||
|                         :name) | ||||
|              (slack-team-name team)))) | ||||
|  | ||||
| (defun slack-ws-handle-im-open (payload team) | ||||
|   (cl-labels | ||||
|       ((notify | ||||
|         (im) | ||||
|         (slack-room-history | ||||
|          im team nil | ||||
|          #'(lambda () | ||||
|              (message "Direct Message Channel with %s is Open" | ||||
|                       (slack-user-name (oref im user) team))) | ||||
|          t))) | ||||
|     (let ((exist (slack-room-find (plist-get payload :channel) team))) | ||||
|       (if exist | ||||
|           (progn | ||||
|             (oset exist is-open t) | ||||
|             (notify exist)) | ||||
|         (with-slots (ims) team | ||||
|           (let ((im (slack-room-create | ||||
|                      (list :id (plist-get payload :channel) | ||||
|                            :user (plist-get payload :user)) | ||||
|                      team 'slack-im))) | ||||
|             (setq ims (cons im ims)) | ||||
|             (notify im))))))) | ||||
|  | ||||
| (defun slack-ws-handle-im-close (payload team) | ||||
|   (let ((im (slack-room-find (plist-get payload :channel) team))) | ||||
|     (oset im is-open nil) | ||||
|     (message "Direct Message Channel with %s is Closed" | ||||
|              (slack-user-name (oref im user) team)))) | ||||
|  | ||||
| (defun slack-ws-handle-message (payload team) | ||||
|   (let ((subtype (plist-get payload :subtype))) | ||||
|     (cond | ||||
|      ((and subtype (string= subtype "file_share")) | ||||
|       (slack-ws-handle-file-share payload team) | ||||
|       (slack-ws-update-message payload team)) | ||||
|      ((and subtype (string= subtype "message_changed")) | ||||
|       (slack-message-edited payload team)) | ||||
|      ((and subtype (string= subtype "message_deleted")) | ||||
|       (slack-message-deleted payload team)) | ||||
|      (t | ||||
|       (slack-ws-update-message payload team))))) | ||||
|  | ||||
| (defun slack-ws-update-message (payload team) | ||||
|   (let ((m (slack-message-create payload))) | ||||
|     (when m | ||||
|       (slack-message-update m team)))) | ||||
|  | ||||
| (defun slack-ws-handle-reply (payload team) | ||||
|   (let ((ok (plist-get payload :ok))) | ||||
|     (if (eq ok :json-false) | ||||
|         (let ((err (plist-get payload :error))) | ||||
|           (message "Error code: %s msg: %s" | ||||
|                    (plist-get err :code) | ||||
|                    (plist-get err :msg))) | ||||
|       (let ((message-id (plist-get payload :reply_to))) | ||||
|         (if (integerp message-id) | ||||
|             (slack-message-handle-reply | ||||
|              (slack-message-create payload) | ||||
|              team)))))) | ||||
|  | ||||
| (cl-defmacro slack-ws-handle-reaction ((payload team) &body body) | ||||
|   `(let* ((item (plist-get ,payload :item)) | ||||
|           (room (slack-room-find (plist-get item :channel) | ||||
|                                  ,team))) | ||||
|      (if room | ||||
|          (let ((msg (slack-room-find-message room (plist-get item :ts)))) | ||||
|            (if msg | ||||
|                (let* ((r-name (plist-get ,payload :reaction)) | ||||
|                       (r-count 1) | ||||
|                       (r-users (list (plist-get ,payload :user))) | ||||
|                       (reaction (make-instance 'slack-reaction | ||||
|                                                :name r-name | ||||
|                                                :count r-count | ||||
|                                                :users r-users))) | ||||
|  | ||||
|                  ,@body | ||||
|                  (slack-message-update msg ,team t t))))))) | ||||
|  | ||||
| (defun slack-ws-handle-reaction-added (payload team) | ||||
|   (slack-ws-handle-reaction | ||||
|    (payload team) | ||||
|    (slack-message-append-reaction msg reaction) | ||||
|    (slack-reaction-notify payload team))) | ||||
|  | ||||
| (defun slack-ws-handle-reaction-removed (payload team) | ||||
|   (slack-ws-handle-reaction | ||||
|    (payload team) | ||||
|    (slack-message-pop-reaction msg reaction))) | ||||
|  | ||||
| (defun slack-ws-handle-channel-created (payload team) | ||||
|   ;; (let ((id (plist-get (plist-get payload :channel) :id))) | ||||
|   ;;   (slack-channel-create-from-info id team)) | ||||
|   ) | ||||
|  | ||||
| (defun slack-ws-handle-room-archive (payload team) | ||||
|   (let* ((id (plist-get payload :channel)) | ||||
|          (room (slack-room-find id team))) | ||||
|     (oset room is-archived t) | ||||
|     (message "Channel: %s is archived" | ||||
|              (slack-room-name-with-team-name room)))) | ||||
|  | ||||
| (defun slack-ws-handle-room-unarchive (payload team) | ||||
|   (let* ((id (plist-get payload :channel)) | ||||
|          (room (slack-room-find id team))) | ||||
|     (oset room is-archived nil) | ||||
|     (message "Channel: %s is unarchived" | ||||
|              (slack-room-name-with-team-name room)))) | ||||
|  | ||||
| (defun slack-ws-handle-channel-deleted (payload team) | ||||
|   (let ((id (plist-get payload :channel))) | ||||
|     (slack-room-deleted id team))) | ||||
|  | ||||
| (defun slack-ws-handle-room-rename (payload team) | ||||
|   (let* ((c (plist-get payload :channel)) | ||||
|          (room (slack-room-find (plist-get c :id) team)) | ||||
|          (old-name (slack-room-name room)) | ||||
|          (new-name (plist-get c :name))) | ||||
|     (oset room name new-name) | ||||
|     (message "Renamed channel from %s to %s" | ||||
|              old-name | ||||
|              new-name))) | ||||
|  | ||||
| (defun slack-ws-handle-room-joined (payload team) | ||||
|   (cl-labels | ||||
|       ((replace-room (room rooms) | ||||
|                      (cons room (cl-delete-if | ||||
|                                  #'(lambda (r) | ||||
|                                      (slack-room-equal-p room r)) | ||||
|                                  rooms)))) | ||||
|     (let* ((c (plist-get payload :channel))) | ||||
|       (if (plist-get c :is_channel) | ||||
|           (let ((channel (slack-room-create c team 'slack-channel))) | ||||
|             (with-slots (channels) team | ||||
|               (setq channels | ||||
|                     (replace-room channel channels))) | ||||
|             (message "Joined channel %s" | ||||
|                      (slack-room-name-with-team-name channel))) | ||||
|         (let ((group (slack-room-create c team 'slack-group))) | ||||
|           (with-slots (groups) team | ||||
|             (setq groups | ||||
|                   (replace-room group groups))) | ||||
|           (message "Joined group %s" | ||||
|                    (slack-room-name-with-team-name group))))))) | ||||
|  | ||||
| (defun slack-ws-handle-presence-change (payload team) | ||||
|   (let* ((id (plist-get payload :user)) | ||||
|          (user (slack-user-find id team)) | ||||
|          (presence (plist-get payload :presence))) | ||||
|     (plist-put user :presence presence))) | ||||
|  | ||||
| (defun slack-ws-handle-bot (payload team) | ||||
|   (let ((bot (plist-get payload :bot))) | ||||
|     (with-slots (bots) team | ||||
|       (push bot bots)))) | ||||
|  | ||||
| (defun slack-ws-handle-file-share (payload team) | ||||
|   (let ((file (slack-file-create (plist-get payload :file)))) | ||||
|     (slack-file-pushnew file team))) | ||||
|  | ||||
| (defun slack-ws-handle-file-deleted (payload team) | ||||
|   (let ((file-id (plist-get payload :file_id)) | ||||
|         (room (slack-file-room-obj team))) | ||||
|     (with-slots (messages last-read) room | ||||
|       (setq messages (cl-remove-if #'(lambda (f) | ||||
|                                        (string= file-id (oref f id))) | ||||
|                                    messages))))) | ||||
| (defun slack-log-time () | ||||
|   (format-time-string "%Y-%m-%d %H:%M:%S")) | ||||
|  | ||||
| (defun slack-ws-set-ping-timer (team) | ||||
|   (with-slots (ping-timer) team | ||||
|     (unless ping-timer | ||||
|       (setq ping-timer | ||||
|             (run-at-time t 10 #'(lambda () (slack-ws-ping team))))))) | ||||
|  | ||||
| (defun slack-ws-current-time-str () | ||||
|   (number-to-string (time-to-seconds (current-time)))) | ||||
|  | ||||
| (defun slack-ws-ping (team) | ||||
|   (slack-message-inc-id team) | ||||
|   (with-slots (message-id) team | ||||
|     (let* ((time (slack-ws-current-time-str)) | ||||
|            (m (list :id message-id | ||||
|                     :type "ping" | ||||
|                     :time time)) | ||||
|            (json (json-encode m))) | ||||
|       (slack-ws-set-check-ping-timer team time) | ||||
|       (slack-ws-send json team)))) | ||||
|  | ||||
| (defun slack-ws-set-check-ping-timer (team time) | ||||
|   (with-slots (ping-check-timers check-ping-timeout-sec) team | ||||
|     (let ((team-id (oref team id))) | ||||
|       (puthash time (run-at-time check-ping-timeout-sec nil | ||||
|                                  #'(lambda () (slack-ws-ping-timeout team-id))) | ||||
|                ping-check-timers)))) | ||||
|  | ||||
| (defun slack-ws-ping-timeout (team-id) | ||||
|   (message "Slack Websocket PING Timeout.") | ||||
|   (let ((team (slack-team-find team-id))) | ||||
|     (slack-ws-cancel-ping-check-timers team) | ||||
|     (slack-ws-close team) | ||||
|     (slack-ws-cancel-ping-timer team) | ||||
|     (if (oref team reconnect-auto) | ||||
|         (with-slots (reconnect-timer reconnect-after-sec) team | ||||
|           (setq reconnect-timer | ||||
|                 (run-at-time t reconnect-after-sec | ||||
|                              #'(lambda () (slack-ws-reconnect team)))))))) | ||||
|  | ||||
| (defun slack-ws-init-ping-check-timers () | ||||
|   (make-hash-table :test 'equal)) | ||||
|  | ||||
| (defun slack-ws-cancel-ping-check-timers (team) | ||||
|   (with-slots (ping-check-timers) team | ||||
|     (maphash #'(lambda (key value) | ||||
|                  (if (timerp value) | ||||
|                      (cancel-timer value))) | ||||
|              ping-check-timers) | ||||
|     (setq ping-check-timers (slack-ws-init-ping-check-timers)))) | ||||
|  | ||||
| (defun slack-ws-cancel-ping-timer (team) | ||||
|   (with-slots (ping-timer) team | ||||
|     (if (timerp ping-timer) | ||||
|         (cancel-timer ping-timer)) | ||||
|     (setq ping-timer nil))) | ||||
|  | ||||
| (defvar slack-disconnected-timer nil) | ||||
| (defun slack-notify-abandon-reconnect () | ||||
|   (unless slack-disconnected-timer | ||||
|     (setq slack-disconnected-timer | ||||
|           (run-with-idle-timer 5 t | ||||
|                                #'(lambda () | ||||
|                                    (message "Reconnect Count Exceeded. Manually invoke `slack-start'.")))))) | ||||
|  | ||||
| (defun slack-cancel-notify-adandon-reconnect () | ||||
|   (if (and slack-disconnected-timer | ||||
|            (timerp slack-disconnected-timer)) | ||||
|       (progn | ||||
|         (cancel-timer slack-disconnected-timer) | ||||
|         (setq slack-disconnected-timer nil)))) | ||||
|  | ||||
| (defun slack-ws-reconnect (team &optional force) | ||||
|   (message "Slack Websocket Try To Reconnect") | ||||
|   (with-slots | ||||
|       (reconnect-count (reconnect-max reconnect-count-max)) team | ||||
|     (if (and (not force) reconnect-max (< reconnect-max reconnect-count)) | ||||
|         (progn | ||||
|           (slack-notify-abandon-reconnect) | ||||
|           (slack-ws-cancel-reconnect-timer team)) | ||||
|       (incf reconnect-count) | ||||
|       (slack-ws-close team) | ||||
|       (slack-authorize | ||||
|        team | ||||
|        (cl-function | ||||
|         (lambda | ||||
|           (&key error-thrown &allow-other-keys) | ||||
|           (message "Slack Reconnect Failed: %s" (cdr error-thrown)))))))) | ||||
|  | ||||
| (defun slack-ws-cancel-reconnect-timer (team) | ||||
|   (with-slots (reconnect-timer) team | ||||
|     (if (timerp reconnect-timer) | ||||
|         (cancel-timer reconnect-timer)) | ||||
|     (setq reconnect-timer nil))) | ||||
|  | ||||
| (defun slack-ws-handle-pong (payload team) | ||||
|   (let ((key (plist-get payload :time))) | ||||
|     (with-slots (ping-check-timers) team | ||||
|       (let ((timer (gethash key ping-check-timers))) | ||||
|         (when timer | ||||
|           (cancel-timer timer) | ||||
|           (remhash key ping-check-timers)))))) | ||||
|  | ||||
| (defun slack-ws-handle-room-marked (payload team) | ||||
|   (let ((room (slack-room-find (plist-get payload :channel) | ||||
|                                team)) | ||||
|         (new-unread-count-display (plist-get payload :unread_count_display))) | ||||
|     (with-slots (unread-count-display) room | ||||
|       (setq unread-count-display new-unread-count-display)))) | ||||
|  | ||||
| (provide 'slack-websocket) | ||||
| ;;; slack-websocket.el ends here | ||||
							
								
								
									
										191
									
								
								elpa/slack-20160928.2036/slack.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										191
									
								
								elpa/slack-20160928.2036/slack.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,191 @@ | ||||
| ;;; slack.el --- slack client for emacs              -*- lexical-binding: t; -*- | ||||
|  | ||||
| ;; Copyright (C) 2015  yuya.minami | ||||
|  | ||||
| ;; Author: yuya.minami <yuya.minami@yuyaminami-no-MacBook-Pro.local> | ||||
| ;; Keywords: tools | ||||
| ;; Version: 0.0.2 | ||||
| ;; Package-Requires: ((websocket "1.5") (request "0.2.0") (oauth2 "0.10") (circe "2.3") (alert "1.2") (emojify "0.4") (emacs "24.3")) | ||||
| ;; This program is free software; you can redistribute it and/or modify | ||||
| ;; it under the terms of the GNU General Public License as published by | ||||
| ;; the Free Software Foundation, either version 3 of the License, or | ||||
| ;; (at your option) any later version. | ||||
|  | ||||
| ;; This program is distributed in the hope that it will be useful, | ||||
| ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| ;; GNU General Public License for more details. | ||||
|  | ||||
| ;; You should have received a copy of the GNU General Public License | ||||
| ;; along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  | ||||
| ;;; Commentary: | ||||
|  | ||||
| ;; | ||||
|  | ||||
| ;;; Code: | ||||
| (require 'cl-lib) | ||||
| (require 'oauth2) | ||||
|  | ||||
| (require 'slack-team) | ||||
| (require 'slack-channel) | ||||
| (require 'slack-im) | ||||
| (require 'slack-file) | ||||
| (require 'slack-message-notification) | ||||
| (require 'slack-message-sender) | ||||
| (require 'slack-message-editor) | ||||
| (require 'slack-message-reaction) | ||||
| (require 'slack-user-message) | ||||
| (require 'slack-bot-message) | ||||
| (require 'slack-search) | ||||
| (require 'slack-reminder) | ||||
|  | ||||
| (require 'slack-websocket) | ||||
| (require 'slack-request) | ||||
|  | ||||
| (defgroup slack nil | ||||
|   "Emacs Slack Client" | ||||
|   :prefix "slack-" | ||||
|   :group 'tools) | ||||
|  | ||||
| (defcustom slack-redirect-url "http://localhost:8080" | ||||
|   "Redirect url registered for Slack.") | ||||
| (defcustom slack-buffer-function #'switch-to-buffer-other-window | ||||
|   "Function to print buffer.") | ||||
|  | ||||
| (defvar slack-use-register-team-string | ||||
|   "use `slack-register-team' instead.") | ||||
|  | ||||
| (defcustom slack-client-id nil | ||||
|   "Client ID provided by Slack.") | ||||
| (make-obsolete-variable | ||||
|  'slack-client-id slack-use-register-team-string | ||||
|  "0.0.2") | ||||
| (defcustom slack-client-secret nil | ||||
|   "Client Secret Provided by Slack.") | ||||
| (make-obsolete-variable | ||||
|  'slack-client-secret slack-use-register-team-string | ||||
|  "0.0.2") | ||||
| (defcustom slack-token nil | ||||
|   "Slack token provided by Slack. | ||||
| set this to save request to Slack if already have.") | ||||
| (make-obsolete-variable | ||||
|  'slack-token slack-use-register-team-string | ||||
|  "0.0.2") | ||||
| (defcustom slack-room-subscription '() | ||||
|   "Group or Channel list to subscribe notification." | ||||
|   :group 'slack) | ||||
| (make-obsolete-variable | ||||
|  'slack-room-subscription slack-use-register-team-string | ||||
|  "0.0.2") | ||||
| (defcustom slack-typing-visibility 'frame | ||||
|   "When to show typing indicator. | ||||
| frame means typing slack buffer is in the current frame, show typing indicator. | ||||
| buffer means typing slack buffer is the current buffer, show typing indicator. | ||||
| never means never show typing indicator." | ||||
|   :type '(choice (const frame) | ||||
|                  (const buffer) | ||||
|                  (const never))) | ||||
|  | ||||
| (defconst slack-oauth2-authorize "https://slack.com/oauth/authorize") | ||||
| (defconst slack-oauth2-access "https://slack.com/api/oauth.access") | ||||
| (defconst slack-authorize-url "https://slack.com/api/rtm.start") | ||||
|  | ||||
| (defvar slack-authorize-requests nil) | ||||
| (defun slack-authorize (team &optional error-callback) | ||||
|   (cl-labels | ||||
|       ((abort-previous () (cl-loop for r in (reverse slack-authorize-requests) | ||||
|                                    do (request-abort r)))) | ||||
|     (setq slack-authorize-requests nil) | ||||
|     (let ((request (slack-request | ||||
|                     slack-authorize-url | ||||
|                     team | ||||
|                     :success (cl-function (lambda (&key data &allow-other-keys) | ||||
|                                             (slack-on-authorize data team))) | ||||
|                     :sync nil | ||||
|                     :error error-callback))) | ||||
|       (push request slack-authorize-requests)))) | ||||
|  | ||||
| (defun slack-update-team (data team) | ||||
|   (cl-labels | ||||
|       ((create-rooms | ||||
|         (datum team class) | ||||
|         (mapcar #'(lambda (data) | ||||
|                     (slack-room-create data team class)) | ||||
|                 (append datum nil)))) | ||||
|     (let ((self (plist-get data :self)) | ||||
|           (team-data (plist-get data :team))) | ||||
|       (oset team id (plist-get team-data :id)) | ||||
|       (oset team name (plist-get team-data :name)) | ||||
|       (oset team channels | ||||
|             (create-rooms (plist-get data :channels) | ||||
|                           team 'slack-channel)) | ||||
|       (oset team groups | ||||
|             (create-rooms (plist-get data :groups) | ||||
|                           team 'slack-group)) | ||||
|       (oset team ims | ||||
|             (create-rooms (plist-get data :ims) | ||||
|                           team 'slack-im)) | ||||
|       (oset team self self) | ||||
|       (oset team self-id (plist-get self :id)) | ||||
|       (oset team self-name (plist-get self :name)) | ||||
|       (oset team users (append (plist-get data :users) nil)) | ||||
|       (oset team bots (append (plist-get data :bots) nil)) | ||||
|       (oset team ws-url (plist-get data :url)) | ||||
|       (oset team connected t) | ||||
|       team))) | ||||
|  | ||||
| (cl-defun slack-on-authorize (data team) | ||||
|   (slack-request-handle-error | ||||
|    (data "slack-authorize") | ||||
|    (message "Slack Authorization Finished - %s" | ||||
|             (oref team name)) | ||||
|    (let ((team (slack-update-team data team))) | ||||
|      (with-slots (groups ims channels) team | ||||
|        (cl-loop for room in (append groups ims channels) | ||||
|                 do (let ((bufname (slack-room-buffer-name room))) | ||||
|                      (when (get-buffer bufname) | ||||
|                        (kill-buffer bufname))))) | ||||
|      (slack-ws-open team)))) | ||||
|  | ||||
| (defun slack-on-authorize-e | ||||
|     (&key error-thrown &allow-other-keys &rest_) | ||||
|   (error "slack-authorize: %s" error-thrown)) | ||||
|  | ||||
| (defun slack-oauth2-auth (team) | ||||
|   (with-slots (client-id client-secret) team | ||||
|     (oauth2-auth | ||||
|      slack-oauth2-authorize | ||||
|      slack-oauth2-access | ||||
|      client-id | ||||
|      client-secret | ||||
|      "client" | ||||
|      nil | ||||
|      slack-redirect-url))) | ||||
|  | ||||
| (defun slack-request-token (team) | ||||
|   (with-slots (token) team | ||||
|     (setq token | ||||
|           (oauth2-token-access-token | ||||
|            (slack-oauth2-auth team))))) | ||||
|  | ||||
| ;;;###autoload | ||||
| (defun slack-start (&optional team) | ||||
|   (interactive) | ||||
|   (cl-labels ((start | ||||
|                (team) | ||||
|                (with-slots (ws-conn token) team | ||||
|                  (if ws-conn | ||||
|                      (slack-ws-close team)) | ||||
|                  (unless token | ||||
|                    (slack-request-token team))) | ||||
|                (slack-authorize team))) | ||||
|     (if team | ||||
|         (start team) | ||||
|       (if slack-teams | ||||
|           (cl-loop for team in slack-teams | ||||
|                    do (start team)) | ||||
|         (slack-start (call-interactively #'slack-register-team)))))) | ||||
|  | ||||
| (provide 'slack) | ||||
| ;;; slack.el ends here | ||||
							
								
								
									
										15
									
								
								elpa/websocket-20160720.2051/websocket-autoloads.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								elpa/websocket-20160720.2051/websocket-autoloads.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| ;;; websocket-autoloads.el --- automatically extracted autoloads | ||||
| ;; | ||||
| ;;; Code: | ||||
| (add-to-list 'load-path (directory-file-name (or (file-name-directory #$) (car load-path)))) | ||||
|  | ||||
| ;;;### (autoloads nil nil ("websocket.el") (22533 17547 135674 20000)) | ||||
|  | ||||
| ;;;*** | ||||
|  | ||||
| ;; Local Variables: | ||||
| ;; version-control: never | ||||
| ;; no-byte-compile: t | ||||
| ;; no-update-autoloads: t | ||||
| ;; End: | ||||
| ;;; websocket-autoloads.el ends here | ||||
							
								
								
									
										2
									
								
								elpa/websocket-20160720.2051/websocket-pkg.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								elpa/websocket-20160720.2051/websocket-pkg.el
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| ;;; -*- no-byte-compile: t -*- | ||||
| (define-package "websocket" "20160720.2051" "Emacs WebSocket client and server" 'nil :keywords '("communication" "websocket" "server")) | ||||
							
								
								
									
										1035
									
								
								elpa/websocket-20160720.2051/websocket.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1035
									
								
								elpa/websocket-20160720.2051/websocket.el
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
		Reference in New Issue
	
	Block a user