Update all my elpa files

This commit is contained in:
Mateus Pinto Rodrigues
2018-05-17 18:02:17 -03:00
parent 216ee979b9
commit 0024c08036
860 changed files with 8617 additions and 7072 deletions

View File

@@ -0,0 +1,39 @@
;;; weechat-autoloads.el --- automatically extracted autoloads
;;
;;; Code:
(add-to-list 'load-path (directory-file-name (or (file-name-directory #$) (car load-path))))
;;;### (autoloads nil "weechat" "weechat.el" (23293 60625 349674
;;;;;; 451000))
;;; Generated autoloads from weechat.el
(autoload 'weechat-connect "weechat" "\
Connect to WeeChat.
HOST is the relay host, `weechat-host-default' by default.
PORT is the port where the relay listens, `weechat-port-default' by default.
PASSWORD is either a string, a function or nil.
MODE is null or 'plain for a plain socket, t or 'ssl for a TLS socket;
a string denotes a command to run. You can use %h and %p to interpolate host
and port number respectively.
\(fn &optional HOST PORT PASSWORD MODE FORCE-DISCONNECT)" t nil)
;;;***
;;;### (autoloads nil nil ("weechat-button.el" "weechat-cmd.el" "weechat-color.el"
;;;;;; "weechat-complete.el" "weechat-core.el" "weechat-corrector.el"
;;;;;; "weechat-image.el" "weechat-latex.el" "weechat-notifications.el"
;;;;;; "weechat-pkg.el" "weechat-read-marker.el" "weechat-relay.el"
;;;;;; "weechat-sauron.el" "weechat-secrets.el" "weechat-smiley.el"
;;;;;; "weechat-speedbar.el" "weechat-spelling.el" "weechat-tracking.el")
;;;;;; (23293 60627 145855 345000))
;;;***
;; Local Variables:
;; version-control: never
;; no-byte-compile: t
;; no-update-autoloads: t
;; End:
;;; weechat-autoloads.el ends here

View File

