;; emchat-utils.el --- misc utils for EMchat -*- Emacs-Lisp -*- ;; Copyright (C) 2007 - 2011 Steve Youngs ;; Author: Steve Youngs ;; Maintainer: Steve Youngs ;; Created: <2007-09-01> ;; Homepage: http://www.emchat.org/ ;; Keywords: utils ICQ emchat ;; This file is part of EMchat. ;; Redistribution and use in source and binary forms, with or without ;; modification, are permitted provided that the following conditions ;; are met: ;; ;; 1. Redistributions of source code must retain the above copyright ;; notice, this list of conditions and the following disclaimer. ;; ;; 2. Redistributions in binary form must reproduce the above copyright ;; notice, this list of conditions and the following disclaimer in the ;; documentation and/or other materials provided with the distribution. ;; ;; 3. Neither the name of the author nor the names of any contributors ;; may be used to endorse or promote products derived from this ;; software without specific prior written permission. ;; ;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR ;; IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ;; DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ;; FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, ;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE ;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN ;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ;;; Commentary: ;; ;; This is where any general-purpose utils for EMchat go ;;; Code: (eval-when-compile (defvar emchat-all-aliases)) (defcustom emchat-glyph-dir (file-name-as-directory (or (locate-data-directory "emchat") "")) "Directory where icons and logos live." :type 'directory :group 'emchat-interface) ;;; Internal variables (defmacro emchat-do-in-xemacs (&rest body) "Execute BODY if in XEmacs." (when (featurep '(and xemacs (not sxemacs))) `(progn ,@body))) (put 'emchat-do-in-xemacs 'lisp-indent-hook 'defun) (defmacro emchat-do-in-sxemacs (&rest body) "Execute BODY if in SXEmacs." (when (featurep 'sxemacs) `(progn ,@body))) (put 'emchat-do-in-sxemacs 'lisp-indent-hook 'defun) (defun emchat-completing-read (prompt table &optional predicate require-match initial-contents history) "Args: PROMPT, TABLE, PREDICATE, REQUIRE-MATCH, INITIAL-CONTENTS, HISTORY. Same as `completing-read' but accepts strings as well as obarray." (completing-read prompt (if (vectorp table) table (mapcar 'list table)) predicate require-match initial-contents history)) (defun emchat-numeric-uin (uin) "Return UIN as number. UIN can be either a string or number." (cond ((numberp uin) uin) ((stringp uin) (string-to-number uin)) (t (error "Invalid UIN type" uin)))) (defun emchat-stringular-uin (uin) "Return UIN as a string. UIN can be either a string or a number." (cond ((numberp uin) (number-to-string uin)) ((stringp uin) uin) (t (error "Invalid UIN type" uin)))) (defun emchat-valid-uin-p (uin) "Return non-nil if UIN is a valid uin." (not (zerop (emchat-numeric-uin uin)))) (defun emchat-completing-aliases (prompt &optional single) "Completing-read aliases/uin. PROMPT is the prompt for reading. SINGLE means read only one alias/uin. Must at least complete one alias, use RET (empty string) to finish entering. It first completing-reads from the union of `emchat-active-aliases' and `emchat-connected-aliases'. If you hit RET and the input string is not in the union it the completing-reads from `emchat-all-aliases'. Tips: You can also enter an uin in place of an alias." (let ((aliases ;; a must for first one (cons (emchat-completing-alias prompt 'required) (unless single (loop collect (emchat-completing-alias prompt nil) into aliases ;; empty string means abort until (string= (car (last aliases)) "") finally return (nbutlast aliases)))))) (delete-duplicates aliases :test 'string=))) (defun emchat-completing-alias (prompt required) "Completing only one alias/uin. PROMPT is the prompt for reading. REQUIRED means cannot abort. Used by `emchat-completing-aliases'. No abortion when `** ' is in prompt. Abort by RET (empty string) when `++ ' is in prompt." (let ((all emchat-all-aliases) (alias (emchat-completing-read prompt emchat-all-aliases nil nil nil 'emchat-alias-history))) (unless (or ;; valid alias (member alias all) ;; valid uin (emchat-valid-uin-p alias) ;; abort (and (string= alias "") (not required))) (loop do (setq alias (emchat-completing-read (concat (if required "** " "++ ") prompt) all nil t alias 'emchat-alias-history)) while (and (string= alias "") required))) alias)) (defun emchat-switch-buffer (buffer) (when buffer (select-window (get-buffer-window buffer)))) (provide 'emchat-utils) ;;; emchat-utils.el ends here