1 ;; jabber-console.el - XML Console mode -*- lexical-binding: t; -*-
3 ;; Copyright (C) 2009, 2010 - Demyan Rogozhin <demyan.rogozhin@gmail.com>
5 ;; This program is free software; you can redistribute it and/or modify
6 ;; it under the terms of the GNU General Public License as published by
7 ;; the Free Software Foundation; either version 2 of the License, or
8 ;; (at your option) any later version.
10 ;; This program is distributed in the hope that it will be useful,
11 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ;; GNU General Public License for more details.
15 ;; You should have received a copy of the GNU General Public License
16 ;; along with this program; if not, write to the Free Software
17 ;; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 ;; Use *-jabber-console-* for sending custom XMPP code. Be careful!
25 (require 'jabber-keymap)
26 (require 'jabber-util)
28 (require 'sgml-mode) ;we base on this mode to hightlight XML
30 (defcustom jabber-debug-log-xml nil
31 "Set to non-nil to log all XML i/o in *-jabber-console-JID-* buffer.
32 Set to string to also dump XML i/o in specified file."
33 :type '(choice (const :tag "Do not dump XML i/o" nil)
34 (const :tag "Dump XML i/o in console" t)
35 (string :tag "Dump XML i/o in console and this file"))
38 (defcustom jabber-console-name-format "*-jabber-console-%s-*"
39 "Format for console buffer name. %s mean connection jid."
43 (defcustom jabber-console-truncate-lines 3000
44 "Maximum number of lines in console buffer.
45 Not truncate if set to 0."
49 (defvar jabber-point-insert nil
50 "Position where the message being composed starts.")
52 (defvar jabber-send-function nil
53 "Function for sending a message from a chat buffer.")
55 (defvar jabber-console-mode-hook nil
56 "Hook called at the end of `jabber-console-mode'.
57 Note that functions in this hook have no way of knowing
58 what kind of chat buffer is being created.")
60 (defvar jabber-console-ewoc nil
61 "The ewoc showing the XML elements of this stream buffer.")
63 (defvar jabber-console-mode-map
64 (let ((map (make-sparse-keymap)))
65 (set-keymap-parent map jabber-common-keymap)
66 (define-key map "\r" 'jabber-chat-buffer-send)
69 (defun jabber-console-create-buffer (jc)
71 (get-buffer-create (format jabber-console-name-format (jabber-connection-bare-jid jc)))
72 (unless (eq major-mode 'jabber-console-mode)
73 (jabber-console-mode))
74 ;; Make sure the connection variable is up to date.
75 (setq jabber-buffer-connection jc)
78 (defun jabber-console-send (jc data)
79 ;; Put manual string into buffers ewoc
80 (jabber-process-console jc "raw" data)
81 ;; ...than sent it to server
82 (jabber-send-string jc data))
84 (defun jabber-console-comment (str)
85 "Insert comment into console buffer."
87 comment-start str "@" (jabber-encode-time (current-time)) ":"
89 (when (stringp jabber-debug-log-xml)
90 (jabber-append-string-to-file string jabber-debug-log-xml))
93 (defun jabber-console-pp (data)
94 "Pretty Printer for XML-sexp and raw data."
95 (let ((direction (car data))
98 (jabber-console-comment direction)
103 (when (stringp jabber-debug-log-xml)
104 (jabber-append-string-to-file raw jabber-debug-log-xml)))
108 (when (stringp jabber-debug-log-xml)
109 (jabber-append-string-to-file
110 "\n" jabber-debug-log-xml 'xml-print xml-list))))))
112 (define-derived-mode jabber-console-mode sgml-mode "Jabber Console"
113 "Major mode for debug XMPP protocol."
114 ;; Make sure to set this variable somewhere
115 (make-local-variable 'jabber-send-function)
116 (make-local-variable 'jabber-point-insert)
117 (make-local-variable 'jabber-console-ewoc)
119 (setq jabber-send-function 'jabber-console-send)
121 (unless jabber-console-ewoc
122 (setq jabber-console-ewoc
123 (ewoc-create #'jabber-console-pp nil "<!-- + -->"))
124 (goto-char (point-max))
125 (put-text-property (point-min) (point) 'read-only t)
126 (let ((inhibit-read-only t))
127 (put-text-property (point-min) (point) 'front-sticky t)
128 (put-text-property (point-min) (point) 'rear-nonsticky t))
129 (setq jabber-point-insert (point-marker))))
131 (put 'jabber-console-mode 'mode-class 'special)
133 (defun jabber-console-sanitize (xml-data)
134 "Sanitize XML-DATA for `jabber-process-console'."
136 (jabber-tree-map (lambda (x) (if (numberp x) (format "%s" x) x)) xml-data)
140 (defun jabber-process-console (jc direction xml-data)
141 "Log XML-DATA i/o as XML in \"*-jabber-console-JID-*\" buffer."
142 (let ((buffer (get-buffer-create (jabber-console-create-buffer jc))))
143 (with-current-buffer buffer
145 (ewoc-enter-last jabber-console-ewoc (list direction (jabber-console-sanitize xml-data)))
146 (when (< 1 jabber-console-truncate-lines)
147 (let ((_jabber-log-lines-to-keep jabber-console-truncate-lines))
148 (jabber-truncate-top buffer jabber-console-ewoc)))))))
150 (provide 'jabber-console)
151 ;;; jabber-console.el ends here