@@ -0,0 +1,348 @@
;;; weechat-button --- Add buttons to text ;; -*- lexical-binding: t -*-
;; Copyright (C) 2013 Rüdiger Sonderfeld <ruediger@c-plusplus.de>
;; Author: Rüdiger Sonderfeld <ruediger@c-plusplus.de>
;; Moritz Ulrich <moritz@tarn-vedra.de>
;; Aristid Breitkreuz <aristidb@gmail.com>
;; Keywords: irc chat network weechat
;; URL: https://github.com/the-kenny/weechat.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 code is heavily inspired by erc-button.el!
;;; Code:
;;
(require 'weechat)
(require 'button)
(require 's)
;;; Customize
(defgroup weechat-button nil
"WeeChat button interface (URLification)."
:link '(url-link "https://github.com/the-kenny/weechat.el")
:prefix "weechat-button"
:group 'weechat)
(defcustom weechat-button-url-regexp
(concat "\\(www\\.\\|\\(s?https?\\|"
"ftp\\|file\\|gopher\\|news\\|telnet\\|wais\\|mailto\\):\\)"
"\\(//[-[:alnum:]_.]+:[0-9]*\\)?"
"[-[:alnum:]_=!?#$@~`%&*+\\/:;.,()]+[-[:alnum:]_=#$@~`%&*+\\/()]")
"Regexp to match URLs.
Copied from erc-button.el."
:type 'regexp
:group 'weechat-button)
(defcustom weechat-button-default-log-buffer "*WeeChat URL Log*"
"Buffer name for URL log.
Valid values include a string describing a buffer name or nil to
disable url logging (except when an explicit buffer name is
defined in `weechat-button-list')"
:group 'weechat-button
:type '(choice (const :tag "No Log" nil)
(string :tag "Buffer Name")))
(defcustom weechat-button-buttonize-url t
"Buttonize url links?"
:group 'weechat-button
:type '(choice (const :tag "Never" nil)
(const :tag "Always" t)
(repeat :tag "If regular expression matches buffer name" regexp)))
(defcustom weechat-button-buttonize-channels t
"Buttonize channel links?"
:group 'weechat-button
:type '(choice (const :tag "Never" nil)
(const :tag "Always" t)
(repeat :tag "If regular expression matches buffer name" regexp)))
(defcustom weechat-button-buttonize-symbols t
"Buttonize symbol links?"
:group 'weechat-button
:type '(choice (const :tag "Never" nil)
(const :tag "Always" t)
(repeat :tag "If regular expression matches buffer name" regexp)))
(defcustom weechat-button-buttonize-emails nil
"Buttonize e-mail link?"
:group 'weechat-button
:type '(choice (const :tag "Never" nil)
(const :tag "Always" t)
(repeat :tag "If regular expression matches buffer name" regexp)))
(defcustom weechat-button-buttonize-man nil
"Buttonize manpage links?
Format is man(1)."
:group 'weechat-button
:type 'boolen)
(defcustom weechat-button-buttonize-info '("#emacs" "#weechat\\.el")
"Buttonize info links?
Format is (info \"link\")."
:group 'weechat-button
:type '(choice (const :tag "Never" nil)
(const :tag "Always" t)
(repeat :tag "If regular expression matches buffer name" regexp)))
(defcustom weechat-button-rfc-url "http://www.faqs.org/rfcs/rfc%s.html"
"URL used to browse rfc references.
%s is replaced by the number."
:group 'weechat-button
:type 'string)
(defcustom weechat-button-buttonize-rfc nil
"Buttonize rfc links?"
:group 'weechat-button
:type '(choice (const :tag "Never" nil)
(const :tag "Always" t)
(repeat :tag "If regular expression matches buffer name" regexp)))
; temporarily disabled due to performance problems
(defcustom weechat-button-buttonize-nicks nil
"Buttonize nicknames?"
:group 'weechat-button
:type '(choice (const :tag "Never" nil)
(const :tag "Always" t)
(repeat :tag "If regular expression matches buffer name" regexp)))
(defcustom weechat-button-list
'((weechat-button-url-regexp 0 weechat-button-buttonize-url t "Browse URL"
browse-url 0)
("#[-#+_.[:alnum:]]+" 0 weechat-button-buttonize-channels nil "Join Channel"
weechat-join 0)
("\\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]\\{2,4\\}\\b" 0 weechat-button-buttonize-emails nil
"email" weechat-button--mailto 0)
("[`]\\([-_.[:alnum:]]+\\)[']" 1 weechat-button-buttonize-symbols nil "Describe Symbol"
weechat-button--describe-symbol 1)
("[[:alpha:][:alnum:]]+([1-9])" 0 weechat-button-buttonize-man nil "Manpage" man 0)
("(info \"\\(([[:alnum:]]+) .+?\\)\"" 1 weechat-button-buttonize-info nil "info"
info 1)
("\\brfc[#: ]?\\([0-9]+\\)" 0 weechat-button-buttonize-rfc nil "RFC"
weechat-button--rfc 1))
"List of potential buttons in WeeChat chat buffers.
Each entry has the form (REGEXP BUTTON-MATCH BUTTONIZE? LOG HELP-ECHO ACTION
DATA-MATCH...), where
REGEXP is a string or variable containing a regular expression to match buttons.
BUTTON-MATCH is the number of the regexp grouping which represents the actual
button.
BUTTONIZE? determines if button should be buttonized.
See `weechat-button--buttonize?' for exact usage.
LOG decides if `weechat-button-log-functions' gets called.
HELP-ECHO is the `help-echo' property of the button.
See Info node `(elisp) Button Properties'.
ACTION the function to call when the button is selected.
DATA-MATCH... numbers of the regexp groupings whose text will be passed to
ACTION.
This is similar (but not identical) to `erc-button-alist' in ERC."
:group 'weechat-button
:type '(repeat :tag "Buttons"
(list (choice :tag "Matches"
regexp
(variable :tag "Variable containing regexp"))
(integer :tag "Number of the regexp section that matches")
(choice :tag "When to buttonize"
(const :tag "Always" t)
(const :tag "Never" nil)
(repeat :tag "If regular expression matches buffer name"
regexp)
(symbol :tag "Variable name"))
(choice :tag "Log match"
(const :tag "To default buffer" t)
(const :tag "Never" nil)
(string :tag "To buffer name"))
(string :tag "Help echo text")
(function :tag "Call this function when button is pressed")
(repeat :tag "Sections of regexp to send to the function"
:inline t
(integer :tag "Regexp section number")))))
(put 'weechat-button-list 'risky-local-variable t)
(defvar weechat-button-log-functions nil
"List of function to run when a button should be logged.
This hook only runs when `LOG' is set to t for the particular
button type.
Functions in list must have two arguments: The button data (the
match string) and a plist describing the button properties.
The functions in this list will be called with
`weechat-narrow-to-line' active.")
;;; Internal functions
(defun weechat-button--handler (button)
"Handle BUTTON actions.
The function in property `weechat-function' gets called with `weechat-data'."
(let ((function (button-get button 'weechat-function))
(data (button-get button 'weechat-data)))
(when function
(apply function data))))
(defun weechat-button--log-to-buffer (button-data button-properties)
(when (and weechat-button-default-log-buffer)
(let ((weechat-buffer-name (buffer-name)))
(with-current-buffer (get-buffer-create
weechat-button-default-log-buffer)
(goto-char (point-max))
(unless (bolp)
(insert "\n"))
(insert weechat-buffer-name "\t")
(apply #'insert-button button-data button-properties)
(insert "\n")))))
(add-hook 'weechat-button-log-functions 'weechat-button--log-to-buffer)
(defun weechat-button--buttonize? (buttonize?)
"Return non-nil if BUTTONIZE? says so.
Return non-nil if BUTTONIZE?:
- is t,
- is a list of strings and one of the strings matches the channel name,
- is a variable then apply the rules to the value of the variable."
(when (and (symbolp buttonize?) (boundp buttonize?))
(setq buttonize? (symbol-value buttonize?)))
(cond
((listp buttonize?)
(let ((name (buffer-name)) ret)
(dolist (i buttonize? ret)
(when (s-matches? i name)
(setq ret t)))))
(t t)))
(defvar weechat-button-log-buffer-last-log nil)
(defun weechat-button--add-do (entry &optional text-buttons)
"Handle each button ENTRY.
If TEXT-BUTTONS is non-nil then use `make-text-button instead of `make-button'."
(save-excursion
(goto-char (point-min))
(cl-destructuring-bind
(regexp-entry button-match buttonize?
log help-echo action &rest data-match) entry
(let* ((regexp (or (and (stringp regexp-entry) regexp-entry)
(and (boundp regexp-entry) (symbol-value regexp-entry))))
(line-date (weechat-line-date))
(run-hooks?
(and line-date
(or (null weechat-button-log-buffer-last-log)
(time-less-p weechat-button-log-buffer-last-log
line-date))))
(button-fn (if text-buttons
#'make-text-button
#'make-button)))
(when regexp
(while (re-search-forward regexp nil t)
(let ((start (match-beginning button-match))
(end (match-end button-match))
(button-data-no-properties
(match-string-no-properties button-match))
(data (mapcar #'match-string data-match)))
(when (and (weechat-button--buttonize? buttonize?)
;; Don't overlap buttons
;; Handles text-buttons and overlay-buttons
(cl-every (lambda (o)
(null (overlay-get o 'button)))
(overlays-in start end))
(not (text-property-not-all start end 'button nil)))
(let ((properties (list 'action #'weechat-button--handler
'help-echo help-echo
'follow-link t
'weechat-function action
'weechat-data data)))
(when (and log
run-hooks?)
;; Hack: Rebind `weechat-button-default-log-buffer'
;; to the value supplied by the button type in
;; `weechat-button-list'
(let ((weechat-button-default-log-buffer
(if (or (stringp log) (bufferp log))
log
weechat-button-default-log-buffer)))
(run-hook-with-args 'weechat-button-log-functions
button-data-no-properties
properties))
(setq weechat-button-log-buffer-last-log line-date))
(apply button-fn start end properties))))))))))
(defun weechat-button--add ()
"Add text buttons to text in buffer."
(dolist (i weechat-button-list)
(weechat-button--add-do i))
(when weechat-button-buttonize-nicks
(weechat-button--add-nickname-buttons)))
(defvar weechat-user-list) ;; See weechat.el
(defun weechat-button--add-nickname-buttons ()
"Add nick name buttons."
(dolist (nick weechat-user-list)
(unless (s-blank? nick)
(weechat-button--add-do (list (concat "\\b" (regexp-quote nick) "\\b")
0 t 0 "Nick Action"
#'weechat-nick-action
0)
'text-button))))
;;; Callback functions
;; This function is copied from `erc-button-describe-symbol'
(defun weechat-button--describe-symbol (symbol-name)
"Describe SYMBOL-NAME.
Use `describe-function' for functions, `describe-variable' for variables,
and `apropos' for other symbols."
(let ((symbol (intern-soft symbol-name)))
(cond ((and symbol (fboundp symbol))
(describe-function symbol))
((and symbol (boundp symbol))
(describe-variable symbol))
(t (apropos symbol-name)))))
(defun weechat-button--mailto (email)
"Call `browse-url' on email with \"mailto:\" prepend."
(browse-url (concat "mailto:" email)))
(defun weechat-button--rfc (rfc)
"Call `browse-url' on RFC using `weechat-button-rfc-url'."
(browse-url (format weechat-button-rfc-url rfc)))
;;; Module load/unload
;;; This is done automatically by `load-library' or `require'.
;;; Unloading is taken care of, because hooks added via `add-hook'
;;; will be removed automatically by `unload-feature'.
;;; If you need special cleanup code, use define a function named
;;; `FEATURE-unload-function'. This function will be called by emacs
;;; right before unloading the feature. Check the docstring of
;;; `unload-feature' for details.
(add-hook 'weechat-insert-modify-hook #'weechat-button--add)
(provide 'weechat-button)
;;; weechat-button.el ends here

Binary file not shown.

View File

@@ -0,0 +1,79 @@
;;; weechat-cmd.el --- Define local weechat commands in elisp
;; Copyright (C) 2013 Moritz Ulrich <moritz@tarn-vedra.de>
;; Author: Moritz Ulrich <moritz@tarn-vedra.de>
;; Rüdiger Sonderfeld <ruediger@c-plusplus.de>
;; Aristid Breitkreuz <aristidb@gmail.com>
;; Keywords: irc chat network weechat
;; URL: https://github.com/the-kenny/weechat.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 modules allows the user to write Emacs Lisp functions which
;; are callable in weechat buffers via normal irc /command syntax.
;;
;; Function names must start with `weechat-cmd-function-prefix' and
;; take one argument, the input of the user.
;;
;; They might return either a string or nil. In case of string the
;; value will be sent to the server. If the return value is nil, the
;; command will be discarded. This is useful if you want to execute
;; local code but not send anything to the server.
;;; Code:
(require 'weechat)
(require 's)
(require 'cl-lib)
(defconst weechat-cmd-function-prefix "weechat-command-")
(defcustom weechat-cmd-prefix "/"
"Prefix used for cmd commands."
:type 'string
:group 'weechat-cmd)
(defun weechat-cmd-find-cmds ()
(let (ret)
(mapatoms
(lambda (x)
(when (s-prefix? weechat-cmd-function-prefix (symbol-name x))
(setq ret (cons x ret)))))
ret))
(defun weechat-cmd-apply (input)
(if (s-prefix? weechat-cmd-prefix input)
(let* ((command (car
(s-split-words
(s-chop-prefix
weechat-cmd-prefix
input))))
(sym (intern-soft (concat weechat-cmd-function-prefix
command)))
(fn (when (fboundp sym)
(symbol-function sym))))
(if (functionp fn)
(funcall fn input)
input))
input))
(add-hook 'weechat-message-filter-functions #'weechat-cmd-apply)
(provide 'weechat-cmd)
;;; weechat-cmd.el ends here

Binary file not shown.

View File

@@ -0,0 +1,379 @@
;;; weechat-color --- Color handling for WeeChat ;; -*- lexical-binding: t -*-
;; Copyright (C) 2013 Moritz Ulrich, Rüdiger Sonderfeld
;; Author: Moritz Ulrich <moritz@tarn-vedra.de>
;; Rüdiger Sonderfeld <ruediger@c-plusplus.de>
;; Aristid Breitkreuz <aristidb@gmail.com>
;; Keywords: irc chat network weechat
;; URL: https://github.com/the-kenny/weechat.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:
;; WeeChat comes with its own (ridiculously complicated) set of color codes.
;; See URL `http://www.weechat.org/files/doc/devel/weechat_dev.en.html#color_codes_in_strings'
;;; Code:
(require 'weechat-core)
(require 'rx)
(require 's)
(defgroup weechat-faces nil
"WeeChat Faces and Color settings"
:link '(url-link "https://github.com/the-kenny/weechat.el")
:prefix "weechat-"
:group 'weechat)
(defface weechat-nick-self-face '((t :weight bold :foreground "brown"))
"Face for your own nick."
:group 'weechat-faces)
(defface weechat-time-face '((t :inherit default))
"Weechat face used for timestamps."
:group 'weechat-faces)
(defface weechat-prompt-face '((t :inherit minibuffer-prompt))
"Weechat face used for the prompt."
:group 'weechat-faces)
(defface weechat-highlight-face
'((((class grayscale) (background light)) :foreground "LightGray" :weight bold)
(((class grayscale) (background dark)) :foreground "DimGray" :weight bold)
(((class color) (min-colors 88) (background light)) :foreground "Purple")
(((class color) (min-colors 88) (background dark)) :foreground "Cyan1")
(((class color) (min-colors 16) (background light)) :foreground "Purple")
(((class color) (min-colors 16) (background dark)) :foreground "Cyan")
(((class color) (min-colors 8)) :foreground "cyan" :weight bold)
(t :weight bold)) ;; Stolen from rcirc.el!
"Weechat face for highlighted lines."
:group 'weechat-faces)
(defface weechat-error-face '((t :inherit error))
"Weechat face used to display errors."
:group 'weechat-faces)
(defcustom weechat-strip-formatting nil
"Remove every kind of formatting or color from messages.
This will look very bland!"
:type 'boolean
:group 'weechat-faces)
(defvar weechat-formatting-regex
(let* ((attr `(in "*!/_|")) ;NOTE:  is not documented
(std `(= 2 digit))
(astd `(seq ,attr (= 2 digit)))
(ext `(seq "@" (= 5 digit)))
(aext `(seq "@" ,attr (= 5 digit))))
(rx-form
`(or (seq ""
(or ,std
,ext
(seq "F" (or ,std ,astd ,ext ,aext))
(seq "B" (or ,std ,ext))
(seq "*" (or ,std
,astd
,ext
,aext
(seq (or ,std ,astd ,ext ,aext)
","
(or ,std ,astd ,ext ,aext))))
(seq "b" (in "FDB_-#il"))
""))
(seq "" ,attr)
(seq "" ,attr)
""))))
(defun weechat-strip-formatting (string)
"Strip weechat color codes from STRING."
(if (stringp string)
(replace-regexp-in-string weechat-formatting-regex "" string)
string))
(defcustom weechat-color-list '(unspecified "black" "dark gray" "dark red" "red"
"dark green" "light green" "brown"
"yellow" "dark blue" "light blue"
"dark magenta" "magenta" "dark cyan"
"light cyan" "gray" "white")
"Mapping of Weechat colors.
Do NOT remove or add new elements to the list. Only change the values.
See URL `http://www.weechat.org/files/doc/devel/weechat_dev.en.html#color_codes_in_strings'."
:type '(repeat (choice (const :tag "Unspecified" unspecified)
(const :tag "Color" color)))
:group 'weechat)
(defvar weechat-color-attributes-alist '((?* . (:weight bold)) (?\1 . (:weight bold)) ; bold
(?! . (:inverse-video t)) (?\2 . (:inverse-video t)) ; reverse??
(?/ . (:slant italic)) (?\3 . (:slant italic)) ; italic
(?_ . (:underline t)) (?\4 . (:underline t)) ; underline
(?| . keep)) ; keep
"Map color attribute specifiers to Emacs face property.")
(defvar weechat-terminal-colors
(concat
"000000cd000000cd00cdcd000000cdcd00cd00cdcde5e5e5"
"4d4d4dff000000ff00ffff000000ffff00ff00ffffffffff"
"00000000002a0000550000800000aa0000d4002a00002a2a"
"002a55002a80002aaa002ad400550000552a005555005580"
"0055aa0055d400800000802a0080550080800080aa0080d4"
"00aa0000aa2a00aa5500aa8000aaaa00aad400d40000d42a"
"00d45500d48000d4aa00d4d42a00002a002a2a00552a0080"
"2a00aa2a00d42a2a002a2a2a2a2a552a2a802a2aaa2a2ad4"
"2a55002a552a2a55552a55802a55aa2a55d42a80002a802a"
"2a80552a80802a80aa2a80d42aaa002aaa2a2aaa552aaa80"
"2aaaaa2aaad42ad4002ad42a2ad4552ad4802ad4aa2ad4d4"
"55000055002a5500555500805500aa5500d4552a00552a2a"
"552a55552a80552aaa552ad455550055552a555555555580"
"5555aa5555d455800055802a5580555580805580aa5580d4"
"55aa0055aa2a55aa5555aa8055aaaa55aad455d40055d42a"
"55d45555d48055d4aa55d4d480000080002a800055800080"
"8000aa8000d4802a00802a2a802a55802a80802aaa802ad4"
"80550080552a8055558055808055aa8055d480800080802a"
"8080558080808080aa8080d480aa0080aa2a80aa5580aa80"
"80aaaa80aad480d40080d42a80d45580d48080d4aa80d4d4"
"aa0000aa002aaa0055aa0080aa00aaaa00d4aa2a00aa2a2a"
"aa2a55aa2a80aa2aaaaa2ad4aa5500aa552aaa5555aa5580"
"aa55aaaa55d4aa8000aa802aaa8055aa8080aa80aaaa80d4"
"aaaa00aaaa2aaaaa55aaaa80aaaaaaaaaad4aad400aad42a"
"aad455aad480aad4aaaad4d4d40000d4002ad40055d40080"
"d400aad400d4d42a00d42a2ad42a55d42a80d42aaad42ad4"
"d45500d4552ad45555d45580d455aad455d4d48000d4802a"
"d48055d48080d480aad480d4d4aa00d4aa2ad4aa55d4aa80"
"d4aaaad4aad4d4d400d4d42ad4d455d4d480d4d4aad4d4d4"
"0808081212121c1c1c2626263030303a3a3a4444444e4e4e"
"5858586262626c6c6c7676768080808a8a8a9494949e9e9e"
"a8a8a8b2b2b2bcbcbcc6c6c6d0d0d0dadadae4e4e4eeeeee"))
(defun weechat--match-color-code (what str i)
"Match std, ext, attr WHAT on STR at position I.
This is internal and used by `weechat-handle-color-codes'."
(when (symbolp what)
(cl-case what
((std)
(let ((std (substring str i (+ i 2))))
(when (s-matches? "^[0-9]+$" std)
(list 'std (+ i 2) (string-to-number std)))))
((ext)
(when (= (aref str i) ?@)
(let ((std (substring str (1+ i) (+ i 6))))
(when (s-matches? "^[0-9]+$" std)
(list 'ext (+ i 6) (string-to-number std))))))
((attr)
(let* ((a (aref str i))
(x (cdr (assq a weechat-color-attributes-alist))))
(when x
(list 'attr (1+ i) x))))
(t (error "Unknown parameter %s" what)))))
(defun weechat--color-keep-attributes (old-face)
"Remove color settings from OLD-FACE but keep the attributes."
(cl-delete-if (lambda (x)
(memq (car x) '(:foreground :background)))
old-face))
(defun weechat--rgb-color (index)
(let* ((colors (substring weechat-terminal-colors (* index 6)))
(r (* 0.85 (string-to-number (substring colors 0 2) 16)))
(g (* 0.85 (string-to-number (substring colors 2 4) 16)))
(b (* 0.85 (string-to-number (substring colors 4 6) 16))))
(format "#%02x%02x%02x" r g b)))
(defun weechat--color-handle-F (str i old-face)
"Handle ?F (A)STD|(A)EXT color code in STR at I with OLD-FACE.
This is an internal function of `weechat-handle-color-codes'."
(let (match-data
face
(j (1+ i)))
(while (setq match-data (weechat--match-color-code 'attr str j)) ;; (A)
(if (eq (cl-third match-data) 'keep)
(setq face (weechat--color-keep-attributes old-face))
(setq face (append (list (cl-third match-data)) face)))
(setq j (cl-second match-data)))
(setq match-data (weechat--match-color-code 'std str j))
(if match-data
(setq face (append (list (list :foreground (nth (cl-third match-data)
weechat-color-list)))
face)) ;; TODO set attribute instead of simply append
(setq match-data (weechat--match-color-code 'ext str j))
(if match-data
(setq face (list (list :foreground (weechat--rgb-color (cl-third match-data)))))
(weechat-relay-log (format "Broken color code (in ?F '%s' %s)" str i)
:warn)))
(if match-data
(cl-values (cl-second match-data)
face)
(cl-values j face))))
(defvar weechat-color-options-list
'(("weechat.color.separator" . "blue") ;; KEEP THE ORDER!
("weechat.color.chat" . default)
("weechat.color.chat_time" . weechat-time-face)
("weechat.color.chat_time_delimiters" . weechat-time-face)
("weechat.color.chat_prefix_error" . "yellow")
("weechat.color.chat_prefix_network" . "magenta")
("weechat.color.chat_prefix_action" . "white")
("weechat.color.chat_prefix_join" . "light green")
("weechat.color.chat_prefix_quit" . "orange red") ;; light red
("weechat.color.chat_prefix_more" . "medium violet red") ;; light magenta
("weechat.color.chat_prefix_suffix" . "green")
("weechat.color.chat_buffer" . "white")
("weechat.color.chat_server" . "brown")
("weechat.color.chat_channel" . "white")
("weechat.color.chat_nick" . "light cyan")
("weechat.color.chat_nick_self" . weechat-nick-self-face)
("weechat.color.chat_nick_other" . "cyan")
(nil . default)
(nil . default)
(nil . default)
(nil . default)
(nil . default)
(nil . default)
(nil . default)
(nil . default)
(nil . default)
(nil . default)
("weechat.color.chat_host" . "cyan")
("weechat.color.chat_delimiters" . "green")
("weechat.color.chat_highlight" . weechat-highlight-face)
("weechat.color.chat_read_marker" . "magenta")
("weechat.color.chat_text_found" . "yellow")
("weechat.color.chat_value" . "cyan")
("weechat.color.chat_prefix_buffer")
("weechat.color.chat_tags" . "red")
("weechat.color.chat_inactive_window" . "dark grey")
("weechat.color.chat_inactive_buffer" . "dark grey")
("weechat.color.chat_prefix_buffer_inactive_buffer" . "dark grey")
("weechat.color.chat_nick_offline" . "dark grey")
("weechat.color.chat_nick_offline_highlight" . default))
"List of color options for \x19XX.")
;; TODO every option here should probably be a face!
(defun weechat--color-std-to-theme (num)
"Turn color code in NUM using option into face."
(if (or (not (integerp num))
(> num (length weechat-color-options-list)))
'default
(let ((face (cdr (nth num weechat-color-options-list))))
(if (stringp face) ;; color value
(list (list :foreground face ))
face))))
(defun weechat-handle-color-codes (str)
"Convert the Weechat color codes in STR to properties.
EXT colors are currently not supported. Any color codes left are stripped.
Be aware that Weechat does not use mIRC color codes.
See URL `http://www.weechat.org/files/doc/devel/weechat_dev.en.html#color_codes_in_strings'."
(let ((i 0)
face
(ret "")
(len (length str)))
(while (< i len)
(cl-case (aref str i)
((?\x19) ;; STD|EXT|?F((A)STD|(A)EXT)|?B(STD|EXT)|?\x1C|?*...|?b...
(let ((old-face face)
(next (aref str (1+ i))))
(setq face nil)
(setq i (1+ i))
(cond
((and (<= ?0 next) (<= next ?9)) ;; STD
(let ((match-data (weechat--match-color-code 'std str i)))
(when match-data
(setq face (weechat--color-std-to-theme (cl-third match-data)))
(setq i (cl-second match-data)))))
((= next ?@) ;; EXT
(let ((match-data (weechat--match-color-code 'ext str i)))
(when match-data
;; TODO
(setq i (cl-second match-data)))))
((= next ?F) ;; ?F(A)STD|?F(A)EXT
(cl-multiple-value-setq (i face) (weechat--color-handle-F str i old-face)))
((= next ?B) ;; ?BSTD|?BEXT
(let ((match-data (weechat--match-color-code 'std str i)))
(if match-data
(setq face (list (list :background (nth (cl-third match-data)
weechat-color-list))))
(setq match-data (weechat--match-color-code 'ext str i))
(if match-data
t ;; TODO ext
(weechat-relay-log (format "Broken color code (in ?B '%s' %s)" str i)
:warn)))
(setq i (if match-data
(cl-second match-data)
(1+ i)))))
((= next ?*) ;; (A)STD | (A)EXT | (A)STD ?, (A)STD | ...
(cl-multiple-value-setq (i face) (weechat--color-handle-F str i old-face))
(if (= (aref str i) ?,)
(let* ((i (1+ i))
(match-data (weechat--match-color-code 'std str i)))
(if match-data
(setq face (append (list (list :background (nth (cl-third match-data)
weechat-color-list)))
face))
(setq match-data (weechat--match-color-code 'ext str i))
(if match-data
t ;; TODO ext
(weechat-relay-log (format "Broken color code (in ?* '%s' %s)" str i)
:warn)))
(setq i (if match-data
(cl-second match-data)
(1+ i))))))
((= next ?b) 'b) ;; ignore for now
((= next ?\x1C) ;; Clear color, leave attributes
(setq face (weechat--color-keep-attributes old-face))))))
((?\x1A) ;; Set ATTR
(let ((match-data (weechat--match-color-code 'attr str (1+ i))))
(if (not match-data)
(progn
(weechat-relay-log (format "Broken color code (in ?\\x1A '%s' %s)" str i)
:warn)
(setq i (1+ i)))
(if (eq (cl-third match-data) 'keep)
(setq face (weechat--color-keep-attributes face))
(setq face (list (cl-third match-data))))
(setq i (cl-second match-data)))))
((?\x1B) ;; Delete ATTR
(let ((match-data (weechat--match-color-code 'attr str (1+ i)))
(old-face (copy-sequence face)))
(if (not match-data)
(progn
(weechat-relay-log (format "Broken color code (in ?\\x1B '%s' %s)" str i)
:warn)
(setq i (1+ i)))
(if (eq (cl-third match-data) 'keep)
(setq face nil) ;; TODO Does keep here means delete all or keep all?
(setq face (delq (cl-third match-data) old-face)))
(setq i (cl-second match-data)))))
((?\x1C) (setq i (1+ i) face nil))) ;; reset face
(let ((r (string-match-p "\\(\x19\\|\x1A\\|\x1B\\|\x1C\\)" str i)))
(if r
(setq ret (concat ret
(propertize (substring str i r) 'face (or face 'default)))
i r)
(setq ret (concat ret (propertize (substring str i) 'face (or face 'default)))
i len)))) ;; STOP
ret))
(provide 'weechat-color)
;;; weechat-color.el ends here

Binary file not shown.

View File

@@ -0,0 +1,188 @@
;;; weechat-complete --- completions for weechat.el. ;; -*- lexical-binding: t -*-
;; Copyright (C) 2013 Rüdiger Sonderfeld
;; Parts copied from `erc-pcomplete.el' are
;; Copyright (C) 2002-2004, 2006-2013 Free Software Foundation, Inc.
;; Author: Rüdiger Sonderfeld <ruediger@c-plusplus.de>
;; Moritz Ulrich <moritz@tarn-vedra.de>
;; Aristid Breitkreuz <aristidb@gmail.com>
;; Martin Yrjölä <martin.yrjola@gmail.com>
;; Keywords: irc chat network weechat
;; URL: https://github.com/the-kenny/weechat.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:
;; Completions for weechat.el. Parts of the code are copied from
;; `erc-pcomplete.el'.
;;; Code:
(require 'weechat)
(require 'pcomplete)
(require 's)
(defvar weechat-user-list)
(defvar weechat-prompt-end-marker)
(defcustom weechat-complete-nick-prefix-and-postfix-alist nil
"Alist of nick prefixes and postfixes to use for certain
buffers Each element looks like (BUFFER-NAME-REGEXP
. (NICK-PREFIX . NICK-POSTFIX). If BUFFER-NAME-REGEXP matches the
current buffer, then NICK-PREFIX is pushed to the beginning of
each nick in `weechat-user-list' and NICK-POSTFIX is appended to
them. One common use case is that a messaging service provides an
IRC server (e.g. Flowdock and Gitter), but the mentions have to
be prefixed with '@' to be highlighted in the other clients."
:type '(alist :key-type regexp :value-type (cons string string))
:group 'weechat)
(defcustom weechat-complete-nick-postfix ":"
"Postfix to nick completions at the beginning of the prompt.
Can be overriden by `weechat-complete-nick-prefix-and-postfix-alist'"
:type 'string
:group 'weechat)
(defcustom weechat-complete-nick-ignore-self t
"Wether to ignore yourself when completing at the begginning of
the input line
Make sure to rebuild each buffer after changing this variable."
:type 'boolean
:group 'weechat)
(defun weechat-pcompletions-at-point ()
"WeeChat completion data from pcomplete.
for use on `completion-at-point-function'.
Copied from `erc-pcompletions-at-point'."
(when (and (eq major-mode 'weechat-mode)
(>= (point) weechat-prompt-end-marker))
(or (let ((pcomplete-default-completion-function #'ignore))
(pcomplete-completions-at-point))
(let ((c (pcomplete-completions-at-point)))
(if c (nconc c '(:exclusive no)))))))
(defun pcomplete-weechat-setup ()
"Setup pcomplete for `weechat-mode'."
(set (make-local-variable 'pcomplete-ignore-case) t)
(set (make-local-variable 'pcomplete-use-paring) nil)
(set (make-local-variable 'pcomplete-parse-arguments-function)
#'pcomplete-weechat-parse-arguments)
(set (make-local-variable 'pcomplete-command-completion-function)
#'pcomplete/weechat/complete-command)
(set (make-local-variable 'pcomplete-command-name-function)
#'pcomplete-weechat-command-name)
(set (make-local-variable 'pcomplete-default-completion-function)
(lambda () (pcomplete-here (pcomplete-weechat-nicks)))))
(defun pcomplete-weechat-parse-arguments ()
"Return a list of parsed whitespace-separated arguments.
These are the words from the beginning of the line after the prompt
up to where point is right now.
Copied from `pcomplete-erc-parse-arguments'."
(let* ((start weechat-prompt-end-marker)
(end (point))
args beginnings)
(save-excursion
(when (< (skip-chars-backward " \t\n" start) 0)
(setq args '("")
beginnings (list end)))
(setq end (point))
(while (< (skip-chars-backward "^ \t\n" start) 0)
(setq beginnings (cons (point) beginnings)
args (cons (buffer-substring-no-properties
(point) end)
args))
(skip-chars-backward " \t\n" start)
(setq end (point))))
(cons args beginnings)))
(defun pcomplete-weechat-command-name ()
"Return the command name of the first argument.
Copied from `pcomplete-erc-command-name'."
(if (eq (aref (pcomplete-arg 'first) 0) ?/)
(upcase (substring (pcomplete-arg 'first) 1))
"SAY"))
(defun pcomplete/weechat/complete-command ()
"Complete the initial command argument."
(pcomplete-here
(append
(pcomplete-weechat-commands)
(pcomplete-weechat-nicks weechat-complete-nick-postfix weechat-complete-nick-ignore-self))))
(defun pcomplete/weechat-mode/WHOIS ()
(pcomplete-here (pcomplete-weechat-all-nicks)))
(defun pcomplete/weechat-mode/QUERY ()
(pcomplete-here (pcomplete-weechat-all-nicks)))
(defun pcomplete/weechat-mode/SAY ()
(while (pcomplete-here (pcomplete-weechat-nicks))))
(defun pcomplete-weechat-commands ()
"Return a list of user commands."
'("/NICK" "/JOIN" "/PART" "/WHOIS" "/QUERY")) ;; TODO
(defun pcomplete-weechat-nicks (&optional postfix ignore-self)
"Return a list of nicks in the current channel.
POSTFIX is an optional string to append to the nickname.
If IGNORE-SELF is non-nil the users nick is ignored."
(let* ((users weechat-user-list)
(prefix-and-postfix
(weechat-complete-nick-prefix-and-postfix-for-current-buffer))
(nick-prefix (car prefix-and-postfix))
(nick-postfix (if prefix-and-postfix
(cdr prefix-and-postfix)
postfix)))
(when ignore-self
(setq users (delete (weechat-get-local-var "nick") users)))
(mapcar (lambda (nick)
(concat
nick-prefix
nick
nick-postfix)) users)))
(defun weechat-complete-nick-prefix-and-postfix-for-current-buffer ()
"Returns the nick-prefix-and-postfix for the current buffer.
The format is (nick-prefix . nick-postfix)."
(let ((found-nick-prefix-and-postfix nil))
(mapc (lambda (element)
(let ((buffer-name-regexp (car element))
(nick-prefix-and-postfix (cdr element)))
(when (string-match buffer-name-regexp (buffer-name))
(setq found-nick-prefix-and-postfix nick-prefix-and-postfix))))
weechat-complete-nick-prefix-and-postfix-alist)
found-nick-prefix-and-postfix))
(defun pcomplete-weechat-all-nicks ()
"Return nick list of all weechat buffers."
(let (result)
(weechat-do-buffers
(setq result (cl-union weechat-user-list result :test #'s-equals?)))
result))
(weechat-do-buffers (pcomplete-weechat-setup))
(add-hook 'weechat-mode-hook #'pcomplete-weechat-setup)
(add-hook 'completion-at-point-functions #'weechat-pcompletions-at-point)
(provide 'weechat-complete)
;;; weechat-complete.el ends here

Binary file not shown.

View File

@@ -0,0 +1,101 @@
;;; weechat-core --- Basic stuff for weechat.el ;; -*- lexical-binding: t -*-
;; Copyright (C) 2013 Moritz Ulrich
;; Author: Moritz Ulrich <moritz@tarn-vedra.de>
;; Rüdiger Sonderfeld <ruediger@c-plusplus.de>
;; Aristid Breitkreuz <aristidb@gmail.com>
;; Keywords: irc chat network weechat
;; URL: https://github.com/the-kenny/weechat.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 package provides a way to chat via WeeChat's relay protocol in
;; Emacs.
;; Please see README.org on how to use it.
;;; Code:
(require 'cl-lib)
(require 's)
(defgroup weechat nil
"WeeChat based IRC client for Emacs."
:link '(url-link "https://github.com/the-kenny/weechat.el")
:prefix "weechat-"
:group 'applications)
(defgroup weechat-relay nil
"WeeChat Relay Settings."
:link '(url-link "https://github.com/the-kenny/weechat.el")
:prefix "weechat-relay"
:group 'weechat)
(defcustom weechat-relay-log-buffer-name "*weechat-relay-log*"
"Buffer name to use as debug log.
Set to nil to disable logging."
:type 'string
:group 'weechat-relay)
(defcustom weechat-relay-log-level :info
"Minimum log level.
Might be one of :debug, :info, :warn, :error or nil."
:type '(choice (const :tag "Off" nil)
(const :tag "Error" :error)
(const :tag "Warnings" :warn)
(const :tag "Info" :info)
(const :tag "Debug" :debug))
:group 'weechat-relay)
(defun weechat-relay-log (text &optional level)
"Log `TEXT' to `weechat-relay-log-buffer-name' if enabled.
`LEVEL' might be one of :debug :info :warn :error. Defaults
to :info"
(let ((log-level-alist '((:debug . 0)
(:info . 1)
(:warn . 2)
(:error . 3))))
(when (and (>= (assoc-default (or level :info) log-level-alist)
(assoc-default weechat-relay-log-level log-level-alist))
weechat-relay-log-level
weechat-relay-log-buffer-name)
(with-current-buffer (get-buffer-create weechat-relay-log-buffer-name)
(let ((old-point (point)))
(save-excursion
(save-restriction
(widen)
(goto-char (point-max))
(insert (s-trim text))
(newline)))
(goto-char old-point))))))
(defun weechat-warn (message &rest args)
"Display MESSAGE with `warn' and log it to `weechat-relay-log-buffer-name'."
(let ((str (apply 'format message args)))
(weechat-relay-log str :warn)
(display-warning 'weechat str)))
(defun weechat-message (format-string &rest args)
"Log MESSAGE with log-level :info and call `message'."
(let ((text (apply 'format format-string args)))
(weechat-relay-log text :info)
(message text)))
(provide 'weechat-core)
;;; weechat-core.el ends here

Binary file not shown.

View File

@@ -0,0 +1,118 @@
;;; weechat-corrector.el --- Fix your messages using s/foo/bar/ syntax
;; Copyright (C) 2013 Moritz Ulrich <moritz@tarn-vedra.de>
;; Author: Moritz Ulrich <moritz@tarn-vedra.de>
;; Rüdiger Sonderfeld <ruediger@c-plusplus.de>
;; Aristid Breitkreuz <aristidb@gmail.com>
;; Keywords: irc chat network weechat
;; URL: https://github.com/the-kenny/weechat.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 module implements support to fix your own messages via the
;; s/foo/bar/ syntax.
;;; Code:
(require 'weechat)
(require 's)
(defgroup weechat-corrector nil
"This module implements support to fix your own messages via the s/foo/bar/ syntax."
:link '(url-link "https://github.com/the-kenny/weechat.el")
:prefix "weechat-corrector"
:group 'weechat)
(defcustom weechat-corrector-search-limit 5
"How many previous lines to check for corrections."
:type 'integer
:group 'weechat-corrector)
(defcustom weechat-corrector-replace-limit 1
"Limit to N replacements."
:type 'integer
:group 'weechat-corrector)
(defcustom weechat-corrector-correct-other nil
"Whether to apply corrections by other people.
Warning: Setting this to non-nil MIGHT be a security problem as untrusted
regular expression will be interpreted by `re-search-forward'."
:type 'boolean
:group 'weechat-corrector)
(defcustom weechat-corrector-support-plain-parentheses nil
"If non-nil, s/a(.)c/\1/ will replace 'abc' with 'b'.
If nil, parentheses must be quotedL s/a\(.\)c/\1/."
:type 'boolean
:group 'weechat-corrector)
(defface weechat-corrector-corrected-face '((t :inherit default))
"Face used to highlight corrected text."
:group 'weechat-corrector)
(defun weechat-corrector-quote-parentheses (re)
(if weechat-corrector-support-plain-parentheses
(weechat->>
re
(s-replace "(" "\\(")
(s-replace ")" "\\)"))
re))
(defvar weechat-corrector-regex "s/\\(.+\\)/\\(.*\\)/")
(defun weechat-corrector-apply ()
(let ((nick (weechat-line-nick))
(line (weechat-line-text)))
(when (and (or weechat-corrector-correct-other
(string= (weechat-line-nick)
(weechat-get-local-var "nick")))
line
(stringp line))
(let* ((text-start (weechat-line-text-start))
(match (s-match weechat-corrector-regex line)))
(when (>= (length match) 3)
(let ((re (weechat-corrector-quote-parentheses
(cadr match)))
(rp (caddr match)))
(save-excursion
(save-restriction
(widen)
(goto-char (point-at-bol))
(let ((count 0))
(dotimes (i weechat-corrector-search-limit)
(when (< count weechat-corrector-replace-limit)
(save-restriction
(let ((line-move-visual nil))
(forward-line -1))
(weechat-narrow-to-line)
(goto-char (weechat-line-text-start))
(when (and (string= nick (weechat-line-nick))
(re-search-forward re nil t))
(replace-match rp)
;; Add `weechat-corrector-corrected-face'
(add-text-properties (match-beginning 0) (match-end 0)
'(face weechat-corrector-corrected-face))
(setq count (1+ count)))))))))))))))
(add-hook 'weechat-insert-modify-hook 'weechat-corrector-apply)
(provide 'weechat-corrector)
;;; weechat-corrector.el ends here

Binary file not shown.

View File

@@ -0,0 +1,338 @@
;;; weechat-image --- Image preview ;; -*- lexical-binding: t -*-
;; Copyright (C) 2013 Rüdiger Sonderfeld <ruediger@c-plusplus.de>
;; Author: Rüdiger Sonderfeld <ruediger@c-plusplus.de>
;; Moritz Ulrich <moritz@tarn-vedra.de>
;; Aristid Breitkreuz <aristidb@gmail.com>
;; Keywords: irc chat network weechat
;; URL: https://github.com/the-kenny/weechat.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:
;;
;; TODO: resize, make buffer more beautiful, test test test
;;; Code:
;;
(require 'weechat)
;;; Customize:
;;
(defgroup weechat-image nil
"Image previews for WeeChat."
:link '(url-link "https://github.com/the-kenny/weechat.el")
:prefix "weechat-image"
:group 'weechat)
(defcustom weechat-image-url-regex "\\.\\(png\\|jpe?g\\|gif\\|svg\\)"
"Regexp to match image URLs.
This gets called on a URL matched with `thing-at-point' and `url'."
:type 'regexp
:group 'weechat-image)
(defcustom weechat-image-url-blacklist-regex "/\\(Datei\\|File\\):"
"Blacklist for image URLs.
E.g., for Wikipedia links starting with File:. They do not link directly to the image."
:type 'regexp
:group 'weechat-image)
(defcustom weechat-image-display-func #'weechat-image-insert-inline
"Function to call to insert image.
The Function should accept the following parameter (URL IMAGE BUFFER MARKER)."
:type '(choice (const :tag "Inline" weechat-image-insert-inline)
(const :tag "Other Buffer" weechat-image-insert-other-buffer)
(function :tag "Call function"))
:group 'weechat-image)
(defcustom weechat-image-buffer "*WeeChat Image Buffer*"
"Buffer used if `weechat-image-display-func' is set to ``Other Buffer''."
:type 'string
:group 'weechat-image)
(defcustom weechat-image-use-imagemagick (fboundp 'imagemagick-types)
;; TODO is there a better way to identify if emacs has imagemagick support?
"Use ImageMagick to load images."
:type 'boolean
:group 'weechat-image)
(defcustom weechat-image-size-limit (* 1024 1024) ;; 1M
"Size limit for images."
:type '(choice (const :tag "No limit" nil)
(integer :tag "Size limit in bytes"))
:group 'weechat-image)
(defcustom weechat-image-max-width (/ (frame-pixel-width nil) 2)
"Max image width.
If `weechate-image-size' is non-nil the image is resized. Be aware that
`weechat-image-size-limit' is checked before."
:type '(choice (const :tag "No limit" nil)
(integer :tag "Max width in pixel"))
:group 'weechat-image)
(defcustom weechat-image-max-height nil
"Max image height.
If `weechate-image-size' is non-nil the image is resized. Be aware that
`weechat-image-size-limit' is checked before."
:type '(choice (const :tag "No limit" nil)
(integer :tag "Max height in pixel"))
:group 'weechat-image)
(defcustom weechat-image-resize weechat-image-use-imagemagick
"Resize image if it's larger than `weechat-image-max-width' and
`weechat-image-max-height'. This only works if imagemagick is used.
See `weechat-image-use-imagemagick'."
:type 'boolean
:group 'weechat-image)
(defcustom weechat-image-time-format "%Y-%m-%dT%T%z" ;; ISO 8601
"Timestamp format used in `weechat-image-buffer'.
See `format-time-string'."
:type 'string
:group 'weechat-image)
(defun weechat-image--remove (button)
"Remove image associated with BUTTON."
(let ((start (button-get button 'weechat-image-begin))
(end (button-get button 'weechat-image-end)))
(remove-images start end)
(delete-region (1- (overlay-start button)) (overlay-end button))
(delete-overlay button)
(save-excursion
(save-restriction
(narrow-to-region (line-beginning-position) (line-end-position))
(let ((inhibit-read-only t))
(weechat-image--add-preview-button))))))
(defun weechat-image-insert-inline (url image buffer marker)
"Insert IMAGE after MARKER in buffer."
(with-current-buffer buffer
(goto-char marker)
(let ((button (button-at marker)))
(delete-region (overlay-start button) (overlay-end button))
(delete-overlay button))
(let ((button-start (point)) button-end image-start)
(insert "[-]")
(setq button-end (point))
(end-of-line)
(setq image-start (point))
(put-image image image-start)
(make-button button-start button-end
'action #'weechat-image--remove
'help-wecho "Remove Preview"
'follow-link t
'weechat-image-begin image-start
'weechat-image-end (point))))
(message "Inserted inline %s %s %s" url buffer marker))
(defun weechat-image-view-next ()
"Go to next image."
(interactive)
(search-forward "URL:" nil t))
(defun weechat-image-view-previous ()
"Go to previous image."
(interactive)
(search-backward "URL:" nil t))
(defun weechat-image-view-remove-entry ()
"Remove current entry."
(interactive)
(save-excursion
(let ((beg
(if (looking-at "^URL:")
(point)
(search-backward "URL:" nil t)))
(end (progn
(end-of-line)
(search-forward "URL:" nil t))))
(if end
(setq end (- end 4))
(setq end (point-max)))
(let ((inhibit-read-only t))
(remove-images beg end)
(delete-region beg end)))))
(defun weechat-image-view-clear ()
"Clear image view buffer."
(interactive)
(when (and (called-interactively-p 'interactive)
(y-or-n-p "Clear buffer? "))
(let ((inhibit-read-only t))
(remove-images (point-min) (point-max))
(erase-buffer))))
(defvar weechat-image-view-mode-map
(let ((map (make-sparse-keymap)))
(define-key map "p" #'weechat-image-view-previous)
(define-key map "n" #'weechat-image-view-next)
(define-key map "c" #'weechat-image-view-clear)
(define-key map "k" #'weechat-image-view-remove-entry)
map)
"Keymap for `weechat-image-view-mode'.")
(easy-menu-define weechat-image-view-mode-menu weechat-image-view-mode-map
"WeeChat Image"
'("WeeChatImage"
["Previous Image" weechat-image-view-previous t]
["Next Image" weechat-image-view-next t]
["Remove Image" weechat-image-view-remove-entry t]
["Clear Buffer" weechat-image-view-clear t]))
(define-derived-mode weechat-image-view-mode special-mode "WeechatImage"
"Mode for the weechat-image viewer
\{weechat-image-view-mode-map}"
:group 'weechat-image)
(defun weechat-image-insert-other-buffer (url image buffer marker)
"Insert IMAGE into `weechat-image-buffer'."
(with-current-buffer (get-buffer-create weechat-image-buffer)
(weechat-image-view-mode)
(goto-char (point-max))
(let ((inhibit-read-only t))
(unless (bolp)
(insert "\n"))
(insert "URL: ")
(insert-button url
'action (lambda (button)
(browse-url (button-get button 'weechat-image-url)))
'help-echo "Browse URL"
'follow-link t
'weechat-image-url url)
(insert "\n")
(let ((channel-name (buffer-name buffer)))
(insert "Channel: ")
(insert-button channel-name
'action (lambda (button)
(let ((buf (button-get button 'weechat-image-buffer))
(mark (button-get button 'weechat-image-marker)))
(when (buffer-live-p buf)
(switch-to-buffer buf)
(with-current-buffer buf
(goto-char mark)))))
'help-echo "Goto buffer"
'follow-link t
'weechat-image-buffer buffer
'weechat-image-marker marker)
(insert "\n"))
(let (nick date)
(with-current-buffer buffer
(goto-char marker)
(beginning-of-line)
(setq nick (get-text-property (point) 'weechat-nick))
(setq date (get-text-property (point) 'weechat-date)))
(when date
(insert "Date: " (format-time-string weechat-image-time-format date) "\n"))
(when nick
(insert "By: ")
(insert-button nick
'action (lambda (button)
(let ((buf (button-get button 'weechat-image-buffer))
(nick (button-get button 'weechat-image-nick)))
(with-current-buffer buf
(weechat-nick-action nick))))
'help-echo "Nick Actions"
'follow-link t
'weechat-image-buffer buffer
'weechat-image-nick nick)
(insert "\n")))
(put-image image (point))
(insert "\n")))
(message "Added new image to %s" weechat-image-buffer)
(switch-to-buffer weechat-image-buffer))
(defun weechat-image-resize (image what px)
"Resize IMAGE.
WHAT should be either `:width' or `:height' and PX is the new size in pixel.
This function is a no-op if `weechat-image-use-imagemagick' is nil."
(if weechat-image-use-imagemagick
(or (create-image (plist-get (cdr image) :data) 'imagemagick t
what px)
image)
image))
(defun weechat-image--get-image (_status url buffer marker)
(goto-char (point-min))
(unless (looking-at "^HTTP/.+ 200 OK$")
(kill-buffer)
(error "Error while fetching image `%s'" url))
(unless (search-forward "\n\n" nil t)
(kill-buffer)
(error "Error while fetching image `%s'. Malformed http reply" url))
(when (and weechat-image-size-limit
(> (- (point-max) (point)) weechat-image-size-limit))
(kill-buffer)
(error "Image %s is too large (%s bytes)" url (- (point-max) (point))))
(let* ((image (create-image (buffer-substring (point) (point-max))
(if weechat-image-use-imagemagick
'imagemagick
nil)
t))
(size (image-size image 'pixels)))
(unless image
(kill-buffer)
(error "Image type not supported or not an image."))
(when (and weechat-image-max-width
(> (car size) weechat-image-max-width))
(if weechat-image-resize
(setq image (weechat-image-resize image :width weechat-image-max-width))
(kill-buffer)
(error "Image %s is too wide (%s px)" url (car size))))
(when (and weechat-image-max-height
(> (cdr size) weechat-image-max-height))
(if weechat-image-resize
(setq image (weechat-image-resize image :height weechat-image-max-width))
(kill-buffer)
(error "Image %s is too heigh (%s px)" url (cdr size))))
(kill-buffer)
(funcall weechat-image-display-func url image buffer marker)))
(defun weechat-image--do-preview (button)
(let ((url (button-get button 'weechat-image-url))
(buffer (button-get button 'weechat-image-buffer))
(marker (button-get button 'weechat-image-marker)))
(url-queue-retrieve url
#'weechat-image--get-image
(list url buffer marker))))
(defun weechat-image--add-preview-button ()
"Add preview buttons after image urls."
(goto-char (point-min))
(search-forward "http" nil t)
(let ((url (thing-at-point 'url)))
(when (and url
(s-matches? weechat-image-url-regex url)
(not (s-matches? weechat-image-url-blacklist-regex url)))
(end-of-thing 'url)
(insert " ")
(insert-button "[+]"
'action #'weechat-image--do-preview
'help-echo "Preview Image"
'follow-link t
'weechat-image-marker (point)
'weechat-image-buffer (current-buffer)
'weechat-image-url url)
(unless (or (eolp) (looking-at "[[:space:]]"))
(insert " ")))))
(add-hook 'weechat-insert-modify-hook #'weechat-image--add-preview-button)
(provide 'weechat-image)
;;; weechat-image.el ends here

Binary file not shown.

View File

@@ -0,0 +1,186 @@
;;; weechat-latex --- Add LateX preview -*- lexical-binding: t -*-
;; Copyright (C) 2013 Rüdiger Sonderfeld <ruediger@c-plusplus.de>
;; Author: Rüdiger Sonderfeld <ruediger@c-plusplus.de>
;; Moritz Ulrich <moritz@tarn-vedra.de>
;; Aristid Breitkreuz <aristidb@gmail.com>
;; Keywords: irc chat network weechat
;; URL: https://github.com/the-kenny/weechat.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:
;;
;; The LaTeX preview is based on `org-mode's `org-format-latex'
;;; Code:
(require 'weechat)
(require 'org)
(defgroup weechat-latex nil
"WeeChat LaTeX preview."
:link '(url-link "https://github.com/the-kenny/weechat.el")
:prefix "weechat-latex"
:group 'weechat)
(defcustom weechat-latex-temp-file-prefix "weechat-latex"
"Prefix for temporary files."
:type 'string
:group 'weechat-latex)
(defcustom weechat-latex-temp-directory-prefix "weechat-latex"
"Prefix for temporary directory."
:type 'string
:group 'weechat-latex)
(defcustom weechat-latex-image-program org-latex-create-formula-image-program
"Program to convert LaTeX fragments.
See `org-latex-create-formula-image-program'"
:type '(choice
(const :tag "dvipng" dvipng)
(const :tag "imagemagick" imagemagick))
:group 'weechat-latex)
(defvar weechat-latex-temp-dir nil
"The temporary directory used for preview images.")
(defun weechat-latex--create-preview (at)
"Wrapper for `org-format-latex'.
The parameter AT should be nil or in (TYPE . POINT) format. With TYPE being a
string showing the matched LaTeX statement (e.g., ``$'') and POINT being the
POINT to replace. If AT is nil replace statements everywhere."
(org-format-latex weechat-latex-temp-file-prefix
weechat-latex-temp-dir
'overlays
"Creating images...%s"
at 'forbuffer
weechat-latex-image-program))
(defun weechat-latex--set-temp-dir ()
"Set `weechat-latex-temp-dir' unless it is already set."
(unless weechat-latex-temp-dir
(setq weechat-latex-temp-dir
(make-temp-file weechat-latex-temp-directory-prefix
'directory))))
(defun weechat-latex-preview ()
"Preview LaTeX fragments."
(interactive)
(save-excursion
(let ((inhibit-read-only t))
(weechat-latex--set-temp-dir)
(org-remove-latex-fragment-image-overlays)
(weechat-latex--create-preview nil))))
(defun weechat-latex-preview-region (beg end)
"Preview LaTeX fragments in region."
(interactive "r")
(let* ((math-regex (assoc "$" org-latex-regexps))
(regex (nth 1 math-regex))
(n (nth 2 math-regex))
matches)
(save-excursion
(goto-char beg)
(while (re-search-forward regex end t)
(setq matches (cons (cons "$" (match-beginning n)) matches)))
(let ((inhibit-read-only t))
(weechat-latex--set-temp-dir)
(dolist (i matches)
(weechat-latex--create-preview i))))))
(defvar weechat-prompt-start-marker) ;; See weechat.el
(defun weechat-latex-preview-line ()
"Preview LaTeX fragments in line."
(interactive)
(weechat-latex-preview-region (point-at-bol)
(min (point-at-eol)
weechat-prompt-start-marker)))
(defun weechat-latex-remove ()
"Remove LaTeX preview images."
(interactive)
(let ((inhibit-read-only t))
(org-remove-latex-fragment-image-overlays)))
(defun weechat-latex-is-active? ()
"Are LaTeX Previews currently displayed?"
org-latex-fragment-image-overlays)
(defun weechat-latex-toggle ()
"Toggle display of LaTeX preview."
(interactive)
(if (weechat-latex-is-active?)
(weechat-latex-remove)
(weechat-latex-preview)))
;;; auto mode
(defun weechat-latex--do-auto-mode ()
"Hook for auto LaTeX preview."
(weechat-latex-preview-region (point-min) (point-max)))
(defun weechat-latex-is-auto-mode-active? ()
"Is auto LaTeX preview active?"
(memq #'weechat-latex--do-auto-mode weechat-insert-modify-hook))
(defcustom weechat-latex-auto-mode-line-string " LaTeX-Preview"
"String displayed in mode line when `weechat-latex-auto-mode' is active."
:type 'string
:group 'weechat-latex)
(defcustom weechat-latex-auto-mode-preview-all t
"Show preview for existing LaTeX fragmetns if auto mode is activated?"
:type 'boolean
:group 'weechat-latex)
(define-minor-mode weechat-latex-auto-mode
"Automatically display LaTeX preview."
:lighter weechat-latex-auto-mode-line-string
:group 'weechat-latex
(if weechat-latex-auto-mode
(progn
(when weechat-latex-auto-mode-preview-all
(weechat-latex-preview))
(add-hook 'weechat-insert-modify-hook #'weechat-latex--do-auto-mode))
(remove-hook 'weechat-insert-modify-hook #'weechat-latex--do-auto-mode)))
;;; module
(easy-menu-add-item weechat-mode-menu nil
["LaTeX Preview" weechat-latex-toggle
:style toggle
:selected (weechat-latex-is-active?)
:help "If selected show LaTeX preview for existing buffer."]
"Toggle Hidden Lines")
(easy-menu-add-item weechat-mode-menu nil
["LaTeX Auto Preview" weechat-latex-auto-mode
:style toggle
:selected (weechat-latex-is-auto-mode-active?)
:help "If selected automatically show LaTeX preview for new messages."]
"Toggle Hidden Lines")
(defun weechat-latex-unload-function ()
"Cleanup WeeChat LaTex module."
(weechat-latex-auto-mode -1)
(weechat-latex-remove)
(easy-menu-remove-item weechat-mode-menu nil "LaTeX Preview")
(easy-menu-remove-item weechat-mode-menu nil "LaTeX Auto Preview"))
(provide 'weechat-latex)
;;; weechat-latex.el ends here

Binary file not shown.

View File

@@ -0,0 +1,119 @@
;;; weechat-notifications --- notifications.el based notifications. ;; -*- lexical-binding: t -*-
;; Copyright (C) 2013 Rüdiger Sonderfeld
;; Author: Moritz Ulrich <moritz@tarn-vedra.de>
;; Rüdiger Sonderfeld <ruediger@c-plusplus.de>
;; Aristid Breitkreuz <aristidb@gmail.com>
;; Keywords: irc chat network weechat
;; URL: https://github.com/the-kenny/weechat.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:
;; Notifications based on notifications.el. Shipped with Emacs.
;;; Code:
(require 'weechat)
(require 'notifications)
(require 'xml) ;; For `xml-escape-string'
(defgroup weechat-notifications nil
"Notifications based on notifications.el."
:link '(url-link "https://github.com/the-kenny/weechat.el")
:prefix "weechat-notifications-"
:group 'weechat)
(defcustom weechat-notifications-icon #'weechat-notifications-icon-function
"Icon used in notifications.
Either nil, a file-name, or a function which is called with (SENDER BUFFER-PTR)."
:type '(choice (const :tag "No icon" nil)
(file :tag "Icon file")
(function :tag "Icon function"))
:group 'weechat-notifications)
(defcustom weechat-notifications-sound t
"Sound to use for notifications:
- nil: No sound
- t: default message-new-instant sound
- string: file name of a sound file."
:type '(choice (const :tag "No sound" nil)
(const :tag "Default system sound" t)
(file :tag "Sound file"))
:group 'weechat-notifications)
(defun weechat-notifications-icon-function (_sender _buffer-ptr)
"Default icon."
(when (boundp 'notifications-application-icon)
notifications-application-icon))
(defvar weechat--notifications-id-to-msg nil
"Map notification ids to buffer-ptrs.")
(defun weechat--notifications-action (id key)
"Handle notifcations.el actions.
See `weechat-notifications-handler'.
Supported actions:
- read: switch to buffer."
(when (string= key "view")
(let* ((buffer-ptr (cdr (assoc id weechat--notifications-id-to-msg))))
(when buffer-ptr
(weechat-switch-buffer buffer-ptr)))))
(defun weechat-notifications-handler (type &optional sender text _date buffer-ptr)
"Notification handler using notifications.el."
(let ((notifications-id
(notifications-notify
:title (xml-escape-string
(or (cl-case type
(:highlight
(concat "Weechat.el: Message from <"
(weechat-strip-formatting sender)
">"))
(:query
(concat "Weechat.el: Query from <"
(weechat-strip-formatting sender)
">"))
(:disconnect "Disconnected from WeeChat"))
""))
:body (when text (xml-escape-string text))
:category "im.received"
:actions '("view" "View")
:on-action #'weechat--notifications-action
:app-icon (cl-typecase weechat-notifications-icon
(string weechat-notifications-icon)
(function (funcall weechat-notifications-icon
sender buffer-ptr)))
:app-name "WeeChat.el"
:sound-name (when (and weechat-notifications-sound
(not (stringp weechat-notifications-sound)))
"message-new-instant")
:sound-file (when (stringp weechat-notifications-sound)
weechat-notifications-sound)
:replaces-id (caar weechat--notifications-id-to-msg))))
(when notifications-id
(setq weechat--notifications-id-to-msg
(append (list (cons notifications-id buffer-ptr))
weechat--notifications-id-to-msg)))))
(add-hook 'weechat-notification-handler-functions
#'weechat-notifications-handler)
(provide 'weechat-notifications)
;;; weechat-notifications.el ends here

Binary file not shown.

View File

@@ -0,0 +1,8 @@
(define-package "weechat" "20180513.310" "Chat via WeeChat's relay protocol in Emacs"
'((s "1.3.1")
(cl-lib "0.2")
(emacs "24")
(tracking "1.2")))
;; Local Variables:
;; no-byte-compile: t
;; End:

View File

@@ -0,0 +1,143 @@
;;; weechat-read-marker.el --- read marker for WeeChat -*- lexical-binding: t -*-
;; Copyright (C) 2015 Hans-Peter Deifel
;; Author: Hans-Peter Deifel <hpd@hpdeifel.de>
;; Created: 22 Jun 2015
;; 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, or (at
;; your option) any later version.
;; This program is distributed in the hope that it will be useful, but
;; WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
;; General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs; see the file COPYING. If not, write to the
;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.
;;; Commentary:
;;; Draw a thin red line between the read and unread lines in a buffer.
;;; See `M-x customize-group weechat-read-marker' for configuration options.
;;; If anything goes wrong, the read marker can be manually reset with
;;; `weechat-read-marker-reset'.
;;; Code:
(require 'weechat)
(defgroup weechat-read-marker nil
"Read marker for WeeChat"
:prefix "weechat-read-marker"
:group 'weechat)
(defcustom weechat-read-marker-char ?─
"Character used to render the read marker."
:type 'character
:group 'weechat-read-marker)
(defface weechat-read-marker
'((t :foreground "brown"))
"Face used to colorize the read marker."
:group 'weechat-read-marker)
(defcustom weechat-read-marker-always-show nil
"Always show read marker, even if it is after last buffer line.
A value of t means that the read marker is displayed directly
over the prompt, if there are no unread lines. With nil, the
marker is simply not displayed in this case."
:type 'boolean
:group 'weechat-read-marker)
(defvar-local weechat-read-marker-overlay nil
"The overlay used to draw the read marker.
Will be nil initially and if the buffer has no unread lines when
`weechat-read-marker-always-show` is not set.")
(defvar-local weechat-read-marker-stale t
"Whether the read marker position is outdated.
This will be set if the buffer is visited, to indicate that the
unread lines are now read.")
(defun weechat-read-marker--set-overlay ()
"Update the `after-string' property on an already existing overlay."
(let* ((width (- (window-width) 1))
(line (make-string width weechat-read-marker-char)))
(overlay-put weechat-read-marker-overlay 'after-string
(concat "\n" (propertize line 'face 'weechat-read-marker)))))
(defun weechat-read-marker--move-overlay ()
"Update the read marker in the current buffer."
(if weechat-read-marker-overlay
(move-overlay weechat-read-marker-overlay (point-at-bol) (point-at-eol))
(setq weechat-read-marker-overlay
(make-overlay (point-at-bol) (point-at-eol) nil t nil))
;; Delete overlay if text is deleted. This is needed to get rid of the
;; overlay, when the buffer is reset.
(overlay-put weechat-read-marker-overlay 'evaporate t))
(weechat-read-marker--set-overlay))
(defun weechat-read-marker-handle-visited ()
"Reset read marker after a buffer is being visited."
(if weechat-read-marker-stale
;; we haven't had any new lines. Reset overlay
(when weechat-read-marker-overlay
(if weechat-read-marker-always-show
(save-excursion
(goto-char (point-max))
(forward-line -1)
(weechat-read-marker--move-overlay))
(delete-overlay weechat-read-marker-overlay)
(setq weechat-read-marker-overlay nil)))
;; otherwise, set the read marker to be stale
(setq weechat-read-marker-stale t)
;; and also recompute the overlay string, since the window-width could have
;; changed
(when weechat-read-marker-overlay
(weechat-read-marker--set-overlay))))
(defun weechat-read-marker-handle-background ()
"Move read-marker in case it is stale."
(when weechat-read-marker-stale
(save-excursion
(goto-char (point-max))
(unless (< (line-number-at-pos) 3)
(forward-line -2)
(weechat-read-marker--move-overlay)
(setq weechat-read-marker-stale nil)))))
(defun weechat-read-marker-reset ()
"Manually reset the read marker in the current buffer."
(interactive "")
(when weechat-read-marker-overlay
;; Always delete (and possibly) recreate overlay in case anything went wrong
;; and the users used this command to reset things.
(delete-overlay weechat-read-marker-overlay)
(if weechat-read-marker-always-show
(save-excursion
(goto-char (point-max))
(forward-line -1)
(weechat-read-marker--set-overlay))
(setq weechat-read-marker-overlay nil)))
(setq weechat-read-marker-stale t))
(add-hook 'weechat-buffer-background-message-hook
'weechat-read-marker-handle-background)
(add-hook 'weechat-buffer-visited-hook
'weechat-read-marker-handle-visited)
(provide 'weechat-read-marker)
;;; weechat-read-marker.el ends here

Binary file not shown.

View File

@@ -0,0 +1,632 @@
;;; weechat-relay --- Implementation of Weechat's relay protocol ;; -*- lexical-binding: t -*-
;; Copyright (C) 2013 Moritz Ulrich
;; Author: Moritz Ulrich (moritz@tarn-vedra.de)
;; Rüdiger Sonderfeld <ruediger@c-plusplus.de>
;; Aristid Breitkreuz <aristidb@gmail.com>
;; Keywords: irc chat network weechat
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;; This file implements low-level code used by weechat.el to connect
;; to remote WeeChat instances using the relay protocol:
;; http://www.weechat.org/files/doc/devel/weechat_relay_protocol.en.html
(require 'weechat-core)
(require 'bindat)
(require 'format-spec)
(require 's)
(require 'pp)
(require 'cl-lib)
(defcustom weechat-relay-buffer-name "*weechat-relay*"
"Buffer holding the connection to the host weechat instance."
:type 'string
:group 'weechat-relay)
(defcustom weechat-relay-message-function nil
"Function to call when receiving a new weechat message."
:type '(choice (const :tag "Off" nil)
(function :tag "Callback Function"))
:group 'weechat-relay)
(defvar weechat-relay-ignored-message-ids '("_nicklist")
"IDs to ignore.")
(defcustom weechat-relay-disconnect-hook nil
"Hook run when the relay disconnects.
It will NOT run when the user disconnects via
`weechat-disconnect'."
:type 'hook
:group 'weechat-relay)
(defcustom weechat-relay-connect-hook nil
"Hook run when the relay connects.
Note: This DOES NOT mean the client can is already authenticated
to the relay server."
:type 'hook
:group 'weechat-relay)
(defcustom weechat-relay-ping-idle-seconds 60
"Idle time in seconds after weechat.el will ping the server."
:type '(choice integer
(const nil))
:group 'weechat-relay)
;;; Code:
(defvar weechat--relay-id-callback-hash (make-hash-table :test 'equal)
"Alist mapping from ids to functions.
Incoming message-ids will be searched in this alist and the
corresponding function will be called.")
(defun weechat--relay-send-message (text &optional id)
"Send message TEXT with optional ID.
Trim TEXT prior to sending it."
(let ((msg (concat (when id (format "(%s) " id)) (s-trim text) "\n")))
(weechat-relay-log (format "Sending msg: '%s'" (s-trim msg))
:debug)
(let ((process (get-buffer-process weechat-relay-buffer-name)))
(if process
(send-string process msg)
(weechat-warn "`get-buffer-process' returned nil for `weechat-relay-buffer-name'")))))
(defun weechat-relay-authenticate (password &optional compression)
"Authenticate to weechat with PASSWORD.
PASSWORD can be a string, a function or nil.
If COMPRESSION is non-nil, enable compression on this connection.
Currently unsupported."
(cl-assert (or (null password)
(stringp password)
(functionp password)))
(let ((pass (if (functionp password)
(funcall password)
password)))
(when (stringp pass)
(setq pass (if (s-blank? (s-trim pass))
nil
(s-trim pass))))
(weechat--relay-send-message
(concat "init "
(s-join ","
(cl-remove-if #'s-blank?
(list
(when pass (format "password=%s" (s-trim pass)))
(format "compression=%s" (if compression "zlib" "off")))))
"\n"))))
(defun weechat--relay-bindat-unsigned-to-signed (num bytes)
"Convert an unsigned int NUM to signed int.
NUM is in two-complement representation with BYTES bytes.
Useful because bindat does not support signed numbers."
(if (> num (- (expt 2 (- (* 8 bytes) 1)) 1))
(- num (expt 2 (* 8 bytes)))
num))
(defun weechat--relay-unpack-int (data)
"Unpack a four-byte signed integer from unibyte string DATA.
Return the value and number of bytes consumed."
(cl-values
(weechat--relay-bindat-unsigned-to-signed
(bindat-get-field
(bindat-unpack '((val u32)) data)
'val)
4)
4))
(defconst weechat--relay-lon-spec
'((len u8)
(val str (eval (weechat--relay-bindat-unsigned-to-signed
(bindat-get-field struct 'len)
1)))))
(defun weechat--relay-unpack-lon (data)
(let ((obj (bindat-unpack weechat--relay-lon-spec data)))
(cl-values (string-to-number (decode-coding-string (bindat-get-field obj 'val) 'utf-8))
(bindat-length weechat--relay-lon-spec obj))))
(defun weechat--relay-unpack-chr (data)
"Unpack a one byte char from unibyte string DATA.
Returns value and bytes consumed."
(cl-values
(bindat-get-field
(bindat-unpack '((val u8)) data)
'val)
1))
(defconst weechat--relay-str-spec
'((len u32)
(val str (eval (let ((len (weechat--relay-bindat-unsigned-to-signed
(bindat-get-field struct 'len)
4)))
;; Hack for signed/unsigned problems
(if (<= len 0) 0 len))))))
(defun weechat--relay-unpack-str (data)
"Unpacks a weechat-relay-string from unibyte string DATA.
Optional second return value contains length of parsed data."
(let ((obj (bindat-unpack weechat--relay-str-spec data)))
(cl-values (decode-coding-string (bindat-get-field obj 'val) 'utf-8)
(bindat-length weechat--relay-str-spec obj))))
(defconst weechat--relay-buf-spec
'((len u32)
(val vec (eval (let ((len (weechat--relay-bindat-unsigned-to-signed
(bindat-get-field struct 'len)
4)))
;; Hack for signed/unsigned problems
(if (<= len 0) 0 len))))))
(defun weechat--relay-unpack-buf (data)
(let ((obj (bindat-unpack weechat--relay-buf-spec data)))
(cl-values (bindat-get-field obj 'val)
(bindat-length weechat--relay-buf-spec obj))))
(defconst weechat--relay-ptr-spec
'((len u8)
(val str (eval (let ((len (weechat--relay-bindat-unsigned-to-signed
(bindat-get-field struct 'len)
1)))
;; Hack for signed/unsigned problems
(if (<= len 0) 0 len))))))
(defun weechat--relay-unpack-ptr (data)
"Unpack a string encoded in weechat's binary representation.
DATA must be an unibyte string. Return string-value and number
of bytes consumed."
(let ((obj (bindat-unpack weechat--relay-ptr-spec data)))
(cl-values (unless (string= "0" (bindat-get-field obj 'val))
(concat "0x" (bindat-get-field obj 'val)))
(bindat-length weechat--relay-ptr-spec obj))))
(defconst weechat--relay-tim-spec
'((len u8)
(val str (eval (let ((len (weechat--relay-bindat-unsigned-to-signed
(bindat-get-field struct 'len)
1)))
;; Hack for signed/unsigned problems
(if (<= len 0) 0 len))))))
(defun weechat--relay-unpack-tim (data)
(let ((obj (bindat-unpack weechat--relay-tim-spec data)))
(cl-values (let ((val (string-to-number
(bindat-get-field obj 'val))))
(unless (zerop val)
(seconds-to-time val)))
(bindat-length weechat--relay-tim-spec obj))))
(defconst weechat--relay-htb-spec
'((key-type str 3)
(val-type str 3)
(count u32)))
(defun weechat--relay-unpack-htb (data)
(let* ((obj (bindat-unpack weechat--relay-htb-spec data))
(count (weechat--relay-bindat-unsigned-to-signed
(bindat-get-field obj 'count)
4))
(key-type (bindat-get-field obj 'key-type))
(val-type (bindat-get-field obj 'val-type))
(key-fn (symbol-function (intern (concat "weechat--relay-unpack-" key-type))))
(val-fn (symbol-function (intern (concat "weechat--relay-unpack-" val-type))))
(offset (bindat-length weechat--relay-htb-spec obj))
(acc ()))
(dotimes (_ count)
(cl-multiple-value-bind (key key-len) (funcall key-fn (substring data offset))
(cl-multiple-value-bind (val val-len) (funcall val-fn (substring data (+ offset key-len)))
(setq acc (cons (cons key val) acc))
(setq offset (+ offset key-len val-len)))))
(cl-values acc
offset)))
(defconst weechat--relay-arr-spec
'((type str 3)
(count u32)))
(defun weechat--relay-unpack-arr (data)
(let* ((obj (bindat-unpack weechat--relay-arr-spec data))
(count (weechat--relay-bindat-unsigned-to-signed
(bindat-get-field obj 'count)
4))
(type (bindat-get-field obj 'type))
(unpack-fn (symbol-function (intern (concat "weechat--relay-unpack-" type))))
(offset (bindat-length weechat--relay-arr-spec obj))
(acc ()))
(dotimes (_ count)
(cl-multiple-value-bind (val val-len) (funcall unpack-fn (substring data offset))
(setq acc (append acc (list val)))
(setq offset (+ offset val-len))))
(cl-values acc offset)))
(defalias 'weechat--relay-parse-chr 'weechat--relay-unpack-chr)
(defalias 'weechat--relay-parse-int 'weechat--relay-unpack-int)
(defalias 'weechat--relay-parse-lon 'weechat--relay-unpack-lon)
(defalias 'weechat--relay-parse-str 'weechat--relay-unpack-str)
(defalias 'weechat--relay-parse-buf 'weechat--relay-unpack-buf)
(defalias 'weechat--relay-parse-ptr 'weechat--relay-unpack-ptr)
(defalias 'weechat--relay-parse-tim 'weechat--relay-unpack-tim)
(defalias 'weechat--relay-parse-arr 'weechat--relay-unpack-arr)
(defun weechat--relay-parse-inf (data)
(cl-multiple-value-bind (name len) (weechat--relay-unpack-str data)
(cl-multiple-value-bind (value len*) (weechat--relay-unpack-str (substring data len))
(cl-values (cons name value)
(+ len len*)))))
(defconst weechat--relay-inl-item-spec
'((name struct weechat--relay-str-spec)
(type str 3)))
(defun weechat--relay-parse-inl-item (data)
(let* ((count (weechat--relay-bindat-unsigned-to-signed
(bindat-get-field
(bindat-unpack '((len u32)) data) 'len)
4))
(offset 4)
(acc ()))
(while (< (length acc) count)
(let* ((obj (bindat-unpack weechat--relay-inl-item-spec
(substring data offset)))
(fun (symbol-function (intern (concat "weechat--relay-unpack-"
(bindat-get-field obj 'type))))))
(setq offset (+ offset (bindat-length weechat--relay-inl-item-spec obj)))
(cl-multiple-value-bind (value offset*) (funcall fun (substring data offset))
(setq offset (+ offset offset*))
(setq acc (cons
(cons (bindat-get-field obj 'name 'val) value)
acc)))))
(cl-values acc
offset)))
(defconst weechat--relay-inl-spec
'((name struct weechat--relay-str-spec)
(count u32)))
(defun weechat--relay-parse-inl (data)
(let* ((obj (bindat-unpack weechat--relay-inl-spec data))
(acc ())
(count (weechat--relay-bindat-unsigned-to-signed
(bindat-get-field obj 'count)
4))
(offset (bindat-length weechat--relay-inl-spec obj)))
(dotimes (_ count)
(cl-multiple-value-bind (item offset*) (weechat--relay-parse-inl-item (substring data offset))
(setq acc (cons item acc))
(setq offset (+ offset offset*))))
(cl-values acc
offset)))
(defun weechat--relay-parse-hda-item (h-path-length name-type-alist data)
(let ((p-path ())
(offset 0)
(result ()))
(dotimes (_ h-path-length)
(cl-multiple-value-bind (el offset*) (weechat--relay-unpack-ptr (substring data offset))
(setq p-path (cons el p-path))
(setq offset (+ offset offset*))))
(dolist (name-type name-type-alist)
(let ((fun (symbol-function (intern (concat "weechat--relay-unpack-" (cdr name-type))))))
(cl-multiple-value-bind (obj offset*) (funcall fun (substring data offset))
(setq result (cons (cons (car name-type) obj) result))
(setq offset (+ offset offset*)))))
(cl-values (cons (reverse p-path) result)
offset)))
(defconst weechat--relay-hdh-spec
'((h-path struct weechat--relay-str-spec)
(keys struct weechat--relay-str-spec)
(count u32)))
;;; from http://lists.gnu.org/archive/html/help-gnu-emacs/2009-06/msg00764.html
(defun weechat--partition-list (list length)
(cl-loop while list
collect (cl-subseq list 0 length)
do (setf list (nthcdr length list))))
(defun weechat--hda-split-keys-string (str)
(mapcar (lambda (x)
(cons (car x)
(cadr x)))
(weechat--partition-list (split-string str "[:,]") 2)))
(defun weechat--relay-parse-hda (data)
(let* ((obj (bindat-unpack weechat--relay-hdh-spec data))
(count (weechat--relay-bindat-unsigned-to-signed
(bindat-get-field obj 'count)
4))
(name-type-alist (weechat--hda-split-keys-string
(bindat-get-field obj 'keys 'val)))
(h-path-length (length (split-string (bindat-get-field obj 'h-path 'val) "[/]")))
(offset (+ (bindat-length weechat--relay-hdh-spec obj)))
(acc ()))
(dotimes (_ count)
(cl-multiple-value-bind (obj offset*) (weechat--relay-parse-hda-item
h-path-length name-type-alist (substring data offset))
(setq acc (cons obj acc))
(setq offset (+ offset offset*))))
(let ((h-path (bindat-get-field obj 'h-path 'val)))
(cl-values (list h-path acc)
offset))))
(defconst weechat--relay-message-spec
'((length u32)
(compression u8)
(id struct weechat--relay-str-spec)
(data vec (eval (let ((l (- (bindat-get-field struct 'length)
4 ;length
1 ;compression
(+ 4 (length (bindat-get-field struct 'id 'val))))))
l)))))
(defun weechat--unpack-message-contents (data)
(let* ((type (substring data 0 3))
(fun (symbol-function (intern (concat "weechat--relay-parse-" type)))))
(cl-multiple-value-bind (obj len) (funcall fun (string-make-unibyte (substring data 3)))
(cl-values obj
(+ len 3)))))
(defun weechat-unpack-message (message-data)
"Unpack weechat relay message in MESSAGE-DATA.
Return a list: (id data)."
(let* ((msg (bindat-unpack weechat--relay-message-spec message-data))
(data (concat (bindat-get-field msg 'data)))
(msg-id (bindat-get-field msg 'id 'val))
(ignore-msg (member msg-id weechat-relay-ignored-message-ids))
(offset 0)
(acc ()))
;; Only no-compression is supported atm
(unless (= 0 (bindat-get-field msg 'compression))
(error "Compression not supported"))
(unless ignore-msg
(while (< offset (length data))
(cl-multiple-value-bind (obj offset*) (weechat--unpack-message-contents
(substring data offset))
(setq offset (+ offset offset*))
(setq acc (cons obj acc)))))
(cl-values (cons msg-id (if ignore-msg '(ignored) (reverse acc)))
(bindat-get-field msg 'length))))
(defun weechat--message-available-p ()
"Check if a weechat relay message available in current buffer."
(and (> (buffer-size) 5)
(>= (buffer-size)
(bindat-get-field
(bindat-unpack '((len u32))
(buffer-string))
'len))))
(defun weechat--relay-parse-new-message ()
(when (weechat--message-available-p)
(cl-multiple-value-bind (ret len) (weechat-unpack-message
(buffer-string))
(weechat-relay-log (format "Consumed %d bytes" len) :debug)
(let ((inhibit-read-only t))
(delete-region (point-min) (+ (point-min) len)))
ret)))
(defun weechat-relay-get-id-callback (id)
(gethash id weechat--relay-id-callback-hash))
(defun weechat-relay-remove-id-callback (id)
(let ((fun (weechat-relay-get-id-callback id)))
(remhash id weechat--relay-id-callback-hash)
fun))
(defun weechat-relay-add-id-callback (id function &optional one-shot force)
(unless id
(error "ID must not be nil"))
(when (weechat-relay-get-id-callback id)
(unless force
(error "ID '%s' is already in `weechat--relay-id-callback-hash'" id))
(weechat-relay-remove-id-callback id))
(let ((function* (if one-shot
(lambda (x)
(funcall function x)
(weechat-relay-remove-id-callback id))
function)))
(puthash id function* weechat--relay-id-callback-hash)))
(defun weechat-relay-send-command (command &optional callback)
"Send COMMAND to relay and call CALLBACK with reply.
CALLBACK takes one argument (the response data) which is a list."
(let ((id (symbol-name (cl-gensym))))
(when (functionp callback)
(weechat-relay-add-id-callback id callback 'one-shot))
(weechat--relay-send-message command id)))
(defvar weechat-relay-last-receive nil
"Stores the time when the last message was received.")
(defun weechat--relay-send-ping (&optional pong-callback)
(weechat-relay-send-command "info version" pong-callback))
;;; TODO: Move this functionality to weechat.el
(defvar weechat--relay-ping-timer nil)
(defun weechat--relay-stop-ping-timer ()
(when (timerp weechat--relay-ping-timer)
(cancel-timer weechat--relay-ping-timer)
(setq weechat--relay-ping-timer nil)))
(defun weechat--relay-start-ping-timer ()
(weechat--relay-stop-ping-timer)
(setq weechat--relay-ping-timer
(run-with-timer 0
(/ weechat-relay-ping-idle-seconds 2)
(lambda ()
(if (weechat-relay-connected-p)
(when (>= (float-time (time-since weechat-relay-last-receive))
weechat-relay-ping-idle-seconds)
(weechat--relay-send-ping))
;; Stop the ping timer if we aren't connected
(weechat--relay-stop-ping-timer))))))
(defun weechat--relay-process-filter (proc string)
(with-current-buffer (process-buffer proc)
(weechat-relay-log (format "Received %d bytes" (length string)) :debug)
;; Insert the text, advancing the process marker.
(goto-char (point-max))
(let ((inhibit-read-only t))
(insert (string-make-unibyte string)))
(let ((inhibit-redisplay t))
(while (weechat--message-available-p)
(let* ((data (weechat--relay-parse-new-message))
(id (weechat--message-id data)))
(setq weechat-relay-last-receive (current-time))
;; If buffer is available, log message.
(when (eq weechat-relay-log-level :debug)
(weechat-relay-log (pp-to-string data) :debug))
;; Call `weechat-relay-message-function'
(when (functionp weechat-relay-message-function)
(funcall weechat-relay-message-function data))
;; Call callback from `weechat--relay-id-callback-hash'
(if (functionp (weechat-relay-get-id-callback id))
(funcall (weechat-relay-get-id-callback id)
(weechat--message-data data))))))))
(defvar weechat--relay-connected-callback)
(defun weechat--relay-handle-process-status (status)
(weechat-relay-log (format "Received status event: %s\n" status))
(cl-case status
((closed exit) (run-hooks 'weechat-relay-disconnect-hook))
(failed (error "Failed to connect to weechat relay")
(weechat-relay-disconnect))))
(defun weechat--relay-process-sentinel (proc _)
(weechat--relay-handle-process-status (process-status proc)))
(defun weechat--relay-open-socket (name buffer host service)
(make-network-process :name name
:buffer buffer
:host host
:service service
:coding 'binary
:keepalive t
:noquery t))
(defun weechat--relay-plain-socket (bname host port)
(weechat-relay-log (format "PLAIN %s:%d" host port) :info)
(weechat--relay-open-socket "weechat-relay" bname host port))
(defun weechat--relay-tls-socket (bname host port)
(weechat-relay-log (format "TLS %s:%d" host port) :info)
(require 'gnutls)
(open-network-stream "weechat-relay-tls"
bname
host
port
:type 'tls
:coding 'binary))
(defun weechat--relay-from-command (cmdspec)
(lambda (bname host port)
(let ((cmd (format-spec cmdspec (format-spec-make
?h host
?p port))))
(weechat-relay-log (format "COMMAND %s:%s: `%s'" host port cmd))
(let ((process-connection-type nil)) ; Use a pipe.
(start-process-shell-command "weechat-relay-cmd" bname cmd)))))
(defun weechat-relay-connect (host port mode &optional callback)
"Open a new weechat relay connection to HOST at PORT.
Argument MODE Null or 'plain for a plain socket, t or 'ssl for a TLS socket;
a string denotes a command to run. You can use %h and %p to interpolate host
and port number respectively.
Optional argument CALLBACK Called after initialization is finished."
;; Clean relay buffer to start with clean state
(with-current-buffer (get-buffer-create weechat-relay-buffer-name)
(let ((inhibit-read-only t))
(delete-region (point-min) (point-max))))
(let* ((pfun (cond
((or (null mode) (eq mode 'plain)) #'weechat--relay-plain-socket)
((or (eq mode t) (eq mode 'ssl)) #'weechat--relay-tls-socket)
((stringp mode) (weechat--relay-from-command mode))))
(process
(funcall pfun weechat-relay-buffer-name host port)))
(set-process-sentinel process #'weechat--relay-process-sentinel)
(set-process-coding-system process 'binary)
(set-process-filter process #'weechat--relay-process-filter)
(with-current-buffer (get-buffer weechat-relay-buffer-name)
(setq buffer-read-only t)
(set-buffer-multibyte nil)
(buffer-disable-undo)))
(with-current-buffer (get-buffer-create
weechat-relay-log-buffer-name)
(buffer-disable-undo))
(when (functionp callback)
(funcall callback))
(run-hooks 'weechat-relay-connect-hook))
(defun weechat-relay-connected-p ()
(and (get-buffer weechat-relay-buffer-name)
(get-buffer-process weechat-relay-buffer-name)
(process-live-p (get-buffer-process weechat-relay-buffer-name))
t))
(defun weechat-relay-disconnect ()
"Disconnect current weechat relay connection and close all buffers."
(when (weechat-relay-connected-p)
(weechat--relay-send-message "quit")
(with-current-buffer weechat-relay-buffer-name
(let ((proc (get-buffer-process (current-buffer))))
;; When disconnecting interactively (e.g. when this function
;; is called), prevent running any disconnect hooks.
(set-process-sentinel proc nil)
(delete-process proc)
;; Stop the ping timer
(weechat--relay-stop-ping-timer))
(kill-buffer))
(when (get-buffer weechat-relay-log-buffer-name)
(kill-buffer weechat-relay-log-buffer-name))))
(defun weechat--message-id (message)
(car message))
(defun weechat--message-data (message)
"Return a list with data in MESSAGE."
(cdr message))
(defun weechat--hdata-path (hdata)
(car hdata))
(defun weechat--hdata-values (hdata)
(cadr hdata))
(defun weechat--hdata-value-pointer-path (value)
(car value))
(defun weechat--hdata-value-alist (value)
(cdr value))
(defun weechat-unload-function ()
(ad-disable-advice 'open-gnutls-stream 'around 'weechat-verifying))
(provide 'weechat-relay)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; weechat-relay.el ends here

Binary file not shown.

View File

@@ -0,0 +1,65 @@
;;; weechat-sauron --- Sauron Notifications ;; -*- lexical-binding: t -*-
;; Copyright (C) 2013 Moritz Ulrich
;; Author: Moritz Ulrich <moritz@tarn-vedra.de>
;; Rüdiger Sonderfeld <ruediger@c-plusplus.de>
;; Aristid Breitkreuz <aristidb@gmail.com>
;; Keywords: irc chat network weechat
;; URL: https://github.com/the-kenny/weechat.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:
;; Notifications using Sauron https://github.com/djcb/sauron
;;; Code:
(require 'weechat)
(if (require 'sauron nil 'noerr)
(progn
(defun weechat-sauron-handler (type &optional sender text _date buffer-ptr)
(setq text (if text (weechat-strip-formatting text)))
(setq sender (if sender (weechat-strip-formatting sender)))
(let ((jump-position (point-max-marker)))
(sauron-add-event 'weechat 3
(cl-case type
(:highlight
(format "%s in %s: %S"
sender
(weechat-buffer-name buffer-ptr)
text))
(:query
(format "Query from %s: %S"
sender
text))
(:disconnect
"Disconnected from WeeChat"))
(lambda ()
(when (fboundp 'sauron-switch-to-marker-or-buffer)
(sauron-switch-to-marker-or-buffer jump-position)))
;; Flood protection based on sender
(when sender
(list :sender sender)))))
(add-hook 'weechat-notification-handler-functions
'weechat-sauron-handler))
(weechat-warn "Error while loading weechat-sauron. Sauron notifications are disabled."))
(provide 'weechat-sauron)
;;; weechat-sauron.el ends here

Binary file not shown.

View File

@@ -0,0 +1,97 @@
;;; weechat --- Support secrets.el -*- lexical-binding: t -*-
;; Copyright (C) 2013 Rüdiger Sonderfeld
;; Author: Moritz Ulrich <moritz@tarn-vedra.de>
;; Rüdiger Sonderfeld <ruediger@c-plusplus.de>
;; Aristid Breitkreuz <aristidb@gmail.com>
;; Keywords: irc chat network weechat
;; URL: https://github.com/the-kenny/weechat.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:
;; secrets.el support for weechat.el
;; Load this file and then set `weechat-password-callback' to
;; `weechat-secrets-get-password'. You can use
;; `weechat-secrets-create' to create new entries and
;; `weechat-secrets-delete' to delete them.
;;; Code:
(require 'weechat)
(require 'secrets)
(defgroup weechat-secrets nil
"Secrets.el support for WeeChat."
:link '(url-link "https://github.com/the-kenny/weechat.el")
:prefix "weechat-secrets"
:group 'weechat)
(defcustom weechat-secrets-collection "weechat.el"
"Collection name."
:type 'string
:group 'weechat-secrets)
(defun weechat-secrets--to-item (host port)
"Convert HOST and PORT to an item name."
(format "%s:%s" host port))
(defun weechat-secrets-create (host port &optional password)
"Associate HOST and PORT with PASSWORD.
A collection named after `weechat-secrets-collection' is created if required."
(interactive
(list
(read-string
(format "Host for password (default '%s'): " weechat-host-default)
nil nil weechat-host-default)
(read-number "Port for password: " weechat-port-default)))
(unless secrets-enabled
(error "Secrets.el-API not available."))
(unless (member weechat-secrets-collection (secrets-list-collections))
(secrets-create-collection weechat-secrets-collection))
(unless password
(setq password (read-passwd "Password: " 'confirm)))
(secrets-create-item weechat-secrets-collection
(weechat-secrets--to-item host port) password
:host host :port (number-to-string port))
(clear-string password))
(defun weechat-secrets-delete (host port &optional allow-empty-collection)
"Delete HOST and PORT entry.
Unless ALLOW-EMPTY-COLLECTION is non-nil then the collection is removed
if it is empty."
(interactive
(list
(read-string
(format "Host for password (default '%s'): " weechat-host-default)
nil nil weechat-host-default)
(read-number "Port for password: " weechat-port-default)))
(let ((item (weechat-secrets--to-item host port)))
(secrets-delete-item weechat-secrets-collection item)
(unless (and allow-empty-collection
(null (secrets-list-items weechat-secrets-collection)))
(secrets-delete-collection weechat-secrets-collection))))
(defun weechat-secrets-get-password (host port)
"Get password for HOST and PORT."
(secrets-get-secret weechat-secrets-collection
(weechat-secrets--to-item host port)))
(provide 'weechat-secrets)
;;; weechat-secrets.el ends here

Binary file not shown.

View File

@@ -0,0 +1,86 @@
;;; weechat-smiley --- Display smiley faces ;; -*- lexical-binding: t -*-
;; Copyright (C) 2013 Rüdiger Sonderfeld <ruediger@c-plusplus.de>
;; Author: Rüdiger Sonderfeld <ruediger@c-plusplus.de>
;; Moritz Ulrich <moritz@tarn-vedra.de>
;; Aristid Breitkreuz <aristidb@gmail.com>
;; Keywords: irc chat network weechat
;; URL: https://github.com/the-kenny/weechat.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 module uses `smiley-region' from Gnus smiley.el.
;; To support short smileys (without nose) use:
;;
;; (setq smiley-regexp-alist
;; '(("\\(;-?)\\)\\W" 1 "blink")
;; ("[^;]\\(;)\\)\\W" 1 "blink")
;; ("\\(:-?]\\)\\W" 1 "forced")
;; ("\\(8-?)\\)\\W" 1 "braindamaged")
;; ("\\(:-?|\\)\\W" 1 "indifferent")
;; ("\\(:-?[/\\]\\)\\W" 1 "wry")
;; ("\\(:-?(\\)\\W" 1 "sad")
;; ("\\(X-?)\\)\\W" 1 "dead")
;; ("\\(:-?{\\)\\W" 1 "frown")
;; ("\\(>:-?)\\)\\W" 1 "evil")
;; ("\\(;-?(\\)\\W" 1 "cry")
;; ("\\(:-?D\\)\\W" 1 "grin")
;; ;; "smile" must be come after "evil"
;; ("\\(\\^?:-?)\\)\\W" 1 "smile")))
;; It might be necessary to run
;;
;; (setq smiley-cached-regexp-alist nil)
;; (smiley-update-cache)
;;
;; To make it work when smiley is already loaded.
;;; Code:
(require 'smiley)
(require 'weechat)
(defun weechat-smiley-buffer ()
"Smiley the region."
(let ((inhibit-read-only t))
(smiley-buffer)))
(defun weechat-smiley--do ()
"Hook for weechat."
(save-excursion
(let ((inhibit-read-only t))
(smiley-region (+ (point-min) weechat-text-column) (point-max)))))
(weechat-do-buffers (weechat-smiley-buffer))
(add-hook 'weechat-insert-modify-hook #'weechat-smiley--do)
(defun weechat-smiley-unload-function ()
"Remove smileys from buffer."
(save-restriction
(widen)
(let ((inhibit-read-only t))
(weechat-do-buffers
;; smiley-toggle-buffer is broken somewhere in
;; `gnus-with-article-buffer'. Remove smileys directly.
(smiley-region (point-min) (point-max))
(gnus-delete-images 'smiley)))))
(provide 'weechat-smiley)
;;; weechat-smiley.el ends here

Binary file not shown.

View File

@@ -0,0 +1,268 @@
;;; weechat --- Chat via Weechat's relay protocol in Emacs ;; -*- lexical-binding: t -*-
;; Copyright (C) 2013 Rüdiger Sonderfeld
;; Author: Rüdiger Sonderfeld <ruediger@c-plusplus.de>
;; Keywords: irc
;; URL: https://github.com/the-kenny/weechat.el
;; 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:
;; This code is inspired by erc-speedbar.el
;;; Code:
(require 'weechat)
(require 'speedbar)
(defvar weechat-speedbar-key-map
(let ((map (speedbar-make-specialized-keymap)))
(define-key map "e" 'speedbar-edit-line)
(define-key map "\C-m" 'speedbar-edit-line)
(define-key map "+" 'speedbar-expand-line)
(define-key map "=" 'speedbar-expand-line)
(define-key map "-" 'speedbar-contract-line)
map)
"Weechat Speedbar Key Map")
(defvar weechat-speedbar-menu-items
'(["Go to buffer" speedbar-edit-line t]
["Expand Node" speedbat-expand-line
(save-excursion (beginning-of-line)
(looking-at "[0-9]+: *.\\+. "))]
["Contract Node" speedbar-contract-line
(save-excursion (beginning-of-line)
(looking-at "[0-9]+: *.-. "))])
"Weechat Speedbar Menu Items")
(defun weechat-speedbar--goto-buffer (_text buffer _indent)
(let ((buf (get-buffer buffer)))
(speedbar-set-timer dframe-update-speed)
(if (buffer-live-p buf)
(switch-to-buffer buf)
(when (y-or-n-p (format "Monitor buffer '%s'? " buffer))
(weechat-monitor-buffer (weechat--find-buffer buffer) 'show)))))
(defvar weechat--buffer-hashes) ;; See weechat.el
(defun weechat-speedbar--buttons (_directory depth)
"Create buttons for speedbar in BUFFER."
(erase-buffer)
(maphash
#'(lambda (_k v)
(let* ((local-vars (gethash "local_variables" v))
(type (cdr (assoc-string "type" local-vars)))
(name (cdr (assoc-string "name" local-vars)))
(server (cdr (assoc-string "server" local-vars))))
(when (string= type "server")
(speedbar-with-writable
(speedbar-make-tag-line
'bracket ?+
#'weechat-speedbar--expand-server server
server
#'weechat-speedbar--goto-buffer name
nil depth)))))
weechat--buffer-hashes))
(defun weechat-speedbar--expand-server (text server indent)
(cond ((string-match "+" text) ; expand node
(speedbar-change-expand-button-char ?-)
(speedbar-reset-scanners)
(speedbar-with-writable
(save-excursion
(forward-line 1)
(weechat-speedbar--channel-buttons nil (1+ indent) server))))
((string-match "-" text) ; contract node
(speedbar-change-expand-button-char ?+)
(speedbar-delete-subblock indent))
(t (error "Not sure what do do!")))
(speedbar-center-buffer-smartly))
(defun weechat-speedbar--channel-buttons (_directory depth for-server)
(maphash
#'(lambda (_k v)
(let* ((local-vars (gethash "local_variables" v))
(type (cdr (assoc-string "type" local-vars)))
(name (cdr (assoc-string "name" local-vars)))
(channel (cdr (assoc-string "channel" local-vars)))
(server (cdr (assoc-string "server" local-vars))))
(when (string= server for-server)
(cond
((string= type "channel")
(speedbar-with-writable
(speedbar-make-tag-line
'bracket ?+
#'weechat-speedbar--expand-channel name
channel
#'weechat-speedbar--goto-buffer name
nil depth)))
((string= type "private")
(speedbar-with-writable
(speedbar-with-writable
(speedbar-make-tag-line ;; TODO org-contacts/gravatar/bbdb?
nil nil
nil nil ;; TODO expand for whois?
channel
#'weechat-speedbar--goto-buffer name
nil depth))))))))
weechat--buffer-hashes))
(defun weechat-speedbar--expand-channel (text name indent)
(cond ((string-match "+" text) ; expand node
(speedbar-change-expand-button-char ?-)
(speedbar-reset-scanners)
(speedbar-with-writable
(save-excursion
(forward-line 1)
(weechat-speedbar--user-buttons nil (1+ indent) name))))
((string-match "-" text) ; contract node
(speedbar-change-expand-button-char ?+)
(speedbar-delete-subblock indent))
(t (error "Not sure what do do!")))
(speedbar-center-buffer-smartly))
(defvar weechat-user-list) ;; See weechat.el
(defun weechat-speedbar--user-buttons (_directory depth name)
(let ((buffer (get-buffer name))
nick-list
topic)
(if (not (buffer-live-p buffer))
(speedbar-with-writable
(speedbar-make-tag-line
'angle ?i
nil nil
"Not Monitored!"
#'weechat-speedbar--goto-buffer name
nil depth))
(with-current-buffer buffer
(setq nick-list weechat-user-list)
(setq topic weechat-topic))
(when topic
(speedbar-with-writable
(speedbar-make-tag-line
'angle ?i
nil nil
(concat "Topic: " topic)
nil nil
nil depth)))
(dolist (nick nick-list)
(speedbar-with-writable
(speedbar-make-tag-line ;; TODO org-contacts/gravatar/bbdb?
nil nil
nil nil ;; TODO expand for whois?
nick
#'weechat-speedbar--user-action nick
nil depth))))))
(defun weechat-speedbar--user-action (_text nick _indent)
(weechat-nick-action nick))
(defun weechat-speedbar-item-info ()
"Display information about the current line."
(let ((data (speedbar-line-token)))
(message "item-info: %s" data)))
(defvar weechat-speedbar--to-do-point t
"Local variable maintaining the current modified check position.")
(defcustom weechat-speedbar-highlight-indicator "<i>"
"Indicator used for highlight events."
:type 'string
:group 'weechat-speedbar)
(defcustom weechat-speedbar-modified-indicator "<M>"
"Indicator used for normal message events."
:type 'string
:group 'weechat-speedbar)
(defun weechat-speedbar--add-indicator (indicator)
"Add INDICATOR to current line.
This is similar to `speedbar-add-indicator' but supports weechat-speedbar
indicators."
(save-excursion
(beginning-of-line)
(end-of-line)
(when (re-search-backward (concat "\\("
(regexp-quote weechat-speedbar-highlight-indicator)
"\\|"
(regexp-quote weechat-speedbar-modified-indicator)
"\\)+")
(line-beginning-position) t)
(delete-region (match-beginning 0) (match-end 0)))
(end-of-line)
(when (not (string= " " indicator))
(let ((start (point)))
(speedbar-with-writable
(insert indicator)
(speedbar-insert-image-button-maybe start (length indicator)))))))
(defun weechat-speedbar--check-modified ()
"Scan all the channels and check if they are modified."
(save-excursion
(when speedbar-buffer
(set-buffer speedbar-buffer))
(when (eq weechat-speedbar--to-do-point t)
(setq weechat-speedbar--to-do-point 0))
(if (not (numberp weechat-speedbar--to-do-point))
t
(goto-char weechat-speedbar--to-do-point)
(while (and (not (input-pending-p))
(re-search-forward "^1: \\(\\[[+-]\\]\\|>\\) " nil t))
(setq weechat-speedbar--to-do-point (point))
(let* ((buffer-name (get-text-property (point) 'speedbar-token))
(buffer-ptr (weechat--find-buffer buffer-name)))
(weechat-speedbar--add-indicator
(if buffer-ptr
(let ((hash (weechat-buffer-hash buffer-ptr)))
(cond
((gethash :background-highlight hash)
weechat-speedbar-highlight-indicator)
((gethash :background-message hash)
weechat-speedbar-modified-indicator)
(t " ")))
" "))))
(if (input-pending-p)
nil ; we are incomplete
(setq weechat-speedbar--to-do-point nil) ; done
t))))
(defun weechat-speedbar-install-variables ()
"Install WeeChat speedbar variables."
(speedbar-add-expansion-list '("WeeChat"
weechat-speedbar-menu-items
weechat-speedbar-key-map
weechat-speedbar--buttons))
(add-to-list 'speedbar-stealthy-function-list
'("WeeChat" weechat-speedbar--check-modified))
(add-hook 'speedbar-scanner-reset-hook
(lambda ()
(setq weechat-speedbar--to-do-point t)))
(speedbar-add-mode-functions-list
'("WeeChat" (speedbar-item-info . weechat-speedbar-item-info))))
(if (featurep 'speedbar)
(weechat-speedbar-install-variables)
(add-hook 'speedbar-load-hook #'weechat-speedbar-install-variables))
(defun weechat-speedbar-unload-function ()
;; TODO
)
(provide 'weechat-speedbar)
;;; weechat-speedbar.el ends here

Binary file not shown.

View File

@@ -0,0 +1,89 @@
;;; weechat-spelling.el --- FlySpell support for WeeChat. -*- lexical-binding: t -*-
;; Copyright (C) 2013 Rüdiger Sonderfeld <ruediger@c-plusplus.de>
;; Author: Rüdiger Sonderfeld <ruediger@c-plusplus.de>
;; Moritz Ulrich <moritz@tarn-vedra.de>
;; Aristid Breitkreuz <aristidb@gmail.com>
;; Keywords: irc chat network weechat
;; URL: https://github.com/the-kenny/weechat.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:
;;
;;; Code:
(require 'weechat)
(require 'flyspell)
(require 's)
(defgroup weechat-spelling nil
"FlySpell support for WeeChat."
:link '(url-link "https://github.com/the-kenny/weechat.el")
:prefix "weechat-spelling"
:group 'weechat)
(defcustom weechat-spelling-dictionaries nil
"An alist mapping buffer names to dictionaries.
The format of each entry is (CHANNEL . DICTIONARY). Where CHANNEL is a regexp
matching the buffer name (\"Server.Channel\") and DICTIONARY is the name of an
`ispell' dictionary.
See `ispell-valid-dictionary-list' for a list of valid dictionaries."
:type '(choice
(const :tag "Default dictionary" nil)
(repeat (cons (string :tag "Server.Channel Regex")
(string :tag "Dictionary"))))
:group 'weechat-spelling)
(defun weechat-spelling-init (&optional buffer)
"Initialize spelling in BUFFER or `current-buffer'."
(with-current-buffer (or buffer (current-buffer))
(dolist (entry weechat-spelling-dictionaries)
(when (s-matches? (car entry) (buffer-name))
(setq ispell-local-dictionary (cdr entry))))
(setq flyspell-generic-check-word-predicate #'weechat-mode-flyspell-verify)
(flyspell-mode 1)))
(defvar weechat-prompt-end-marker) ;; See weechat.el
(defvar weechat-user-list) ;; See weechat.el
(defun weechat-mode-flyspell-verify ()
"Function used for `flyspell-generic-check-word-predicate' in `weechat-mode'."
(not (or
;; Spell-check only input line
(< (point) weechat-prompt-end-marker)
(let ((word-data (flyspell-get-word)))
(or
;; Don't spell-check nick names
(member (car word-data) weechat-user-list)
;; Don't spell-check words starting with a /
(eq (char-before (cadr word-data)) ?/))))))
(put 'weechat-mode
'flyspell-mode-predicate
#'weechat-mode-flyspell-verify)
(weechat-do-buffers (weechat-spelling-init))
(add-hook 'weechat-mode-hook #'weechat-spelling-init)
(defun weechat-spelling-unload-function ()
(weechat-do-buffers (flyspell-mode -1))
nil)
(provide 'weechat-spelling)
;;; weechat-spelling.el ends here

Binary file not shown.

View File

@@ -0,0 +1,107 @@
;;; weechat-tracking --- Tracking support for weechat.el ;; -*- lexical-binding: t -*-
;; Copyright (C) 2013 Rüdiger Sonderfeld
;; Author: Moritz Ulrich <moritz@tarn-vedra.de>
;; Rüdiger Sonderfeld <ruediger@c-plusplus.de>
;; Aristid Breitkreuz <aristidb@gmail.com>
;; Keywords: irc chat network weechat
;; URL: https://github.com/the-kenny/weechat.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 module provides tracking support, similar to erc-track, for weechat.el.
;; It requires the tracking library
;; https://github.com/jorgenschaefer/circe/wiki/Tracking
;; It should be available from marmalade or el-get.
;;; Code:
(require 'tracking)
(require 'cl-lib)
(require 'weechat)
(defgroup weechat-tracking nil
"Tracking support for Weechat.el."
:link '(url-link "https://github.com/the-kenny/weechat.el")
:prefix "weechat-tracking-"
:group 'weechat)
(defcustom weechat-tracking-types '(:highlight)
"A list of message types which should show up in tracking.
List elements can either be one of :highlight or :message, or a
cons-cell like (regex . level). The former will be applied to all
buffers while the latter will apply to all buffers whose namesn
matches `regex'.
Supported values are :message and :highlight."
:type '(repeat (choice
symbol
(cons string symbol)))
:group 'weechat-tracking)
(defcustom weechat-tracking-faces-priorities '(weechat-highlight-face)
"A list of faces which should show up in the tracking.
The first face is kept if the new message has only lower faces,
or faces that don't show up at all."
:type '(repeat face)
:group 'weechat-tracking)
(defun weechat-tracking-setup ()
"Set up tracking in weechat buffer."
(set (make-local-variable 'tracking-faces-priorities) weechat-tracking-faces-priorities))
(defun weechat-tracking-show-buffer? (message-type &optional buffer)
(or (cl-find message-type weechat-tracking-types)
(cl-some (lambda (c)
(and (consp c)
(s-matches? (car c) (buffer-name buffer))
(eq message-type (cdr c))))
weechat-tracking-types)))
(defun weechat-tracking-handle-highlight ()
(when (weechat-tracking-show-buffer? :highlight (current-buffer))
(tracking-add-buffer (current-buffer) '(weechat-highlight-face))))
(defun weechat-tracking-handle-message ()
(when (weechat-tracking-show-buffer? :message (current-buffer))
(tracking-add-buffer (current-buffer))))
(defun weechat-tracking-handle-reset ()
(tracking-remove-buffer (current-buffer)))
(defun weechat-tracking-clear-buffers ()
(interactive)
(mapcar #'tracking-remove-buffer (weechat-buffer-list)))
(weechat-do-buffers (weechat-tracking-setup))
(add-hook 'weechat-mode-hook #'weechat-tracking-setup)
(add-hook 'weechat-buffer-background-message-hook
'weechat-tracking-handle-message)
(add-hook 'weechat-buffer-background-highlight-hook
'weechat-tracking-handle-highlight)
(add-hook 'weechat-buffer-visited-hook
'weechat-tracking-handle-reset)
(tracking-mode 1)
(provide 'weechat-tracking)
;;; weechat-tracking.el ends here

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.