diff options
| author | Jose Antonio Ortega Ruiz <jao@gnu.org> | 2010-10-12 23:39:29 +0200 | 
|---|---|---|
| committer | Jose Antonio Ortega Ruiz <jao@gnu.org> | 2010-10-12 23:39:29 +0200 | 
| commit | 1b0abee054235ea4ac7589dd92d3939e1386d24a (patch) | |
| tree | 91d2aa7d5a810bb0032dfe1585ad8e0023c5f81e | |
| download | elibs-1b0abee054235ea4ac7589dd92d3939e1386d24a.tar.gz elibs-1b0abee054235ea4ac7589dd92d3939e1386d24a.tar.bz2 | |
Initial contents
61 files changed, 6401 insertions, 0 deletions
| diff --git a/README.org b/README.org new file mode 100644 index 0000000..49f7038 --- /dev/null +++ b/README.org @@ -0,0 +1,10 @@ +* Elisp libraries + +  - *themes* color themes based on Emacs builtin custom themes +  - *org* utilities for org-mode +  - *emms* utilities for EMMS +  - *prog* utilities for programming modes +  - *skels* skeletons for source files +  - *net* utilities for networking (w3m &c.) +  - *sys* generic utilities for external programs +  - *bmk* a web bookmark manager diff --git a/bmk/bmk-mgr-w3.el b/bmk/bmk-mgr-w3.el new file mode 100644 index 0000000..c22700f --- /dev/null +++ b/bmk/bmk-mgr-w3.el @@ -0,0 +1,58 @@ +;;; bmk-mgr-w3.el --- w3 specific code for bmk-mgr + +;; Copyright (C) 2007, 2008  Jose Antonio Ortega Ruiz. +;; +;; Author: Robert D. Crawford +;; Author: Jose A Ortega Ruiz <jao@gnu.org> +;; Keywords: hypermedia + +;; This file is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. + +;; This file is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING.  If not, write to +;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: +;; +;;  Set up bmk-mgr for w3. + +;;; Code: + +;;;; Dependencies: + +(require 'bmk-mgr) +(require 'w3) + +(defun bmk-mgr-w3-current-url () +  "Returns the current document url +without the string properties." +  (interactive) +  (substring-no-properties (url-view-url))) + +(defun bmk-mgr-w3-document-title-fixed () +  "Removes the newline in long titles that +seems to have cropped up in current versions of w3." +  (replace-regexp-in-string "\n" " " (buffer-name))) + +(add-hook 'w3-mode-hook +          (lambda () +            (setq bmk-mgr-document-title +		  'bmk-mgr-w3-document-title-fixed) +            (setq bmk-mgr-url-at-point 'w3-view-this-url) +            (setq bmk-mgr-current-url 'bmk-mgr-w3-current-url))) +;;            (setq bmk-mgr-document-title 'buffer-name) +(provide 'bmk-mgr-w3) + +;; Local variables ** +;; indent-tabs-mode: nil  ** +;; end ** +;;; bmk-mgr-w3.el ends here diff --git a/bmk/bmk-mgr-w3m.el b/bmk/bmk-mgr-w3m.el new file mode 100644 index 0000000..cc53d41 --- /dev/null +++ b/bmk/bmk-mgr-w3m.el @@ -0,0 +1,84 @@ +;;; bmk-mgr-w3m.el --- w3m specific code for bmk-mgr + +;; Copyright (C) 2007  Jose Antonio Ortega Ruiz. +;; +;; Author: Robert D. Crawford +;; Author: Jose A Ortega Ruiz <jao@gnu.org> +;; Keywords: hypermedia + +;; This file is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; This file is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING.  If not, write to +;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: +;; +;;  Set up bmk-mgr for w3m. + +;;; Code: + +;;;; Dependencies: + +(require 'bmk-mgr) +(require 'w3m) + +(defsubst bmk-mgr-w3m-url-at-point () +  "Return the url at point in w3m." +  (or (w3m-anchor (point)) (w3m-image (point)))) + +(defsubst bmk-mgr-w3m-current-url () +  "Returns the value of w3m-current-url." +  w3m-current-url) + +(add-hook 'w3m-fontify-after-hook +          (lambda () +            (setq bmk-mgr-document-title 'w3m-current-title) +            (setq bmk-mgr-url-at-point 'bmk-mgr-w3m-url-at-point) +            (setq bmk-mgr-current-url 'bmk-mgr-w3m-current-url))) + +(bmk-mgr-import-add-formatter "w3m" 'bmk-mgr-w3m-import) + +(defun bmk-mgr-w3m-import (file name) +  (if (not (file-readable-p file)) (error "Cannot read file")) +  (with-temp-buffer +    (let ((result (bmk-mgr-node-folder-new (or name "w3m"))) +          (coding-system-for-read +           (if (boundp 'w3m-bookmark-file-coding-system) +               w3m-bookmark-file-coding-system +             coding-system-for-read)) +          (sec-delim (if (boundp 'w3m-bookmark-section-delimiter) +                         w3m-bookmark-section-delimiter +                       "<!--End of section (do not delete this comment)-->\n"))) +      (insert-file-contents file) +      (goto-char 1) +      (while (re-search-forward "<h2>\\([^<]+\\)</h2>\n<ul>\n" nil t) +        (let* ((folder +                (bmk-mgr-node-folder-new (match-string 1) t)) +               (limit +                (save-excursion +                  (and (search-forward sec-delim nil t) (point))))) +          (while (search-forward "<li><a href=\"" limit t) +            (if (re-search-forward "\\([^\"]+\\)\">\\([^<]+\\)</a>\n" nil t) +                (bmk-mgr-node-add-child +                 folder +                 (bmk-mgr-node-url-new (match-string 2) (match-string 1))))) +          (bmk-mgr-node-add-child result folder))) +      result))) + +(provide 'bmk-mgr-w3m) + +;; Local variables ** +;; indent-tabs-mode: nil  ** +;; end ** + +;;; bmk-mgr-w3m.el ends here diff --git a/bmk/bmk-mgr.el b/bmk/bmk-mgr.el new file mode 100644 index 0000000..336447b --- /dev/null +++ b/bmk/bmk-mgr.el @@ -0,0 +1,1478 @@ +;;; bmk-mgr.el --- Bookmark manager: + +;; Copyright (C) 2003, 2004, 2006, 2007  Jose Antonio Ortega Ruiz. +;; + +(defconst bmk-mgr-version "0.1.2") + +;; Author: Jose A Ortega Ruiz <jao@gnu.org> +;; Keywords: hypermedia + +;; This file is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; This file is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING.  If not, write to +;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;;;; INTRODUCTION: +;;;;  Emacs Bookmark Manager. +;;;; +;;;; INSTALLATION: +;;;; +;;;; CUSTOMIZATION: +;;;; +;;;; HISTORY: +;;;;  - 0.1.1 (May 2006). XBEL importing corrected. +;;;; +;;;; TODO: +;;;;   - Export: xbel, HTML, bmk +;;;;   - Add menu: display bookmarks as a menu +;;;; +;;;; THANKS: +;;;;   - David Magill, for lots of help in debugging. +;;;; + +;;; Code: + +;;;; Dependencies: + +(require 'cl) +(require 'outline) +(require 'browse-url) + +;;;; Compatibility: +(if (< emacs-major-version 22) +    (progn +      (defun substring-no-properties (x) x) +      (defsubst bmk-string-to-int (x) (string-to-int x))) +  (progn +    (defsubst bmk-string-to-int (x) (string-to-number x)))) + +;;;; Customization: + +;;;;; Customization buffer: +(defgroup bmk-mgr nil +  "Bookmark manager" +  :group 'hypermedia +  :prefix "bmk-mgr-") + +(defcustom bmk-mgr-bookmark-file "~/.emacs.bookmarks" +  "The file where bookmarks are stored." +  :group 'bmk-mgr +  :type 'file) + +(defcustom bmk-mgr-autosave t +  "If on, save bookmarks whenever they are modified." +  :group 'bmk-mgr +  :type 'boolean) + +(defcustom bmk-mgr-indent-width 2 +  "The amount of indentation for evey new subfolder level." +  :group 'bmk-mgr +  :type 'number) + +(defcustom bmk-mgr-link-mark "" +  "The string used to prefix link names." +  :group 'bmk-mgr +  :type 'string) + +(defcustom bmk-mgr-open-mark "- " +  "The string used to prefix open folder names." +  :group 'bmk-mgr +  :type 'string) + +(defcustom bmk-mgr-closed-mark "+ " +  "The string used to prefix closed folder names." +  :group 'bmk-mgr +  :type 'string) + +(defconst bmk-mgr-available-browsers +  '(choice +    (function-item :tag "Default" :value nil) +    (function-item :tag "Emacs W3" :value  browse-url-w3) +    (function-item :tag "W3 in another Emacs via `gnudoit'" +                   :value  browse-url-w3-gnudoit) +    (function-item :tag "Mozilla" :value  browse-url-mozilla) +    (function-item :tag "Galeon" :value  browse-url-galeon) +    (function-item :tag "Netscape" :value  browse-url-netscape) +    (function-item :tag "Mosaic" :value  browse-url-mosaic) +    (function-item :tag "Mosaic using CCI" :value  browse-url-cci) +    (function-item :tag "IXI Mosaic" :value  browse-url-iximosaic) +    (function-item :tag "Lynx in an xterm window" +                   :value browse-url-lynx-xterm) +    (function-item :tag "Lynx in an Emacs window" +                   :value browse-url-lynx-emacs) +    (function-item :tag "Grail" :value  browse-url-grail) +    (function-item :tag "MMM" :value  browse-url-mmm) +    (function-item :tag "KDE" :value browse-url-kde) +    (function-item :tag "Specified by `Browse Url Generic Program'" +                   :value browse-url-generic) +    (function-item :tag "Default Windows browser" +                   :value browse-url-default-windows-browser) +    (function-item :tag "GNOME invoking Mozilla" +                   :value browse-url-gnome-moz) +    (function-item :tag "Default browser" +                   :value browse-url-default-browser) +    (function :tag "Your own function") +    (alist :tag "Regexp/function association list" +           :key-type regexp :value-type function))) + +(defcustom bmk-mgr-browser-function nil +  "*Function to display the current bookmark in a WWW browser. + +This has the same semantics as `browse-url''s `browse-url-browser-function'. +If you set this variable to nil, the latter will be used. Otherwise, +if the value is not a function it should be a list of pairs +\(REGEXP . FUNCTION).  In this case the function called will be the one +associated with the first REGEXP which matches the current URL.  The +function is passed the URL and any other args of `browse-url'.  The last +regexp should probably be \".\" to specify a default browser." +  :type  bmk-mgr-available-browsers +  :group 'bmk-mgr) + +(defcustom bmk-mgr-alt-browser-function nil +  "Alternative function to display the current bookmark in a WWW browser. + +This has the same semantics as `bmk-mgr-browser-function'. You can use +it to have a second browsing function available (activated by pressing +`shift-return' instead of just `return'). A typical application is to +have one to display the bookmark in the current tab, and another to +display the bookmark in a new tab." +  :type  bmk-mgr-available-browsers +  :group 'bmk-mgr) + + +(defcustom bmk-mgr-inhibit-welcome-message nil +  "When on, do not display a welcome message in the minibuffer upon +entering the bookmark manager." +  :group 'bmk-mgr +  :type 'boolean) + +(defcustom bmk-mgr-inhibit-minibuffer nil +  "When on, do not automatically display info about the current folder +or bookmark in the minibuffer." +  :group 'bmk-mgr +  :type 'boolean) + +(defcustom bmk-mgr-ignore-fold-state nil +  "Turn this variable on to display the initial tree with all +subfolders closed, instead of using their last state." +  :group 'bmk-mgr +  :type 'boolean) + +(defcustom bmk-mgr-use-images nil +  "If on, images are used by default." +  :type 'boolean +  :group 'bmk-mgr) + +(defcustom bmk-mgr-folder-open-image "folder-open.xpm" +  "Image to use for representing open folders." +  :type 'file +  :group 'bmk-mgr) + +(defcustom bmk-mgr-folder-closed-image "folder-closed.xpm" +  "Image to use for representing closed folders." +  :type 'file +  :group 'bmk-mgr) + +(defcustom bmk-mgr-bookmark-image "url.xpm" +  "Image to use for representing bookmarks." +  :type 'file +  :group 'bmk-mgr) + +(defcustom bmk-mgr-use-own-frame nil +  "Whether the bookmars buffer should be displayed on its own frame." +  :type 'boolean +  :group 'bmk-mgr) + +(defcustom bmk-mgr-frame-parameters '((width . 60)) +  "Parameters of the bookmars buffer frame, when +`bmk-mgr-use-own-frame' has been set to non-nil" +  :type '(repeat (sexp :tag "Parameter:")) +  :group 'bmk-mgr) + +(defface bmk-mgr-folder-face '((t (:bold t :foreground nil :weight bold))) +  "Face for folder names." +  :group 'bmk-mgr) + +(defface bmk-mgr-sel-folder-face +  '((t (:bold t :foreground "IndianRed" :weight bold))) +  "Face for selected folder names." +  :group 'bmk-mgr) + +(defface bmk-mgr-bookmark-face '((t ())) +  "Face for bookmark names." +  :group 'bmk-mgr) + +(defface bmk-mgr-sel-bookmark-face '((t (:foreground "IndianRed"))) +  "Face for selected bookmark names." +  :group 'bmk-mgr) + +;;;;; Other variables: + +(defvar bmk-mgr-bookmark-buffer-name "*Bookmarks*" +  "*Name of the bookmarks buffer.") + +(defvar bmk-mgr-kill-ring-size 50 +  "*Maximum number of killed bookmarks to be remembered.") + +(defvar bmk-mgr-line-spacing 2 +  "*Additional space to put between lines when displaying the +bookmarks buffer. + +The space is measured in pixels, and put below lines on window +systems.") + +(defvar bmk-mgr-document-title nil +  "Function variable returning the current document title.") + +(defvar bmk-mgr-url-at-point nil +  "Function variable returning the value of the url under point.") + +(defvar bmk-mgr-current-url nil +  "Function variable returning the value of the current document url.") + +(make-variable-buffer-local 'bmk-mgr-document-title) +(make-variable-buffer-local 'bmk-mgr-url-at-point) +(make-variable-buffer-local 'bmk-mgr-current-url) + +;;;; User interactive functions: + +(defun bmk-mgr-create-bookmark-buffer () +  (let ((tree (bmk-mgr-read-from-file bmk-mgr-bookmark-file))) +    (when tree +      (when bmk-mgr-use-own-frame +        (select-frame (make-frame bmk-mgr-frame-parameters))) +      (switch-to-buffer +       (get-buffer-create bmk-mgr-bookmark-buffer-name)) +      (bmk-mgr-mode tree) +      (current-buffer)))) + +(defsubst bmk-mgr-get-bookmark-buffer () +  (or (get-buffer bmk-mgr-bookmark-buffer-name) +      (bmk-mgr-create-bookmark-buffer))) + +(defun bmk-mgr-show-bookmarks () +  "Display the bookmarks buffer." +  (interactive) +  (let ((display-buffer-reuse-frames bmk-mgr-use-own-frame) +        (pop-up-frames bmk-mgr-use-own-frame)) +    (switch-to-buffer (bmk-mgr-get-bookmark-buffer)))) + +(defun bmk-mgr-show-bookmarks-other-window () +  "Display the bookmarks buffer in other window" +  (interactive) +  (let ((display-buffer-reuse-frames nil) +        (pop-up-frames nil)) +    (split-window-horizontally (/ (* 2 (window-width)) 3)) +    (other-window 1) +    (switch-to-buffer (bmk-mgr-get-bookmark-buffer)))) + +(defun bmk-mgr-add-url-at-point () +  "Add URL at point to the bookmarks collection. +If there is no URL at point, this command asks for it." +  (interactive) +  (if bmk-mgr-url-at-point +      (bmk-mgr-add-bookmark-at-folder (funcall bmk-mgr-url-at-point)) +    (progn +      (require 'ffap) +      (bmk-mgr-add-bookmark-at-folder (ffap-url-at-point))))) + +;; the following 2 functions need to  be combined and generalized +(defun bmk-mgr-add-current-page () +  "Adds the current page to the bookmark list." +  (interactive) +  (unless bmk-mgr-current-url +    (error "Current buffer has no associated URL.")) +  ;; please leave these here, as I will need them later -- rdc +  ;; (message "bmk-mgr-current-url value as function is %s" +  ;;              bmk-mgr-current-url) +  ;; (message "bmk-mgr-current-url value as variable is %s" +  ;;             (funcall bmk-mgr-current-url)) +  ;; (message "bmk-mgr-document-title value as function is %s" +  ;;              bmk-mgr-document-title) +  ;; (message "bmk-mgr-document-title value as variable is %s" +  ;;           (funcall bmk-mgr-document-title)) +  (bmk-mgr-add-bookmark-at-folder +   (funcall bmk-mgr-current-url) +   (funcall bmk-mgr-document-title))) + +;;;; Bookmark mode: + +;;;;; Variables: + +(defvar bmk-mgr-kill-ring nil "Killed nodes list") + +(defmacro bmk-mgr-folder-or-url (ffun ufun) +  `(lambda () +     (interactive) +     (if (bmk-mgr-node-folder-p (bmk-mgr-get-node-at-point)) +         (funcall ',ffun) +       (funcall ',ufun)))) + +(defvar bmk-mgr-mode-map +  (let ((map (make-keymap))) +    (suppress-keymap map) +    (define-key map [(control ?a)] 'beginning-of-line) +    (define-key map [(control ?e)] 'end-of-line) +    (define-key map [(control ?k)] 'bmk-mgr-kill-bookmark) +    (define-key map [(control ?n)] 'bmk-mgr-next-line) +    (define-key map [(control ?p)] 'bmk-mgr-previous-line) +    (define-key map [(control ?y)] 'bmk-mgr-yank-bookmark) +    (define-key map [??] 'describe-mode) +    (define-key map [?A] 'bmk-mgr-add-folder) +    (define-key map [?I] 'bmk-mgr-toggle-images) +    (define-key map [?N] 'bmk-mgr-next-folder) +    (define-key map [?P] 'bmk-mgr-previous-folder) +    (define-key map [?Q] 'bmk-mgr-quit) +    (define-key map [?V] 'bmk-mgr-version) +    (define-key map [?a] 'bmk-mgr-add-bookmark) +    (define-key map [?c] 'bmk-mgr-close-children) +    (define-key map [?d] 'bmk-mgr-move-bookmark-down) +    (define-key map [?e] 'bmk-mgr-edit-bookmark) +    (define-key map [?f] 'bmk-mgr-find-folder) +    (define-key map [?h] 'describe-mode) +    (define-key map [?i] 'bmk-mgr-import) +    (define-key map [?n] 'bmk-mgr-next-line) +    (define-key map [?p] 'bmk-mgr-previous-line) +    (define-key map [?q] 'bmk-mgr-quit-ask) +    (define-key map [?s] 'bmk-mgr-save-bookmarks) +    (define-key map [?u] 'bmk-mgr-move-bookmark-up) +    (define-key map [?v] 'bmk-mgr-bookmark-info) +    (define-key map [?y] 'bmk-mgr-copy-url) +    (define-key map (kbd "<up>") 'bmk-mgr-previous-line) +    (define-key map (kbd "<down>") 'bmk-mgr-next-line) +    (define-key map (kbd "<left>") 'beginning-of-line) +    (define-key map (kbd "<right>") 'end-of-line) +    (define-key map (kbd "<mouse-1>") 'bmk-mgr-mouse-click) +    (define-key map (kbd "<mouse-2>") 'bmk-mgr-mouse-click-alt) +    (define-key map (kbd "<S-return>") 'bmk-mgr-browse-url-alt) +    (define-key map (kbd "M-RET") 'bmk-mgr-browse-url-alt) +    (define-key map (kbd "RET") 'bmk-mgr-browse-url) +    (define-key map (kbd "TAB") 'bmk-mgr-toggle-folder) +    map) +  "Keymap for `bmk-mgr-mode'.") + +(defvar bmk-mgr-mode-syntax-table +  (let ((st (make-syntax-table))) +    st) +  "Syntax table for `bmk-mgr-mode'.") + +;; regexps used by bmk-mgr-mode and other functions +(defvar bmk-mgr-outline-regexp nil) + +;; images +(defvar bmk-mgr-url-img) +(defvar bmk-mgr-fopen-img) +(defvar bmk-mgr-fclosed-img) + +;;;;; Mode definition: + +;;;###autoload +(defun bmk-mgr-mode (&optional tree) +  "\\<bmk-mgr-mode-map> +   Major mode for displaying bookmark files. + +Commands: + +<DIGIT>+<key>\tRepeat command denoted by <key> the number of times +             \tpreviously typed. Commands accepting a prefix count are +             \tmarked with (*) below. + +\\[bmk-mgr-next-line]\tGo to next visible line (*). +\\[bmk-mgr-previous-line]\tGo to previous visible line (*). +\\[bmk-mgr-next-folder]\tGo to next visible folder (*). +\\[bmk-mgr-previous-folder]\tGo to previous visible folder (*). +\\[beginning-of-line]\tGo to the beginning of text in current line. +\\[end-of-line]\tGo to the end of text in current line. +\\[bmk-mgr-toggle-folder]\tOpens or closes current folder. +\\[bmk-mgr-close-children]\tCloses all subfolders of current folder. +\\[bmk-mgr-bookmark-info]\tDisplay info about current bookmark or folder. +\\[bmk-mgr-copy-url]\tPut the current URL (if any) in the kill ring. +\\[bmk-mgr-find-folder]\tFind bookmarks folder. + +\\[bmk-mgr-mouse-click]\tDisplay or toggle the clicked URL or folder. +\\[bmk-mgr-mouse-click-alt]\tDisplay or toggle the clicked URL or folder, +                           \tusing the alternate browser. +\\[bmk-mgr-browse-url]\tDisplay current URL in browser. +\\[bmk-mgr-browse-url-alt]\tDisplay current URL in alternate browser. + +\\[bmk-mgr-move-bookmark-up]\tMoves current bookmark one line up (*). +\\[bmk-mgr-move-bookmark-down]\tMoves current bookmark one line down (*). +\\[bmk-mgr-edit-bookmark]\tEdit bookmark or folder in current line. +\\[bmk-mgr-add-bookmark]\tAdd a new bookmark (asks for its name and URL). +\\[bmk-mgr-add-folder]\tAdd a new bookmark folder (asks for its path). +\\[bmk-mgr-kill-bookmark]\tKills current bookmark or folder, putting it in the kill ring (*). +\\[bmk-mgr-yank-bookmark]\tYanks a previously killed bookmark or folder (*). + +\\[bmk-mgr-import]\tImports an external bookmarks file (xbel, w3m, bmk). + +\\[bmk-mgr-toggle-images]\tToggle display of images. + +\\[bmk-mgr-save-bookmarks]\tSave current bookmarks. +\\[bmk-mgr-quit]\tQuit Bookmark Manager. +\\[bmk-mgr-quit-ask]\tQuit Bookmark Manager asking for confirmation. + +\\[bmk-mgr-version]\tShow version. +\\[describe-mode]\tShows this help page. +" +  (kill-all-local-variables) +  (buffer-disable-undo) +  (setq major-mode 'bmk-mgr-mode) +  (setq mode-name "bmk") +  (use-local-map bmk-mgr-mode-map) + +  (let ((prefix (make-string bmk-mgr-indent-width 32))) +    (setq bmk-mgr-outline-regexp (concat "\\(" prefix "\\)*."))) +  (set (make-local-variable 'outline-regexp) bmk-mgr-outline-regexp) +  (set (make-local-variable 'truncate-lines) t) +  (set (make-local-variable 'automatic-hscrolling) t) +  (set (make-local-variable 'line-spacing) bmk-mgr-line-spacing) +  (set (make-local-variable 'kill-whole-line) t) +  (set (make-local-variable 'next-line-add-newlines) t) +  (goto-char 1) +  (bmk-mgr-refresh tree) +  (toggle-read-only 1) +  (unless bmk-mgr-inhibit-welcome-message +    (message +     "Emacs Bookmark Manager, version %s. Type `h' for help." bmk-mgr-version))) + +;;;;; Functions: + +;;;;;; Helper macros: +(defmacro bmk-mgr-with-bookmarks-buffer (&rest body) +  `(with-current-buffer (bmk-mgr-get-bookmark-buffer) +     (unwind-protect +         (prog1 +             (let ((inhibit-read-only t)) +               (bmk-mgr-unmark-current) +               ,@body) +           (if (not bmk-mgr-inhibit-minibuffer) (bmk-mgr-bookmark-info))) +       (bmk-mgr-mark-current)))) + +(defmacro bmk-mgr-with-current-node (&rest body) +  `(bmk-mgr-with-bookmarks-buffer +    (beginning-of-line) +    (let ((bmk-node (bmk-mgr-get-node-at-point)) +          (bmk-path (bmk-mgr-get-path-at-point))) +      ,@body))) + +(defmacro bmk-mgr-with-current-node-save (&rest body) +  `(bmk-mgr-with-current-node +    (prog1 +        (progn ,@body) +      (if bmk-mgr-autosave +          (progn +            (bmk-mgr-save-current-tree) +            (set-buffer-modified-p nil)))))) + +(defmacro bmk-mgr-repeat (&rest body) +  `(let ((count bmk-mgr-repeat-count)) +     (while (> count 0) +       (decf count) +       ,@body))) + +;;;;;; Helper functions: +(defun bmk-mgr-outline-level () +  (save-excursion +    (beginning-of-line) +    (if (looking-at bmk-mgr-outline-regexp) +        (length (match-string 0)) +      0))) + +(defun bmk-mgr-mark-current () +  (let* ((inhibit-read-only 1) +         (node (bmk-mgr-get-node-at-point)) +         (face (if (bmk-mgr-node-folder-p node) 'bmk-mgr-sel-folder-face +                 'bmk-mgr-sel-bookmark-face))) +    (beginning-of-line) +    (save-excursion +      (add-text-properties (progn (bmk-mgr-beginning) (point)) +                           (progn (end-of-line) (point)) +                       `(face ,face))))) + +(defun bmk-mgr-unmark-current () +  (let* ((inhibit-read-only 1) +         (node (bmk-mgr-get-node-at-point)) +         (face (if (bmk-mgr-node-folder-p node) 'bmk-mgr-folder-face +                 'bmk-mgr-bookmark-face))) +    (add-text-properties (progn (bmk-mgr-beginning) (point)) +                         (save-excursion (end-of-line) (point)) +                         `(face ,face)))) + +(defun bmk-mgr-unmark-all () +  (save-excursion +    (goto-char 1) +    (while (not (eobp)) +      (bmk-mgr-unmark-current) +      (next-line 1)))) + +(defun bmk-mgr-push-to-kill-ring (node) +  (push (copy-list node) bmk-mgr-kill-ring) +  (when (> (length bmk-mgr-kill-ring) bmk-mgr-kill-ring-size) +    (setcdr (nthcdr (1- bmk-mgr-kill-ring-size) bmk-mgr-kill-ring) nil))) + +(defsubst bmk-mgr-pop-kill-ring () (pop bmk-mgr-kill-ring)) + +(defsubst bmk-mgr-url-at-point () +  "Get the URL of the current bookmark, if any." +  (bmk-mgr-node-url (bmk-mgr-get-node-at-point))) + +(defun bmk-mgr-save-current-tree () +  (bmk-mgr-save-to-file (bmk-mgr-get-root-node-in-buffer) +                        bmk-mgr-bookmark-file)) + +(defun bmk-mgr-ask-path (prompt &optional path) +  (let ((PC-word-delimiters ".") +        (bmk-mgr-inhibit-minibuffer t) +        (path (or path (list (bmk-mgr-node-name +                               (bmk-mgr-get-root-node-in-buffer)))))) +    (bmk-mgr-string-to-path +     (completing-read prompt 'bmk-mgr-complete-path nil nil +                      (concat (bmk-mgr-path-to-string path) "/"))))) + +(defun bmk-mgr-complete-path (pstr fun flag) +  (bmk-mgr-with-bookmarks-buffer +   (let* ((root (bmk-mgr-get-root-node-in-buffer)) +         (partial (not (string-match "/$" pstr))) +         (pc (split-string pstr "/")) +         (path (or pc (list (bmk-mgr-node-name root)))) +         (ppath (if partial (bmk-mgr-path-parent path) path)) +         (partstr (concat "^" (regexp-quote (bmk-mgr-path-leaf path)))) +         (str (concat (bmk-mgr-path-to-string ppath) "/")) +         (children (bmk-mgr-node-child-folders root ppath)) +         (comp (mapcar (lambda (x) (concat str (bmk-mgr-node-name x) "/")) +                        (if partial +                            (remove-if-not +                             (lambda (x) +                               (string-match partstr (bmk-mgr-node-name x))) +                             children) +                          children))) +         (len (length comp))) +     (case flag +       ((nil) (cond +               ((and (not partial) (zerop len)) t) +               ((= len 1) (car comp)) +               ((zerop len) nil) +               (t pstr))) +       ((lambda) (not partial)) +       (t comp))))) + +;;;;;; Mode functions: + +(defun bmk-mgr-version () +  "Display version." +  (interactive) +  (message "Emacs Bookmark Manager, version %s" bmk-mgr-version)) + +(defun bmk-mgr-toggle-images () +  "Toggle image display." +  (interactive) +  (setq bmk-mgr-use-images (not bmk-mgr-use-images)) +  (bmk-mgr-refresh)) + +(defun bmk-mgr-refresh (&optional tree) +  "Refresh the bookmarks buffer." +  (interactive) +  (message "Redisplaying bookmarks...") +  (bmk-mgr-with-bookmarks-buffer +   (if window-system +       (progn +         (clear-image-cache +          (window-frame (get-buffer-window (current-buffer)))) +         (setq bmk-mgr-url-img +               (find-image +                `((:file ,bmk-mgr-bookmark-image :type xpm :ascent center)))) +         (setq bmk-mgr-fopen-img +               (find-image +                `((:file ,bmk-mgr-folder-open-image :type xpm :ascent 95)))) +         (setq bmk-mgr-fclosed-img +               (find-image +                `((:file ,bmk-mgr-folder-closed-image :type xpm :ascent 95))))) +     (setq bmk-mgr-url-img nil bmk-mgr-fopen-img nil bmk-mgr-fclosed-img nil +           bmk-mgr-use-images nil)) +   (let ((tree (or tree (bmk-mgr-get-root-node-in-buffer)))) +     (save-excursion +       (erase-buffer) +       (if bmk-mgr-ignore-fold-state (bmk-mgr-node-close-all-children tree)) +       (bmk-mgr-print-tree tree) +       (goto-char 1) +       (bmk-mgr-unmark-all) +       (bmk-mgr-refresh-open-close))) +  (message "Redisplaying bookmarks... done."))) + +(defsubst bmk-mgr-beginning () +  "Go to beginning of current bookmark." +  (interactive) +  (beginning-of-line) +  (re-search-forward "^ *")) + +(defun bmk-mgr-next-line (arg) +  "Go to next visible bookmark line." +  (interactive "P") +  (bmk-mgr-with-bookmarks-buffer +   (outline-next-visible-heading (if arg (prefix-numeric-value arg) 1)) +   (if (eobp) (outline-previous-visible-heading 1)))) + +(defun bmk-mgr-previous-line (arg) +  "Go to previous visible bookmark line." +  (interactive "P") +  (bmk-mgr-with-bookmarks-buffer +   (outline-previous-visible-heading (if arg (prefix-numeric-value arg) 1)))) + +(defun bmk-mgr-bookmark-info () +  "Show info about current bookmark or folder." +  (interactive) +  (let ((node (bmk-mgr-get-node-at-point))) +    (if node +        (if (bmk-mgr-node-url-p node) +            (let ((url (bmk-mgr-node-url node))) +              (and url (message "%s" url))) +          (let ((children (bmk-mgr-node-child-folders node))) +            (if children +                (message +                 "%s" +                 (concat "Subfolders: " +                         (mapconcat 'bmk-mgr-node-name children ", "))))))))) + +(defun bmk-mgr-copy-url () +  "Put current URL in the kill ring." +  (interactive) +  (bmk-mgr-with-current-node +   (let ((url (bmk-mgr-node-url bmk-node))) +     (when url +       (kill-new url) +       (message "%s copied" url))))) + +(defun bmk-mgr-next-folder (arg) +  "Go to next visible bookmark folder." +  (interactive "P") +  (bmk-mgr-with-bookmarks-buffer +   (let ((count (if arg (prefix-numeric-value arg) 1)) +         (test (lambda () (bmk-mgr-node-url-p (bmk-mgr-get-node-at-point))))) +     (while (> count 0) +       (decf count) +       (if (not (funcall test)) (outline-next-visible-heading 1)) +       (while (funcall test) +         (outline-next-visible-heading 1)))) +   (if (eobp) (outline-previous-visible-heading 1)) +   (bmk-mgr-beginning))) + +(defun bmk-mgr-previous-folder (arg) +  "Go to previous visible bookmark folder." +  (interactive "P") +  (bmk-mgr-with-bookmarks-buffer +   (let ((count (if arg (prefix-numeric-value arg) 1)) +         (test (lambda () (bmk-mgr-node-url-p (bmk-mgr-get-node-at-point))))) +     (while (> count 0) +       (decf count) +       (if (not (funcall test)) (outline-previous-visible-heading 1)) +       (while (funcall test) +         (outline-previous-visible-heading 1)))) +   (bmk-mgr-beginning))) + +(defun bmk-mgr-browse-url () +  "Display current bookmark in browser." +  (interactive) +  (let ((browse-url-browser-function +         (or bmk-mgr-browser-function browse-url-browser-function)) +        (url (bmk-mgr-node-url (bmk-mgr-get-node-at-point)))) +    (if url (browse-url url) (bmk-mgr-toggle-folder)))) + +(defun bmk-mgr-browse-url-alt () +  "Display current bookmark in alternate browser." +  (interactive) +  (bmk-mgr-with-current-node +   (let ((browse-url-browser-function +          (or bmk-mgr-alt-browser-function browse-url-browser-function)) +         (url (bmk-mgr-node-url (bmk-mgr-get-node-at-point)))) +     (if url (browse-url url) (bmk-mgr-toggle-folder))))) + +(defun bmk-mgr-mouse-click (event) +  "Visit the clicked bookmark or toogle the folder state." +  (interactive "e") +  (set-buffer (bmk-mgr-get-bookmark-buffer)) +  (goto-char (posn-point (event-start event))) +  (let ((node (bmk-mgr-get-node-at-point))) +    (if (bmk-mgr-node-url-p node) +        (bmk-mgr-browse-url) +      (if (bmk-mgr-node-folder-p node) +          (bmk-mgr-toggle-folder))))) + +(defun bmk-mgr-mouse-click-alt (event) +  "Visit the clicked bookmark or toogle the folder state." +  (interactive "e") +  (set-buffer (bmk-mgr-get-bookmark-buffer)) +  (goto-char (posn-point (event-start event))) +  (let ((node (bmk-mgr-get-node-at-point))) +    (if (bmk-mgr-node-url-p node) +        (bmk-mgr-browse-url-alt) +      (if (bmk-mgr-node-folder-p node) +          (bmk-mgr-toggle-folder))))) + +(defun bmk-mgr-toggle-folder () +  "Toggle the open/closed status of folder at point, if any." +  (interactive) +  (bmk-mgr-with-current-node +   (when (bmk-mgr-node-folder-p bmk-node) +     (bmk-mgr-node-toggle-open-closed bmk-node) +     (bmk-mgr-redraw-node-at-point)))) + +(defun bmk-mgr-close-children () +  "Close all subfolders of folder at point, if any." +  (interactive) +  (bmk-mgr-with-current-node +   (when (bmk-mgr-node-folder-p bmk-node) +     (bmk-mgr-node-close-all-children bmk-node) +     (bmk-mgr-update-tree-at-point) +     (bmk-mgr-refresh-open-close)))) + +(defun bmk-mgr-find-folder () +  "Find a bookmarks folder." +  (interactive) +  (bmk-mgr-with-bookmarks-buffer +   (bmk-mgr-find-path-in-buffer (bmk-mgr-ask-path "Find folder: ") t))) + +(defun bmk-mgr-save-bookmarks () +  "Save current bookmars." +  (interactive) +  (when (y-or-n-p "Save current bookmarks? ") +    (with-current-buffer (bmk-mgr-get-bookmark-buffer) +      (bmk-mgr-save-current-tree) +      (set-buffer-modified-p nil)))) + +(defun bmk-mgr-edit-bookmark () +  "Edit the current bookmark." +  (interactive) +  (bmk-mgr-with-current-node-save +   (when bmk-node +     (let ((newtitle (read-string "Name: " (bmk-mgr-node-title bmk-node)))) +       (if (> (length newtitle) 0) (bmk-mgr-node-set-name bmk-node newtitle)) +       (if (bmk-mgr-node-url-p bmk-node) +           (let ((newurl (read-string "URL: " (bmk-mgr-node-url bmk-node)))) +             (if (> (length newurl) 0) (bmk-mgr-node-set-url bmk-node newurl)))) +       (bmk-mgr-redraw-node-at-point +        (append (bmk-mgr-path-parent bmk-path) (list newtitle))) +       (if (bmk-mgr-node-folder-p bmk-node) ; update children paths +           (save-excursion +             (let ((cl (bmk-mgr-outline-level)) +                   (pos (length (bmk-mgr-path-parent bmk-path)))) +               (forward-line 1) +               (while (> (bmk-mgr-outline-level) cl) +                 (setf (nth pos (bmk-mgr-get-path-at-point)) newtitle) +                 (forward-line 1))))) +       (beginning-of-line))))) + +(defun bmk-mgr-add-bookmark-at-folder (&optional url title) +  (let ((path +         (bmk-mgr-with-current-node +          (bmk-mgr-ask-path "Add bookmark to folder: " +                            (if (bmk-mgr-node-folder-p bmk-node) bmk-path +                              (bmk-mgr-path-parent bmk-path)))))) +    (bmk-mgr-add-bookmark path nil url title t))) + + +(defun bmk-mgr-add-bookmark (&optional path node url title after) +  "Insert bookmark at a given path or current point." +  (interactive) +  (bmk-mgr-with-current-node-save +   (let* ((title (or title +                     (and node (bmk-mgr-node-name node)) +                     (read-string "Name of new bookmark: "))) +          (url (or (and node "") url (read-string "URL: "))) +          (node (or node (bmk-mgr-node-url-new title url)))) +     (if (and path (not (bmk-mgr-find-path-in-buffer path t))) +         (error "Folder %s does not exist" +                (bmk-mgr-path-to-string path))) +     (message "adding with path %S (%S)" path after) +     (if (not (or path bmk-path)) (outline-previous-visible-heading 1)) +     (if (and (bmk-mgr-node-folder-p (bmk-mgr-get-node-at-point)) +              (bmk-mgr-node-open-p (bmk-mgr-get-node-at-point))) +         (bmk-mgr-insert-child-at-point node (not after)) +       (bmk-mgr-insert-sibling-at-point node nil)) +     (while (not (or (eobp) (eq node (bmk-mgr-get-node-at-point)))) +       (outline-next-visible-heading 1))))) + +(defun bmk-mgr-add-folder () +  "Insert new bookmarks folder." +  (interactive) +  (bmk-mgr-with-current-node-save +   (let* ((fpath (if (bmk-mgr-node-folder-p bmk-node) bmk-path +                   (bmk-mgr-path-parent bmk-path))) +          (npath (bmk-mgr-ask-path "New folder: " fpath)) +          (pnpath (bmk-mgr-path-parent npath)) +          (sibling (and (not (equal bmk-path fpath)) ; inserting besides a url +                        (equal fpath pnpath))))      ; in the same folder +     (if (and (not (equal fpath pnpath)) +              (not (bmk-mgr-find-path-in-buffer pnpath t))) +         (error "Folder %s does not exist" (bmk-mgr-path-to-string pnpath))) +     (let ((node (bmk-mgr-node-folder-new (bmk-mgr-path-leaf npath)))) +       (if sibling +           (bmk-mgr-insert-sibling-at-point node nil) +         (bmk-mgr-insert-child-at-point node t)) +       (bmk-mgr-goto-node-around node))))) + +(defun bmk-mgr-yank-bookmark (arg) +  "Yank last killed bookmark at point." +  (interactive "P") +  (let ((count (if arg (prefix-numeric-value arg) 1))) +    (while (> count 0) +      (decf count) +      (bmk-mgr-with-current-node-save +       (bmk-mgr-add-bookmark nil (bmk-mgr-pop-kill-ring)))))) + +(defun bmk-mgr-delete-node-at-point () +  (let ((path (bmk-mgr-get-path-at-point))) +    (beginning-of-line) +    (hide-subtree) +    (let ((a (point)) +          (b (save-excursion (outline-next-visible-heading 1) (point)))) +      (if bmk-mgr-use-images (remove-images a b)) +      (delete-region a b) +      (if (eobp) (outline-previous-visible-heading 1))) +    (bmk-mgr-delete-node (bmk-mgr-get-root-node-in-buffer) path))) + +(defun bmk-mgr-kill-bookmark (arg) +  "Delete bookmark at point." +  (interactive "P") +  (let ((count (if arg (prefix-numeric-value arg) 1))) +    (while (> count 0) +      (decf count) +      (bmk-mgr-with-current-node-save +       (if (not (bmk-mgr-path-parent bmk-path)) +           (error "Cannot kill root node")) +       (if (and (bmk-mgr-node-folder-p bmk-node) +                (not (null (bmk-mgr-node-children bmk-node))) +                (not (y-or-n-p +                      (format +                       "Killing `%s' and all its contents. Are you sure? " +                       (bmk-mgr-path-leaf bmk-path))))) +           (error "Cancelled")) +       (bmk-mgr-push-to-kill-ring bmk-node) +       (bmk-mgr-delete-node-at-point))))) + +(defun bmk-mgr-transpose-lines (node path count &optional up) +  (beginning-of-line) +  (outline-next-visible-heading (if up count (* -1 count))) +  (let ((eol (save-excursion (end-of-line) (point)))) +    (if bmk-mgr-use-images (remove-images (point) eol)) +    (delete-region (point) (1+ eol)) +    (outline-next-visible-heading (if up (* -1 count) count)) +    (bmk-mgr-print-single-node-at-point node path t))) + +(defun bmk-mgr-goto-node-around (node &optional width) +  (let ((width (or width 2))) +    (outline-previous-visible-heading (1+ width)) +    (do ((max (1+ (* 2 width))) (n 0 (incf n))) +        ((or (> n max) (eq node (bmk-mgr-get-node-at-point)))) +      (outline-next-visible-heading 1)))) + +(defun bmk-mgr-move-bookmark-up (arg) +  "Move bookmark at point one line up." +  (interactive "P") +  (bmk-mgr-with-current-node-save +   (let ((ppath (bmk-mgr-path-parent bmk-path)) +         (count (if arg (prefix-numeric-value arg) 1))) +     (when (and (> count 0) +                (bmk-mgr-node-url-p bmk-node) +                (> (length bmk-path) 1)) +       (beginning-of-line) +       (let ((p (point))) +         (outline-previous-visible-heading count) +         (if (= (bmk-mgr-outline-level) 1) +             (progn +               (outline-next-visible-heading 1) +               (when (not (equal bmk-node (bmk-mgr-get-node-at-point))) +                 (goto-char p) +                 (bmk-mgr-delete-node-at-point) +                 (goto-char 1) +                 (bmk-mgr-insert-child-at-point bmk-node t))) +           (let* ((current (bmk-mgr-get-node-at-point)) +                  (iscl (bmk-mgr-node-closed-p current)) +                  (isurl (bmk-mgr-node-url-p current)) +                  (cpath (bmk-mgr-get-path-at-point)) +                  (cppath (bmk-mgr-path-parent cpath))) +             (cond +              ((and (equal ppath cppath) (or isurl iscl)) +               (bmk-mgr-node-swap-children-at-path +                (bmk-mgr-get-root-node-in-buffer) ppath bmk-node current) +               (bmk-mgr-transpose-lines bmk-node bmk-path count t)) +              (t +               (outline-next-visible-heading count) +               (bmk-mgr-delete-node-at-point) +               (outline-previous-visible-heading count) +               (if (or isurl iscl (equal cpath ppath)) +                   (bmk-mgr-insert-sibling-at-point bmk-node +                                                    (equal cpath ppath)) +                 (bmk-mgr-insert-child-at-point bmk-node nil))))))) +       (bmk-mgr-goto-node-around bmk-node))))) + +(defun bmk-mgr-move-bookmark-down (arg) +  "Move bookmark at point one line down." +  (interactive "P") +  (bmk-mgr-with-current-node-save +   (let ((ppath (bmk-mgr-path-parent bmk-path)) +         (count (if arg (prefix-numeric-value arg) 1))) +     (when (and (> count 0) +                (bmk-mgr-node-url-p bmk-node) +                (> (length bmk-path) 1)) +     (beginning-of-line) +     (let ((p (point))) +       (outline-next-visible-heading count) +       (if (null (bmk-mgr-get-node-at-point)) +           (progn +             (outline-previous-visible-heading 1) +             (when (not (equal bmk-node (bmk-mgr-get-node-at-point))) +               (goto-char p) +               (bmk-mgr-delete-node-at-point) +               (goto-char 1) +               (bmk-mgr-insert-child-at-point bmk-node nil) +               (goto-char (point-max)))) +         (let* ((current (bmk-mgr-get-node-at-point)) +                (iscl (bmk-mgr-node-closed-p current)) +                (isurl (bmk-mgr-node-url-p current)) +                (cpath (bmk-mgr-get-path-at-point)) +                (isout (< (length cpath) (length bmk-path))) +                (cppath (bmk-mgr-path-parent cpath))) +           (cond +            ((and (equal ppath cppath) (or isurl iscl)) +             (bmk-mgr-node-swap-children-at-path +              (bmk-mgr-get-root-node-in-buffer) ppath bmk-node current) +             (bmk-mgr-transpose-lines bmk-node bmk-path count nil)) +            (t +             (outline-previous-visible-heading count) +             (bmk-mgr-delete-node-at-point) +             (outline-next-visible-heading (1- count)) +             (if (or isurl iscl isout) +                 (bmk-mgr-insert-sibling-at-point bmk-node isout) +               (bmk-mgr-insert-child-at-point bmk-node t))))))) +     (bmk-mgr-goto-node-around bmk-node))))) + +(defvar bmk-mgr-import-formats '(("xbel" . bmk-mgr-import-xbel) +                                 ("bmk" . bmk-mgr-import-bmk))) + +(defun bmk-mgr-import-add-formatter (name fun) +  (add-to-list 'bmk-mgr-import-formats `(,name . ,fun))) + +(defun bmk-mgr-import () +  "Import bookmarks file." +  (interactive) +  (let* ((formats bmk-mgr-import-formats) +         (names (mapcar 'car formats)) +         (prompt (concat "Format (" (mapconcat 'identity names ", ") "): ")) +         (sel (completing-read prompt formats nil 1)) +         (fun (cdr (assoc sel formats)))) +    (if fun +        (bmk-mgr-with-bookmarks-buffer +         (let* ((file (read-file-name "File: " nil nil t)) +                (folder (bmk-mgr-ask-path "Import to folder: ")) +                (ign (message "Reading %s..." file)) +                (node (funcall fun file (bmk-mgr-path-leaf folder)))) +           (when node +             (message "Importing bookmarks...") +             (if (bmk-mgr-find-path-in-buffer folder t) +                 (let ((parent (bmk-mgr-get-node-at-point)) +                       (children (bmk-mgr-node-children node))) +                   (if (bmk-mgr-node-folder-p parent) +                       (progn +                         (mapc (lambda (x) +                                 (bmk-mgr-node-add-child parent x)) children) +                         (bmk-mgr-update-tree-at-point) +                         (bmk-mgr-refresh-open-close) +                         (message nil)) +                     (message "`%s' is not a correct insertion point" +                              (bmk-mgr-node-name parent)))) +               (if (bmk-mgr-find-path-in-buffer (bmk-mgr-path-parent folder) t) +                   (progn +                     (bmk-mgr-insert-child-at-point node nil) +                     (message nil)))))))))) + +(defun bmk-mgr-quit-ask () +  "Quit bookmarks buffer, asking for confirmation." +  (interactive) +  (when (y-or-n-p "Close bookmarks browser? ") (bmk-mgr-quit))) + +(defun bmk-mgr-quit () +  "Quit bookmarks buffer." +  (interactive) +  (with-current-buffer (bmk-mgr-get-bookmark-buffer) +   (bmk-mgr-save-current-tree) +   (kill-buffer (current-buffer)))) + +;;;; Import/export: + +;;;;; xbel: +(defun bmk-mgr-xbel-get-title (node def) +  (let* ((title-node (car (xml-get-children node 'title))) +         (title-body (or (and title-node (xml-node-children title-node)) +                         '()))) +    (bmk-mgr-filter-html +     (or (and title-body (stringp (car title-body)) (car title-body)) def)))) + +(defun bmk-mgr-xbel-to-bmk (xbel &optional name) +  (when (listp xbel) +    (case (xml-node-name xbel) +      (xbel (bmk-mgr-node-folder-new +             (or name "xbel") nil +             (mapcar 'bmk-mgr-xbel-to-bmk +                     (append (xml-get-children xbel 'bookmark) +                             (xml-get-children xbel 'folder))))) +      (folder (bmk-mgr-node-folder-new +               (bmk-mgr-xbel-get-title xbel "folder") +               (equal (xml-get-attribute xbel 'folded) "yes") +               (mapcar 'bmk-mgr-xbel-to-bmk +                       (append (xml-get-children xbel 'bookmark) +                               (xml-get-children xbel 'folder))))) +      (bookmark +       (let* ((href (bmk-mgr-filter-html (xml-get-attribute xbel 'href))) +              (title (bmk-mgr-xbel-get-title xbel href))) +         (bmk-mgr-node-url-new title href)))))) + +(defun bmk-mgr-import-xbel (file name) +  (save-current-buffer +    (if (not (file-readable-p file)) (error "Cannot read file")) +    (require 'xml) +    (message "Reading XBEL file...") +    (bmk-mgr-xbel-to-bmk +     (car (with-temp-buffer +            (insert-buffer (find-file-noselect file)) +            (beginning-of-buffer) +            (while (re-search-forward "\n" nil t) (replace-match "")) +            (beginning-of-buffer) +            (while (re-search-forward "\"\"" nil t) (replace-match "\"empty\"")) +            (beginning-of-buffer) +            (while (re-search-forward "> +<" nil t) (replace-match "><")) +            (xml-parse-region (point-min) (point-max)))) +     name))) + +;;;;; aux: +(defconst bmk-mgr-html-scp  "&#[0-9]+\\;") + +(defun bmk-mgr-filter-html (str) +  (let* ((str (substring-no-properties str)) +         (result "") +         (p0 0) +         (p1 (string-match bmk-mgr-html-scp str))) +    (while p1 +      (let* ((p2 (match-end 0)) +             (ch +              (char-to-string (bmk-string-to-int (substring +                                                  str (+ 2 p1) (1- p2)))))) +        (setf result (concat result (substring str p0 p1) ch)) +        (setf p0 p2) +        (setf p1 (string-match bmk-mgr-html-scp str p2)))) +    (concat result (substring str p0)))) + +;;;; Bookmarks buffer: + +;;;;; Functions: +(defun bmk-mgr-print-single-node-at-point (node path &optional insert) +  (beginning-of-line) +  (let ((kill-whole-line nil) +        (inhibit-read-only t) +        (depth (* (- (length path) 1) bmk-mgr-indent-width)) +        (txt-mark "") +        (img)) +    (if (bmk-mgr-node-folder-p node) +        (if (bmk-mgr-node-open-p node) +            (setq txt-mark bmk-mgr-open-mark img bmk-mgr-fopen-img) +          (setq txt-mark bmk-mgr-closed-mark img bmk-mgr-fclosed-img)) +      (if (> (length (bmk-mgr-node-url node)) 0) +          (setq txt-mark bmk-mgr-link-mark img bmk-mgr-url-img))) +    (if insert +        (progn (newline) +               (forward-line -1)) +      (kill-line)) +    (delete-trailing-whitespace) +    (remove-images (point) (save-excursion (end-of-line) (point))) +    (insert (make-string depth 32)) +    (if bmk-mgr-use-images +        (if img ; no image for separators +            (progn (put-image img (point)) (insert " "))) +      (insert txt-mark)) +    (insert (bmk-mgr-node-title node)) +    (bmk-mgr-set-path-at-point path) +    (bmk-mgr-set-node-at-point node))) + +(defun bmk-mgr-print-tree (tree &optional path level) +  (let* ((kill-whole-line nil) +         (inhibit-read-only t) +         (next-line-add-newlines nil) +         (insertp +          (lambda (node path) +            (not +             (and (equal path (bmk-mgr-get-path-at-point)) +                  (equal (bmk-mgr-node-type node) +                         (bmk-mgr-node-type (bmk-mgr-get-node-at-point))))))) +         (pfun +          (lambda (n w) +            (beginning-of-line) +            (let* ((title (bmk-mgr-node-title n)) +                   (neww (append w (list title)))) +              (bmk-mgr-print-single-node-at-point +               n neww (funcall insertp n neww)) +              (if (eobp) (newline)) +              (next-line 1) +              (cons neww t))))) +    (bmk-mgr-visit-tree tree pfun path))) + +(defsubst bmk-mgr-update-tree-at-point () +  (save-excursion +    (bmk-mgr-print-tree (bmk-mgr-get-node-at-point) +                        (bmk-mgr-path-parent (bmk-mgr-get-path-at-point))))) + +(defsubst bmk-mgr-set-path-at-point (path &optional buffer) +  (let ((inhibit-field-text-motion t) +        (pos (save-excursion (end-of-line) (point)))) +    (save-excursion +      (beginning-of-line) +      (add-text-properties (point) pos (list 'bmk-mgr-path path) buffer)))) + +(defsubst bmk-mgr-set-node-at-point (node &optional buffer) +  (let ((inhibit-field-text-motion t) +        (pos (save-excursion (end-of-line) (point)))) +    (save-excursion +      (beginning-of-line) +      (add-text-properties (point) pos (list 'bmk-mgr-node node) buffer) +      (when (bmk-mgr-node-url-p node) +        (bmk-mgr-beginning) +        (add-text-properties (point) (1- pos) +                             (list 'mouse-face 'bmk-mgr-sel-bookmark-face) +                           buffer))))) + +(defsubst bmk-mgr-get-path-at-point (&optional buffer) +  (get-text-property (point) 'bmk-mgr-path buffer)) + +(defsubst bmk-mgr-get-node-at-point (&optional buffer) +  (get-text-property (point) 'bmk-mgr-node buffer)) + +(defun bmk-mgr-get-root-node-in-buffer (&optional buffer) +  (save-current-buffer +    (if buffer (set-buffer buffer)) +    (save-excursion +      (goto-char (point-min)) +      (bmk-mgr-get-node-at-point)))) + +(defun bmk-mgr-refresh-open-close () +  (save-excursion +    (let* ((node (bmk-mgr-get-node-at-point)) +           (path (bmk-mgr-get-path-at-point)) +           (cl (length path))) +      (unless (eobp) +        (bmk-mgr-unmark-current) +        (if (bmk-mgr-node-open-p node) +            (progn +              (show-children) +              (outline-next-visible-heading 1) +              (while (> (length (bmk-mgr-get-path-at-point)) cl) +                (bmk-mgr-refresh-open-close) +                (outline-next-visible-heading 1))) +          (hide-subtree)))))) + +(defun bmk-mgr-redraw-node-at-point (&optional path) +  (save-excursion +    (let ((node (bmk-mgr-get-node-at-point))) +      (when node +        (show-children) +        (bmk-mgr-print-single-node-at-point +         node (or path (bmk-mgr-get-path-at-point))) +        (beginning-of-line) +        (when (bmk-mgr-node-folder-p node) +          (if (bmk-mgr-node-open-p node) +              (bmk-mgr-refresh-open-close) +            (hide-subtree))))))) + +(defun bmk-mgr-find-path-in-buffer (path &optional begin) +  (beginning-of-line) +  (let ((ip (point)) +        (ppos) +        (found)) +    (if begin (goto-char (point-min))) +    (while (not (or found (eobp))) +      (let* ((cp (bmk-mgr-get-path-at-point)) +             (node (bmk-mgr-get-node-at-point)) +             (isf (and node (bmk-mgr-node-folder-p node))) +             (isclf (and isf (bmk-mgr-node-closed-p node)))) +        (cond +         ((equal path cp) +          (save-excursion +            (mapc (lambda (p) +                    (goto-char p) +                    (bmk-mgr-toggle-folder) +                    (bmk-mgr-unmark-current)) +                  (reverse (if isclf (cons (point) ppos) ppos)))) +          (setf found t)) +         ((or (and isf (bmk-mgr-path-contains cp path)) +              (and (not isf) (equal (bmk-mgr-path-parent cp) +                                    (bmk-mgr-path-parent path)))) +          (if isclf (setf ppos (cons (point) ppos))) +          (forward-line 1)) +         (t (let ((cl (bmk-mgr-outline-level))) +              (forward-line 1) +              (while (and (not (eobp)) +                          (< cl (bmk-mgr-outline-level))) +                (forward-line 1))))))) +    (if (not found) (goto-char ip) +      (save-excursion (goto-char ip) (bmk-mgr-unmark-current))) +    (and found (point)))) + +(defun bmk-mgr-insert-sibling-at-point (node before) +  (let ((bmk-node (bmk-mgr-get-node-at-point)) +        (bmk-path (bmk-mgr-get-path-at-point)) +        (pos (point))) +    (save-excursion +      (if (and node +               (bmk-mgr-find-path-in-buffer (bmk-mgr-path-parent bmk-path) t)) +          (let* ((path (list (bmk-mgr-path-leaf (bmk-mgr-get-path-at-point)) +                             (bmk-mgr-path-leaf bmk-path))) +                 (newtree (bmk-mgr-insert-node (bmk-mgr-get-node-at-point) +                                               node path t before))) +            (if newtree +                (progn +                  (goto-char pos) +                  (when (not before) +                    (outline-next-visible-heading 1) +                    (if (eobp) (newline))) +                  (save-excursion +                    (bmk-mgr-print-tree node +                                        (bmk-mgr-path-parent bmk-path))) +                  (bmk-mgr-refresh-open-close)) +              (error "Internal error"))) +        (error "Path to node not found"))))) + + +(defun bmk-mgr-insert-child-at-point (node before) +  (let ((bmk-node (bmk-mgr-get-node-at-point)) +        (bmk-path (bmk-mgr-get-path-at-point))) +    (if (bmk-mgr-node-url-p bmk-node) +        (bmk-mgr-insert-sibling-at-point node before) +      (when node +        (let* ((path (list (bmk-mgr-path-leaf bmk-path))) +               (newtree (bmk-mgr-insert-node bmk-node node path nil before))) +          (if newtree +              (progn +                (if (bmk-mgr-node-closed-p bmk-node) (bmk-mgr-toggle-folder)) +                (forward-line 1) +                (if (and (not before) +                         (> (length (bmk-mgr-node-children bmk-node)) 1)) +                    (condition-case nil +                        (while (not (eobp)) (outline-forward-same-level 1)) +                      (error (forward-line 1)))) +                (save-excursion +                  (bmk-mgr-print-tree node bmk-path)) +                (bmk-mgr-refresh-open-close)))))))) + +;;;; Bookmark tree datatype: + +;;;;; paths: + +(defsubst bmk-mgr-path-parent (path) (and (listp path) (subseq path 0 -1))) +(defsubst bmk-mgr-path-leaf (path) (and (listp path) (car (subseq path -1)))) +(defsubst bmk-mgr-path-to-string (path) +  (mapconcat (lambda (x) (and (stringp x) x)) +             (delete-if (lambda (x) (string= x "")) path) "/")) +(defsubst bmk-mgr-string-to-path (path) +  (delete-if (lambda (x) (string= x "")) +             (split-string path "/"))) +(defsubst bmk-mgr-path-contains (parent child) +  (equal parent (subseq child 0 (length parent)))) + +;;;;; constructors: +(defsubst bmk-mgr-node-url-new (title url) (list title url)) +(defsubst bmk-mgr-node-folder-new (name &optional closed children) +  (cons name (cons (if closed :closed :open) children))) + +;;;;; accessors: +(defsubst bmk-mgr-node-children (n) (cddr n)) +(defsubst bmk-mgr-node-name (n) (nth 0 n)) +(defsubst bmk-mgr-node-folder-p (n) (and n (symbolp (nth 1 n)))) +(defsubst bmk-mgr-node-open-p (n) (equal :open (nth 1 n))) +(defsubst bmk-mgr-node-closed-p (n) (equal :closed (nth 1 n))) +(defsubst bmk-mgr-node-url-p (n) (stringp (nth 1 n))) +(defsubst bmk-mgr-node-url (n) (and (stringp (nth 1 n)) (nth 1 n))) +(defsubst bmk-mgr-node-title (n) (nth 0 n)) +(defsubst bmk-mgr-node-type (n) (if (bmk-mgr-node-url-p n) 'url 'folder)) + +(defun bmk-mgr-node-child-folders (node &optional path) +  (let ((node (or (and (null path) node) +                  (and node path (bmk-mgr-find-node node path))))) +    (when node +      (remove-if 'bmk-mgr-node-url-p +                 (bmk-mgr-node-children node))))) + +(defun bmk-mgr-find-node (tree path) +  (let* ((node nil) +         (ffun (lambda (n p) +                 (if (equal (car p) (bmk-mgr-node-name n)) +                     (if (null (cdr p)) +                         (progn +                           (setq node n) +                           (cons nil nil)) +                       (cons (cdr p) t)) +                   (cons nil nil))))) +    (bmk-mgr-visit-tree tree ffun path) +    node)) + +(defun bmk-mgr-find-node-and-parent (tree path) +  (let* ((parent tree) +         (node nil) +         (fnode (lambda (n p) +                  (if (equal (car p) (bmk-mgr-node-name n)) +                      (if (null (cdr p)) +                          (progn (setq node n) +                                 (cons nil nil)) +                        (progn (setq parent n) +                               (cons (cdr p) t))) +                    (cons nil nil))))) +    (bmk-mgr-visit-tree tree fnode path) +    (cons (and node parent) node))) + +;;;;; modifiers: +(defsubst bmk-mgr-node-set-name (node name) +  (when (stringp name) (setf (car node) name))) + +(defsubst bmk-mgr-node-set-url (node url) +  (when (and (bmk-mgr-node-url-p node) (stringp url)) (setf (nth 1 node) url))) + +(defun bmk-mgr-node-toggle-open-closed (node) +  (when (bmk-mgr-node-folder-p node) +    (setf (nth 1 node) (if (bmk-mgr-node-closed-p node) :open :closed)))) + +(defsubst bmk-mgr-node-close (node) +  (when (bmk-mgr-node-folder-p node) (setf (nth 1 node) :closed))) + +(defsubst bmk-mgr-node-close-all (tree) +  (when (bmk-mgr-node-folder-p tree) +    (bmk-mgr-node-close tree) +    (mapc #'bmk-mgr-node-close-all (bmk-mgr-node-children tree)))) + +(defsubst bmk-mgr-node-close-all-children (tree) +  (when (bmk-mgr-node-folder-p tree) +    (mapc #'bmk-mgr-node-close-all (bmk-mgr-node-children tree)))) + +(defun bmk-mgr-node-set-children (node children) +  (when (bmk-mgr-node-folder-p node) +    (setf (nthcdr 2 node) children))) + +(defun bmk-mgr-node-swap-children (node c0 c1) +  "Swap the positions of C0 and C1, which are children of NODE. + +If C0 is null, C1 gets promoted to the top of the children list. +Conversely, if C1 is null, C0 goes to the tail." +  (when (and (bmk-mgr-node-folder-p node) (or c0 c1)) +    (let* ((children (bmk-mgr-node-children node)) +           (p0 (position c0 children)) +           (p1 (position c1 children))) +      (when (and children (or p0 p1)) +        (if (and c1 p1) (setf (nth (or p0 2) children) c1)) +        (if (and c0 p0) +            (setf (nth (or p1 (1- (length children))) children) c0)))))) + +(defun bmk-mgr-node-swap-children-at-path (tree path c0 c1) +  "Calls `bmk-mgr-node-swap-children' on the node of TREE denoted by +path." +  (when tree +    (let ((node (bmk-mgr-find-node tree path))) +      (if node (bmk-mgr-node-swap-children node c0 c1))))) + +(defun bmk-mgr-node-add-child (tree node &optional prev before) +  "Add NODE as a new child of TREE, after (or before, if BEFORE is not +null) node PREV if it exists. + +Returns the updated TREE if successful, nil otherwise." +  (when (bmk-mgr-node-folder-p tree) +    (let* ((pos (or (position prev tree) (if before 2))) +           (insp (if (not pos) (length tree) (if before pos (1+ pos))))) +      (setf (nthcdr insp tree) (cons node (nthcdr insp tree))) +      tree))) + +(defun bmk-mgr-insert-node (tree node path &optional sibling before) +  "Insert the NODE at the given PATH of TREE. + +If SIBLING is not null, the new node will be inserted as a sibling of +the one denoted by PATH. Otherwise, PATH is the path of NODE's parent. +If BEFORE is not null, NODE is inserter before or as the first child +denoted by path. + +Returns the updated parent of NODE if successful, nil otherwise." +  (let* ((np (bmk-mgr-find-node-and-parent tree path)) +         (parent (and np (car np))) +         (found (and np (cdr np)))) +    (when found +      (if (or sibling (bmk-mgr-node-url-p found)) +          (bmk-mgr-node-add-child parent node found before) +        (bmk-mgr-node-add-child found node nil before))))) + +(defun bmk-mgr-delete-node (tree path) +  (let* ((np (bmk-mgr-find-node-and-parent tree path)) +         (parent (and np (car np))) +         (found (and np (cdr np))) +         (children (and found (bmk-mgr-node-children parent)))) +    (when children +      (bmk-mgr-node-set-children parent (remove found children))))) + +;;;;; input/output: +(defun bmk-mgr-read-from-file (filename) +  (let ((rfname (expand-file-name filename))) +    (if (file-readable-p rfname) +        (with-temp-buffer +          (insert-file-contents rfname) +          (goto-char (point-min)) +          (let ((sexp (read (current-buffer)))) +            (and (bmk-mgr-node-folder-p sexp) sexp))) +      '("Bookmarks" :open +        ("Emacs bookmark manager" +         "http://www.emacswiki.org/cgi-bin/wiki/EmacsBmkMgr"))))) + +(defun bmk-mgr-save-to-file (bmks filename) +  (require 'pp) +  (when (bmk-mgr-node-folder-p bmks) +    (let ((rfname (expand-file-name filename)) +          (b (if bmk-mgr-ignore-fold-state (subst :closed :open bmks) bmks))) +      (with-temp-buffer +        (insert ";;; File automatically generated by Emacs Bookmark Manager" +                "\n") +        (if bmk-mgr-ignore-fold-state (bmk-mgr-node-toggle-open-closed b)) +        (pp b (current-buffer)) +        (insert "\n;;; End of " (file-name-nondirectory rfname) "\n") +        (write-region (point-min) (point-max) rfname))))) + + +;;;;; aux functions: +(defun bmk-mgr-visit-tree (tree fun arg) +  "Visit a bookmarks tree aplying FUN to its nodes." +  (when tree +    (let ((arg (funcall fun tree arg))) +      (when (cdr arg) +        (mapc (lambda (n) (bmk-mgr-visit-tree n fun (car arg))) +              (bmk-mgr-node-children tree)))))) + + + +(provide 'bmk-mgr) + + + + + +;;; Local stuff: +;;;; Local Variables: ;; +;;;; mode: emacs-lisp ;; +;;;; mode: outline-minor ;; +;;;; outline-regexp: ";;[;\f]+ " ;; +;;;; outline-heading-end-regexp: ":\n" ;; +;;;; indent-tabs-mode: nil ;; +;;;; End: ;; + +;;; bmk-mgr.el ends here diff --git a/bmk/dot-emacs.el b/bmk/dot-emacs.el new file mode 100644 index 0000000..01f00d0 --- /dev/null +++ b/bmk/dot-emacs.el @@ -0,0 +1,42 @@ +;;; sample initialisation file for bmk-mgr + +(if (require 'bmk-mgr nil t) +    (progn +      (setq bmk-mgr-bookmark-file "~/.emacs.d/bookmarks") +      (setq bmk-mgr-inhibit-welcome-message nil) +      (setq bmk-mgr-inhibit-minibuffer t) +      (setq bmk-mgr-use-own-frame nil) +      (setq bmk-mgr-use-images t) +      (setq bmk-mgr-ignore-fold-state t) + +      (define-key bmk-mgr-mode-map "g" 'bmk-mgr-browse-url) +      (define-key bmk-mgr-mode-map "G" 'bmk-mgr-browse-url-alt) +      (global-set-key "\C-cB" 'bmk-mgr-show-bookmarks) +      (global-set-key "\C-cA" 'bmk-mgr-add-url-at-point) + +      ;;;; integration with emacs-w3m (optional) +      (when (require 'w3m nil t) +        (require 'bmk-mgr-w3m) +        (defun browse-bmk-w3m (url &rest ig) +          (goto-w3m-buffer) +          (w3m-goto-url url t)) + +        (defun browse-bmk-new-tab-w3m (url &rest ig) +          (goto-w3m-buffer) +          (w3m-goto-url-new-session url t)) + +        (defun goto-w3m-buffer () (interactive) +          (let ((display-buffer-reuse-frames 1) +                (pop-up-windows nil) +                (buffer (w3m-alive-p))) +            (if buffer (pop-to-buffer buffer)))) + +        (define-key bmk-mgr-mode-map "w" 'goto-w3m-buffer) +        (setq bmk-mgr-browser-function 'browse-bmk-w3m) +        (setq bmk-mgr-alt-browser-function 'browse-bmk-new-tab-w3m)) + +      ;; integration with w3 +      (require 'bmk-mgr-w3))) + +  (message "bookmark manager not available")) + diff --git a/bmk/folder-closed.xpm b/bmk/folder-closed.xpm new file mode 100644 index 0000000..ece8a9e --- /dev/null +++ b/bmk/folder-closed.xpm @@ -0,0 +1,31 @@ +/* XPM */ +static char *folder-closed[] = { +/* columns rows colors chars-per-pixel */ +"16 16 9 1", +"  c gray100", +". c #FFFFCC", +"X c #CCCCFF", +"o c #C0C0C0", +"O c #9999FF", +"+ c #6666CC", +"@ c #222222", +"# c black", +"$ c None", +/* pixels */ +"$$$$$$$$$$$$$$$$", +"$$$$$$$$$$$$$$$$", +"$$$$$$$$$$$$$$$$", +"$$$$$$$$$$$$$$$$", +"$$++++O$$$$$$$$$", +"$+ XXO.++++++$$$", +"+ XXXXXXXXXXXO$$", +"+ OXOXOXOXOXO+$$", +"+ XOXOXOXOXOX+#$", +"+ OXOXOXOXOXO+#$", +"+ XOXOXOXOXOX+#$", +"+ OXOXOXOXOXO+#$", +"+ XOXOXOXOXOX+#$", +"+XOXOXOXOXOXO+#$", +"++++++++++++++#$", +"$#@@###########$" +}; diff --git a/bmk/folder-open.xpm b/bmk/folder-open.xpm new file mode 100644 index 0000000..f03f65c --- /dev/null +++ b/bmk/folder-open.xpm @@ -0,0 +1,39 @@ +/* XPM */ +static char *folder-open[] = { +/* columns rows colors chars-per-pixel */ +"16 16 17 1", +"  c gray100", +". c #FFFFCC", +"X c magenta", +"o c #CCCCFF", +"O c #C0C0C0", +"+ c #9999FF", +"@ c #6666CC", +"# c #222222", +"$ c black", +"% c black", +"& c black", +"* c black", +"= c black", +"- c black", +"; c black", +": c black", +"> c None", +/* pixels */ +">>>>>>>>>>>>>>>>", +">>>>>>>>>>>>>>>>", +">>>>>>>>>>>>>>>>", +">>>>>>>>>>>>>>>>", +">>@@@@>>>>>>>>>>", +">@   @@@@@@@@@>>", +">@ +O.......#+@>", +">@ O.......#+o@>", +">+ .......#+o+@$", +"@@@@@@@@@@#@+o@$", +"@         O$o+@$", +">@+O+O+O+O+O$o@$", +">@O+O+O+O+O+#$@$", +">>@O+O+O+O+O+#$$", +">>@@@@@@@@@@@@@$", +">>>$$$$$$$$$$$$$" +}; diff --git a/bmk/url-alt.xpm b/bmk/url-alt.xpm new file mode 100644 index 0000000..4cb2c14 --- /dev/null +++ b/bmk/url-alt.xpm @@ -0,0 +1,31 @@ +/* XPM */ +static char *document[] = { +/* columns rows colors chars-per-pixel */ +"16 16 9 1", +"  c gray100", +". c #CECEBF", +"X c gray80", +"o c #272724", +"O c black", +"+ c black", +"@ c black", +"# c black", +"$ c None", +/* pixels */ +"$oooooooooo$$$$$", +"$o........oO$$$$", +"$o........oXO$$$", +"$o........oooo$$", +"$o...........o$$", +"$o...........o$$", +"$o..o.oo.oo..o$$", +"$o...........o$$", +"$o..oooo.oo..o$$", +"$o...........o$$", +"$o..oo.oo.o..o$$", +"$o...........o$$", +"$o...........o$$", +"$o...........o$$", +"$o...........o$$", +"$ooooooooooooo$$" +}; diff --git a/bmk/url.xpm b/bmk/url.xpm new file mode 100644 index 0000000..60cad93 --- /dev/null +++ b/bmk/url.xpm @@ -0,0 +1,39 @@ +/* XPM */ +static char *article[] = { +/* columns rows colors chars-per-pixel */ +"16 16 17 1", +"  c black", +". c #BF0000", +"X c #00BF00", +"o c #BFBF00", +"O c #0000BF", +"+ c #BF00BF", +"@ c #00BFBF", +"# c #C0C0C0", +"$ c #808080", +"% c red", +"& c green", +"* c yellow", +"= c blue", +"- c magenta", +"; c cyan", +": c gray100", +"> c None", +/* pixels */ +"OOOOOOOOOOO>>>>>", +"O:::::::::O>>>>>", +"O: #$ # #:OOO>>>", +"O:$ # $  :O*O>>>", +"O:::::::::O:O$>>", +"O:#$:$$#$:O*O$>>", +"O:::::::::O:O$>>", +"O:$$:$#$$:O*O$>>", +"O:::::::::O:O$>>", +"O:#$:$$$#:O*O$>>", +"O:::::::::O:O$>>", +"OOOOOOOOOOO*O$>>", +">>O:*:*:*:*:O$>>", +">>OOOOOOOOOOO$>>", +">>>>$$$$$$$$$$>>", +">>>>>>>>>>>>>>>>" +}; diff --git a/emms/jao-emms-info-track.el b/emms/jao-emms-info-track.el new file mode 100644 index 0000000..5fac8f3 --- /dev/null +++ b/emms/jao-emms-info-track.el @@ -0,0 +1,123 @@ +;; jao-emms-info-track.el -- utilities to show tracks + +;; Copyright (C) 2009, 2010 Jose Antonio Ortega Ruiz + +;; Author: Jose Antonio Ortega Ruiz <jao@gnu.org> +;; Start date: Sat Jul 04, 2009 13:47 + +;; This file is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3 of the License, or +;; (at your option) any later version. + +;; This file is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program.  If not, see <http://www.gnu.org/licenses/>. + +;;; Code: + +(require 'emms) +(require 'jao-osd) +(require 'jao-emms) + +(defgroup jao-emms-faces nil "Faces" +  :group 'faces +  :group 'jao-emms) + +(defface jao-emms-font-lock-album '((t (:foreground "lightgoldenrod2"))) +  "Album name in EMMS track message." +  :group 'jao-emms-faces) + +(defface jao-emms-font-lock-track '((t (:bold t))) +  "Track number in EMMS track message." +  :group 'jao-emms-faces) + +(defface jao-emms-font-lock-title '((t (:foreground "dodgerblue2"))) +  "Track title in EMMS track message." +  :group 'jao-emms-faces) + +(defface jao-emms-font-lock-artist '((t (:foreground "dodgerblue3"))) +  "Artist name in EMMS track message." +  :group 'jao-emms-faces) + +(defcustom jao-emms-show-osd-p nil +  "Whether to show osd notices on track change" +  :group 'jao-emms) + + + +(defun jao-emms-info-track-stream (track) +  "Return track info for streams" +  (let ((name (emms-track-name track)) +        (title (or (emms-track-get track 'title nil) +                   (car (emms-track-get track 'metadata nil))))) +    (format "♪ %s (%s)" title (if title (emms-track-type track) name)))) + +(defsubst jao--put-face (str face) +  (put-text-property 0 (length str) 'face face str) +  str) + +(defun jao-emms-info-track-file (track) +  "Return a description of the current track." +  (let ((no (string-to-number (emms-track-get track 'info-tracknumber "0"))) +        (time (emms-track-get track 'info-playing-time)) +        (artist (emms-track-get track 'info-artist "")) +        (composer (emms-track-get track 'info-composer nil)) +        (title (emms-track-get track 'info-title "")) +        (album (emms-track-get track 'info-album)) +        (last-played (or (emms-track-get track 'last-played) '(0 0 0))) +        (play-count (or (emms-track-get track 'play-count) 0))) +    (if (or (not title) (not album)) +        (emms-track-simple-description track) +      (format "♪ %s%s%s%s%s %s" +              (if time (format "[%02d:%02d] " (/ time 60) (mod time 60)) "") +              (jao--put-face artist 'jao-emms-font-lock-artist) +              (jao--put-face (if composer (format " [%s]" composer) "") +                             'jao-emms-font-lock-artist) +              (jao--put-face (if album (format " (%s)" album) " *") +                             'jao-emms-font-lock-album) +              (jao--put-face (if (zerop no) "" (format " %02d." no)) +                             'jao-emms-font-lock-track) +              (jao--put-face title +                             'jao-emms-font-lock-title))))) + +(defun jao-emms-info-track-description (track) +  (if (memq (emms-track-type track) '(streamlist url)) +      (jao-emms-info-track-stream track) +    (jao-emms-info-track-file track))) + +(defun jao-emms-toggle-osd () +  (interactive) +  (setq jao-emms-show-osd-p (not jao-emms-show-osd-p)) +  (message "Emms OSD %s" (if jao-emms-show-osd-p "enabled" "disabled"))) + +(defsubst jao-emms-current-track-str () +  (substring-no-properties (jao-emms-info-track-description +                            (emms-playlist-current-selected-track)))) + +(defun jao-emms-show-osd () +  (interactive) +  (let ((str (jao-emms-current-track-str))) +    (when str (jao-osd-cat 'emms (substring str 2))) +    t)) + +(defun jao-emms-show-osd-hook () +  (interactive) +  (when jao-emms-show-osd-p (jao-emms-show-osd)) +  t) + +(defun jao-emms-info-setup (&optional show-osd show-echo-line) +  (setq emms-track-description-function 'jao-emms-info-track-description) +  (setq jao-emms-show-osd-p show-osd) +  (add-hook 'emms-player-started-hook 'jao-emms-show-osd-hook) +  (unless show-echo-line +    (eval-after-load 'emms-player-mpd +      '(remove-hook 'emms-player-started-hook 'emms-player-mpd-show)))) + + +(provide 'jao-emms-info-track) +;;; jao-emms-info-track.el ends here diff --git a/emms/jao-emms-lyrics.el b/emms/jao-emms-lyrics.el new file mode 100644 index 0000000..965f7cd --- /dev/null +++ b/emms/jao-emms-lyrics.el @@ -0,0 +1,171 @@ +;; jao-emms-lyrics.el -- simple show lyrics in emms + +;; Copyright (C) 2009, 2010 Jose Antonio Ortega Ruiz + +;; Author: Jose Antonio Ortega Ruiz <jao@gnu.org> +;; Start date: Sat Jul 04, 2009 13:41 + +;; This file is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3 of the License, or +;; (at your option) any later version. + +;; This file is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program.  If not, see <http://www.gnu.org/licenses/>. + +;;; Code: + +(require 'emms) + +(defvar jao-emms-lyrics-cache-dir "~/.emacs.d/emms-lyrics") + +(defun jao-emms-lyrics--filename (artist title) +  (expand-file-name (format "%s.lyr" title) +                    (jao-emms-lyrics--ensure-dir artist))) + +(defun jao-emms-lyrics--ensure-dir (artist) +  (let ((candidate (expand-file-name artist jao-emms-lyrics-cache-dir))) +    (unless (file-directory-p candidate) +      (make-directory candidate t)) +    candidate)) + +(defun jao-emms-lyrics--get-cached (artist title) +  (let ((candidate (jao-emms-lyrics--filename artist title))) +    (and (file-exists-p candidate) +         (with-current-buffer (find-file-noselect candidate) +           (prog1 +               (buffer-string) +             (kill-buffer)))))) + +(defun jao-emms-lyrics--cache (artist title lyrics) +  (with-current-buffer +      (find-file-noselect (jao-emms-lyrics--filename artist title)) +    (delete-region (point-min) (point-max)) +    (insert lyrics) +    (save-buffer) +    (kill-buffer))) + +(make-variable-buffer-local + (defvar jao-emms-lyrics--path nil)) + +(defvar jao-emms-lyrics-mode-map) +(setq jao-emms-lyrics-mode-map +      (let ((map (make-keymap))) +        (suppress-keymap map) +        (define-key map [?q] 'bury-buffer) +        (define-key map [?g] 'jao-emms-show-lyrics) +        (define-key map [?G] 'jao-emms-show-lyrics-force) +        (define-key map [?e] 'jao-emms-edit-lyrics) +        map)) + +(defvar jao-emms-font-lock-artist 'bold) +(defvar jao-emms-font-lock-title 'bold) + +(defun jao-emms-lyrics-mode () +  (interactive) +  (kill-all-local-variables) +  (use-local-map jao-emms-lyrics-mode-map) +  (setq major-mode 'jao-emms-lyrics-mode) +  (setq mode-name "lyrics") +  (toggle-read-only 1)) + +(defun jao-emms-lyrics-buffer () +  (or (get-buffer "*Emms Lyrics*") +      (with-current-buffer (get-buffer-create "*Emms Lyrics*") +        (jao-emms-lyrics-mode) +        (current-buffer)))) + +(defun jao-emms-lyrics-track-data () +  (let ((track (or (emms-playlist-current-selected-track) +                   (error "No playing track")))) +    (cons (or (emms-track-get track 'info-artist nil) +              (error "No artist")) +          (or (emms-track-get track 'info-title nil) +              (error "No artist"))))) + +(defun jao-emms-edit-lyrics () +  (interactive) +  (unless jao-emms-lyrics--path +    (error "No track data available.")) +  (find-file-other-window jao-emms-lyrics--path)) + + + +(defconst jao-emms--wiki-fmt +  (concat"http://lyrics.wikia.com/api.php?action=lyrics&fmt=xml&func=getSong" +         "&artist=%s&song=%s")) + +(defun jao-emms-show-lyrics/wiki () +  (interactive) +  (let* ((a/t (jao-emms-lyrics-track-data)) +         (artist (car a/t)) +         (title (cdr a/t)) +         (buffer (jao-emms-lyrics-buffer)) +         (url (format jao-emms--wiki-fmt +                      (url-hexify-string artist) +                      (url-hexify-string title))) +         (url-request-method "GET") +         (data-buffer (url-retrieve-synchronously url)) +         (inhibit-read-only t)) +    (set-buffer data-buffer) +    ;; (unless (re-search-forward "<pre>" nil t) +    ;;   (error "Lyrics not found")) +    (let ((begin (point))) +      ;; (unless (re-search-forward "</pre>" nil t) +      ;;   (error "Lyrics not found")) +      (copy-to-buffer buffer begin (match-beginning 0))) +    (with-current-buffer buffer +      (goto-char (point-min)) +      (insert (format "♪ %s - %s\n" artist title))) +    (pop-to-buffer buffer))) + +(defvar jao-emms-show-lyrics/script +  (expand-file-name "lyricwiki.rb" (file-name-directory load-file-name))) + +(defun jao-emms-lyrics--download (artist title) +  (message "Retrieving lyrics...") +  (prog1 +      (shell-command-to-string (format "%s \"%s\" \"%s\"" +                                       jao-emms-show-lyrics/script +                                       artist title)) +    (message nil))) + +(defun jao-emms-show-lyrics (&optional force) +  (interactive "P") +  (let* ((a/t (jao-emms-lyrics-track-data)) +         (artist (or (car a/t) "")) +         (title (or (cdr a/t) "")) +         (buffer (jao-emms-lyrics-buffer)) +         (cached (and (not force) (jao-emms-lyrics--get-cached artist title))) +         (cached (and (not (zerop (length cached))) cached)) +         (lyrics (or cached (jao-emms-lyrics--download artist title))) +         (inhibit-read-only t)) +    (with-current-buffer buffer +      (delete-region (point-min) (point-max)) +      (insert (format "♪ %s - %s\n\n" +                      (propertize artist 'face jao-emms-font-lock-artist) +                      (propertize title 'face jao-emms-font-lock-title))) +      (when lyrics +        (insert lyrics) +        (goto-char (point-min)) +        (when (not cached) +          (save-excursion +            (while (search-forward "
" nil t) +              (replace-match "" nil t))))) +      (when (and lyrics (not cached)) +        (jao-emms-lyrics--cache artist title lyrics)) +      (setq jao-emms-lyrics--path (jao-emms-lyrics--filename artist title))) +    (pop-to-buffer buffer))) + +(defun jao-emms-show-lyrics-force () +  (interactive) +  (jao-emms-show-lyrics t)) + + +(provide 'jao-emms-lyrics) +;;; jao-emms-lyrics.el ends here diff --git a/emms/jao-emms-random-album.el b/emms/jao-emms-random-album.el new file mode 100644 index 0000000..04dcd89 --- /dev/null +++ b/emms/jao-emms-random-album.el @@ -0,0 +1,113 @@ +;; jao-emms-random-album.el -- play random albums in emms + +;; Copyright (C) 2009, 2010 Jose Antonio Ortega Ruiz + +;; Author: Jose Antonio Ortega Ruiz <jao@gnu.org> +;; Start date: Sat Jul 04, 2009 13:06 + +;; This file is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3 of the License, or +;; (at your option) any later version. + +;; This file is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program.  If not, see <http://www.gnu.org/licenses/>. + + +(require 'emms) + +(defvar jao-emms-random-album-p t) +(defvar jao-emms-random-lines nil) +(defvar jao-emms-random-lines-file +  (expand-file-name "~/.emacs.d/random-lines")) + +(defun jao-emms-random-lines () +  (or jao-emms-random-lines +      (and (file-exists-p jao-emms-random-lines-file) +           (with-current-buffer +               (find-file-noselect jao-emms-random-lines-file) +             (goto-char (point-min)) +             (setq jao-emms-random-lines (read (current-buffer))))) +      (dotimes (n (1- (line-number-at-pos (point-max))) +                  jao-emms-random-lines) +        (push (1+ n) jao-emms-random-lines)))) + +(defun jao-emms-random-lines-save () +  (with-current-buffer (find-file-noselect jao-emms-random-lines-file) +    (delete-region (point-min) (point-max)) +    (insert (format "%s\n" jao-emms-random-lines)) +    (save-buffer))) + +(defun jao-emms-goto-random-album () +  (let* ((pos (random (length (jao-emms-random-lines)))) +         (line (nth pos jao-emms-random-lines))) +    (setq jao-emms-random-lines (remove line jao-emms-random-lines)) +    (jao-emms-random-lines-save) +    (goto-line line))) + +(defun jao-emms-next-noerror () +  (interactive) +  (when emms-player-playing-p +    (error "A track is already being played")) +  (cond (emms-repeat-track +         (emms-start)) +        ((condition-case nil +             (progn +               (emms-playlist-current-select-next) +               t) +           (error nil)) +         (emms-start)) +        (t +         (if jao-emms-random-album-p +             (jao-emms-random-album-next) +           (message "No next track in playlist"))))) + + +;; User interface +(defun jao-emms-random-album-start () +  (interactive) +  (setq jao-emms-random-album-p t) +  (jao-emms-random-album-next)) + +(defun jao-emms-random-album-stop () +  (interactive) +  (setq jao-emms-random-album-p nil) +  (emms-stop)) + +(defun jao-emms-random-album-toggle () +  (interactive) +  (setq jao-emms-random-album-p (not jao-emms-random-album-p)) +  (message "Random album %s" +           (if jao-emms-random-album-p "enabled" "disabled"))) + +(defun jao-emms-random-album-next () +  (interactive) +  (let ((buffer (emms-browser-get-buffer))) +    (save-excursion +      (if buffer (set-buffer buffer) (emms-browser)) +      (ignore-errors (emms-browser-clear-playlist)) +      (emms-browse-by-album) +      (jao-emms-goto-random-album) +      (emms-browser-add-tracks-and-play) +      (jao-osd-cat 'emms +                   (format  "Next album %s" +                            (substring-no-properties (thing-at-point 'line) +                                                     0 -1))) +      (emms-browser-bury-buffer)))) + +(defun jao-emms-random-album-reset () +  (interactive) +  (setq jao-emms-random-lines nil) +  (jao-emms-random-lines-save)) + +(defun jao-emms-random-album-setup () +  (setq emms-player-next-function 'jao-emms-next-noerror)) + + +(provide 'jao-emms-random-album) +;;; jao-emms-random-album.el ends here diff --git a/emms/jao-emms.el b/emms/jao-emms.el new file mode 100644 index 0000000..53b3513 --- /dev/null +++ b/emms/jao-emms.el @@ -0,0 +1,27 @@ +;; jao-emms.el -- shared bits + +;; Copyright (C) 2009, 2010 Jose Antonio Ortega Ruiz + +;; Author: Jose Antonio Ortega Ruiz <jao@gnu.org> +;; Start date: Sat Jul 04, 2009 13:51 + +;; This file is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3 of the License, or +;; (at your option) any later version. + +;; This file is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program.  If not, see <http://www.gnu.org/licenses/>. + +;;; Code: + +(defgroup jao-emms nil "Emms extensions" :group 'emms) + + +(provide 'jao-emms) +;;; jao-emms.el ends here diff --git a/emms/leoslyrics.py b/emms/leoslyrics.py new file mode 100755 index 0000000..5e4f8c8 --- /dev/null +++ b/emms/leoslyrics.py @@ -0,0 +1,84 @@ +#!/usr/bin/python +# +#  (c) 2004-2008 The Music Player Daemon Project +#  http://www.musicpd.org/ +# +#  This program is free software; you can redistribute it and/or modify +#  it under the terms of the GNU General Public License as published by +#  the Free Software Foundation; either version 2 of the License, or +#  (at your option) any later version. +# +#  This program is distributed in the hope that it will be useful, +#  but WITHOUT ANY WARRANTY; without even the implied warranty of +#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +#  GNU General Public License for more details. +#  You should have received a copy of the GNU General Public License +#  along with this program; if not, write to the Free Software +#  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA +# + +# +# Load lyrics from leoslyrics.com +# + +from sys import argv, exit +from urllib import urlencode, urlopen +from xml.sax import make_parser, SAXException +from xml.sax.handler import ContentHandler + +class SearchContentHandler(ContentHandler): +    def __init__(self): +        self.code = None +        self.hid = None + +    def startElement(self, name, attrs): +        if name == 'response': +            self.code = int(attrs['code']) +        elif name == 'result': +            if self.hid is None or attrs['exactMatch'] == 'true': +                self.hid = attrs['hid'] + +def search(artist, title): +    query = urlencode({'auth': 'ncmpc', +                       'artist': artist, +                       'songtitle': title}) +    url = "http://api.leoslyrics.com/api_search.php?" + query +    f = urlopen(url) +    handler = SearchContentHandler() +    parser = make_parser() +    parser.setContentHandler(handler) +    parser.parse(f) +    return handler.hid + +class LyricsContentHandler(ContentHandler): +    def __init__(self): +        self.code = None +        self.is_text = False +        self.text = None + +    def startElement(self, name, attrs): +        if name == 'text': +            self.text = '' +            self.is_text = True +        else: +            self.is_text = False + +    def characters(self, chars): +        if self.is_text: +            self.text += chars + +def lyrics(hid): +    query = urlencode({'auth': 'ncmpc', +                       'hid': hid}) +    url = "http://api.leoslyrics.com/api_lyrics.php?" + query +    f = urlopen(url) +    handler = LyricsContentHandler() +    parser = make_parser() +    parser.setContentHandler(handler) +    parser.parse(f) +    return handler.text + +hid = search(argv[1], argv[2]) +if hid is None: +    exit(2) +print lyrics(hid).encode('utf-8') diff --git a/emms/lyricwiki.rb b/emms/lyricwiki.rb new file mode 100755 index 0000000..db7b970 --- /dev/null +++ b/emms/lyricwiki.rb @@ -0,0 +1,51 @@ +#!/usr/bin/env ruby +# +#  (c) 2004-2008 The Music Player Daemon Project +#  http://www.musicpd.org/ +# +#  This program is free software; you can redistribute it and/or modify +#  it under the terms of the GNU General Public License as published by +#  the Free Software Foundation; either version 2 of the License, or +#  (at your option) any later version. +# +#  This program is distributed in the hope that it will be useful, +#  but WITHOUT ANY WARRANTY; without even the implied warranty of +#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +#  GNU General Public License for more details. +#  You should have received a copy of the GNU General Public License +#  along with this program; if not, write to the Free Software +#  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA +# + +# +# Load lyrics from lyrics.wikia.com, formerly lyricwiki.org +# + +require 'uri' +require 'net/http' +require 'cgi' + +url = "http://lyrics.wikia.com/api.php?action=lyrics&fmt=xml&func=getSong" + \ +    "&artist=#{URI.escape(ARGV[0])}&song=#{URI.escape(ARGV[1])}" +response = Net::HTTP.get(URI.parse(url)) + +if not response =~ /<url>\s*(.*?)\s*<\/url>/im +	$stderr.puts "No URL in response!" +	exit(1) +end + +url = $1 +exit(69) if url =~ /action=edit$/ + +response = Net::HTTP.get(URI.parse(url)) +if not response =~ /<div class='lyricbox'>\s*(.*?)\s*<!--/im +	$stderr.puts "No <div class='lyricbox'> in lyrics page!\n" +	exit(1) +end + +if not $1 =~ /^.*<\/div>(.*?)$/im +	$stderr.puts "Couldn't remove leading XML tags in lyricbox!\n" +	exit(1) +end + +puts CGI::unescapeHTML($1.gsub(/<br \/>/, "\n")) diff --git a/net/jao-frm.el b/net/jao-frm.el new file mode 100644 index 0000000..1635f00 --- /dev/null +++ b/net/jao-frm.el @@ -0,0 +1,214 @@ +;;; jao-frm.el --- use frm to show mailbox + +;; Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 + +;; Author: Jose Antonio Ortega Ruiz <jao@gnu.org> +;; Keywords: mail + +;; This file is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. + +;; This file is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING.  If not, write to +;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;;  Little hack to see the contents of your mailbox using GNU mailutils' +;;  `frm' program. +;; +;;  Just put (require 'jao-frm) in your .emacs, and M-x jao-frm will pop up a +;;  new window with your mailbox contents (from and subject) as +;;  printed by frm. In this buffer, use `n' and `p' to move, `q' to close +;;  the window. `g' will call Gnus. +;; + +;;; Code: + +;;;; Customisation: + +(defgroup jao-frm nil +  "Frm-base mailbox checker" +  :prefix "jao-frm-") + +(defcustom jao-frm-exec-path "frm" +  "frm executable path" +  :group 'jao-frm +  :type 'file) + +(defcustom jao-frm-mail-command 'gnus +  "Emacs function to invoke when `g' is pressed on an frm buffer." +  :group 'jao-frm +  :type 'symbol) + +(defcustom jao-frm-mailboxes nil +  "List of mailboxes to check, or directory containing them." +  :group 'jao-frm +  :type '(choice directory (repeat file))) + +(defface jao-frm-mailno-face '((t (:foreground "dark slate grey"))) +  "Face for the mail number." +  :group 'jao-frm) + +(defface jao-frm-from-face '((t (:foreground "slate grey"))) +  "Face for From: header." +  :group 'jao-frm) + +(defface jao-frm-subject-face '((t (:foreground "slate blue"))) +  "Face for Subject: header." +  :group 'jao-frm) + +(defface jao-frm-mailbox-face '((t (:bold t :weight bold))) +  "Face for mailbox name." +  :group 'jao-frm) + +;;;; Mode: + +(defvar jao-frm-mode-map +  (let ((map (make-keymap))) +    (suppress-keymap map) +    (define-key map [?q] 'jao-frm-delete-window) +    (define-key map [?n] 'next-line) +    (define-key map [?p] 'previous-line) +    (define-key map [?g] jao-frm-mail-command) +    (define-key map [(control k)] 'jao-frm-delete-message) +    map)) + +(setq jao-frm-font-lock-keywords + '(("^[^ :]+:" . 'jao-frm-mailbox-face) +   ("^\\([ 0-9]+\\):\t+\\([^\t]+\\)\t+\\([^\n]+$\\)" +    (1 'jao-frm-mailno-face) +    (2 'jao-frm-from-face) +    (3 'jao-frm-subject-face)))) + +(defvar jao-frm-mode-syntax-table +  (let ((st (make-syntax-table))) +    st)) + +(defun jao-frm-mode () +  "Major mode for displaying frm output." +  (interactive) +  (kill-all-local-variables) +  (buffer-disable-undo) +  (use-local-map jao-frm-mode-map) +  (set (make-local-variable 'font-lock-defaults) +       '(jao-frm-font-lock-keywords)) +  (set (make-local-variable 'truncate-lines) t) +  (set (make-local-variable 'kill-whole-line) t) +  (set (make-local-variable 'next-line-add-newlines) nil) +  (setq major-mode 'jao-frm-mode) +  (setq mode-name "frm") +  (toggle-read-only 1) +  (goto-char 1)) + +;;;; Mode commands: +(defvar jao-frm-last-config nil) + +(defun jao-frm-delete-window () +  "Delete frm window and restore last win config" +  (interactive) +  (if (and (consp jao-frm-last-config) +           (window-configuration-p (car jao-frm-last-config))) +      (progn +        (set-window-configuration (car jao-frm-last-config)) +        (goto-char (cadr jao-frm-last-config)) +        (setq jao-frm-last-config nil)) +    (bury-buffer))) + +(defun jao-frm-delete-message () +  "Delete message at point" +  (interactive) +  (when (eq (current-buffer) (get-buffer "*frm*")) +    (beginning-of-line) +    (when (search-forward-regexp "^ +\\([0-9]+\\):" nil t) +      (let ((mn (string-to-number (match-string 1)))) +        (when (y-or-n-p (format "Delete message number %d? " mn)) +          (toggle-read-only -1) +          (shell-command (format "echo 'd %d'|mail" mn) t) +          (jao-frm) +          (when (= (point-max) (point-min)) +            (jao-frm-delete-window) +            (message "Mailbox is empty"))))))) + +;;;; Activate frm: +(defun jao-frm-mbox-mails (mbox) +  (let ((no (ignore-errors +              (substring +               (shell-command-to-string (format "frm %s|wc -l" mbox)) 0 -1)))) +    (if (stringp no) (string-to-number no) 0))) + +(defun jao-frm-mail-number () +  (let ((no 0)) +    (dolist (b (jao-frm-mboxes) no) (setq no (+ no (jao-frm-mbox-mails b)))))) + +(defun jao-frm-default-count-formatter (m n) +  (format "%s: %s" (file-name-sans-extension (file-name-nondirectory m)) n)) + +(defun jao-frm-mail-counts (fmt) +  (let ((fmt (or fmt 'jao-frm-default-count-formatter))) +    (remove nil +            (mapcar (lambda (m) +                      (let ((n (jao-frm-mbox-mails m))) +                        (unless (zerop n) (funcall fmt m n)))) +                    (jao-frm-mboxes))))) + +(defun jao-frm-display-mailbox (mbox) +  (when (not (zerop (jao-frm-mbox-mails mbox))) +    (insert (or (file-name-nondirectory mbox) mbox) ":\n\n") +    (apply 'call-process +           `(,jao-frm-exec-path nil ,(current-buffer) nil +                                "-n" "-t" ,@(and mbox (list mbox)))) +    (newline 2))) + +(defun jao-frm-mboxes () +  (cond ((null jao-frm-mailboxes) (list (getenv "MAIL"))) +        ((listp jao-frm-mailboxes) jao-frm-mailboxes) +        ((stringp jao-frm-mailboxes) +         (if (file-directory-p jao-frm-mailboxes) +             (directory-files jao-frm-mailboxes t "^[^.]") +           (list jao-frm-mailboxes))) +        (t (error "Error in mbox specification. Check `jao-frm-mailboxes'")))) + +(defun jao-frm () +  "Run frm." +  (interactive) +  (let ((fbuff (get-buffer-create "*frm*")) +        (inhibit-read-only t)) +    (if (not (eq fbuff (current-buffer))) +        (setq jao-frm-last-config +              (list (current-window-configuration) (point-marker)))) +    (with-current-buffer fbuff +      (delete-region (point-min) (point-max)) +      (mapc 'jao-frm-display-mailbox (jao-frm-mboxes)) +      (unless (eq major-mode 'jao-frm-mode) +        (jao-frm-mode)) +      (goto-char (point-min)) +      (if (= (point-min) (point-max)) +          (message "Mailbox is empty.") +        (pop-to-buffer fbuff)) +      (when (and (boundp 'display-time-mode) display-time-mode) +        (display-time-update))))) + +(defun jao-frm-show-mail-numbers () +  (interactive) +  (let ((counts (jao-frm-mail-counts nil))) +    (message (if counts (mapconcat 'identity counts ", ") "No mail")))) + +(defun jao-frm-mail-string () +  (let ((counts (jao-frm-mail-counts +                 (lambda (m n) +                   (let ((m (substring (file-name-nondirectory m) 0 1))) +                     (format "%s %s" m n)))))) +    (mapconcat 'identity counts " "))) + +(provide 'jao-frm) + +;;; jao-frm.el ends here diff --git a/net/jao-w3m-session.el b/net/jao-w3m-session.el new file mode 100644 index 0000000..7b8979b --- /dev/null +++ b/net/jao-w3m-session.el @@ -0,0 +1,410 @@ +;;; w3m-session.el --- Persistent emacs-w3m sessions + +;; Copyright (C) 2003, 2004, 2006, 2007, 2008, 2009  Jose A Ortega Ruiz + +;; Author: Jose A Ortega Ruiz <jao@member.fsf.org> +;; Version: 0.3.6 +;; Keywords: hypermedia, w3m, WWW + +;; This file is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. + +;; This file is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING.  If not, write to +;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; INTRODUCTION: +;; +;; jao-w3m-session provides persistent emacs-w3m browsing sessions. When +;; quitting w3m (or, if you request it, at any other time while using +;; it) you can save the current w3m session (that is, the set of open +;; tabs and the URLs they're visiting). Upon restarting emacs-w3m +;; (possibly after restarting Emacs itself) you'll have the possibity +;; of recovering the saved session (that is, of re-opening the saved +;; tabs and URLs). You also have at your disposal a command to recover +;; the saved session at any other time. +;; +;; INSTALLATION: +;; +;; Just put this file somewhere on your Emacs load path and add the +;; following line to your .emacs file: +;; +;;   (require 'jao-w3m-session) +;; +;; After restarting Emacs (or evaluating the form above), each time +;; you start emacs-w3m with 'w3m' you'll get a prompt asking whether +;; your last browsing session should be loaded. Likewise, when +;; quitting the browser, you'll have the possibility of saving your +;; current session (overwriting the previous one). +;; +;; In addition, two new interactive functions are defined: +;; +;;   jao-w3m-session-load  --  load the last stored session +;;   jao-w3m-session-save  --  save the current session +;; +;; These functions can be invoked at any time while running emacs-w3m. +;; Optionally, you can bind them to key shortcuts with the proper +;; variations of the following elisp magic in your .emacs: +;;  (defun w3m-add-keys () +;;    (define-key w3m-mode-map "S" 'jao-w3m-session-save) +;;    (define-key w3m-mode-map "L" 'jao-w3m-session-load)) +;;  (add-hook 'w3m-mode-hook 'w3m-add-keys) +;; +;; CUSTOMIZATION: +;; +;; A new customization group, jao-w3m-session, is available. There you can +;; customize the following variables: +;; +;;   jao-w3m-session-load-always     -- if t, `jao-w3m-session-load' will *not* ask +;;                                for confirmation (default nil) +;;   jao-w3m-session-save-always     -- if t, `jao-w3m-session-save' will *not* ask +;;                                for confirmation (default nil) +;;   jao-w3m-session-show-titles     -- if t, the load prompt will list the +;;                                session URL titles (default t) +;;   jao-w3m-session-duplicate-tabs  -- what to do when loading a session that +;;                                contains a URL already open +;;   jao-w3m-session-file            -- the file where w3m session info +;;                                is stored (default "~/.jao-w3m-session") +;;   jao-w3m-session-autosave-period -- the period, in seconds, for automatic +;;                                session backup file updating. +;; +;; +;; You can also customize them in your .emacs file, to wit: +;; +;;   (setq jao-w3m-session-file "~/.emacs.d/jao-w3m-session") +;;   (setq jao-w3m-session-save-always nil) +;;   (setq jao-w3m-session-load-always nil) +;;   (setq jao-w3m-session-show-titles t) +;;   (setq jao-w3m-session-duplicate-tabs 'ask) ;  'never, 'always, 'ask +;; +;; HISTORY: +;; +;;   Version 0.3.7 : +;; +;;     - `jao-w3m-session-deactivate-builtin-sessions', to do what it +;;       says. +;; +;;   Version 0.3.6 (Sat Apr 19, 2008): +;; +;;     - w3m-session -> jao-w3m-session to avoid collisions with +;;       emacs-w3m's session manager. +;; +;;   Version 0.3.5 (Sun Jan 14, 2007): +;; +;;     - automatic session backup every `jao-w3m-session-autosave-period' +;;       seconds. +;; +;;   Version 0.3.4 (Wed Jul 19, 2006): +;; +;;     - save session file on quitting Emacs (without using +;;       desktop.el) +;; +;;   Version 0.3.3 (Thu Jun  8, 2006): +;; +;;     - save session file with pretty print. +;;     - handle correctly multiple emacs-w3m (re)starts during a +;;       single emacs session. +;;     - save URLs in hexified form to allow & in them. +;;     - code cleanup. +;; +;;   Version 0.3.2 (Mon Sep 29, 2003): +;; +;;     - bug fix: when searching or going to home/bookmarks/etc, +;;       keep the current tab's focus. +;; +;;   Version 0.3.1 (Tue Aug 26, 2003): +;; +;;     - type of `jao-w3m-session-file' set to 'file' in customisation +;;       buffer. +;;     - bug fix: syntax error due to a typo in `jao-w3m-session-file' +;; +;;   Version 0.3 (Mon Aug 25, 2003): +;; +;;     - the load session tab lists the titles of the session's pages +;;       (customizable via 'jao-w3m-session-show-titles'). +;;     - the duplicated tab prompt displays also the URL's title. +;;     - bug fix: active tab in session now is correctly saved. +;; +;;   Version 0.2 (Fri Aug 22, 2003): +;; +;;     - the session info now includes the active tab, which gets +;;       displayed when the session is reloaded. +;;     - when reloading a session in a running emacs-w3m, if the +;;       session contains a URL that is already being displayed by the +;;       browser, the tab can be reused or duplicated (customizable +;;       via `jao-w3m-session-duplicate-tabs'). +;; +;;   Version 0.1 (Wed Aug 20, 2003) -- Initial release. +;; + + +;;; Code: + +;;; Dependencies: + +(require 'w3m) +(require 'advice) +(require 'url-util) + +;;; Custom variables: + +(defgroup jao-w3m-session nil +  "w3m - session saving in w3m." +  :group 'w3m +  :prefix "jao-w3m-session-") + +(defcustom jao-w3m-session-save-always nil +  "If on, always save w3m session without asking." +  :group 'jao-w3m-session +  :type 'boolean) + +(defcustom jao-w3m-session-load-always nil +  "If on, always load w3m session without asking." +  :group 'jao-w3m-session +  :type 'boolean) + +(defcustom jao-w3m-session-show-titles t +  "If on, show URL titles in the load prompt." +  :group 'jao-w3m-session +  :type 'boolean) + +(defcustom jao-w3m-session-duplicate-tabs 'never +  "How to treat session URL already being visited. + +When loading a session with `jao-w3m-session-load', if one of the URLs in +the session is already displayed in a w3m tab, jao-w3m-session can: +- `never' create a new tab (just reload it), or +- `always' duplicate the URL in a new tab, or +- `ask' the user what to do." +  :group 'jao-w3m-session +  :type  '(choice (const :value never) +                  (const :value always) +                  (const :value ask))) + +(defcustom jao-w3m-session-file "~/.jao-w3m-session" +  "File to save the w3m session data." +  :group 'jao-w3m-session +  :type 'file) + +(defvar jao-w3m-session-autosave-period 180 +  "A backup of the current session is saved with this period (in secs).") + +(defvar jao-w3m-url-filters nil "URL filters.") + +;;; Interactive functions: + +(defun jao-w3m-session-save () +  "Save the current w3m session." +  (interactive) +  (when (and (w3m-alive-p) +             (or jao-w3m-session-save-always +                 (y-or-n-p "Save current w3m session? "))) +    (jao-w3m-session-current-to-file) +    (jao-w3m-session--restart--autosave))) + +(defun jao-w3m-session-load () +  "Load last stored session into w3m." +  (interactive) +  (let ((s (jao-w3m-session-load-aux))) +    (when s +      (jao-w3m-session--restart--autosave) +      (let* ((urls (jao-w3m-session-url s)) +             (offset (jao-w3m-session-offset s)) +             (buffers (unless (equal jao-w3m-session-duplicate-tabs 'always) +                        (jao-w3m-session-find-duplicated urls)))) +        (w3m-goto-url-new-session urls t) +        (when buffers (jao-w3m-session-close-buffers buffers)) +        (unless (zerop offset) (w3m-next-buffer offset)))))) + +(defun jao-w3m-session-set-autosave-period (secs) +  "Set new value for the period between session backup autosaves." +  (interactive "p") +  (let ((secs (or secs (read-number "New period (secs): " 0)))) +    (when (> secs 0) +      (setq jao-w3m-session-autosave-period secs) +      (jao-w3m-session--restart--autosave)))) + +(defun jao-w3m-session-deactivate-builtin-sessions () +  "Deactivate emacs-w3m's builtin session handling." +  (setq w3m-session-deleted-save nil +        w3m-session-autosave nil +        w3m-session-deleted-keep-number 0 +        w3m-session-crash-recovery nil)) + +;;; Internals: + +;;;; advice w3m to use session management + +(defadvice w3m (before jao-load-session activate) +  "Optionally load last w3m session on startup." +  (interactive +   (let ((s (jao-w3m-session-load-aux))) +     (list (or (and s (jao-w3m-session-url s)) w3m-home-page) t t)))) + +(defadvice w3m (after jao-select-tab activate) +  "Goto the saved focused tab" +  (interactive) +  (let ((offset (jao-w3m-session-offset))) +    (unless (zerop offset) +      (w3m-next-buffer offset)) +    (ad-deactivate 'w3m))) + +(defadvice w3m-quit (before jao-save-session activate) +  "Save session before quitting." +  (interactive) +  (jao-w3m-session-save) +  ;; this is a little hack: when quitting a w3m session with a tab +  ;; selected other than the first, the frame is not automatically +  ;; closed as should be when w3m-pop-up-frames is t: +  (switch-to-buffer (car (w3m-list-buffers))) +  (ad-activate 'w3m)) + +;;;; save session on exit +(add-to-list 'kill-emacs-query-functions +             '(lambda () (jao-w3m-session-save) t)) + + +;;;; auxiliary functions + +(defvar jao-w3m-current-session '(jao-w3m-session 0 nil)) + +(defun jao-w3m-session--filter (url filters) +  (cond ((not filters) url) +        ((string-match-p (caar filters) url) +         (cond ((functionp (cdar filters)) (funcall (cadr filters) url)) +               ((stringp (cdar filters)) (cdar filters)))) +        (t (jao-w3m-session--filter url (cdr filters))))) + +(defun jao-w3m-session--current-urls () +  (let ((urls) +        (current-buffer (w3m-alive-p)) +        (pos 0) +        (count 0)) +    (dolist (b (w3m-list-buffers) (list pos (reverse urls))) +      (set-buffer b) +      (let ((url (jao-w3m-session--filter w3m-current-url jao-w3m-url-filters))) +        (when url +          (when (eq b current-buffer) (setq pos count)) +          (setq count (1+ count)) +          (push (cons (url-hexify-string url) (w3m-buffer-title b)) urls)))))) + +(defun jao-w3m-session-url (&optional s) +  (let ((s (or s jao-w3m-current-session))) +    (concat "group:" +            (mapconcat 'car (nth 2 s) "&")))) + +(defun jao-w3m-session-offset (&optional s) +  (let ((s (or s jao-w3m-current-session))) +    (nth 1 s))) + +(defun jao-w3m-session-titles (&optional s) +  (let ((s (or s jao-w3m-current-session))) +    (mapcar 'cdr (nth 2 s)))) + +(defun jao-w3m-session-current (&optional s) +  (save-current-buffer +    (setq jao-w3m-current-session +          (or s (cons 'jao-w3m-session (jao-w3m-session--current-urls)))))) + +(defun jao-w3m-session-current-url () +  (when (w3m-alive-p) +    (save-current-buffer +      (concat "group:" +              (mapconcat (lambda  (b) (set-buffer b) w3m-current-url) +                         (w3m-list-buffers) "&"))))) + +(defun jao-w3m-session-find-duplicated (urls) +  (when (w3m-alive-p) +    (save-current-buffer +      (let* ((duplicate-p +              (lambda (b) +                (y-or-n-p +                 (format "'%s' (%s) is already open. Duplicate tab? " +                         (w3m-buffer-title b) w3m-current-url)))) +             (test-b +              (lambda (b) +                (set-buffer b) +                (if (and +                     (string-match (regexp-quote w3m-current-url) urls) +                     (or (equal jao-w3m-session-duplicate-tabs 'never) +                         (not (funcall duplicate-p b)))) +                    b 'not))) +             (buffers (mapcar test-b (w3m-list-buffers)))) +        (delete 'not buffers))))) + +(defun jao-w3m-session-close-buffers (buffers) +  (save-current-buffer +    (mapc 'kill-buffer buffers))) + +(defun jao-w3m-session-load-aux () +  (let ((new-session (jao-w3m-session-from-file +                      (expand-file-name jao-w3m-session-file)))) +    (if (and new-session +             (or jao-w3m-session-load-always +                 (y-or-n-p +                  (if jao-w3m-session-show-titles +                      (format "Load last w3m session %S? " +                              (jao-w3m-session-titles new-session)) +                    "Load last w3m session? ")))) +        (jao-w3m-session-current new-session) +      nil))) + +(defun jao-w3m-session-from-file (fname) +  (let ((fname (jao-w3m-session--check--backup fname))) +    (if (file-readable-p fname) +        (with-temp-buffer +          (insert-file-contents fname) +          (goto-char (point-min)) +          (let ((sexp (read (current-buffer)))) +            (and (equal 'jao-w3m-session (car sexp)) sexp))) +      nil))) + +(defsubst jao-w3m-session-current-to-file () +  (jao-w3m-session--to--file jao-w3m-session-file)) + +(defun jao-w3m-session--to--file (filename &optional is-auto) +  (require 'pp) +  (let ((msg (if is-auto (current-message)))) +    (with-temp-buffer +      (insert ";;;; File generated by jao-w3m-session. DO NOT EDIT!\n") +      (pp (jao-w3m-session-current) (current-buffer)) +      (insert "\n" ";;;; End of " +              (file-name-nondirectory jao-w3m-session-file) "\n") +      (write-region (point-min) (point-max) (expand-file-name filename))) +    (if is-auto (message msg)))) + +(defvar jao-w3m-session--timer nil) + +(defun jao-w3m-session--backup-name (fname) +  (concat (expand-file-name fname) ".bak")) + +(defun jao-w3m-session--check--backup (fname) +  (let ((bfname (jao-w3m-session--backup-name fname))) +    (if (and (file-newer-than-file-p bfname fname) +             (y-or-n-p "A newer autosaved session exists. Use it? ")) +        bfname +      fname))) + +(defun jao-w3m-session--restart--autosave () +  (when (> jao-w3m-session-autosave-period 0) +    (if jao-w3m-session--timer (cancel-timer jao-w3m-session--timer)) +    (setq jao-w3m-session--timer +          (run-at-time jao-w3m-session-autosave-period +                       jao-w3m-session-autosave-period +                       'jao-w3m-session--to--file +                       (jao-w3m-session--backup-name jao-w3m-session-file) +                       t)))) + +(provide 'jao-w3m-session) + +;;; jao-w3m-session.el ends here diff --git a/net/jao-weather.el b/net/jao-weather.el new file mode 100644 index 0000000..6760eb1 --- /dev/null +++ b/net/jao-weather.el @@ -0,0 +1,219 @@ +;;  Based on code by Thierry Volpiatto +;;  (http://mercurial.intuxication.org/hg/xml-weather) + +(require 'xml) +(require 'derived) + + +;;; config: +(defvar jao-weather-format-id-url +  "http://xoap.weather.com/search/search?where=%s") + +(defvar jao-weather-format-xml-from-id-url ; id, unit=m,day-forecast=5,login,key +  "http://xoap.weather.com/weather/local/%s?cc=*&unit=%s&dayf=%s&prod=xoap&par=%s&key=%s") + +(defvar jao-weather-unit "m" +  "*m mean metric, you will have wind speed in km/h, temperature in °C and so on.") + +(defvar jao-weather-login nil) +(defvar jao-weather-key nil) + +(defvar jao-weather-day-forecast-num 5 +  "*Number of days for forecast; Maximum 5.") + +(defvar jao-weather-default-id "SPXX0015") + +(defvar jao-weather-timer-delay 3600) + +(defvar jao-weather-last-data nil) + + +;;; access: +(defun jao-weather-authentify () +  "Authentify user from .authinfo file. +You have to setup correctly `auth-sources' to make this function +finding the path of your .authinfo file that is normally ~/.authinfo. +Entry in .authinfo should be: +machine xoap.weather.com port http login xxxxx password xxxxxx" +  (let ((auth (auth-source-user-or-password  '("login" "password") +                                             "xoap.weather.com" +                                             "http"))) +    (setq jao-weather-login (car auth) +          jao-weather-key (cadr auth)))) + +(defun jao-weather--url (id) +  (unless (and jao-weather-login jao-weather-key) +    (jao-weather-authentify)) +  (format jao-weather-format-xml-from-id-url +          (or id jao-weather-default-id) +          jao-weather-unit +          (min jao-weather-day-forecast-num 5) +          jao-weather-login +          jao-weather-key)) + +(defvar jao-weather-hook nil) + +;; http://xoap.weather.com/weather/local/[locid] +;; Replace the [locid], of course, with the location ID obtained in the previous step. +;; Appended to this URL is a mix of other parameters, +;; some required and some optional. A typical example might be: +;; http://xoap.weather.com/weather/local/NLXX0002?cc=*&dayf=5&prod=xoap&par=[partner id]&key=[license key] +(defun jao-weather--get-info-async (&optional id) +  (let ((url (jao-weather--url id)) +        (url-show-status nil)) +    (url-retrieve url (lambda (res) +                        (when (not res) +                          (let ((data (jao-weather-get-alist))) +                            (when data +                              (setq jao-weather-last-data data) +                              (run-hooks 'jao-weather-hook)))) +                        (kill-buffer (current-buffer)))))) + +(defun jao-weather--get-info-now (&optional id) +  (let* ((url (jao-weather--url id)) +         (buffer (url-retrieve-synchronously url)) +         (data (and buffer +                    (with-current-buffer buffer +                      (jao-weather-get-alist))))) +    (when buffer (kill-buffer buffer)) +    (when data +      (setq jao-weather-last-data data) +      (run-hooks 'jao-weather-hook)) +    data)) + + +;;; formatting: +(defun jao-weather--flist (c fs) +  (when c +    (let (result) +      (dolist (f fs result) +        (let ((v (caddr (assoc (cadr f) c)))) +          (when (and (stringp v) (not (string-equal v "N/A"))) +            (push (cons (car f) v) result))))))) + +(defun jao-weather--parse-cc (cc) +  (append (jao-weather--flist cc '((:date lsup) +                                   (:observatory obst) +                                   (:temperature tmp) +                                   (:condition t) +                                   (:pressure r))) +          (jao-weather--flist (assoc 'wind cc) '((:windir d) +                                                 (:wind-tilt t) +                                                 (:gust gust))))) + +(defun jao-weather--parse-location (loc) +  (jao-weather--flist loc '((:city dnam) +                            (:time tm) +                            (:latitude lat) +                            (:longitude lon) +                            (:sunrise sunr) +                            (:sunset suns)))) + +(defun jao-weather--parse-day (d) +  (let ((p2 (assoc 'part +                   (remove (assoc 'part (cdr d)) +                           (cdr d)))) +        (wday (or (cdr (assoc 't (cadr d))) "day"))) +    `(,(cdr (assoc 'dt (cadr d))) +      (:weekday . ,wday) +      (:weekday-abbrev . ,(substring wday 0 3)) +      ,@(jao-weather--flist (cdr d) '((:max hi) +                                      (:min low) +                                      (:sunrise sunr) +                                      (:sunset suns) +                                      (:humidity hmid))) +      ,@(jao-weather--flist (assoc 'wind (assoc 'part (cdr d))) +                            '((:wind-dir 't) (:wind-speed 's))) +      ,@(jao-weather--flist (assoc 'wind p2) '((:night-wind-dir wea) +                                               (:night-wind-speed s))) +      ,@(jao-weather--flist p2 +                            '((:night-condition t) (:night-humidity hmid)))))) + +(defun jao-weather-get-alist () +  (let* ((pxml (car (xml-parse-region (point-min) (point-max)))) +         (loc (car (xml-get-children pxml 'loc))) +         (cc (car (xml-get-children pxml 'cc))) +         (dayf (xml-get-children pxml 'dayf)) +         (dayfs (xml-get-children (car dayf) 'day)) +         (today (append (jao-weather--parse-cc cc) +                        (jao-weather--parse-location loc))) +         (forecast (mapcar 'jao-weather--parse-day dayfs))) +    `((today ,@today) (forecast ,@forecast)))) + +(defun jao-weather--format-fields (data fields sep) +  (if data +      (mapconcat '(lambda (kv) +                    (let ((v (cdr (assoc (car kv) data)))) +                      (if (not v) "" +                        (format (or (cdr kv) "%s") v)))) +             fields +             sep) +    "")) + +(defsubst jao-weather--today-string (fields sep) +  (jao-weather--format-fields (cdr (assoc 'today jao-weather-last-data)) +                              fields sep)) + +(defun jao-weather--forecast-string (n fields sep) +  (jao-weather--format-fields (nth n (cdr (assoc 'forecast +                                                 jao-weather-last-data))) +                              fields sep)) + + +;;; update daemon: +(defvar jao-weather--timer nil) +(defun jao-weather-start (&optional delay) +  (interactive) +  (jao-weather-stop) +  (setq jao-weather--timer +        (run-with-timer (or delay 0) +                        jao-weather-timer-delay +                        'jao-weather--get-info-async))) + +(defun jao-weather-stop () +  (interactive) +  (when jao-weather--timer +    (cancel-timer jao-weather--timer) +    (setq jao-weather--timer nil))) + + +;;; today +(defun jao-weather-today-msg (&optional arg) +  (interactive "p") +  (when (> arg 4) (jao-weather--get-info-now)) +  (if (= 4 arg) (jao-weather-forecast-msg) +    (message "%s" (jao-weather--today-string '((:temperature . " %s°C") +                                               (:condition . "(%s)") +                                               (:sunrise . "↑ %s") +                                               (:sunset . "↓ %s") +                                               (:date . "[%s]")) +                                             " ")))) + +(defun jao-weather-forecast-msg (&optional arg) +  (interactive "P") +  (when arg (jao-weather--get-info-now)) +  (message " %s" (mapconcat +                 (lambda (n) +                   (jao-weather--forecast-string n +                                                 '((:weekday-abbrev . "%s ") +                                                   (:max . "%s°/") +                                                   (:min . "%s°") +                                                   (:condition . ", %s") +                                                   (:night-condition . ", %s")) +                                                 "")) +                 '(1 2 3 4) " | "))) + +(defun jao-weather-temperature () +  (string-to-number (jao-weather--today-string '((:temperature)) ""))) + + +(defun jao-weather-temperature* (&optional sep) +  (concat (jao-weather--today-string '((:temperature . "%s°")) "") +          (or sep " ") +          (jao-weather--forecast-string 1 +                                        '((:max . "%s°/") (:min . "%s°") +                                          (:night-condition . " %s")) +                                        ""))) + +;; Provide +(provide 'jao-weather) diff --git a/org/jao-org-gnus.el b/org/jao-org-gnus.el new file mode 100644 index 0000000..8891e20 --- /dev/null +++ b/org/jao-org-gnus.el @@ -0,0 +1,72 @@ +;; Support for saving Gnus messages by Message-ID +(defun mde-org-gnus-save-by-mid () +  (when (memq major-mode '(gnus-summary-mode gnus-article-mode)) +    (when (eq major-mode 'gnus-article-mode) +      (gnus-article-show-summary)) +    (let* ((group gnus-newsgroup-name) +           (method (gnus-find-method-for-group group))) +      (when (eq 'nnml (car method)) +        (let* ((article (gnus-summary-article-number)) +               (header (gnus-summary-article-header article)) +               (from (mail-header-from header)) +               (message-id +                (save-match-data +                  (let ((mid (mail-header-id header))) +                    (if (string-match "<\\(.*\\)>" mid) +                        (match-string 1 mid) +                      (error "Malformed message ID header %s" mid))))) +               (date (mail-header-date header)) +               (subject (gnus-summary-subject-string))) +          (org-store-link-props :type "mid" :from from :subject subject +                                :message-id message-id :group group +                                :link (org-make-link "mid:" message-id)) +          (apply 'org-store-link-props +                 :description (org-email-link-description) +                 org-store-link-plist) +          t))))) + +(defvar mde-mid-resolve-methods '() +  "List of methods to try when resolving message ID's.  For Gnus, +it is a cons of 'gnus and the select (type and name).") +(setq mde-mid-resolve-methods +      '((gnus nnml ""))) + +(defvar mde-org-gnus-open-level 1 +  "Level at which Gnus is started when opening a link") +(defun mde-org-gnus-open-message-link (msgid) +  "Open a message link with Gnus" +  (require 'gnus) +  (require 'org-table) +  (catch 'method-found +    (message "[MID linker] Resolving %s" msgid) +    (dolist (method mde-mid-resolve-methods) +      (cond +       ((and (eq (car method) 'gnus) +             (eq (cadr method) 'nnml)) +        (funcall (cdr (assq 'gnus org-link-frame-setup)) +                 mde-org-gnus-open-level) +        (when gnus-other-frame-object +          (select-frame gnus-other-frame-object)) +        (let* ((msg-info (nnml-find-group-number +                          (concat "<" msgid ">") +                          (cdr method))) +               (group (and msg-info (car msg-info))) +               (message (and msg-info (cdr msg-info))) +               (qname (and group +                           (if (gnus-methods-equal-p +                                (cdr method) +                                gnus-select-method) +                               group +                             (gnus-group-full-name group (cdr method)))))) +          (when msg-info +            (gnus-summary-read-group qname nil t) +            (gnus-summary-goto-article message nil t)) +          (throw 'method-found t))) +       (t (error "Unknown link type")))))) + +(eval-after-load 'org-gnus +  '(progn +     (add-to-list 'org-store-link-functions 'mde-org-gnus-save-by-mid) +     (org-add-link-type "mid" 'mde-org-gnus-open-message-link))) + +(provide 'jao-org-gnus) diff --git a/org/jao-org-links.el b/org/jao-org-links.el new file mode 100644 index 0000000..ca57f69 --- /dev/null +++ b/org/jao-org-links.el @@ -0,0 +1,29 @@ +(require 'org) + +;; doc links +(defvar jao-org--sink-dir "./") +(org-add-link-type "doc" 'jao-org-follow-doc 'identity) +(defun jao-org-follow-doc (link) +  (let ((dest-path (concat "./doc/" +                           (and (boundp 'docs-dir) +                                (concat (symbol-name docs-dir) "/")) +                           link))) +    (when (not (file-exists-p dest-path)) +      (let* ((sink-file (expand-file-name link jao-org--sink-dir)) +             (real-file (if (file-exists-p sink-file) sink-file +                          (read-file-name "Import file: " +                                          jao-org--sink-dir link link)))) +        (shell-command (format "mv %s %s" real-file dest-path)))) +    (browse-url (format "file://%s" (expand-file-name  dest-path))))) + +(defsubst jao-org--title->file (title) +  (concat (mapconcat 'downcase (split-string title nil t) "-") ".pdf")) + +(defun jao-org-insert-doc (title) +  (interactive "sDocument title: ") +  (insert (format "[[doc:%s][%s]]" (jao-org--title->file title) title))) + +(defun jao-org-links-setup (sink-dir) +  (setq jao-org--sink-dir (file-name-as-directory sink-dir))) + +(provide 'jao-org-links)
\ No newline at end of file diff --git a/org/jao-org-popup.el b/org/jao-org-popup.el new file mode 100644 index 0000000..eb5b24d --- /dev/null +++ b/org/jao-org-popup.el @@ -0,0 +1,31 @@ +;;; frame popups +;; http://metajack.im/2008/12/30/gtd-capture-with-emacs-orgmode/ +(defsubst jao-remember--frame-p () +  (equal "*Remember*" (frame-parameter nil 'name))) + +(defadvice remember-finalize (after delete-remember-frame activate) +  "Advise remember-finalize to close the frame if it is the remember frame" +  (when (jao-remember--frame-p) (delete-frame))) + +(defadvice remember-destroy (after delete-remember-frame activate) +  "Advise remember-destroy to close the frame if it is the remember frame" +  (when (jao-remember--frame-p) (delete-frame))) + +;; make the frame contain a single window. by default org-remember +;; splits the window. +(defun jao-remember--delete-other-windows () +  (when (jao-remember--frame-p) (delete-other-windows))) + +(add-hook 'remember-mode-hook 'jao-remember--delete-other-windows) + +(defun make-remember-frame () +  "Create a new frame and run org-remember" +  (interactive) +  (make-frame-on-display (getenv "DISPLAY") +                         '((name . "*Remember*") +                           (width . 80) +                           (height . 10))) +  (select-frame-by-name "*Remember*") +  (org-remember nil ?x)) + +(provide 'jao-org-popup)
\ No newline at end of file diff --git a/org/jao-org-tags.el b/org/jao-org-tags.el new file mode 100644 index 0000000..b00276d --- /dev/null +++ b/org/jao-org-tags.el @@ -0,0 +1,61 @@ +;; lifted from http://orgmode.org/worg/org-hacks.php + +(require 'org) + +(defvar ba/org-adjust-tags-column nil) + +(defun ba/org-adjust-tags-column-reset-tags () +  "In org-mode buffers it will reset tag position according to +`org-tags-column'." +  (when (and +         (not (string= (buffer-name) "*Remember*")) +         (eql major-mode 'org-mode)) +    (let ((b-m-p (buffer-modified-p))) +      (condition-case nil +          (save-excursion +            (goto-char (point-min)) +            (command-execute 'outline-next-visible-heading) +            ;; disable (message) that org-set-tags generates +            (flet ((message (&rest ignored) nil)) +              (org-set-tags 1 t)) +            (set-buffer-modified-p b-m-p)) +        (error nil))))) + +(defun ba/org-adjust-tags-column-now () +  "Right-adjust `org-tags-column' value, then reset tag position." +  (set (make-local-variable 'org-tags-column) +       (- (- (window-width) 3))) +  (ba/org-adjust-tags-column-reset-tags)) + +(defun ba/org-adjust-tags-column-maybe () +  "If `ba/org-adjust-tags-column' is set to non-nil, adjust tags." +  (when ba/org-adjust-tags-column +    (ba/org-adjust-tags-column-now))) + +(defun ba/org-adjust-tags-column-before-save () +  "Tags need to be left-adjusted when saving." +  (when ba/org-adjust-tags-column +    (setq org-tags-column 1) +    (ba/org-adjust-tags-column-reset-tags))) + +(defun ba/org-adjust-tags-column-after-save () +  "Revert left-adjusted tag position done by before-save hook." +  (ba/org-adjust-tags-column-maybe) +  (set-buffer-modified-p nil)) + +;; automatically align tags on right-hand side +(defun jao-org-tags-setup () +  (setq ba/org-adjust-tags-column t) +  (add-hook 'window-configuration-change-hook +            'ba/org-adjust-tags-column-maybe) +  (add-hook 'before-save-hook 'ba/org-adjust-tags-column-before-save) +  (add-hook 'after-save-hook 'ba/org-adjust-tags-column-after-save)) + +(defun jao-org-tags-uninstall () +  (setq ba/org-adjust-tags-column nil) +  (remove-hook 'window-configuration-change-hook +            'ba/org-adjust-tags-column-maybe) +  (remove-hook 'before-save-hook 'ba/org-adjust-tags-column-before-save) +  (remove-hook 'after-save-hook 'ba/org-adjust-tags-column-after-save)) + +(provide 'jao-org-tags) diff --git a/org/jao-org-utils.el b/org/jao-org-utils.el new file mode 100644 index 0000000..535e8f4 --- /dev/null +++ b/org/jao-org-utils.el @@ -0,0 +1,37 @@ +(require 'org) + +;;; links +(defun jao-org-link-at-point () +  (when (thing-at-point-looking-at "\\[\\[\\([^]]+\\)\\]\\[[^]]+\\]\\]") +    (match-string-no-properties 1))) + +(defun jao-org-copy-link-at-point () +  (interactive) +  (message "%s" (or (jao-org-link-at-point) "No link at point"))) + +;;; eldoc +(defun jao-org-eldoc--hook () +  (set (make-local-variable 'eldoc-documentation-function) +       'jao-org-link-at-point) +  (eldoc-mode)) + +(defun jao-org-utils-eldoc-setup () +  (add-hook 'org-mode-hook 'jao-org-eldoc--hook)) + +;;; play fair with saveplace +(defun jao-org--show-if-hidden () +  (when (outline-invisible-p) +    (save-excursion +      (outline-previous-visible-heading 1) +      (org-show-subtree)))) + +;;; verifying org refile targets +(defun jao-org--refile-target-verify () +  (not (looking-at-p ".*\\[\\[.+$"))) + +(defun jao-org-utils-setup () +  (setq org-refile-target-verify-function 'jao-org--refile-target-verify) +  (add-hook 'org-mode-hook 'jao-org--show-if-hidden t)) + + +(provide 'jao-org-utils) diff --git a/prog/jao-cabal.el b/prog/jao-cabal.el new file mode 100644 index 0000000..699fa1b --- /dev/null +++ b/prog/jao-cabal.el @@ -0,0 +1,22 @@ +(require 'jao-dominating-file) + +(defun jao-haskell-locate-cabal-file () +  (jao-locate-dominating-file ".+\\.cabal")) + +(eval-after-load 'haskell-mode +  '(add-hook 'haskell-mode-hook +             (lambda () +               (set (make-local-variable 'compile-command) "cabal build")))) + +(defun jao-haskell-cabal-build () +  (interactive) +  (let ((cabal-file (jao-haskell-locate-cabal-file))) +    (unless cabal-file +      (error "Couldn't find associated cabal file")) +    (let ((default-directory (file-name-directory cabal-file))) +      (call-interactively 'compile)))) + +;;(eval-after-load 'haskell-mode +;;  '(define-key haskell-mode-map [?\C-c ?c] 'jao-haskell-cabal-build)) + +(provide 'jao-cabal) diff --git a/prog/jao-dominating-file.el b/prog/jao-dominating-file.el new file mode 100644 index 0000000..f845abc --- /dev/null +++ b/prog/jao-dominating-file.el @@ -0,0 +1,34 @@ +(defun jao-locate-dominating-files (regexp &optional file) +  "Look up the directory hierarchy from FILE for a file matching REGEXP. +  Stop at the first parent where a matching file is found and return the list +  of files that that match in this directory." +  (catch 'found +    (let ((dir (file-name-as-directory (or file (buffer-file-name)))) +          files) +      (while (and dir +                  (not (string-match locate-dominating-stop-dir-regexp +                                     dir))) +        (if (setq files (condition-case nil +                            (directory-files dir 'full regexp 'nosort) +                          (error nil))) +            (throw 'found files) +          (if (equal dir +                     (setq dir (file-name-directory +                                (directory-file-name dir)))) +              (setq dir nil)))) +      nil))) + + +(defun jao-locate-dominating-file (regexp &optional from) +  (car (jao-locate-dominating-files regexp from))) + +(defun jao-relative-path (regexp &optional from) +  (let* ((from (or from (buffer-file-name))) +         (dfile (jao-locate-dominating-file regexp from)) +         (ddir (and dfile (file-name-directory dfile))) +         (fdir (file-name-directory from))) +    (when ddir +      (and (string-match (format "%s\\(.+\\)/" (regexp-quote ddir)) fdir) +           (match-string-no-properties 1 fdir))))) + +(provide 'jao-dominating-file) diff --git a/prog/jao-java-ant.el b/prog/jao-java-ant.el new file mode 100644 index 0000000..27c6420 --- /dev/null +++ b/prog/jao-java-ant.el @@ -0,0 +1,20 @@ +(require 'jao-dominating-file) + +(eval-after-load 'cc-mode +  '(progn +     (add-hook 'java-mode-hook +               (lambda () +                 (set (make-local-variable 'compile-command) "ant"))) +     (define-key java-mode-map "\C-cc" 'jao-java-ant-build))) + +(defun jao-java-ant-build () +  (interactive) +  (let ((build-file (jao-locate-dominating-file "build\\.xml"))) +    (unless build-file +      (error "Couldn't find associated build file")) +    (let ((default-directory (file-name-directory build-file))) +      (call-interactively 'compile)))) + +(provide 'jao-java-ant) + +;; End of jao-java-ant.el diff --git a/skels/all-skels.el b/skels/all-skels.el new file mode 100644 index 0000000..720b08e --- /dev/null +++ b/skels/all-skels.el @@ -0,0 +1,49 @@ +;;; all-skels.el --- Convenience package loading all skels + +;; Copyright (C) 2008  Jose Ortega + +;; Author: Jose Ortega <jao@google.com> +;; Keywords: languages + +;; 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: + +;; Require this file to load all defined skels + +;;; Code: + +(require 'init-skel) + +(require 'cpp-skel) +(require 'cppunit-skel) +(require 'perl-skel) +(require 'readme-skel) +(require 'make-skel) +(require 'caml-skel) +(require 'latex-skel) +(require 'noweb-skel) +(require 'lisp-skel) +(require 's48-skel) +(require 'haskell-skel) +(require 'scsh-skel) +(require 'lisa-skel) +(require 'texinfo-skel) +(require 'python-skel) +(require 'muse-skel) +(require 'asdf-skel) + +(provide 'all-skels) + +;;; all-skels.el ends here diff --git a/skels/asdf-skel.el b/skels/asdf-skel.el new file mode 100644 index 0000000..939eb8d --- /dev/null +++ b/skels/asdf-skel.el @@ -0,0 +1,52 @@ +;;; asdf-skel.el --- Skels for ASDF system definition files + +;; Copyright (C) 2007  Jose Antonio Ortega Ruiz + +;; Author: Jose Antonio Ortega Ruiz <jao@gnu.org> +;; Keywords: lisp + +;; This file is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; This file is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING.  If not, write to +;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +;; Boston, MA 02110-1301, USA. + +;;; Code: + +(require 'common-skel) + +(define-skeleton jao-skel-asdf-file +  "ASDF file header" +  "Description: " +  '(setq sys (jao-basename)) +  '(lisp-mode) +  ";; -*- lisp -*- " sys " definition" +  \n \n +  "(defpackage " sys "-system" \n "  (:use :common-lisp :asdf))" +  \n \n +  "(in-package " sys "-system)" +  \n \n +  "(defsystem " sys +  > \n ":description \"" str "\"" +  > \n ":version \"0.1\"" +  > \n ":author \"" (user-full-name) " <" user-mail-address ">\"" +  > \n ":maintainer \"" (user-full-name) " <" user-mail-address ">\"" +  > \n ":licence \"GPL\"" +  > \n ":depends-on ()" +  > \n ":components ((:file \"packages\")))" +  \n \n) + +(add-to-list 'auto-insert-alist '("\\.asd\\'" . jao-skel-asdf-file)) + + +(provide 'asdf-skel) +;;; asdf-skel.el ends here diff --git a/skels/caml-skel.el b/skels/caml-skel.el new file mode 100644 index 0000000..65a5db2 --- /dev/null +++ b/skels/caml-skel.el @@ -0,0 +1,42 @@ +;; Copyright (C) 2004, 2005, 2009 Jose Antonio Ortega Ruiz + +;; Author: Jose A Ortega Ruiz <jao@gnu.org> +;; Keywords: tools + +;; This file is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. + +;; This file is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING.  If not, write to +;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; Caml skeletons + +;;; Code: + +(require 'common-skel) + +(define-skeleton jao-skel-caml-file +  "OCaml file header" +  "Brief description: " +  "(* " (file-name-nondirectory (buffer-file-name)) ": " str " *)" +  > \n \n +  (jao-copyright-line "(* " " *)") +  > ?\n +  (jao-insert-copyright-file) +  "(* $" "Id$ *)" \n \n _) + +(jao-provide-skel "\\.ml[i]?" 'jao-skel-caml-file) + +(provide 'caml-skel) + diff --git a/skels/common-skel.el b/skels/common-skel.el new file mode 100644 index 0000000..97ee301 --- /dev/null +++ b/skels/common-skel.el @@ -0,0 +1,151 @@ +;; common definitions and functions + +;; Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Jose Antonio Ortega Ruiz + +;; Author: Jose A Ortega Ruiz <jao@gnu.org> +;; Keywords: tools + +;; This file is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. + +;; This file is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING.  If not, write to +;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; Aux functions used in other skeletons + +;;; Code: + +(require 'skeleton) + +(defvar jao-company-name nil +  "Company name used in copyright notice") + +(defvar jao-copyright-file ".copyright" +  "Basename of the raw (uncommented) copyright file") + +(defvar jao-skels-default-scm nil +  "Default SCM system") + +(defun jao-prefix (pref) (or pref (concat comment-start " "))) +(defun jao-suffix (suff) (or suff (concat " " comment-end))) + +(defun jao-copyright-line (prefix &optional suffix omit-cpy) +  "Create a brief copyright notice with given PREFIX and SUFFIX" +  (concat (jao-prefix prefix) +          (if omit-cpy "" "Copyright ") +          "(c) " (format-time-string "%Y") " " +          (or jao-company-name (user-full-name)) +          (jao-suffix suffix) "\n")) + +(defun jao-date-line (prefix &optional suffix) +  "Create a start date line" +  (concat (jao-prefix prefix) +          "Start date: " (format-time-string "%a %b %d, %Y %H:%M") +          (jao-suffix suffix) "\n")) + +(defun jao-author-line (prefix &optional suffix) +  "Create an author date line" +  (concat (jao-prefix prefix) +          "Author: " (user-full-name) " <" user-mail-address "> " +          (jao-suffix suffix) "\n")) + +(defun jao-cvs-line (prefix &optional suffix) +  "Create a CVS ID line" +  (concat (jao-prefix prefix) "$" "Id$" (jao-suffix suffix) "\n")) + +(defun jao-svn-line (prefix &optional suffix) +  "Create a SVN ID line" +  (concat (jao-prefix prefix) "X-SVN: $" "Id$" (jao-suffix suffix) "\n")) + +(defun jao-arch-line (&optional prefix suffix) +  "Create an arch-tag line" +  (let ((uuid (shell-command-to-string "uuidgen"))) +    (concat (jao-prefix prefix) "arch-tag: " uuid (jao-suffix suffix) "\n"))) + +(defun jao-insert-arch-line () +  (interactive) +  (insert (jao-arch-line))) + +(defun jao-scm-line (prefix &optional suffix) +  "Create an scm line" +  (let* ((formats '(("arch" . jao-arch-line) +                    ("svn" . jao-svn-line) +                    ("cvs" . jao-cvs-line) +                    ("none" . (lambda (p f) "")))) +         (names (mapcar 'car formats)) +         (prompt (concat "SCM (" (mapconcat 'identity names ", ") "): ")) +         (sel (or jao-skels-default-scm +                  (completing-read prompt formats nil 1))) +         (fun (cdr (assoc sel formats)))) +    (when fun (concat (funcall fun prefix suffix))))) + +(defun jao-c&co-line (&optional prefix suffix) +  (concat (jao-scm-line prefix suffix) "\n" +          (jao-co-line prefix suffix))) + +(defun jao-co-line (&optional prefix suffix) +  (concat (jao-copyright-line prefix suffix) "\n" +          (jao-author-line prefix suffix) +          (jao-date-line prefix suffix))) + +;; aux functions --------------------------------------------------------- +(defun jao-basename () +  "Get buffer file name without dir nor extension" +  (file-name-sans-extension (file-name-nondirectory (buffer-file-name)))) + +(defun jao-basedir () +  "Base directory" +  (file-name-nondirectory +   (substring (file-name-directory (buffer-file-name)) 0 -1))) + +(defun jao-dir-level (l) +  (let ((elems (split-string +                (file-name-sans-extension (buffer-file-name)) "/"))) +    (mapconcat 'identity (nthcdr (- (length elems) (+ 1 l)) elems) "/"))) + +(defun jao-extension () +  "Find the extension of the currently visited file" +  (let ((elems (split-string (file-name-nondirectory (buffer-file-name)) +                             "\\."))) +    (nth (- (length elems) 1) elems))) + +(defun jao-other-file-name (ext1 ext2) +  "Find the complimentary file name of header/source file" +  (let ((extension (jao-extension)) +        (basename (jao-basename))) +    (if (string= extension ext1) (concat basename "." ext2) +      (concat basename "." ext1)))) + +(defun jao-insert-commented-file (file-name) +  (let* ((start (point)) +         (end (+ start (cadr (insert-file-contents file-name))))) +    (goto-char end) +    (comment-region start (point)))) + +(defun jao-insert-copyright-file () +  (let ((dir (locate-dominating-file (buffer-file-name) jao-copyright-file))) +    (when dir +      (let ((file (expand-file-name jao-copyright-file dir))) +        (when (file-exists-p file) +          (jao-insert-commented-file file)))))) + +(defun jao-provide-skel (regexp skel) +  (let ((ex (assoc regexp auto-insert-alist))) +    (if ex (setf (cdr ex) skel) +      (add-to-list 'auto-insert-alist (cons regexp skel))))) + +(defsubst jao-skel-provide (lst) +  (mapc (lambda (x) (apply #'jao-provide-skel x))  lst)) + +(provide 'common-skel) diff --git a/skels/cpp-skel.el b/skels/cpp-skel.el new file mode 100644 index 0000000..806f1df --- /dev/null +++ b/skels/cpp-skel.el @@ -0,0 +1,255 @@ +;;; cpp-skel.el + +;; Copyright (C) 2004, 2005, 2008, 2009 Jose Antonio Ortega Ruiz + +;; Author: Jose A Ortega Ruiz <jao@gnu.org> +;; Keywords: tools + +;; This file is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. + +;; This file is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING.  If not, write to +;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; C++ skeletons. + +;;; Code: + +(require 'common-skel) +(require 'thingatpt) + +;;; Variables +(defvar jao-skel-cpp-root-namespace nil +  "The root C++ namespace") + +(defvar jao-skel-cpp-brief-header-p nil +  "If non-nil, generate brief header comments") + +(defvar jao-skel-cpp-make-guard-function #'jao-skel-cpp-make-guard-name +  "Function generating #include guards") + +(defvar jao-skel-cpp-use-namespaces t +  "Whether to generate namespaces") + +(defvar jao-skel-cpp-single-line-namespaces t +  "Whether to put consecutive namespace decls in a single line") + +(defvar jao-skel-cpp-header-extension "hpp") + +;;; Auxiliar functions +(defun jao-skel-cpp--find-other (ext) +  (file-name-nondirectory +   (or (ff-other-file-name) +       (concat (file-name-sans-extension (buffer-name)) "." ext)))) + +(defun jao-skel-cpp-make-guard-name (ns) +  "Create a standard include guard name" +  (upcase (mapconcat #'identity +                     `(,@ns ,(jao-basename) ,(jao-extension) +                            ,(user-login-name) +                            ,(format-time-string "%y%m%d%H%M")) +                     "_"))) + +;; namespaces +(defsubst jao-skel-cpp--read-ns (curr) +  (read-string (format "Add namespace (current: %s): " (or curr "[none]")))) + +(defsubst jao-skel-cpp--ns2str (ns) (mapconcat 'identity ns "::")) + +(defun jao-skel-cpp--get-ns-list (&optional acc) +  (do* ((result acc (cons next result)) +        (next (jao-skel-cpp--read-ns (jao-skel-cpp--ns2str acc)) +              (jao-skel-cpp--read-ns (jao-skel-cpp--ns2str (reverse result))))) +      ((string= next "") (reverse result)))) + +(defun jao-skel-cpp--insert-open-ns-list (ns) +  (dolist (n ns) +    (insert (format "namespace %s {%s" +                    n +                    (if jao-skel-cpp-single-line-namespaces " " "\n"))) +    (indent-according-to-mode)) +  (when jao-skel-cpp-single-line-namespaces +    (newline) +    (indent-according-to-mode))) + +(defun jao-skel-cpp--insert-close-ns-list (ns) +  (if jao-skel-cpp-single-line-namespaces +      (insert (format "%s // namespace %s\n" +                      (make-string (length ns) ?}) +                      (jao-skel-cpp--ns2str ns))) +    (dolist (n (reverse ns)) +      (insert (format "}  // namespace %s\n" n))))) + +(defun jao-skel-cpp--copy-ns-lines () +  (let ((lines)) +    (save-excursion +      (goto-char (point-min)) +      (while (re-search-forward "namespace\\s-\\w+\\s-{\\|}+\\s-//\\s-namespace" +                                nil t) +        (push (thing-at-point 'line) lines) +        (next-line))) +    lines)) + +(defun jao-skel-cpp--copy-namespace () +  (let* ((name (ff-other-file-name)) +         (buff (and name (find-file-noselect name))) +         (nlines)) +    (when buff +      (let ((lines (save-current-buffer +                     (set-buffer buff) +                     (jao-skel-cpp--copy-ns-lines)))) +        (dolist (line lines) +          (push line nlines) +          (when (string-match "}" line) +            (push "\n\n\n\n" nlines))))) +    (mapconcat #'identity nlines "\n"))) + +(defsubst jao-skel-cpp--get-new-namespace () +  (when jao-skel-cpp-use-namespaces +    (jao-skel-cpp--get-ns-list +     (and jao-skel-cpp-root-namespace (list jao-skel-cpp-root-namespace))))) + +;; skeletons +(define-skeleton jao-skel-cpp-header-long +  "Initial file header blurb" +  "Brief file description: " +  "/**" +  > \n +  "* @file     " (file-name-nondirectory (buffer-file-name)) +  > \n +  "* @brief    " str +  > \n +  "* @author   " (user-full-name) " <"user-mail-address">" +  > \n +  "* @date     " (format-time-string "%a %b %d, %Y %H:%M") +  > \n +  "*" +  > \n +  (jao-copyright-line "* " "") +  "*" +  > ?\n +  (jao-insert-copyright-file) +  > \n \n _) + +(define-skeleton jao-skel-cpp-header-brief +  "Brief initial header blurb" +  nil +  (jao-copyright-line "/* " " */") +  \n) + +(define-skeleton jao-skel-cpp-header-comment +  "Insert a standard comment block" +  nil +  '(if jao-skel-cpp-brief-header-p +       (jao-skel-cpp-header-brief) +     (jao-skel-cpp-header-long))) + +;; source C/C++ file ------------------------------------------------------ +(define-skeleton jao-skel-cpp-source-header +  "Insert a standard C++ source header" +  nil +  '(jao-skel-cpp-header-comment) +  ? \n +  "#include \"" (jao-skel-cpp--find-other jao-skel-cpp-header-extension) "\"" +  > \n \n _ +  (jao-skel-cpp--copy-namespace) +  \n) + +(define-skeleton jao-skel-c-source-header +  "Insert a standard C source header" +  nil +  '(jao-skel-cpp-header-comment) +  "#include \"" (jao-skel-cpp--find-other "h") "\"" +  > _ \n \n \n \n +  (jao-scm-line "/* " " */") +  > \n) + + +;; header C/C++ files ------------------------------------------------------ +;; header guard + +;; class definition +(define-skeleton jao-skel-cpp-class-def +  "Insert a class definition" +  nil +  '(setq v1 (jao-basename)) +  > \n +  "/**" +  > \n +  "*" +  > \n +  "*" +  > \n +  "*/" +  > \n +  "class " v1 +  > \n +  "{" +  > \n +  "public:" +  > \n +  "~" v1 "();" +  > \n +  v1 "();" +  > \n +  v1 "(const " v1 "& other);" +  > \n \n +  "private:" +  > \n +  "};" +  > \n) + +(define-skeleton jao-skel-cpp-header +  "Insert a standard C++ header (hpp files)" +  nil +  '(setq v1 (jao-skel-cpp--get-new-namespace)) +  '(setq v2 (funcall jao-skel-cpp-make-guard-function v1)) +  '(jao-skel-cpp-header-comment) +  > \n +  "#ifndef " v2 +  > \n +  "#define " v2 +  > \n \n +  '(when v1 (jao-skel-cpp--insert-open-ns-list v1)) +  _ '(jao-skel-cpp-class-def) +  > \n \n +  '(when v1 (jao-skel-cpp--insert-close-ns-list v1)) +  > \n \n +  "#endif // " v2 +  > \n) + +(define-skeleton jao-skel-c-header +  "Insert a standard C header (.h files)" +  nil +  '(jao-skel-cpp-header-comment) +  > \n +  '(setq v1 (funcall jao-skel-cpp-make-guard-function nil)) +  "#ifndef " v1 +  > \n +  "#define " v1 +  > _ \n \n \n \n +  "#endif /* " v1 " */" +  > \n \n +  (jao-scm-line "/* " " */") +  > \n) + +(jao-skel-provide + '(("\\.cpp$" jao-skel-cpp-source-header) +   ("\\.hpp$" jao-skel-cpp-header) +   ("\\.c$" jao-skel-c-source-header) +   ("\\.h$" jao-skel-c-header))) + +(provide 'cpp-skel) + +;;; cpp-skel.el ends here diff --git a/skels/cppunit-skel.el b/skels/cppunit-skel.el new file mode 100644 index 0000000..729f392 --- /dev/null +++ b/skels/cppunit-skel.el @@ -0,0 +1,91 @@ +;;; cppunit-skel.el + +;; Copyright (C) 2004, 2005 Jose Antonio Ortega Ruiz + +;; Author: Jose A Ortega Ruiz <jao@gnu.org> +;; Keywords: tools + +;; This file is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; This file is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING.  If not, write to +;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; Skeletons creating cppunit classes. + +;;; Code: + +(require 'common-skel) + +(define-skeleton jao-cppunit-main +  "Insert CPPUNIT main function" +  nil +  "#include <cppunit/extensions/TestFactoryRegistry.h>" > \n +  "#include <cppunit/ui/text/TestRunner.h>" > \n \n +  "int" > \n +  "main(int argc, char* argv[])" > \n +  "{" > \n +  "CppUnit::TextUi::TestRunner runner;" > \n +  "CppUnit::TestFactoryRegistry& registry =" > \n +  "CppUnit::TestFactoryRegistry::getRegistry();" > \n \n +  "runner.addTest(registry.makeTest());" > \n \n +  "return !runner.run(\"\", false);" > \n +  "}" > \n) + +(define-skeleton jao-cppunit-class +  "Create a CPPUNIT class definition preamble" +  nil +  > +  "CPPUNIT_TEST_SUITE(" (jao-basename) ");" +  > \n +  "CPPUNIT_TEST(test);" +  > \n +  "CPPUNIT_TEST_SUITE_END();" +  > \n \n +  "private:" +  > \n \n +  "void test();" +  > \n \n +  "private:" +  > \n \n +  "void set_up();" +  > \n +  "void tear_down();" +  > \n) + +(define-skeleton jao-cppunit-classdef +  "Create a CPPUNIT class implementation preamble" +  nil +  > +  "CPPUNIT_TEST_SUITE_REGISTRATION(" (jao-basename) ");" +  > \n \n +  "void" +  > \n +  (jao-basename) "::set_up()" +  > \n +  "{" +  > \n +  "}" +  > \n \n +  "void" +  > \n +  (jao-basename) "::tear_down()" +  > \n +  "{" +  > \n +  "}" +  > \n) + +(provide 'cppunit-skel) + diff --git a/skels/dot.emacs.el b/skels/dot.emacs.el new file mode 100644 index 0000000..a82e500 --- /dev/null +++ b/skels/dot.emacs.el @@ -0,0 +1,11 @@ +;; boilerplate skels configuration: + +;;; add skels directory to your load path +(add-to-list 'load-path "~/lib/emacs/skels") +(load "init-skel") + +;;; set configuration variables +(setq jao-company-name "Free Software Foundation, Inc.") +(setq jao-cpp-root-namespace "") +(setq jao-copyright-file ".copyright") + diff --git a/skels/fsf-copyright b/skels/fsf-copyright new file mode 100644 index 0000000..af83705 --- /dev/null +++ b/skels/fsf-copyright @@ -0,0 +1,12 @@ +This file is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3 of the License, or +(at your option) any later version. + +This file is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program.  If not, see <http://www.gnu.org/licenses/>. diff --git a/skels/fuel-skel.el b/skels/fuel-skel.el new file mode 100644 index 0000000..786f4ec --- /dev/null +++ b/skels/fuel-skel.el @@ -0,0 +1,45 @@ +;;; fuel-skel.el --- skeleton for fuel elisp files + +;; Copyright (C) 2008  Jose Antonio Ortega Ruiz + +;; Author: Jose Antonio Ortega Ruiz <jao@gnu.org> +;; Keywords: lisp + +;; 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/>. + +;;; Code: + +(require 'common-skel) + +(define-skeleton jao-skel-fuel-file +  "Fuel file header" +  "Brief description: " +  ";;; " (file-name-nondirectory (buffer-file-name)) " -- " str "" +  \n \n +  (jao-copyright-line ";; ") +  ";; See http://factorcode.org/license.txt for BSD license." +  \n \n (jao-author-line ";; ") ";; Keywords: languages, fuel, factor" +  \n (jao-date-line ";; ") +  \n ";;; Comentary: " \n \n ";; " _ \n +  \n ";;; Code: " \n \n \n \n +  "" \n "(provide '" (jao-basename) ")" \n +  ";;; " (file-name-nondirectory (buffer-file-name)) " ends here" +  \n +  \n) + +(jao-provide-skel "misc/fuel/.+\\.el\\'" 'jao-skel-fuel-file) + + +(provide 'fuel-skel) +;;; fuel-skel.el ends here diff --git a/skels/geiser-skel.el b/skels/geiser-skel.el new file mode 100644 index 0000000..3c9181a --- /dev/null +++ b/skels/geiser-skel.el @@ -0,0 +1,50 @@ +;; geiser-skel.el -- geiser skeletons + +;; Copyright (C) 2009 Jose Antonio Ortega Ruiz + +;; Author: Jose Antonio Ortega Ruiz <jao@gnu.org> +;; Start date: Fri Sep 11, 2009 00:31 + +(require 'common-skel) + +(defconst jao-skel-geiser--bsd +  ";; This program is free software; you can redistribute it and/or +;; modify it under the terms of the Modified BSD License. You should +;; have received a copy of the license along with this program. If +;; not, see <http://www.xfree86.org/3.3.6/COPYRIGHT2.html#5>. +") + +(defsubst jao-skel-geiser--end-line () +  (format ";;; %s ends here\n\n" (file-name-nondirectory (buffer-file-name)))) + +(define-skeleton jao-skel-geiser--common +  "Geiser elisp header" +  "Brief description: " +  ";;; " (file-name-nondirectory (buffer-file-name)) " -- " str "" +  \n \n +  (jao-copyright-line ";; ") \n +  jao-skel-geiser--bsd +  \n (jao-date-line ";; ") \n) + +(define-skeleton jao-skel-geiser-elisp +  "Geiser elisp header" +  nil +  '(jao-skel-geiser--common) +  "" \n _ \n \n "" \n "(provide '" (jao-basename) ")" \n +  (jao-skel-geiser--end-line)) + +(jao-provide-skel "geiser/elisp/.+\\.el\\'" 'jao-skel-geiser-elisp) + +(define-skeleton jao-skel-geiser-scheme +  "Geiser scheme header" +  nil +  '(jao-skel-geiser--common) _ +  \n (jao-skel-geiser--end-line)) + +(jao-provide-skel "geiser/scheme/.+\\.\\(scm\\|ss\\|sls\\)\\'" +                  'jao-skel-geiser-scheme) + + + +(provide 'geiser-skel) +;;; geiser-skel.el ends here diff --git a/skels/haskell-skel.el b/skels/haskell-skel.el new file mode 100644 index 0000000..e105f31 --- /dev/null +++ b/skels/haskell-skel.el @@ -0,0 +1,69 @@ +;;; haskell-skel.el --- skeleton for haskell source files +;; Copyright (C) 2003, 2004, 2005, 2009, 2010 Jose A Ortega Ruiz + +;; Author: Jose A Ortega Ruiz <jao@member.fsf.org> +;; Keywords: languages + +;; This file is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. + +;; This file is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING.  If not, write to +;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; + +;;; Code: + +(require 'common-skel) +(require 'jao-dominating-file) + +;;; Auxiliar +(defun jao-skel--read-haskell-module () +  (let* ((ddir (jao-relative-path "\\.cabal\\'")) +         (mbase (and ddir (concat (replace-in-string ddir "/" ".") "."))) +         (m (read-string "Module prefix (empty for no module): " +                         (concat (or mbase "") (jao-basename))))) +    (or m ""))) + +(defconst jao-skel--haskell-line (make-string 78 ?-)) + +;;; Skeletons +(define-skeleton jao-skel-haskell-file +  "Haskell hs file header" +  "Brief description: " +  '(setq v (jao-skel--read-haskell-module)) +  jao-skel--haskell-line \n +  "-- |" \n +  "-- Module: " v \n +  (jao-copyright-line "-- Copyright: " "" t) +  "-- License: BSD3-style (see LICENSE)" \n +  "--" \n +  "-- Maintainer: " user-mail-address \n +  "-- Stability: unstable" \n +  "-- Portability: portable" \n +  "-- Created: " (format-time-string "%a %b %d, %Y %H:%M") \n +  "--" \n +  "--" \n +  "-- " str \n +  "--" \n +  jao-skel--haskell-line +  \n \n \n +  "module " v " where " \n \n \n) + +(jao-provide-skel "\\.hs\\'"  'jao-skel-haskell-file) +;; (jao-provide-skel "\\.lhs\\'" 'jao-skel-lit-haskell-file) + +(provide 'haskell-skel) + +;;; haskell-skel.el ends here diff --git a/skels/init-skel.el b/skels/init-skel.el new file mode 100644 index 0000000..7612f92 --- /dev/null +++ b/skels/init-skel.el @@ -0,0 +1,39 @@ +;; skeleton configuration + +;; Copyright (C) 2004, 2005, 2006, 2007, 2008 Jose Antonio Ortega Ruiz + +;; Author: Jose A Ortega Ruiz <jao@gnu.org> +;; Keywords: tools + +;; This file is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. + +;; This file is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING.  If not, write to +;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; Initialisation file for jao skeletons + +;;; Code: + +(require 'autoinsert) +(setq auto-insert t) +(add-hook 'find-file-hooks 'auto-insert) +(setq auto-insert-directory "~/.autoinsert/") +(setq auto-insert-query t) + +(require 'common-skel) + +(provide 'init-skel) + +;;;; init-skel.el ends here diff --git a/skels/latex-skel.el b/skels/latex-skel.el new file mode 100644 index 0000000..330be22 --- /dev/null +++ b/skels/latex-skel.el @@ -0,0 +1,52 @@ +;; latex skeletons + +;; Copyright (C) 2004, 2005, 2009 Jose Antonio Ortega Ruiz + +;; Author: Jose A Ortega Ruiz <jao@gnu.org> +;; Keywords: tools + +;; This file is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. + +;; This file is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING.  If not, write to +;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; LaTeX skeletons + +;;; Code: + +(require 'common-skel) + +(define-skeleton jao-skel-latex +  "Latex standard header" +  nil +  "%%" +  \n +  "%% Author: " (user-full-name) " <"user-mail-address">" +  \n +  "%% Start date: " (format-time-string "%a %b %d, %Y %H:%M") +  \n +  "%% $" "Id$" +  \n +  "%%" +  ?\n +  (jao-copyright-line "% ") +  \n +  "%%" +  \n \n) + +(jao-provide-skel "\\.tex$\\|\\.sty$\\|\\.cls$" 'jao-skel-latex) + +(provide 'latex-skel) + diff --git a/skels/lisa-skel.el b/skels/lisa-skel.el new file mode 100644 index 0000000..6cf3083 --- /dev/null +++ b/skels/lisa-skel.el @@ -0,0 +1,157 @@ +;;; lisa variants of c skeletons + +;; Copyright (C) 2004, 2005, 2006 Jose Antonio Ortega Ruiz + +;; Author: Jose A Ortega Ruiz <jao@gnu.org> +;; Keywords: tools + +;; This file is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; This file is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING.  If not, write to +;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; Lisa variants for c skeletons + +;;; Code: + +(require 'common-skel) + +(defun jao-lisa-filename () +  (let* ((fname (expand-file-name (buffer-file-name))) +         (parts (split-string fname "/")) +         (dirs (member "src" parts))) +    (mapconcat 'identity dirs "/"))) + + +(defun jao-lisa-guard () +  (upcase (concat (jao-basename) +                  "_" (jao-extension) "_" +                  (format-time-string "%y%m%d%H%M")))) + +(defun jao-lisa-header (&optional desc group prf) +  (concat "/**" +          "\n * @file     " (jao-lisa-filename) +          "\n * @author   " (user-full-name) " <"user-mail-address">" +          "\n * @date     " (format-time-string "%a %b %d, %Y %H:%M") +          "\n * @brief    " (or desc (read-string "Description: ")) +          (if group (concat "\n * @ingroup  " group) "") +          (if prf (concat "\n * @uutrx    " prf) "") +          "\n **/\n\n" +          (jao-arch-line "// " ""))) + +(define-skeleton jao-skel-lisa-h +  "Standard lisa c header" +  nil +  '(setq guard (jao-lisa-guard)) +  (jao-lisa-header) +  \n \n +  "#ifndef " guard \n +  "#define " guard \n +  \n \n "#include \"" _ "\"" \n \n \n +  "" \n "// Types" \n \n \n +  "" \n "// Constants" \n \n \n +  "" \n "// Functions" \n \n \n +  \n \n +  "#endif // " guard +  \n \n) + +(define-skeleton jao-skel-lisa-c +  "Standard lisa c body" +  nil +  (jao-lisa-header (concat (jao-other-file-name "h" "c") " implementation")) +  \n \n +  "#include \"" +  (jao-basename) +  ".h\"" > +  > \n \n \n +  "" \n "// Private" \n \n \n +  _ +  "" \n "// Public" \n \n \n +  ) + +(define-skeleton jao-skel-lisa-test +  "Cantata++ test file" +  nil +  '(setq v1 (read-string "File under test (sans extension): ")) +  '(setq v0 (read-string "Doxygen group under test: ")) +  '(setq v2 (concat "UnitTest" v0)) +  (jao-lisa-header (concat "Unit tests for " v1) +                   v2 +                   (read-string "Prefix of functions being tested (e.g. 'rtos_?+'): ")) +  \n \n +  "#include \"test/test.h\"" > \n +  "#include \"" v1 ".h\"" > \n \n \n +  "// Test name"  > \n +  "char const *test_name = \"" (concat v1 "_test") "\";" > \n \n +  "// Prototypes for test functions" > \n +  "/**" \n +  "* @defgroup " v2 " Unit tests" > \n +  "* @ingroup " v0 > \n +  "**/" > \n +  "//@{" > \n +  "//@}" > \n +  \n \n \n +  "void" > \n +  "run_tests (void)" > \n +  "{" > \n +  "}" > \n \n +  "// Test functions" > \n \n \n) + +(defun jao-add-cantata-test () +  "Call this function inside a test buffer to add a new test fun" +  (interactive) +  (let* ((fn (read-string "Function under test: ")) +         (tfn (concat "test_" fn))) +    (goto-char (point-min)) +    (if (not (search-forward-regexp "^// Prototypes for test functions$" nil t)) +        (error "No beginning of test fun declarations found")) +    (if (not (search-forward-regexp "//@\\}$" nil t)) +        (error "Missing doxygen group marks in prototype function decls")) +    (beginning-of-line) +    (open-line 1) +    (insert "/**\n * Unit tests for @ref " fn "\n */\n") +    (insert "static void " tfn " (void);\n") +    (if (not (search-forward-regexp "run_tests (void)$" nil t)) +        (error "No run_tests() definition found")) +    (if (not (search-forward-regexp "^}" nil t)) +        (error "End of run_tests() not found")) +    (beginning-of-line) +    (insert "\n") +    (previous-line 1) +    (insert tfn " ();") +    (indent-according-to-mode) +    (goto-char (point-max)) +    (jao-insert-cantata-test-fun tfn))) + +(defun jao-insert-cantata-test-fun (fn) +  (beginning-of-line) +  (insert "void\n" fn " (void)\n{\n") +  (insert "START_TEST (\"" fn +          "\", \"" (read-string "Test case description: ") "\");") +  (indent-according-to-mode) +  (insert "\n\n\nEND_TEST ();") +  (indent-according-to-mode) +  (insert "\n}\n")) + + +(defun jao-skel-lisa-activate () +  (interactive) +  (jao-provide-skel "\\.c$" 'jao-skel-lisa-c) +  (jao-provide-skel "\\.h$" 'jao-skel-lisa-h) +  (jao-provide-skel "tests/.*\\.c$" 'jao-skel-lisa-test)) + + +(provide 'lisa-skel) + diff --git a/skels/lisp-skel.el b/skels/lisp-skel.el new file mode 100644 index 0000000..e5bb91a --- /dev/null +++ b/skels/lisp-skel.el @@ -0,0 +1,50 @@ +;;; lisp-skel.el --- skeleton for lisp-like languages + +;; Copyright (C) 2003, 2004, 2005, 2008, 2009  Jose A Ortega Ruiz + +;; Author: Jose A Ortega Ruiz <jao@gnu.org> +;; Keywords: lisp + +;; This file is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. + +;; This file is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING.  If not, write to +;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; Skeleton for lisp like languages + +;;; Code: + +(require 'common-skel) + +(define-skeleton jao-skel-lisp-file +  "Lisp file header" +  "Brief description: " +  ";; " (file-name-nondirectory (buffer-file-name)) " -- " str "" +  ?\n +  (jao-c&co-line ";; ") +  ?\n +  (jao-insert-copyright-file) +  \n ";;; Comentary: " \n \n ";; " _ \n +  \n ";;; Code: " \n \n \n \n +  '(when (eq major-mode 'emacs-lisp-mode) +     (insert (format "\n(provide '%s)\n" (jao-basename)))) +  ";;; " (file-name-nondirectory (buffer-file-name)) " ends here" +  \n +  \n) + +(jao-provide-skel "\\.\\(scm\\|ss\\|lisp\\|cl\\|el\\)\\'" 'jao-skel-lisp-file) + +(provide 'lisp-skel) +;;; lisp-skel.el ends here diff --git a/skels/make-skel.el b/skels/make-skel.el new file mode 100644 index 0000000..5607dbe --- /dev/null +++ b/skels/make-skel.el @@ -0,0 +1,53 @@ +;; makefile skeletons + +;; Copyright (C) 2004, 2005, 2009 Jose Antonio Ortega Ruiz + +;; Author: Jose A Ortega Ruiz <jao@gnu.org> +;; Keywords: tools + +;; This file is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. + +;; This file is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING.  If not, write to +;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; Makefile skeletons + +;;; Code: + +(require 'common-skel) + +(define-skeleton jao-skel-makefile +  "Makefile standard header" +  nil +  "#" +  \n +  "# $" "Id$" +  \n +  "# " +  \n +  "# Author: " (user-full-name) " <"user-mail-address">" +  \n +  "# Start date: " (format-time-string "%a %b %d, %Y %H:%M") +  \n +  "#" +  ?\n +  (jao-copyright-line "# ") +  \n +  (jao-insert-copyright-file)) + +(jao-provide-skel "\\.mk$\\|Makefile\\(\\.am\\)?\\|configure\\.in" 'jao-skel-makefile) + +(provide 'make-skel) + diff --git a/skels/muse-skel.el b/skels/muse-skel.el new file mode 100644 index 0000000..86686d9 --- /dev/null +++ b/skels/muse-skel.el @@ -0,0 +1,41 @@ +;;; muse-skel.el --- muse pages + +;; Copyright (C) 2006  Jose Antonio Ortega Ruiz + +;; Author: Jose Antonio Ortega Ruiz <jao@gnu.org> +;; Keywords: tools + +;; This file is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; This file is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING.  If not, write to +;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +;; Boston, MA 02110-1301, USA. + +;;; Code: + +(require 'common-skel) + +(define-skeleton jao-skel-muse-file +  "Muse file skeleton" +  "Documents (sub)dir: " +  _ \n \n \n \n \n \n \n +  "----" \n +  ";;; Local Variables:" \n +  ";;; wiki-docs: " str \n +  ";;; End:" \n \n +   '(hack-local-variables)) + +(add-to-list 'auto-insert-alist +             '("\\.muse\\'" . jao-skel-muse-file)) + +(provide 'muse-skel) +;;; muse-skel.el ends here diff --git a/skels/noweb-skel.el b/skels/noweb-skel.el new file mode 100644 index 0000000..0e37702 --- /dev/null +++ b/skels/noweb-skel.el @@ -0,0 +1,48 @@ +;;; noweb-skel.el --- skeleton for noweb files + +;; Copyright (C) 2003, 2004, 2005  Jose Antonio Ortega Ruiz + +;; Author: Jose A Ortega Ruiz <jao@gnu.org> +;; Keywords: tools + +;; This file is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; This file is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING.  If not, write to +;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; Skeleton for noweb files + +;;; Code: + +(require 'common-skel) +(require 'latex-skel) + +(define-skeleton jao-skel-noweb +  "Noweb standard header" +  "Code mode (without -mode suffix): " +  "% -*- mode: Noweb; noweb-code-mode: " str "-mode -*-" +  '(setq noweb-code-mode (intern (concat str "-mode"))) +  \n +  '(jao-skel-latex) +  \n _ \n \n +  "%%% end of file" +  \n) + +(add-to-list 'auto-insert-alist '("\\.nw$" . jao-skel-noweb)) + +(provide 'noweb-skel) + + +;;; noweb-skel.el ends here diff --git a/skels/perl-skel.el b/skels/perl-skel.el new file mode 100644 index 0000000..a5b5bb4 --- /dev/null +++ b/skels/perl-skel.el @@ -0,0 +1,78 @@ +;;; perl-skel.el + +;; Copyright (C) 2004, 2005, 2009 Jose Antonio Ortega Ruiz + +;; Author: Jose A Ortega Ruiz <jao@gnu.org> +;; Keywords: tools + +;; This file is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. + +;; This file is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING.  If not, write to +;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; Perl skeletons + +;;; Code: + +(require 'common-skel) + +(define-skeleton jao-skel-perl-script +  "Standard perl script header" +  "Brief file description: " +  "#! /usr/bin/perl -w" +  > \n +  "#" +  > \n +  "# $Id" "$" +  > \n +  "# " (file-name-nondirectory (buffer-file-name)) ": " str +  > \n +  "#" +  > ?\n +  (jao-copyright-line "# ") +  > ?\n +  (jao-insert-copyright-file) +  > \n +  "use strict;" +  > \n \n +  > \n _) + +(define-skeleton jao-skel-perl-module +  "Standard perl module header" +  "Brief module description: " +  "#" +  > \n +  "# " (file-name-nondirectory (buffer-file-name)) ": "str +  > \n +  "#" +  > ?\n +  (jao-copyright-line "# ") +  > ?\n +  (jao-insert-copyright-file) +  "# " +  > \n \n +  "package " +  (read-string (concat "Module name (" (jao-basename) "): ") +	       nil nil (jao-basename)) +  ";" +  > \n \n _ \n \n +  "1;" +  > \n) + +(jao-provide-skel "\\.pl$" 'jao-skel-perl-script) +(jao-provide-skel "\\.pm$" 'jao-skel-perl-module) + +(provide 'perl-skel) + diff --git a/skels/pika-skel.el b/skels/pika-skel.el new file mode 100644 index 0000000..654792d --- /dev/null +++ b/skels/pika-skel.el @@ -0,0 +1,88 @@ +;;; pika variants of c skeletons + +;; Copyright (C) 2004, 2005 Jose Antonio Ortega Ruiz + +;; Author: Jose A Ortega Ruiz <jao@gnu.org> +;; Keywords: tools + +;; This file is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; This file is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING.  If not, write to +;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; Pika variants for c skeletons + +;;; Code: + +(require 'common-skel) + +(defun jao-pika-guard () +  (upcase (concat "include__" (jao-basedir) "__" (jao-basename) "_h"))) + +(define-skeleton jao-pika-header +  "" +  "Brief file description: " +  "/* " (file-name-nondirectory (buffer-file-name)) ": " str +  \n "*" > \n +  "****************************************************************" +  > \n (jao-copyright-line "* ") +  > \n "*" > \n +  "* See the file \"COPYING\" for further information about" +  > n +  "* the copyright and warranty status of this work." +  > n +  "*/" \n "" \n _) + +(define-skeleton jao-skel-pika-h +  "Standard pika c header" +  nil +  (jao-pika-header) +  '(setq guard (jao-pika-guard)) +  "#ifndef " guard \n +  "#define " guard \n +  "" +  \n \n "#include \"" _ "\""\n \n +  "" +  \n \n \n +  "" +  \n +  "#endif /* " guard " */" +  \n \n "" \n +  (jao-arch-line "/* " "*/") +  \n) + +(define-skeleton jao-skel-pika-c +  "Standard pika c body" +  nil +  (jao-pika-header) +  \n "#include \"" (jao-dir-level 2) ".h\"" \n +  \n +  "" +  \n \n _ \n \n "" \n +  (jao-arch-line "/* " "*/") +  \n) + +(defun jao-skel-pika-activate () +  (interactive) +  (let ((c (assoc "\\.c$" auto-insert-alist)) +        (h (assoc "\\.h$" auto-insert-alist))) +    (if c (setf (cdr c) 'jao-skel-pika-c) +      (add-to-list 'auto-insert-alist '("\\.c$" . jao-skel-pika-c))) +    (if h (setf (cdr h) 'jao-skel-pika-h) +      (add-to-list 'auto-insert-alist '("\\.h$" . jao-skel-pika-h))))) + + +(provide 'pika-skel) + diff --git a/skels/python-skel.el b/skels/python-skel.el new file mode 100644 index 0000000..536f825 --- /dev/null +++ b/skels/python-skel.el @@ -0,0 +1,53 @@ +;;; python-skel.el + +;; Copyright (C) 2004, 2005, 2009 Aleix Conchillo Flaque + +;; Author: Aleix Conchillo Flaque <aleix@member.fsf.org> +;; Keywords: tools + +;; This file is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. + +;; This file is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING.  If not, write to +;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; Python skeletons + +;;; Code: + +(require 'common-skel) + +(define-skeleton jao-skel-python-module +  "Standard python module header" +  "Brief file description: " +  "#! /usr/bin/env python" +  > \n +  "#" +  > \n +  "# $Id" "$" +  > \n \n +  "# " (file-name-nondirectory (buffer-file-name)) ": " str +  > \n +  "#" +  > ?\n +  (jao-copyright-line "# ") +  > ?\n +  (jao-insert-copyright-file) +  > \n +  > \n _) + +(jao-provide-skel "\\.py$" 'jao-skel-python-module) + +(provide 'python-skel) + diff --git a/skels/readme-skel.el b/skels/readme-skel.el new file mode 100644 index 0000000..9c22cce --- /dev/null +++ b/skels/readme-skel.el @@ -0,0 +1,44 @@ +;; Copyright (C) 2004, 2005 Jose Antonio Ortega Ruiz + +;; Author: Jose A Ortega Ruiz <jao@gnu.org> +;; Keywords: tools + +;; This file is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; This file is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING.  If not, write to +;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; Simple skeleton for README files. + +;;; Code: + +(require 'common-skel) + +(define-skeleton jao-skel-readme-file +  "README file header" +  "Brief description: " +  \n str +  \n "-----------------------------------------------------" \n +  _ \n \n \n +  "-----------------------------------------------------" \n +  (jao-copyright-line "" "") +  \n \n +  "$Id" "$" +  \n) + +(add-to-list 'auto-insert-alist '("README" . jao-skel-readme-file)) + +(provide 'readme-skel) + diff --git a/skels/s48-skel.el b/skels/s48-skel.el new file mode 100644 index 0000000..30e749f --- /dev/null +++ b/skels/s48-skel.el @@ -0,0 +1,61 @@ +;;; s48-skel.el --- skeleton for s48 + +;; Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009  Jose A Ortega Ruiz + +;; Author: Jose A Ortega Ruiz <jao@gnu.org> +;; Keywords: lisp + +;; This file is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. + +;; This file is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING.  If not, write to +;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; Skeleton for s48/slime48 like languages + +;;; Code: + +(require 'common-skel) +(require 'lisp-skel) + +(define-skeleton jao-skel-s48-file +  "Slime/Scheme48 file header" +  "Package: " +  ";; -*- mode: scheme48; scheme48-package: " str " -*-" +  ?\n +  (jao-co-line ";; ") +  ?\n +  (jao-insert-copyright-file) +  \n ";;; Comentary: " \n \n ";; " _ \n +  \n ";;; Code: " \n \n \n \n +  ";;; " (file-name-nondirectory (buffer-file-name)) " ends here" +  '(scheme48-mode) +  \n +  \n) + +(define-skeleton jao-skel-s48-file-maybe +  "Choose between a s48 file and a plain scheme one" +  nil +  '(if (y-or-n-p "Is this a s48 file? ") (jao-skel-s48-file) +     (jao-skel-lisp-file)) +    '(hack-local-variables)) + + +(jao-provide-skel "\\.scm\\'" 'jao-skel-s48-file-maybe) + + +(provide 's48-skel) + + +;;; lisp-skel.el ends here diff --git a/skels/scsh-skel.el b/skels/scsh-skel.el new file mode 100644 index 0000000..495925f --- /dev/null +++ b/skels/scsh-skel.el @@ -0,0 +1,45 @@ +;;; scsh-skel.el --- skeleton for scsh scripts + +;; Copyright (C) 2003, 2004, 2005, 2006, 2008  Jose Antonio Ortega Ruiz + +;; Author: Jose Antonio Ortega Ruiz <jao@gnu.org> +;; Keywords: abbrev + +;; This file is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. + +;; This file is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING.  If not, write to +;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +(require 'common-skel) + +(define-skeleton jao-skel-scsh +  "Scsh script skeleton" +  "Brief description: " +  "#! " (executable-find "scsh") " \\" \n +  "-e " (file-name-nondirectory (buffer-file-name)) " -s" \n +  "!#" \n \n +  ";;;; " str \n +  "(define (" (file-name-nondirectory (buffer-file-name)) " args)" +  \n +  > _ " )" +  > \n \n \n +  ";; Local Variables:" \n +  ";; mode: scheme" \n +  ";; End:" +  '(hack-local-variables) +  \n \n) + +(provide 'scsh-skel) + + +;;; scsh-skel.el ends here diff --git a/skels/texinfo-skel.el b/skels/texinfo-skel.el new file mode 100644 index 0000000..dc73835 --- /dev/null +++ b/skels/texinfo-skel.el @@ -0,0 +1,131 @@ +;;; texinfo-skel.el --- skeletons for texinfo files + +;; Author: Jose Antonio Ortega Ruiz <jao@gnu.org> +;; Keywords: languages + +;; This file is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; This file is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING.  If not, write to +;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; Skeletons to generate texinfo files templates. + +;;; Code: + +(require 'common-skel) + +(defun jao-dir-entry () +  "Read dir file entry" +  (let ((cat (read-string "Dir file category: ")) +        (ent (read-string "Direntry name: ")) +        (desc (read-string "Direntry description: "))) +    (concat "@dircategory " cat +            "\n@direntry\n" ent +            ": (" (jao-basename) ").        " desc "." +            "\n@end direntry\n"))) + +(define-skeleton jao-skel-main-texinfo +  "Main texinfo file skeleton" +  "Document title: " +  "\\input texinfo" +  \n "@ignore" > +  \n (jao-scm-line "") +  "@end ignore" > +  \n > "@c %**start of header" +  \n "@setfilename " (jao-basename) ".info" > +  \n "@settitle " str > +  \n "@syncodeindex pg cp" > +  \n "@setchapternewpage odd" > +  \n "@footnotestyle separate" > +  \n "@c %**end of header" > +  \n \n +  (jao-dir-entry) +  \n +  "@set UPDATED " (format-time-string "%B %Y") +  \n "@set EDITION 0.1" +  \n "@set VERSION 0.1" +  \n "@set AUTHOR " (user-full-name) +  \n \n "@copying" +  \n "This manual is for " str " (version @value{VERSION}, @value{UPDATED})." +  \n +  \n "Copyright @copyright{} " (format-time-string "%Y") " " jao-company-name +  \n +  \n "@quotation" +  \n "Permission is granted to copy, distribute and/or modify this document" +  \n "under the terms of the GNU Free Documentation License, Version 1.1 or" +  \n "any later version published by the Free Software Foundation; with no" +  \n "Invariant Sections, with the Front-Cover Texts being ``A GNU Manual,''" +  \n "and with the Back-Cover Texts as in (a) below.  A copy of the" +  \n "license is included in the section entitled ``GNU Free Documentation" +  \n "License.''" +  \n +  \n "(a) The FSF's Back-Cover Text is: ``You have freedom to copy and modify" +  \n "this GNU Manual, like GNU software.  Copies published by the Free" +  \n "Software Foundation raise funds for GNU development.''" +  \n "@end quotation" +  \n "@end copying" +  \n \n "@titlepage" +  \n "@title " str +  \n "@subtitle Edition @value{EDITION}, for version @value{VERSION}" +  \n "@subtitle @value{UPDATED}" +  \n "@author by @value{AUTHOR} (@email{jao@@gnu.org})" +  \n "@page" +  \n "@vskip 0pt plus 1filll" +  \n "@insertcopying" +  \n "@end titlepage" +  \n +  \n "@shortcontents" +  \n "@contents" +  \n +  \n "@ifnottex" +  \n "@node Top, , (dir), (dir)" +  \n \n "@insertcopying" +  \n "@end ifnottex" +  \n \n +  "@menu" > \n "@detailmenu" \n \n > "@end detailmenu" > \n "@end menu" +  \n \n \n +  "@include intro.texi" > +  \n \n \n +  "@bye" +  \n) + +(define-skeleton jao-skel-child-texinfo +  "Template for child texinfo docs" +  "Node name: " +  "@node " str \n +  > "@chapter " str \n +  > "@ignore" \n +  (jao-scm-line "") +  > "@end ignore" \n \n +  _ \n \n +  "@c This is part of the " (read-string "Main doc title: ") \n +  "@c See the main file for copying conditions." +  \n \n) + +(define-skeleton jao-skel-texinfo +  "Skeleton for texinfo files" +  nil +  '(if (y-or-n-p "Is this the main texinfo file? ") +       (jao-skel-main-texinfo) +     (jao-skel-child-texinfo)) +  _) + +(add-to-list 'auto-insert-alist '("\\.texi$" . jao-texinfo-skel)) + + +(provide 'texinfo-skel) + + +;;; texinfo-skel.el ends here diff --git a/sys/furl.applescript b/sys/furl.applescript new file mode 100644 index 0000000..6823ff0 --- /dev/null +++ b/sys/furl.applescript @@ -0,0 +1 @@ +tell application "Firefox" to get Çclass curlÈ of window 1 diff --git a/sys/jao-applescript.el b/sys/jao-applescript.el new file mode 100644 index 0000000..233186c --- /dev/null +++ b/sys/jao-applescript.el @@ -0,0 +1,65 @@ +;;; AppleScript and some macish bits +(autoload 'applescript-mode "applescript-mode" +   "major mode for editing AppleScript source." t) +(setq auto-mode-alist +      (cons '("\\.applescript$" . applescript-mode) auto-mode-alist)) + +(defun do-applescript (script) +  (with-temp-buffer +    (insert script) +    (shell-command-on-region (point-min) (point-max) "osascript" t) +    (buffer-string))) + +(defun jao-as-tell-app (app something) +  (let ((res (do-applescript (format "tell application \"%s\"\n%s\nend tell" +                                     app something)))) +    (or (and (stringp res) (substring res 0 -1)) ""))) + +(defmacro jao-as-get-doc (name application &optional doc) +  `(defun ,name () +     (interactive) +     (let ((url (jao-as-tell-app ,application +                                 ,(format "get the URL of %s 1" +                                          (or doc "document")))) +           (name (jao-as-tell-app ,application "get the name of document 1"))) +       (cons url name)))) +(jao-as-get-doc jao-as-safari-doc "Safari") +(jao-as-get-doc jao-as-webkit-doc "WebKit") +(jao-as-get-doc jao-as-camino-doc "Camino" "window") + +(defun jao-as-firefox-doc () +  (interactive) +  (let ((url (shell-command-to-string +              (concat "osascript " +                      (expand-file-name "furl.applescript" +                                        (file-name-directory load-file-name))))) +        (name (jao-as-tell-app "Firefox" "get the name of window 1"))) +    (cons (substring url 0 -1) name))) + + +;;; quicksilver +(defun jao-qs-buffer () +  "Opens the current file in Quicksilver" +  (interactive) +  (cond ((and buffer-file-name (file-exists-p buffer-file-name)) +         (call-process-shell-command (concat "qs \"" buffer-file-name "\""))) +        ;; dired handling +        ((eq major-mode 'dired-mode) +         (dired-do-shell-command "qs * " +                                 current-prefix-arg +                                 (dired-get-marked-files t current-prefix-arg))) +         ;; buffer-menu mode +        ((and (eq major-mode 'Buffer-menu-mode) +              (file-exists-p (buffer-file-name (Buffer-menu-buffer nil)))) +         (call-process-shell-command +          (concat "qs \"" (buffer-file-name (Buffer-menu-buffer nil)) "\""))) +        (t +         (error "Not visiting a file or file doesn't exist")))) + + (defun jao-qs-region (start end) +   "Opens the contents of the region in Quicksilver as text." +   (interactive "r") +   (call-process-region start end "qs" nil 0 nil "-")) + + +(provide 'jao-applescript) diff --git a/sys/jao-devon.el b/sys/jao-devon.el new file mode 100644 index 0000000..417cb6d --- /dev/null +++ b/sys/jao-devon.el @@ -0,0 +1,42 @@ +;; DEVONthink interaction + +(require 'jao-applescript) + +(defconst *jao-devon-sep* "####") + +(defun jao-devon-path (dvp) +  (car (split-string dvp *jao-devon-sep*))) +(defun jao-devon-url (dvp) +  (cadr (split-string dvp *jao-devon-sep*))) +(defun jao-devon-name (dvp) +  (car (last (split-string (jao-devon-path dvp) "/")))) + +(defun jao-devon-make-dvp (path url) (concat path *jao-devon-sep* name)) +(defun jao-devon-dvp-p (dvp) +  (and (stringp dvp) +       (string-match (concat "^/.+" *jao-devon-sep*) dvp))) + +(defconst *jao-devon-sel-as* + (concat "set rs to the selection +  set r to item 1 of rs +  set rn to the name of r +  set rl to the location of r +  set ru to the URL of r +  rl & rn & \"" *jao-devon-sep* "\" & ru")) + +(defun jao-devon-selection () +  (interactive) +  (jao-as-tell-app "DEVONThink Pro" *jao-devon-sel-as*)) + +(defun jao-devon-open-as (path) +  (concat "set r to get record at \"" path "\"" +          "\n open window for record r\n activate")) + +(defun jao-devon-open (dvp) +  (if (eq system-type 'darwin) +      (let ((path (jao-devon-path dvp))) +        (when path +          (jao-as-tell-app "DEVONThink Pro" (jao-devon-open-as path) t))) +    (browse-url (jao-devon-url dvp)))) + +(provide 'jao-devon) diff --git a/sys/jao-osd.el b/sys/jao-osd.el new file mode 100644 index 0000000..0b2c433 --- /dev/null +++ b/sys/jao-osd.el @@ -0,0 +1,55 @@ +;; candy +(defvar jao-osd-cat-color-fg "black") +(defvar jao-osd-cat-color-bg "white") +(defvar jao-osd-cat-font "Andika Basic 16") +(defun jao-osd-cat-font (&optional font) +  (or font jao-osd-cat-font)) + +(defun jao-osd-process-args (&optional font fg bg) +  `("-n" ,(jao-osd-cat-font font) +    "-R" ,(or bg jao-osd-cat-color-fg) "-B" ,(or fg jao-osd-cat-color-bg) +    "-b" "200" "-r" "255" +    "-e" "0" "-t" "2" "-d" "10" "-p" "0" "-x" "10" "-y" "10" "-u" "5000")) + +(setq jao-osd-processes (make-hash-table)) + +(defsubst jao-osd--delete-process (name) +  (remhash name jao-osd-processes)) + +(defun jao-osd-process (name &optional font color) +  (let ((proc (gethash name jao-osd-processes))) +    (or (and proc (eq (process-status proc) 'run) proc) +        (puthash name +                 (apply 'start-process +                        `("notifications" +                          ,(format "*notifications/%s*" name) +                          "aosd_cat" +                          ,@(jao-osd-process-args))) +                 jao-osd-processes)))) + +(defun jao-osd-cat (name lines) +  (let* ((proc (jao-osd-process name)) +         (lines (if (listp lines) lines (list lines))) +         (trail (- 5 (length lines)))) +    (when proc +      (dolist (line lines) +        (send-string proc (format "%s\n" line)))))) +      ; (when (> trail 0) (send-string proc (make-string trail ?\n)))))) + +(defun jao-osd--names () +  (let (names) +    (maphash (lambda (n k) (push n names)) jao-osd-processes) +    (reverse names))) + +(defun jao-osd-kill (name) +  (let ((proc (gethash name jao-osd-processes))) +    (when (processp proc) +      (kill-process proc)))) + +(defun jao-osd-kill-notifiers () +  (interactive) +  (maphash (lambda (n p) (ignore-errors (kill-process p))) jao-osd-processes) +  (clrhash jao-osd-processes)) + +(provide 'jao-osd) + diff --git a/themes/autumn-ec b/themes/autumn-ec new file mode 100755 index 0000000..ca63787 --- /dev/null +++ b/themes/autumn-ec @@ -0,0 +1,40 @@ +#!/bin/bash + +font=${EC_TERM_FACE:-xft:Inconsolata:size=11,[codeset=iso8859-7]xft:Andale Mono:size=12} + +frg="grey55" +bkg="grey1" +bw=4 +bw=${EC_TERM_BORDER:-3} +tr="-tr -sh 8" +tr="+tr" + +exec urxvtcd -cr tomato -sl 0 +rv +ptab +ssr -b $bw -bd "$bkg" \ +             -bg "$bkg" -fg "$frg" \ +             +sbg $tr -fn "${font}" -name "emacsclient" \ +             -xrm "*colorBD: ${frg}" \ +             -xrm "*colorUL: ${frg}" \ +             -xrm "*color0: ${frg}" \ +             -xrm "*color8: grey20" \ +             -xrm "*color1: tan3" \ +             -xrm "*color9: sienna3" \ +             -xrm "*color2: peachpuff4" \ +             -xrm "*color10: navajowhite4" \ +             -xrm "*color3: grey40" \ +             -xrm "*color11: darkseagreen4" \ +             -xrm "*color4: #9D9064" \ +             -xrm "*color12: #BAA68F" \ +             -xrm "*color5: cornsilk3" \ +             -xrm "*color13: sienna4" \ +             -xrm "*color6: grey40" \ +             -xrm "*color14: tan4" \ +             -xrm "*color7: ${frg}" \ +             -xrm "*color15: grey50" \ +             -e emacsclient -t $* + + + +# fname=${EC_XTERM_FN:-Inconsolata} +# fsize=${EC_XTERM_FS:-11} +# exec xterm -cr tomato -sl 0 +rv -b 4 -bg "$bkg" -bd "$bkg" -fg "$frg" \ +#            -bdc -ulc -u8 -fa "$fname" -fs $fsize -name "emacsclient" \ diff --git a/themes/dark-ec b/themes/dark-ec new file mode 100755 index 0000000..caed4f4 --- /dev/null +++ b/themes/dark-ec @@ -0,0 +1,42 @@ +#!/bin/bash + +# font=${EC_TERM_FACE:-xft:Andale Mono:size=11} +font=${EC_TERM_FACE:-xft:Inconsolata:size=11,[codeset=iso8859-7]xft:Andale Mono:size=12} +# font=${EC_TERM_FACE:-xft:Terminus:size=12,[codeset=iso8859-7]xft:Andale Mono:size=12} +# font=${EC_TERM_FACE:-xft:DejaVu Sans Mono:size=11} + +frg="grey50" +bkg="black" +bw=${EC_TERM_BORDER:-2} +tr=${EC_TRANS_SPEC} + +exec urxvtcd -cr tomato -sl 0 +ptab +rv +ssr -b $bw -bd "$bkg" \ +             -bg "$bkg" -fg "$frg" \ +             +sbg $tr -fn "${font}" -name "emacsclient" \ +             -xrm "*colorBD: ${frg}" \ +             -xrm "*colorUL: ${frg}" \ +             -xrm "*color0: ${bkg}" \ +             -xrm "*color8: grey20" \ +             -xrm "*color1: lightgoldenrod3" \ +             -xrm "*color9: sienna3" \ +             -xrm "*color2: darkslategray" \ +             -xrm "*color10: #44836e" \ +             -xrm "*color3: grey40" \ +             -xrm "*color11: #648f81" \ +             -xrm "*color4: lightcyan4" \ +             -xrm "*color12: darkseagreen4" \ +             -xrm "*color5: paleturquoise4" \ +             -xrm "*color13: aquamarine4" \ +             -xrm "*color6: grey7" \ +             -xrm "*color14: azure4" \ +             -xrm "*color7: ${frg}" \ +             -xrm "*color15: grey50" \ +             -e emacsclient -t $* + + +#             -xrm "*color6: #3F4D5C" \ + +# fname=${EC_XTERM_FN:-Inconsolata} +# fsize=${EC_XTERM_FS:-11} +# exec xterm -cr tomato -sl 0 +rv -b 4 -bg "$bkg" -bd "$bkg" -fg "$frg" \ +#            -bdc -ulc -u8 -fa "$fname" -fs $fsize -name "emacsclient" \ diff --git a/themes/jao-dark-theme.el b/themes/jao-dark-theme.el new file mode 100644 index 0000000..7976337 --- /dev/null +++ b/themes/jao-dark-theme.el @@ -0,0 +1,63 @@ +(jao-define-custom-theme jao-dark-theme +  (:palette (fg unspecified "grey55") +            (bg unspecified "grey2") +            (box "yellow" "grey30") +            (button ((c 11) nul)) +            (hilite ((c nil 8))) +            (strike-through ((c 8))) +            (italic ((c 13))) +            (link ((c 5) ul)) +            (visited-link ((c 3) ul)) +            (tab-sel ((c 9 8) nbf)) +            (tab-unsel ((c 15 6) bx)) +            (comment ((c 3))) +;;            (keyword ((c 12) nbf)) +            (keyword ((c 11) nbf)) +            (type ((c 11) nbf)) +;;            (function ((c 10) nbf)) +            (function ((c 10) nbf)) +            (variable-name ((c nil))) +            (constant ((c 3))) +            (string ((c 14))) +            (warning ((c 1))) +            (error ((c 9))) +            (dimm ((c 3))) +            (gnus-mail ((c 15 nil))) +            (gnus-news ((c 15 nil))) +            (outline ((c 7))) +            (f00 ((c 5))) +            (f01 ((c 11))) +            (f02 ((c 10))) +            (f10 ((p f00))) +            (f11 ((p f01))) +            (f12 ((p f02)))) +  (:faces (bold (c nil nil) nul) +          (gnus-button (c nil nil) nul) +          (gnus-summary-selected (c nil nil) ul nbf) +          (mm-uu-extract (c nil 6)) +          (mode-line (c 7 8) nbf nul) +          (mode-line-inactive (c 8 6) nbf nul) +          (org-hide (c 0 nil)) +          (rcirc-other-nick (c 14)) +          (vertical-border (c 8 nil) :inherit nil) +          (w3m-image (c 1)) +          (w3m-tab-background (c 0 0)) +          (w3m-tab-line (c 0 0)) +          (widget-button (c nil nil) nul)) +  (:x-faces (gnus-button (c nil nil) nul) +            (gnus-summary-selected (c "grey40" nil) ul) +            (mode-line (c 14 8) bf nul bx) +            (mode-line-inactive (c 3 8) nbf nul bx) +            (org-hide (c 0 nil)) +            (fringe (p dimm)) +            (rcirc-other-nick (c 6)) +            (vertical-border (c 8 nil) :inherit nil) +            (w3m-image (c 9)) +            (w3m-tab-background (c 0 0)) +            (widget-button (c nil nil) nul)) +  (:x-colors "black" "lightgoldenrod3" "darkslategray" "grey40" "lightcyan4" +             "paleturquoise4" "#3F4D5C" "grey55" +             "grey20" "lightgoldenrod4" "#44836e" "#648f81" "darkseagreen4" +             "aquamarine4" "azure4" "grey60")) + +(provide 'jao-dark-theme) diff --git a/themes/jao-light-theme.el b/themes/jao-light-theme.el new file mode 100644 index 0000000..3b826b0 --- /dev/null +++ b/themes/jao-light-theme.el @@ -0,0 +1,74 @@ +(jao-define-custom-theme jao-light-theme +  (:palette (fg "black" "black") +            (bg "white" "#efebe7") +            (box "color-86" "antiquewhite3") +            (button ((c 13 nil) nbf nul) (bx)) +            (hilite ((c nil 5))) +            (strike-through ((c 1)) (st)) +            (italic ((c 4) nbf it) (dfg dbg it)) +            (link ((c 8) ul nbf)) +            (visited-link (link)) +            (tab-sel ((~ mode-line))) +            (tab-unsel ((~ mode-line-inactive))) +            (comment ((c 11) it)) ;; italic +            (keyword ((c 14) nul bf)) +            (type ((c 4) nbf nul) ((c "grey30") bf)) +            (function ((c 0 nil) bf)) +            (variable-name ((c 0))) +            (constant ((c 8)) ((c "grey40"))) +            (string ((c 10)) ((c "dark olive green"))) +            (warning ((c 9))) +            (error ((c 1))) +            (dimm ((c 12))) +            (gnus-mail ((c 0))) +            (gnus-news ((c 0))) +            (outline ((c 0))) +            (f00 ((c 14))) +            (f01 ((c 10))) +            (f02 ((c 8))) +            (f10 ((p f00))) +            (f11 ((p f01))) +            (f12 ((p f02)))) +  (:faces (bold (c 80) bf) +          (company-tooltip-common (c 1 6) nbf) +          (company-tooltip-common-selection (~ company-tooltip-selection) +                                            (c nil 6) bf) +          (company-tooltip-selection (~ company-tooltip) bf nul) +          (compilation-info (c nil nil) bf) +          (diary (c 14) bf) +          (gnus-summary-selected (c nil 79)) +          (jao-gnus-face-tree (c nil 78)) +          (header-line (c nil 79) nul) +          (italic it) +          (mode-line (c 0 5) nbf nul) +          (mode-line-inactive (c 12 5) nbf nul) +          (org-hide (c 7 nil)) +          (vertical-border (c 11 nil) :inherit nil) +          (w3m-bold (c nil nil) bf) +          (w3m-image (c 3)) +          (w3m-tab-background (c 12 5))) +  (:x-faces (button (c 10 nil) nbf) +            (gnus-button (c nil nil) nbf) +            (company-tooltip-common (c 1 6) nbf) +            (company-tooltip-common-selection (~ company-tooltip-selection) +                                              (c nil 6) bf) +            (company-tooltip-selection (~ company-tooltip) bf nul) +            (compilation-info (c nil nil) bf) +            (fringe (c 9 nil)) +            (gnus-summary-selected (c nil "white")) +            (header-line (~ mode-line-inactive) (c 14)) +            (mode-line (c 0 7) :box (:line-width -1 :color "grey60")) +            (mode-line-inactive (~ mode-line) (c 12)) +            (org-hide (c 7 nil)) +            (vertical-border (c 12 nil)) +            (w3m-image (c 3)) +            (w3m-tab-selected (c nil "white") nbf) +            (w3m-tab-selected-retrieving (~ w3m-tab-selected) (c 1)) +           (w3m-tab-background (c 7 7) nul)) +  (:x-colors "black" "sienna3" "#597B59" "#D38108" "#3B3152" +             "#E0DACC" "lightyellow3" +             "#EFEBE7" "grey20" "orangered4" "darkslategray" "#59513A" +             "lemonchiffon4" "#386858" "#223142" "#EFEBE7")) + +(provide 'jao-light-theme) + diff --git a/themes/jao-themes.el b/themes/jao-themes.el new file mode 100644 index 0000000..bcedc36 --- /dev/null +++ b/themes/jao-themes.el @@ -0,0 +1,682 @@ +;;; palette +(defvar jao-themes--face-family "Inconsolata") +(defvar jao-themes--fg "black") +(defvar jao-themes--bg "white") +(defvar jao-themes--box "grey75") +(defvar jao-themes--hilite nil) +(defvar jao-themes--italic '(it)) +(defvar jao-themes--button '(ul)) +(defvar jao-themes--strike-through '(:strike-through t)) +(defvar jao-themes--outline '((c "darkslategrey"))) +(defvar jao-themes--link '((c "darkgoldenrod4"))) +(defvar jao-themes--visited-link '((c "darkolivegreen4") nul)) +(defvar jao-themes--gnus-mail '(dfg)) +(defvar jao-themes--gnus-news '(dfg)) +(defvar jao-themes--tab-sel '((c nil "grey90") bx)) +(defvar jao-themes--tab-unsel '((c "grey30" "grey85") nbf bx)) +(defvar jao-themes--comment '((c "grey30"))) +(defvar jao-themes--warning '((c "indianred3") nbf)) +(defvar jao-themes--error '((c "indianred3") bf)) +(defvar jao-themes--constant '((c "darkolivegreen") nbf)) +(defvar jao-themes--function '((c "darkolivegreen") nbf)) +(defvar jao-themes--keyword '((c "darkslategrey") nbf)) +(defvar jao-themes--string '((c "skyblue4"))) +(defvar jao-themes--type '((c "darkslategrey"))) +(defvar jao-themes--variable-name '((c "DodgerBlue4"))) +(defvar jao-themes--dimm '((c "grey30") nbf)) +(defvar jao-themes--f00 '((c "dodgerblue4"))) +(defvar jao-themes--f01 '((c "cadetblue4"))) +(defvar jao-themes--f02 '((c "darkslategrey"))) +(defvar jao-themes--f10 '((c "dodgerblue4"))) +(defvar jao-themes--f11 '((c "cadetblue4"))) +(defvar jao-themes--f12 '((c "darkslategrey"))) + +(defsubst jao-themes--palette-face (face) +  (intern (format "jao-themes--%s" face))) + +(defun jao-themes--normalize-body (body) +  (dolist (p '(:inverse-video :underline :inherit) body) +    (unless (member p body) +      (setq body (append body (list p nil)))))) + +(defun jao-themes--parse-face-body (f) +  (cond ((null f) nil) +        ((listp f) +         (jao-themes--normalize-body +          (apply 'append (mapcar 'jao-themes--parse-face-sym f)))))) + +(defvar jao-themes--cidxs +  '("black" "red" "green" "yellow" "blue" "magenta" "cyan" "white" +    "brightblack" "brightred" "brightgreen" "brightyellow" "brightblue" +    "brightmagenta" "brightcyan" "brightwhite")) + +(defvar jao-themes--x-colors nil) + +(defun jao-themes--color (clr) +  (cond ((stringp clr) clr) +        ((numberp clr) (or (nth clr jao-themes--cidxs) +                           (format "color-%s" clr))) +        (t 'unspecified))) + +(defun jao-themes--parse-face-sym (s) +  (cond ((listp s) +         (case (car s) +           (c `(:foreground ,(jao-themes--color (cadr s)) +                            :background ,(jao-themes--color (caddr s)))) +           (p (let ((var (jao-themes--palette-face (cadr s)))) +                (when (boundp var) +                  (let ((val (symbol-value var))) +                    (if (listp val) +                        (jao-themes--parse-face-body val) +                      val))))) +           (~ (cdr (assq (cadr s) *jao--parsed-faces*))) +           (t (list s)))) +        ((atom s) +         (case s +           (~ '(:inherit)) +           (dbg `(:background ,jao-themes--bg)) +           (dfg `(:foreground ,jao-themes--fg)) +           (link (jao-themes--parse-face-body jao-themes--link)) +           (vlink (jao-themes--parse-face-body jao-themes--visited-link)) +           (bf '(:bold t :weight bold)) +           (nbf '(:bold t :weight normal)) +           (it '(:italic t :slant italic)) +           (nit '(:italic nil :slant normal)) +           (niv '(:inverse-video nil)) +           (ul '(:underline t)) +           (nul '(:underline nil)) +           (st '(:strike-through t)) +           (bx `(:box (:line-width -1 :color ,jao-themes--box))) +           (t (list s)))))) + +(defun jao-themes--make-faces (fs &optional cidxs) +  (let ((*jao--parsed-faces* nil) +        (jao-themes--cidxs (or cidxs jao-themes--cidxs)) +        (result nil)) +    (dolist (f (sort (jao-themes--dfs fs) 'jao--cmp-faces) (reverse result)) +      (let ((body (jao-themes--parse-face-body (cdr f)))) +        (push (cons (car f) body) *jao--parsed-faces*) +        (push (list (car f) body) result))))) + +(defun jao--cmp-faces (a b) +  (let ((ai (cadr (assq '~ a))) +        (bi (cadr (assq '~ b)))) +    (cond ((and ai (not bi)) nil) +          ((and bi (not ai)) t) +          ((eq (car a) bi) t) +          ((eq (car b) ai) nil) +          (t (string< (symbol-name (car a)) +                      (symbol-name (car b))))))) + +(defun jao-themes--dfs (fs) +  (let ((dfs +         (append +          `((bbdb-company) +            (bbdb-field-name bf) +            (bbdb-field-value nil) +            (bbdb-name ul) +            (bmk-mgr-bookmark-face nil) +            (bmk-mgr-folder-face bf) +            (bmk-mgr-sel-bookmark-face link) +            (bmk-mgr-sel-folder-face bf) +            (bold bf) +            (bold-italic bf) +            (border (c nil nil)) +            (buffer-menu-buffer bf) +            (button (p button))) +          `((calendar-holiday-marker (p f00)) +            (cursor (p error))) +          `((diredp-compressed-file-suffix (~ diredp-file-suffix)) +            (diredp-date-time (p f01)) +            (diredp-deletion (p error)) +            (diredp-deletion-file-name (~ diredp-deletion)) +            (diredp-dir-heading bf dfg dbg) +            (diredp-dir-priv dfg dbg bf) +            (diredp-display-msg (p f00)) +            (diredp-exec-priv dfg dbg bf) +            (diredp-executable-tag (p error)) +            (diredp-file-name dfg dbg) +            (diredp-file-suffix (~ diredp-file-name)) +            (diredp-flag-mark (p f00) bf) +            (diredp-flag-mark-line (p hilite)) +            (diredp-ignored-file-name (p dimm)) +            (diredp-link-priv (~ diredp-symlink)) +            (diredp-no-priv (~ diredp-read-priv)) +            (diredp-other-priv dfg dbg) +            (diredp-rare-priv dfg dfg) +            (diredp-read-priv dfg dbg bf) +            (diredp-symlink (p warning)) +            (diredp-write-priv dfg dbg bf)) +          `((change-log-acknowledgement (p f02)) +            (change-log-conditionals (p f02)) +            (change-log-date (p f01)) +            (change-log-email (p f00)) +            (change-log-file (p f10)) +            (change-log-function (p function)) +            (change-log-list (p f11)) +            (change-log-name (p keyword)) +            (comint-highlight-input (p f01) nbf) +            (comint-highlight-prompt (p f00)) +            (company-tooltip (~ highlight)) +            (company-tooltip-selection (~ company-tooltip) ul) +            (company-tooltip-common (~ company-tooltip) bf) +            (company-tooltip-common-selection +             (~ company-tooltip-selection) bf) +            (company-preview (~ highlight)) +            (company-preview-common (~ company-preview) bf) +            (compilation-column-number (p f00) nul) +            (compilation-error nbf (p error) nul) +            (compilation-info nbf (p f02) nul) +            (compilation-line-number (p f01) nul) +            (compilation-warning nbf (p warning) nul) +            (completions-common-part nbf :width normal) +            (completions-first-difference bf dfg dbg) +            (cursor dfg dbg) +            (custom-button (~ button)) +            (custom-button-mouse (~ button)) +            (custom-button-pressed (~ button)) +            (custom-button-pressed-unraised (~ button)) +            (custom-button-unraised (~ button)) +            (custom-changed (p warning)) +            (custom-comment (p string)) +            (custom-comment-tag (p keyword)) +            (custom-documentation (p string)) +            (custom-face-tag nbf) +            (custom-group-tag bf (p f00) :height 11) +            (custom-group-tag-1 bf :family ,jao-themes--face-family +                                (p f00) :height 11) +            (custom-invalid (p error)) +            (custom-link link) +            (custom-modified (p f10)) +            (custom-rogue (p error)) +            (custom-saved ul) +            (custom-set (p f11)) +            (custom-state (p f12)) +            (custom-themed (p f00)) +            (custom-variable-button (~ button)) +            (custom-variable-tag (p variable-name) bf) +            (cvs-handled (p dimm))) +          `((darcsum-change-line-face (p warning)) +            (darcsum-filename-face (p f00)) +            (darcsum-header-face (p f01)) +            (darcsum-marked-face (p f00) bf) +            (darcsum-need-action-face (p warning)) +            (darcsum-need-action-marked-face bf (p warning)) +            (diary (p f02)) +            (diff-added (p warning)) +            (diff-changed (p f02)) +            (diff-context (p dimm)) +            (diff-file-header dfg dbg nbf) +            (diff-function (p function)) +            (diff-header nbf dfg dbg) +            (diff-hunk-header (~ diff-file-header)) +            (diff-index bf dfg dbg) +            (diff-indicator-added (~ diff-added)) +            (diff-indicator-changed (~ diff-changed)) +            (diff-indicator-removed (~ diff-removed)) +            (diff-nonexistent bf (p error)) +            (diff-refine-change (~ diff-changed) ul) +            (diff-removed (p error)) +            (dired-directory (p f02)) +            (dired-flagged bf) +            (dired-header (p f01)) +            (dired-ignored (p dimm)) +            (dired-mark (p f00) bf) +            (dired-marked bf (p f00)) +            (dired-symlink (p f11)) +            (dired-warn-writable (p warning)) +            (dired-warning (p warning))) +          `((ediff-current-diff-A (~ diff-added)) +            (ediff-current-diff-Ancestor (c nil ,jao-themes--box)) +            (ediff-current-diff-B (~ ediff-current-diff-A)) +            (ediff-current-diff-C (~ ediff-current-diff-A)) +            (ediff-even-diff-A (~ diff-added) bf) +            (ediff-even-diff-Ancestor (c nil ,jao-themes--box)) +            (ediff-even-diff-B (~ ediff-even-diff-A)) +            (ediff-even-diff-C (~ ediff-even-diff-A)) +            (ediff-fine-diff-A (~ ediff-current-diff-A) nbf ul) +            (ediff-fine-diff-Ancestor (c nil ,jao-themes--box)) +            (ediff-fine-diff-B (~ ediff-fine-diff-A)) +            (ediff-fine-diff-C (~ ediff-fine-diff-A)) +            (ediff-odd-diff-A (~ ediff-even-diff-A)) +            (ediff-odd-diff-Ancestor (~ ediff-odd-diff-A) nbf) +            (ediff-odd-diff-B (~ ediff-odd-diff-A)) +            (ediff-odd-diff-C (~ ediff-odd-diff-A)) +            (emms-browser-album-face (p f00) :height 1.0) +            (emms-browser-artist-face (p f01) :height 1.0) +            (emms-browser-composer-face (p f02) :height 1.0) +            (emms-browser-track-face (p f10) :height 1.0) +            (emms-browser-year/genre-face (p f11) :height 1.0) +            (emms-metaplaylist-mode-current-face (p f00) bf) +            (emms-metaplaylist-mode-face (p f00)) +            (emms-playlist-selected-face (p f00) bf) +            (emms-playlist-track-face (p f00) nbf) +            (emms-stream-name-face (p f00)) +            (emms-stream-url-face link) +            (epa-field-body) +            (epa-field-name bf) +            (epa-mark bf (p f00)) +            (epa-string (p f01)) +            (epa-validity-disabled) +            (epa-validity-high bf) +            (epa-validity-low) +            (epa-validity-medium) +            (escape-glyph (p dimm)) +            (eshell-ls-archive (p f12)) +            (eshell-ls-backup (p dimm)) +            (eshell-ls-clutter (p dimm)) +            (eshell-ls-directory (p f02)) +            (eshell-ls-executable (p warning)) +            (eshell-ls-missing (p dimm)) +            (eshell-ls-product (p f01)) +            (eshell-ls-readonly (p f01) bf) +            (eshell-ls-special bf (p f10)) +            (eshell-ls-symlink bf (p f11)) +            (eshell-ls-unreadable (p dimm)) +            (eshell-prompt (p f00))) +          `((factor-font-lock-comment (~ font-lock-comment-face)) +            (factor-font-lock-constructor (~ font-lock-function-name-face)) +            (factor-font-lock-declaration (~ font-lock-type-face)) +            (factor-font-lock-getter-word (~ font-lock-function-name-face)) +            (factor-font-lock-parsing-word (~ font-lock-keyword-face)) +            (factor-font-lock-setter-word (~ font-lock-function-name-face)) +            (factor-font-lock-stack-effect (~ font-lock-comment-face)) +            (factor-font-lock-string (~ font-lock-string-face)) +            (factor-font-lock-symbol (~ font-lock-keyword-face)) +            (factor-font-lock-symbol-definition (~ font-lock-builtin-face)) +            (factor-font-lock-type-definition (~ font-lock-type-face)) +            (factor-font-lock-type-name (~ font-lock-type-face)) +            (factor-font-lock-vocabulary-name (~ font-lock-constant-face)) +            (factor-font-lock-word (~ font-lock-function-name-face)) +            (ffap) +            (file-name-shadow (p dimm)) +            (fixed-pitch :family ,jao-themes--face-family) +            (flyspell-duplicate nbf (p warning)) +            (flyspell-incorrect nbf (p error)) +            (font-lock-builtin-face (p keyword)) +            (font-lock-comment-delimiter-face (p comment)) +            (font-lock-comment-face (p comment)) +            (font-lock-constant-face (p constant)) +            (font-lock-doc-face (p comment)) +            (font-lock-function-name-face (p function)) +            (font-lock-keyword-face (p keyword)) +            (font-lock-negation-char-face nil) +            (font-lock-preprocessor-face (p constant)) +            (font-lock-regexp-grouping-backslash bf) +            (font-lock-regexp-grouping-construct bf) +            (font-lock-string-face (p string)) +            (font-lock-type-face (p type)) +            (font-lock-variable-name-face (p variable-name)) +            (font-lock-warning-face (p warning)) +            (fringe nil) +            (fuel-font-lock-debug-error (p error) nul) +            (fuel-font-lock-debug-info (p f01) nul) +            (fuel-font-lock-stack-region (p hilite)) +            (fuel-font-lock-xref-link link nul) +            (fuel-font-lock-xref-vocab italic nul) +            (fuel-font-lock-markup-link link) +            (fuel-font-lock-markup-title (~ outline-1)) +            (fuel-font-lock-markup-emphasis (~ italic)) +            (fuel-font-lock-markup-heading (~ outline-1)) +            (fuel-font-lock-markup-strong (~ bold))) +          `((geiser-font-lock-autodoc-current-arg (~ highlight)) +            (geiser-font-lock-autodoc-identifier +             (~ font-lock-function-name-face)) +            (geiser-font-lock-doc-button (~ button)) +            (geiser-font-lock-doc-link link) +            (geiser-font-lock-doc-title bf) +            (geiser-font-lock-xref-header bf) +            (geiser-font-lock-xref-link link nul) +            (gnus-button (~ button)) +            (gnus-cite-attribution nil) +            (gnus-cite-1 (p f10)) +            (gnus-cite-2 (p f11)) +            (gnus-cite-3 (p f12)) +            (gnus-cite-4 (p dimm)) +            (gnus-cite-5 (p dimm)) +            (gnus-cite-6 (p dimm)) +            (gnus-cite-7 (p dimm)) +            (gnus-cite-8 (p dimm)) +            (gnus-cite-9 (p dimm)) +            (gnus-cite-10 (p dimm)) +            (gnus-cite-11 (p dimm)) +            (gnus-emphasis-bold bf) +            (gnus-emphasis-bold-italic bf) +            (gnus-emphasis-highlight-words (p hilite)) +            (gnus-emphasis-italic nil) +            (gnus-emphasis-strikethru st) +            (gnus-emphasis-underline ul) +            (gnus-emphasis-underline-bold bf ul) +            (gnus-emphasis-underline-bold-italic bf ul) +            (gnus-emphasis-underline-italic ul) +            (gnus-group-mail-1 (p gnus-mail) bf) +            (gnus-group-mail-1-empty (p gnus-mail) nbf) +            (gnus-group-mail-2 (~ gnus-group-mail-1)) +            (gnus-group-mail-2-empty (~ gnus-group-mail-1-empty)) +            (gnus-group-mail-3 (~ gnus-group-mail-1)) +            (gnus-group-mail-3-empty (~ gnus-group-mail-1-empty)) +            (gnus-group-mail-4 (~ gnus-group-mail-1)) +            (gnus-group-mail-4-empty (~ gnus-group-mail-1-empty)) +            (gnus-group-mail-5 (p f00) bf) +            (gnus-group-mail-5-empty (p f00)) +            (gnus-group-mail-6 (p dimm) bf) +            (gnus-group-mail-6-empty (p dimm)) +            (gnus-group-mail-low bf (p dimm)) +            (gnus-group-mail-low-empty (p dimm)) +            (gnus-group-news-low bf (p dimm)) +            (gnus-group-news-low-empty (p dimm)) +            (gnus-group-news-1 (p gnus-news) bf) +            (gnus-group-news-1-empty (p gnus-news) nbf) +            (gnus-group-news-2 (~ gnus-group-news-1)) +            (gnus-group-news-2-empty (~ gnus-group-news-1-empty)) +            (gnus-group-news-3 (~ gnus-group-news-1)) +            (gnus-group-news-3-empty (~ gnus-group-news-1-empty)) +            (gnus-group-news-4 (~ gnus-group-news-1)) +            (gnus-group-news-4-empty (~ gnus-group-news-1-empty)) +            (gnus-group-news-5 (p f00) bf) +            (gnus-group-news-5-empty (p f00)) +            (gnus-group-news-6 (p dimm) bf) +            (gnus-group-news-6-empty (p dimm)) +            (gnus-header-content (p f02)) +            (gnus-header-from (p f01)) +            (gnus-header-name nbf (p f02)) +            (gnus-header-newsgroups (p dimm)) +            (gnus-header-subject (p f00) nbf) +            (gnus-mouse-face nil) +            (gnus-server-agent nbf) +            (gnus-server-closed (p warning)) +            (gnus-server-denied bf (p error)) +            (gnus-server-offline (p dimm)) +            (gnus-server-opened bf) +            (gnus-signature nit (p f10)) +            (gnus-splash dfg dbg) +            (gnus-summary-high-undownloaded bf nit dfg dbg) +            (gnus-summary-cancelled (p strike-through)) +            (gnus-summary-high-unread bf nit) +            (gnus-summary-normal-ancient (p dimm)) +            (gnus-summary-normal-read (p dimm)) +            (gnus-summary-high-ticked bf nit dfg dbg) +            (gnus-summary-low-ancient (p dimm)) +            (gnus-summary-low-read (p dimm) st) +            (gnus-summary-low-ticked (p dimm)) +            (gnus-summary-low-unread (p dimm)) +            (gnus-summary-low-undownloaded (p dimm)) +            (gnus-summary-normal-ancient (p dimm)) +            (gnus-summary-normal-read (p dimm)) +            (gnus-summary-normal-ticked (p f10) nbf) +            (gnus-summary-normal-undownloaded bf dfg dbg) +            (gnus-summary-normal-unread dfg dbg) +            (gnus-summary-selected (p hilite)) +            (gnus-x-face) +            (gui-button-face (~ button)) +            (gui-element (~ gui-button-face))) +          `((header-line (~ mode-line)) +            (help-argument-name) +            (highlight (p hilite))) +          `((ido-first-match (p warning)) +            (ido-incomplete-regexp (p error)) +            (ido-indicator (p error) nbf) +            (ido-only-match (p f00)) +            (ido-subdir (p f01)) +            (info-header-node bf dfg) +            (info-header-xref dfg) +            (info-menu-header bf) +            (info-menu-star bf dfg) +            (info-node (p f00)) +            (info-title-1 (~ outline-1) bf) +            (info-title-2 (~ outline-2) bf) +            (info-title-3 (~ outline-3) bf) +            (info-title-4 (~ outline-4) bf) +            (info-xref link) +            (info-xref-visited vlink) +            (isearch bf (p hilite)) +            (isearch-fail (p error)) +            (italic (p italic))) +          `((jabber-activity-face dbg dfg nbf) +            (jabber-activity-personal-face (p warning) nbf) +            (jabber-chat-error (p error)) +            (jabber-chat-prompt-foreign (p f00) nbf) +            (jabber-chat-prompt-local (p f01) nbf) +            (jabber-chat-prompt-system (p f02) nbf) +            (jabber-rare-time-face (p dimm)) +            (jabber-roster-user-away (p dimm)) +            (jabber-roster-user-chatty (p warning) nbf) +            (jabber-roster-user-offline (p dimm)) +            (jabber-roster-user-online (p f01) nbf) +            (jabber-roster-user-xa (p dimm)) +            (jabber-title-large (~ default) bf) +            (jabber-title-medium bf) +            (jabber-title-roster bf (p warning)) +            (jao-emms-font-lock-album (p f01)) +            (jao-emms-font-lock-artist (p f02)) +            (jao-emms-font-lock-title (p f01)) +            (jao-emms-font-lock-track dfg dbg) +            (jao-frm-from-face (p f00)) +            (jao-frm-mailbox-face bf) +            (jao-frm-subject-face (p f01)) +            (jao-frm-mailno-face bf) +            (jao-gnus-face-tree (p dimm)) +            (jde-java-font-lock-constant-face (~ font-lock-constant-face)) +            (jde-java-font-lock-doc-tag-face (p f02)) +            (jde-java-font-lock-package-face (p f02)) +            (jde-java-font-lock-link-face (p link)) +            (jde-java-font-lock-number-face (~ font-lock-constant-face)) +            (jde-java-font-lock-public-face (~ font-lock-keyword-face)) +            (jde-java-font-lock-private-face (~ font-lock-keyword-face)) +            (jde-java-font-lock-protected-face (~ font-lock-keyword-face)) +            (jde-java-font-lock-modifier-face (~ font-lock-keyword-face))) +          `((lazy-highlight (p hilite)) +            (link link nul) +            (link-visited vlink nul)) +          `((magit-diff-add (~ diff-added)) +            (magit-diff-del (~ diff-removed)) +            (magit-diff-file-header (~ diff-file-header)) +            (magit-diff-hunk-header (~ diff-hunk-header)) +            (magit-diff-none (p dimm)) +            (magit-item-highlight (p hilite)) +            (magit-item-mark (p warning)) +            (magit-log-head-label (p keyword) bf) +            (magit-log-tag-label (p keyword)) +            (match (p hilite)) +            (menu nil) +            (message-cited-text (p f01) nbf) +            (message-header-cc (p f00) nbf) +            (message-header-name (p f01) nbf) +            (message-header-newsgroups (p dimm) nbf) +            (message-header-other (p f00) nbf) +            (message-header-subject (p f00) nbf) +            (message-header-to (p f00) nbf) +            (message-header-xheader (p f00) nbf) +            (message-mml (p warning) nbf) +            (message-separator (p warning) nbf) +            (mm-uu-extract (p hilite)) +            (minibuffer-prompt (p f00)) +            (mode-line-buffer-id nbf (c nil nil)) +            (mode-line-emphasis (p warning)) +            (mode-line-highlight (~ mode-line)) +            (modeline-mousable (~ mode-line-active)) +            (modeline-mousable-minor-mode (~ modeline-mousable)) +            (mouse dfg dbg ul) +            (muse-link link) +            (muse-verbatim (p f02))) +          `((next-error (p hilite)) +            (nobreak-space dbg dfg ul)) +          `((org-agenda-date-weekend (p dimm)) +            (org-agenda-done (p dimm)) +            (org-agenda-restriction-lock (~ default)) +            (org-agenda-structure (p f00)) +            (org-archived (p dimm)) +            (org-code (p f02)) +            (org-column dfg dbg :height 1.0) +            (org-date (p f02) nul) +            (org-done (p dimm) nbf niv) +            (org-drawer (p f02)) +            (org-ellipsis (p dimm)) +            (org-formula (p f02)) +            (org-headline-done (p dimm)) +            (org-hide (c ,jao-themes--bg)) +            (org-latex-and-export-specials (~ default)) +            (org-level-1 (~ outline-1)) +            (org-level-2 (~ outline-2)) +            (org-level-3 (~ outline-3)) +            (org-level-4 (~ outline-4)) +            (org-level-5 (~ outline-5)) +            (org-level-6 (~ outline-6)) +            (org-level-7 (~ outline-7)) +            (org-level-8 (~ outline-8)) +            (org-link link) +            (org-property-value nil) +            (org-scheduled (p f01)) +            (org-scheduled-previously (p warning) nbf) +            (org-scheduled-today (p f00)) +            (org-sexp-date (p f01)) +            (org-special-keyword (p keyword)) +            (org-table (p f01)) +            (org-tag (p dimm) nbf) +            (org-target ul) +            (org-time-grid dfg dbg) +            (org-todo bf niv (p warning)) +            (org-upcoming-deadline (p f02)) +            (org-verbatim  (p hilite)) +            (org-warning bf (p warning)) +            (outline-1 bf (p outline)) +            (outline-2 bf (p outline)) +            (outline-3 nbf (p outline)) +            (outline-4 nbf (p outline)) +            (outline-5 nbf (p outline)) +            (outline-6 nbf (p outline)) +            (outline-7 nbf (p outline)) +            (outline-8 nbf (p outline))) +          `((query-replace bf (p hilite))) +          `((rcirc-bright-nick (p hilite)) +            (rcirc-my-nick (p error)) +            (rcirc-nick-in-message (p error)) +            (rcirc-nick-in-message-full-line nbf) +            (rcirc-other-nick (p keyword)) +            (rcirc-prompt bf) +            (rcirc-server (p dimm)) +            (rcirc-timestamp (p dimm)) +            (rcirc-track-nick (~ rcirc-my-nick) niv) +            (rcirc-url nbf link) +            (reb-match-0 (p hilite)) +            (reb-match-1 (~ secondary-selection)) +            (reb-match-2 (~ secondary-selection) bf) +            (reb-match-3 (~ secondary-selection) ul) +            (region (p hilite))) +          `((secondary-selection (p hilite)) +            (sh-quoted-exec (p f00)) +            (show-paren-match (p hilite)) +            (show-paren-mismatch (p error)) +            (slime-repl-prompt-face (p f00)) +            (slime-repl-input-face (p f00) bf) +            (slime-repl-inputed-output-face (p f02)) +            (slime-repl-output-face (p string)) +            (speedbar-directory-face (~ diredp-dir-heading)) +            (speedbar-file-face (~ diredp-file-name)) +            (speedbar-highlight-face (p hilite)) +            (speedbar-selected-face ul) +            (speedbar-separator-face (p f00)) +            (scroll-bar nil) +            (shadow nil)) +          `((tool-bar nil) +            (tooltip :family ,jao-themes--face-family (c nil "lightyellow")) +            (trailing-whitespace (p error))) +          `((underline nul)) +          `((variable-pitch :family ,jao-themes--face-family :height 11) +            (vertical-border (c ,jao-themes--box nil) :inherit default)) +          `((w3m-anchor link) +            (w3m-arrived-anchor vlink) +            (w3m-bold bf dbg dfg) +            (w3m-current-anchor nbf ul) +            (w3m-form dfg dbg ul) +            (w3m-form-button (~ button)) +            (w3m-form-button-mouse (~ custom-button-mouse)) +            (w3m-form-button-pressed (~ custom-button-pressed)) +            (w3m-header-line-location-content +             :box (:line-width 3 :color ,jao-themes--bg) dfg dbg) +            (w3m-header-line-location-title +             :box (:line-width 3 :color ,jao-themes--bg) dfg dbg) +            (w3m-history-current-url (c nil nil) ul) +            (w3m-image (p f10)) +            (w3m-image-anchor (c nil nil)) +            (w3m-insert (p f12)) +            (w3m-italic (~ italic)) +            (w3m-linknum-match (p warning)) +            (w3m-linknum-minibuffer-prompt (~ minibuffer-prompt)) +            (w3m-session-select (p f10)) +            (w3m-session-selected bf nul (p f10)) +            (w3m-strike-through st) +            (w3m-tab-background nul (c nil nil)) +            (w3m-tab-mouse nil) +            (w3m-tab-selected (p tab-sel)) +            (w3m-tab-selected-background nil) +            (w3m-tab-selected-retrieving (p tab-sel) it) +            (w3m-tab-unselected (p tab-unsel)) +            (w3m-tab-unselected-retrieving (p tab-unsel) it) +            (w3m-tab-unselected-unseen (p tab-unsel)) +            (w3m-underline ul) +            (widget-button (~ button)) +            (widget-button-pressed nbf (~ custom-button-pressed)) +            (widget-button-face (~ button)) +            (widget-button-pressed-face (~ button)) +            (widget-documentation (p dimm)) +            (widget-field (p hilite) bx) +            (widget-inactive (p dimm)) +            (Widget-single-line-field (~ widget-field)) +            (woman-bold (p f00) bf) +            (woman-italic (p f01) nul nit) +            (woman-italic-no-ul (p f01) nul nit))))) +    (dolist (df dfs fs) +      (when (not (assq (car df) fs)) +        (push df fs))))) + +(defsubst jao-themes--let-palette (palette xp) +  (mapcar (lambda (f) +            `(,(jao-themes--palette-face (car f)) +              ',(or (and xp (caddr f)) (cadr f)))) +          palette)) + +(defun jao-themes--extract-faces (t-faces x-faces) +  (let ((result)) +    (dolist (f t-faces (reverse result)) +      (let ((xfb (cdr (assq (car f) x-faces)))) +        (push `(,(car f) ((((type x darwin)) ,@xfb) +                          (t ,@(cdr f)))) result))))) + +(defun jao-themes--set-fbg (kind) +  (let* ((kvs (cdr (assoc kind window-system-default-frame-alist))) +         (f-alist (assq-delete-all 'background-color kvs)) +         (f-alist (assq-delete-all 'foreground-color f-alist))) +    (when jao-themes--fg +      (push (cons 'foreground-color jao-themes--fg) f-alist)) +    (when jao-themes--bg +      (push (cons 'background-color jao-themes--bg) f-alist)) +    (setq window-system-default-frame-alist +          (cons +           (cons kind f-alist) +           (assq-delete-all kind window-system-default-frame-alist))))) + +(defmacro jao-define-custom-theme (name &rest args) +  (let ((t-faces (make-symbol "t-faces")) +        (xfaces (make-symbol "xfaces")) +        (tx-faces (make-symbol "tx-faces")) +        (palette (cdr (assoc :palette args))) +        (faces (cdr (assoc :faces args))) +        (x-faces (cdr (assoc :x-faces args))) +        (x-colors (cdr (assoc :x-colors args)))) +    `(let* ,(jao-themes--let-palette palette nil) +       (jao-themes--set-fbg nil) +       (let ((,t-faces (jao-themes--make-faces ',faces))) +         (let* ,(jao-themes--let-palette palette t) +           (jao-themes--set-fbg 'x) +           (let* ((,xfaces (jao-themes--make-faces ',x-faces ',x-colors)) +                  (,tx-faces (jao-themes--extract-faces ,t-faces ,xfaces))) +             (deftheme ,name) +             (put ',name 'theme-immediate t) +             (apply 'custom-theme-set-faces (cons ',name ,tx-faces)) +             (provide-theme ',name))))))) + +(put 'jao-define-custom-theme 'lisp-indent-function 1) + + +(provide 'jao-themes) diff --git a/themes/light-ec b/themes/light-ec new file mode 100755 index 0000000..bde38f9 --- /dev/null +++ b/themes/light-ec @@ -0,0 +1,40 @@ +#!/bin/bash + +font=${EC_TERM_FACE:-xft:Inconsolata:size=11,[codeset=iso8859-7]xft:Andale Mono:size=12,[codeset=japanese-jisx0208]xft:Andale Mono:size=12} +ifont=${EC_TERM_FACE_ITALIC:-xft:Inconsolata-11:slant=italic} +#font="xft:DejaVu Sans Mono-9" +#ifont="xft:DejaVu Sans Mono-9:italic" + +frg="black" +bkg="#EFEBE7" + +bw=${EC_TERM_BORDER:-2} +tr=${EC_TRANS_SPEC} + +exec urxvtcd $tr -cr tomato +ptab -bg "$bkg" -bd "$bkg" -fg "$frg" \ +             -sl 0 +rv +ssr -b $bw +sbg -fn "${font}" -fi "${ifont}" \ +             -xrm "*colorBD: grey20" \ +             -xrm "*colorUL: grey20" \ +             -xrm "*color0: ${frg}" \ +             -xrm "*color8: grey20" \ +             -xrm "*color1: sienna3" \ +             -xrm "*color9: orangered4" \ +             -xrm "*color2: #597B59" \ +             -xrm "*color10: #254242" \ +             -xrm "*color3: #D38108" \ +             -xrm "*color11: #59513A" \ +             -xrm "*color4: #3B3152" \ +             -xrm "*color12: lemonchiffon4" \ +             -xrm "*color5: #E0DACC" \ +             -xrm "*color13: #386858" \ +             -xrm "*color6: lightyellow3" \ +             -xrm "*color14: #1F3D4F" \ +             -xrm "*color7: ${bkg}" \ +             -xrm "*color15: #EFEBE7" \ +             -name "emacsclient" \ +             -e emacsclient -t $* + +# fname=${EC_XTERM_FN:-Inconsolata} +# fsize=${EC_XTERM_FS:-11} +# exec xterm -cr tomato -sl 0 +rv -b "$bw" -bg "$bkg" -bd "$bkg" -fg "$frg" \ +#            -bdc -ulc -u8 -fa "$fname" -fs $fsize \ | 
