summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuo Jinghua <sunmoon1997@gmail.com>2010-01-03 19:58:20 +0800
committerLuo Jinghua <sunmoon1997@gmail.com>2010-01-03 19:58:20 +0800
commitbd43daeed39aff3f6d64252ef2d32083f9d52c96 (patch)
treea8c683cedee463d030030beff29e4075beeee46f
Initial commit of my emacs configuration
-rw-r--r--emacs332
-rw-r--r--emacs.d/lisp/emacs-wiki.el333
-rw-r--r--emacs.d/lisp/erc-tab.el269
-rw-r--r--emacs.d/lisp/guess-offset.el382
-rw-r--r--emacs.d/lisp/tabbar.el1336
5 files changed, 2652 insertions, 0 deletions
diff --git a/emacs b/emacs
new file mode 100644
index 0000000..b23572f
--- /dev/null
+++ b/emacs
@@ -0,0 +1,332 @@
+(set-default-font "Bitstream Vera Sans Mono-9")
+(set-fontset-font (frame-parameter nil 'font)
+ 'han '("Microsoft YaHei" . "unicode-bmp"))
+
+(setq inhibit-startup-message t)
+(setq ecb-auto-activate t)
+(setq semantic-load-turn-useful-things-on t)
+
+(load "/usr/share/emacs/site-lisp/site-gentoo")
+
+;;(setq-default make-backup-files nil)
+(require 'ecb)
+
+(require 'color-theme)
+(color-theme-initialize)
+(color-theme-bharadwaj-slate)
+
+;;color terminal
+(require 'ansi-color)
+(add-hook 'shell-mode-hook 'ansi-color-for-comint-mode-on)
+
+(fset 'yes-or-no-p 'y-or-n-p)
+
+(transient-mark-mode t)
+
+(add-hook 'find-file-hooks 'auto-insert)
+
+(show-paren-mode t)
+
+;;(setq lazy-lock-defer-on-scrolling t)
+;;(setq font-lock-support-mode 'lazy-lock-mode)
+;;(setq font-lock-maximum-decoration t)
+
+(global-set-key [f5] 'ecb-activate)
+(global-set-key [f6] 'ecb-deactivate)
+(global-set-key [f9] 'compile)
+(global-set-key [f12] 'gdb)
+
+(add-to-list 'load-path "~/.emacs.d/session")
+(add-to-list 'load-path "~/.emacs.d/lisp")
+(require 'session)
+(add-hook 'after-init-hook 'session-initialize)
+
+;;----------------------------------------------------------------------------
+(setq tab-width 4)
+;;(setq c-basic-offset 4)
+;;(setq c-hanging-comment-ender-p nil)
+;;(setq-default indent-tabs-mode nil)
+
+;; define a new indentation style
+(require 'cc-styles)
+(add-to-list 'c-style-alist
+ '("ljh"
+ (indent-tabs-mode nil)
+ (c-basic-offset . 4)
+ (c-comment-only-line-offset . 0)
+ (c-offsets-alist . ((statement-block-intro . +)
+ (knr-argdecl-intro . 0)
+ (substatement-open . 0)
+ (substatement-label . 0)
+ (label . 1)
+ (statement-cont . +)
+ (arglist-intro . c-lineup-arglist-intro-after-paren)
+ (arglist-close . c-lineup-arglist)
+ ))
+ )
+ )
+
+(add-to-list 'c-style-alist
+ '("tables"
+ (c-basic-offset . 8)
+ (c-comment-only-line-offset . 0)
+ (c-offsets-alist . ((statement-block-intro . +)
+ (knr-argdecl-intro . 0)
+ (substatement-open . 0)
+ (substatement-label . 0)
+ (label . 1)
+ (statement-cont . +)
+ (arglist-intro . c-lineup-arglist-intro-after-paren)
+ (arglist-close . c-lineup-arglist)
+ ))
+ )
+ )
+
+(add-hook 'c-mode-common-hook
+ (function
+ (lambda ()
+ ;; (c-set-style "ljh")
+ (hl-line-mode t)
+ )))
+(add-hook 'c++-mode-hook
+ (function
+ (lambda ()
+ (c-set-style "ljh")
+ (hl-line-mode t)
+ )))
+
+(add-hook 'python-mode-hook
+ (function
+ (lambda ()
+ (hl-line-mode t)
+ )))
+
+(defun gstreamer-c-mode ()
+ "C mode with adjusted defaults for use with GStreamer."
+ (interactive)
+ (c-mode)
+ (c-set-style "K&R")
+ (setq c-basic-offset 2))
+
+(setq auto-mode-alist (cons '("gst.*/.*\\.[ch]$" . gstreamer-c-mode)
+ auto-mode-alist))
+
+(defun ljh-c-mode ()
+ "C mode with adjusted defaults for myself."
+ (interactive)
+ (c-mode)
+ (c-set-style "ljh"))
+(setq auto-mode-alist (cons '("milkway.*/.*\\.[ch]$" . ljh-c-mode)
+ auto-mode-alist))
+
+(setq auto-mode-alist (cons '("openpps.*/.*\\.[ch]$" . ljh-c-mode)
+ auto-mode-alist))
+
+(require 'semanticdb)
+;;(global-semanticdb-minor-mode 1)
+(require 'semantic-ia)
+(global-set-key [(control p)] 'semantic-ia-complete-symbol-menu)
+;;# semantic-ia-complete-symbol
+;;# semantic-ia-complete-symbol-menu
+;;# semantic-ia-complete-tip
+
+(load-file "~/.emacs.d/lisp/tabbar.el")
+(require 'tabbar)
+(tabbar-mode)
+(global-set-key [(s-down)] 'tabbar-backward-group);;
+(global-set-key [(s-up)] 'tabbar-forward-group)
+(global-set-key (kbd "s-b") 'tabbar-backward);;
+(global-set-key (kbd "s-f") 'tabbar-forward)
+
+;;M-x desktop-clear
+;;(load "desktop")
+;;(desktop-save-mode)
+;;(desktop-read)
+;;(global-set-key [f11] 'desktop-save)
+
+;;(global-semantic-show-dirty-mode -1)
+(global-semantic-show-unmatched-syntax-mode -1)
+(require 'semantic-load)
+;;(global-semantic-idle-completions-mode 1)
+
+;;(load "xrefactory")
+
+(require 'doxymacs)
+(add-hook 'c-mode-common-hook 'doxymacs-mode)
+
+;;auto-complete
+(require 'auto-complete)
+(require 'auto-complete-config)
+(require 'yasnippet)
+
+(add-to-list 'auto-mode-alist '("SConstruct" . python-mode))
+(add-to-list 'auto-mode-alist '("SConscript" . python-mode))
+(add-to-list 'interpreter-mode-alist '("python" . python-mode))
+
+(global-auto-complete-mode t)
+(setq ac-auto-start 2)
+
+(define-key ac-complete-mode-map "\t" 'ac-expand)
+(define-key ac-complete-mode-map "\r" 'ac-complete)
+(define-key ac-complete-mode-map (kbd "M-j") 'ac-complete)
+(define-key ac-complete-mode-map (kbd "M-n") 'ac-next)
+(define-key ac-complete-mode-map (kbd "M-p") 'ac-previous)
+
+(setq ac-dwim t)
+(setq ac-candidate-menu-height 20)
+(setq ac-candidate-max ac-candidate-menu-height)
+
+(set-default 'ac-sources
+ '(ac-source-semantic
+ ac-source-yasnippet
+ ac-source-abbrev
+ ac-source-words-in-buffer
+ ac-source-words-in-all-buffer
+ ac-source-imenu
+ ac-source-files-in-current-dir
+ ac-source-filename))
+;;(setq ac-modes ac+-modes)
+
+(setq ac-trigger-commands '(self-insert-command autopair-insert-or-skip-quote))
+
+(defun ac-settings-4-lisp ()
+ "Auto complete settings for lisp mode."
+ (setq ac-omni-completion-sources '(("require\s+'" ac-source-emacs-lisp-features)
+ ("load\s+\"" ac-source-emacs-lisp-features)))
+ (setq ac-sources
+ '(ac-source-yasnippet
+ ac-source-symbols
+ ac-source-semantic
+ ac-source-abbrev
+ ac-source-words-in-buffer
+ ac-source-words-in-all-buffer
+ ac-source-imenu
+ ac-source-files-in-current-dir
+ ac-source-filename)))
+
+(defun ac-settings-4-java ()
+ (setq ac-omni-completion-sources (list (cons "\\." '(ac-source-semantic))
+ (cons "->" '(ac-source-semantic))))
+ (setq ac-sources
+ '(ac-source-semantic
+ ac-source-yasnippet
+ ac-source-abbrev
+ ac-source-words-in-buffer
+ ac-source-words-in-all-buffer
+ ac-source-files-in-current-dir
+ ac-source-filename)))
+
+(defun ac-settings-4-c ()
+ (setq ac-omni-completion-sources (list (cons "\\." '(ac-source-semantic))
+ (cons "->" '(ac-source-semantic))))
+ (setq ac-sources
+ '(ac-source-semantic
+ ac-source-yasnippet
+ ac-source-c-keywords
+ ac-source-abbrev
+ ac-source-words-in-buffer
+ ac-source-words-in-all-buffer
+ ac-source-files-in-current-dir
+ ac-source-filename)))
+
+(defun ac-settings-4-cpp ()
+ (setq ac-omni-completion-sources
+ (list (cons "\\." '(ac-source-semantic))
+ (cons "->" '(ac-source-semantic))))
+ (setq ac-sources
+ '(ac-source-semantic
+ ac-source-yasnippet
+ ac-source-c++-keywords
+ ac-source-abbrev
+ ac-source-words-in-buffer
+ ac-source-words-in-all-buffer
+ ac-source-files-in-current-dir
+ ac-source-filename)))
+
+(defun ac-settings-4-python ()
+ (setq ac-omni-completion-sources
+ '(("\\." ac-source-ropemacs)))
+ (setq ac-sources
+ '(ac-source-semantic
+ ac-source-yasnippet
+ ac-source-abbrev
+ ac-source-words-in-buffer
+ ac-source-words-in-all-buffer
+ ac-source-files-in-current-dir
+ ac-source-filename)))
+
+(defun ac-settings-4-text ()
+ (setq ac-sources
+ '(;;ac-source-semantic
+ ac-source-yasnippet
+ ac-source-abbrev
+ ac-source-words-in-buffer
+ ac-source-words-in-all-buffer
+ ac-source-imenu)))
+
+(defun ac-settings-4-eshell ()
+ (setq ac-sources
+ '(;;ac-source-semantic
+ ac-source-yasnippet
+ ac-source-abbrev
+ ac-source-words-in-buffer
+ ac-source-words-in-all-buffer
+ ac-source-files-in-current-dir
+ ac-source-filename
+ ac-source-symbols
+ ac-source-imenu)))
+
+(defun ac-settings-4-ruby ()
+ (setq ac-omni-completion-sources
+ (list (cons "\\." '(ac-source-rcodetools))
+ (cons "::" '(ac-source-rcodetools)))))
+
+(defun ac-settings-4-html ()
+ (setq ac-sources
+ '(ac-source-semantic
+ ac-source-yasnippet
+ ac-source-abbrev
+ ac-source-words-in-buffer
+ ac-source-words-in-all-buffer
+ ac-source-files-in-current-dir
+ ac-source-filename)))
+
+(dolist (hook (list 'lisp-mode-hook 'emacs-lisp-mode-hook 'lisp-interaction-mode-hook
+ 'svn-log-edit-mode))
+ (add-hook hook 'ac-settings-4-lisp))
+
+(add-hook 'java-mode-hook 'ac-settings-4-java)
+(add-hook 'c-mode-hook 'ac-settings-4-c)
+(add-hook 'c++-mode-hook 'ac-settings-4-cpp)
+(add-hook 'python-mode-hook 'ac-settings-4-python)
+(add-hook 'text-mode-hook 'ac-settings-4-text)
+(add-hook 'eshell-mode-hook 'ac-settings-4-eshell)
+(add-hook 'html-mode-hook 'ac-settings-4-html)
+
+;;(dolist (mode ac-modes)
+;; (let ((mode-name (symbol-name mode)))
+;; (when (and (intern-soft mode-name) (intern-soft (concat mode-name "-map")))
+;; (define-key (symbol-value (concat-name mode-name "-map")) (kbd "C-c a") 'ac-start))))
+
+(custom-set-variables
+ ;; custom-set-variables was added by Custom.
+ ;; If you edit it by hand, you could mess it up, so be careful.
+ ;; Your init file should contain only one such instance.
+ ;; If there is more than one, they won't work right.
+ '(column-number-mode t)
+ '(display-time-mode t)
+ '(ecb-options-version "2.40")
+ '(ecb-source-path (quote (("/" "/") ("~/Projects" "Projects"))))
+ '(scroll-bar-mode (quote right))
+ '(show-paren-mode t)
+ '(show-trailing-whitespace t)
+ '(size-indication-mode t)
+ '(transient-mark-mode t)
+(custom-set-faces
+ ;; custom-set-faces was added by Custom.
+ ;; If you edit it by hand, you could mess it up, so be careful.
+ ;; Your init file should contain only one such instance.
+ ;; If there is more than one, they won't work right.
+ )
+
+(put 'narrow-to-region 'disabled nil)
diff --git a/emacs.d/lisp/emacs-wiki.el b/emacs.d/lisp/emacs-wiki.el
new file mode 100644
index 0000000..d11d0b4
--- /dev/null
+++ b/emacs.d/lisp/emacs-wiki.el
@@ -0,0 +1,333 @@
+;;;;;;;;;;;;;;;;;;;;;;;;;;; -*- Mode: Emacs-Lisp -*- ;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; .emacs-wiki.el ---
+;;
+;; Filename: .emacs-wiki.el
+;; Description: emacs-wiki配置模板
+;; Author: 李代斌
+;; Maintainer: 李代斌
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; ====================
+;; Emacs Wiki配置模板说明
+;; ====================
+;;
+;; 这是一个Emacs-wiki的配置文件模板,它的作用是
+;;
+;; - 集中常用的Emacs-wiki的配置选项在一个文件中
+;; - 为新手提供一个入门指南
+;; - 做为中文FAQ的补充,让大家可以少敲几个字:^)
+;; - 针对中文Emacs用户解决一个中文的问题
+;;
+;; 这个模板的制作原因是出于对Emacs-wiki这个基于[[Emacs]]的Wiki系统喜爱
+;; ,希望你也喜欢它,也欢迎你帮助我完善这个模板。
+;;
+;; =============
+;; 下载、安装和使用
+;; =============
+;;
+;; * 下载
+;;
+;; 地址 http://lidaibin.kmip.net/gentoo/conf/emacs-wiki.el
+;;
+;; 模板以一个el文件形式(文件名emacs-wiki.el)提供下载,在遵守GNU
+;; Public License的原则下分发。
+;;
+;; * 安装
+;;
+;; 请将下载得到的文件置于硬盘某处(推荐放置在HOME文件夹,也就是.emacs的
+;; 同一个目录,并更名为.emacs-wiki.el),在你的.emacs中加入如下一行
+;;
+;; (load-file "path/to/.emacs-wiki.el")
+;;
+;; 请将"path/to/"改成相应的路径(放置于HOME文件夹即为"~/")。然后用最顺
+;; 手的编辑器进入文件修改,仔细阅读其中的注释项,并且按照指示修改适应你
+;; 的情况,然后保存。重新启动Emacs即可以开始使用Emacs-wiki。
+;;
+;; * 使用
+;;
+;; Emacs-wiki配置模板中的各项配置使用请参照模板中注释说明,或者参考
+;; Emacs-wiki自带的文档、EmacsWikiNode、Emacs-wiki中文FAQ等资源。
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; * 基本设置 *
+;;
+;; 都是Emacs-wiki的基本设置,请按照注释修改
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; 主程序,必须包含进来,Gentoo下不需要配置这行,已加入/usr/share/emacs/site-lisp/site-gentoo.el
+;;(require 'emacs-wiki)
+
+;; 设置Wiki页面存储的目录,Wiki的源文件将存储至此
+;;(setq emacs-wiki-directories '("~/Wiki/webpage"))
+;; 设置publish的目录,生成的HTML页面将存储至此
+;;(setq emacs-wiki-publishing-directory "~/publish/webpage")
+
+;; 设置存储源文件使用的默认的文字编码,使用GB2312环境的可以将值更改为gb2312
+(setq emacs-wiki-coding-default "gbk")
+;; 设置发布HTML页面使用的charset(字符集),使用GB2312环境的可以将值更改为gb2312
+(setq emacs-wiki-charset-default "gbk")
+
+;; 设置你的mail地址,它将做为不存在页面的默认链接地址
+(setq emacs-wiki-maintainer "mailto:lidaibin@gmail.com")
+
+;; 更改默认页面的名字(一般不用更改)
+;;(setq emacs-wiki-default-page "WelcomePage")
+;; 更改默认索引页面的名字(一般不用更改)
+;;(setq emacs-wiki-index-page "WikiIndex")
+
+;; 启用changelog美化支持,为真时会将changelog也当作Wiki页面发布
+;;(setq emacs-wiki-pretty-changelogs t)
+
+;; 设置inline图片的查找路径,Emacs-wiki会在指定目录的根目录和images目录中查找
+;;(setq emacs-wiki-inline-relative-to 'emacs-wiki-publishing-directory)
+
+;; 定义一个变量emacs-wiki-style-sheet,用于在页眉中指定CSS
+(setq emacs-wiki-style-sheet
+ "<link rel=\"stylesheet\" type=\"text/css\" href=\"../css/main.css\">")
+
+;; 定义页眉页脚放置于文件中,如果文件未找到则插入默认的页眉页脚
+(setq emacs-wiki-publishing-header "<lisp>(my-publishing-header)</lisp>")
+(setq emacs-wiki-publishing-footer "<lisp>(my-publishing-footer)</lisp>")
+
+(defun my-publishing-header ()
+ (if (file-readable-p "header.wiki")
+ (ignore (insert-file-contents "header.wiki"))
+ ;;这里是默认的页眉
+ "<?xml version=\"1.0\"?>
+<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"xhtml11.dtd\">
+<html xmlns=\"http://www.w3.org/1999/xhtml\">
+ <head>
+ <title><lisp>(emacs-wiki-page-title)</lisp></title>
+ <meta name=\"generator\" content=\"emacs-wiki.el\" />
+ <meta http-equiv=\"<lisp>emacs-wiki-meta-http-equiv</lisp>\"
+ content=\"<lisp>emacs-wiki-meta-content</lisp>\" />
+ <link rev=\"made\" href=\"<lisp>emacs-wiki-maintainer</lisp>\" />
+ <link rel=\"home\" href=\"<lisp>(emacs-wiki-published-name
+ emacs-wiki-home-page)</lisp>\" />
+ <link rel=\"index\" href=\"<lisp>(emacs-wiki-published-name
+ emacs-wiki-index-page)</lisp>\" />
+ <lisp>emacs-wiki-style-sheet</lisp>
+ </head>
+ <body>
+
+ <!-- If you want a menu, uncomment the following lines and
+ put (require 'emacs-wiki-menu) in your Emacs setup somewhere.
+
+ <lisp>(when (boundp 'emacs-wiki-menu-factory)
+ (funcall emacs-wiki-menu-factory))</lisp>
+ -->
+
+ <h1 id=\"top\"><lisp>(emacs-wiki-page-title)</lisp></h1>
+ <hr />
+
+ <!-- Page published by Emacs Wiki begins here -->\n"
+ ))
+
+(defun my-publishing-footer ()
+ (if (file-readable-p "footer.wiki")
+ (ignore (insert-file-contents "footer.wiki"))
+ ;;这里是默认的页脚
+ "
+ <!-- Page published by Emacs Wiki ends here -->
+ <div class=\"navfoot\">
+ <hr />
+ <table width=\"100%\" border=\"0\" summary=\"Footer navigation\">
+ <col width=\"33%\"/><col width=\"34%\"/><col width=\"33%\"/>
+ <tr>
+ <td align=\"left\">
+ <lisp>
+ (if buffer-file-name
+ (concat
+ \"<span class=\\\"footdate\\\">最近更新: \"
+ (format-time-string emacs-wiki-footer-date-format
+ (nth 5 (file-attributes buffer-file-name)))
+ (and emacs-wiki-serving-p
+ (emacs-wiki-editable-p (emacs-wiki-page-name))
+ (concat
+ \" / \"
+ (emacs-wiki-link-href
+ (concat \"editwiki?\" (emacs-wiki-page-name))
+ \"Edit\")))
+ \"</span>\"))
+ </lisp>
+ </td>
+ <td align=\"center\">
+ <span class=\"foothome\">
+ <a href=\"../index.html\">主页</a> /
+ <lisp>
+ (concat
+ (and (emacs-wiki-page-file emacs-wiki-home-page t)
+ (not (emacs-wiki-private-p emacs-wiki-home-page))
+ (concat
+ (emacs-wiki-link-href emacs-wiki-home-page \"Wiki主页\")
+ \" / \"))
+ (emacs-wiki-link-href emacs-wiki-index-page \"索引\")
+ (and (emacs-wiki-page-file \"ChangeLog\" t)
+ (not (emacs-wiki-private-p \"ChangeLog\"))
+ (concat
+ \" / \"
+ (emacs-wiki-link-href \"ChangeLog\" \"Changes\"))))
+ </lisp>
+ </span>
+ </td>
+ <td align=\"right\">
+ <lisp>
+ (if emacs-wiki-serving-p
+ (concat
+ \"<span class=\\\"footfeed\\\">\"
+ (emacs-wiki-link-href \"searchwiki?get\" \"搜索\")
+ (and buffer-file-name
+ (concat
+ \" / \"
+ (emacs-wiki-link-href
+ (concat \"searchwiki?q=\" (emacs-wiki-page-name))
+ \"Referrers\")))
+ \"</span>\"))
+ </lisp>
+ </td>
+ </tr>
+ </table>
+ </div>
+ </body>
+</html>\n"
+ ))
+
+;; 自定义函数emacs-wiki-preview-source,快速查看publish的HTML代码
+(defun emacs-wiki-preview-source ()
+ (interactive)
+ (emacs-wiki-publish-this-page)
+ (find-file (emacs-wiki-published-file)))
+
+;; 自定义函数emacs-wiki-preview-html,快速本地预览生成的HTML
+(defun emacs-wiki-preview-html ()
+ (interactive)
+ (emacs-wiki-publish-this-page)
+ (browse-url (emacs-wiki-published-file)))
+
+;; 自定义函数emacs-wiki-unline-toggle,用于自动对WikiName添加/删除<nop>标记
+;;{{{ copy from yason@emacswiki, modified by Yu Li
+(defun emacs-wiki-unlink-toggle ()
+ "Toggle <nop> string in the beginning of the current word, to
+un/make a word emacs-wiki link. The current word depends on the
+point: if the cursor is on a non-whitespace character, it's
+considered a word surrounded by whitespace. If the cursor is on a
+whitespace character, the next word is looked up. This way
+addressing a word works intuitively after having arrived on the
+spot using forward-word."
+ (interactive)
+ (save-excursion
+ (with-current-buffer (current-buffer)
+ (if (looking-at "[ \t]")
+ (goto-char (- (re-search-forward "[A-Za-z<>]") 1))
+ (goto-char (+ (re-search-backward "[^A-za-z<>]") 1)))
+ (if (looking-at "<nop>")
+ (delete-char 5)
+ (insert "<nop>")))))
+;;}}}
+
+;; 绑定自定义函数到相应的键位组合
+(add-hook 'emacs-wiki-mode-hook
+ (lambda ()
+ (define-key emacs-wiki-mode-map (kbd "C-c C-h") 'emacs-wiki-preview-html)
+ (define-key emacs-wiki-mode-map (kbd "C-c C-c") 'emacs-wiki-preview-source)
+ (define-key emacs-wiki-mode-map (kbd "C-c C-v") 'emacs-wiki-change-project)
+ (define-key emacs-wiki-mode-map (kbd "C-c C-n") 'emacs-wiki-unlink-toggle)
+ ))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; * Emacs-wiki多个project的设置 *
+;;
+;; 多个project设置,你可以用这种方式来组织你的网站的不同topic
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(setq emacs-wiki-projects
+ `(("linux" .
+ ((emacs-wiki-directories . ("~/Wiki/linux"))
+ (emacs-wiki-project-server-prefix . "../linux/")
+ (emacs-wiki-publishing-directory . "/data/myweb/public_html/linux")))
+ ("programming" .
+ ((emacs-wiki-directories . ("~/Wiki/programming"))
+ (emacs-wiki-project-server-prefix . "../programming/")
+ (emacs-wiki-publishing-directory . "/data/myweb/public_html/programming")))
+;; 你可以添加新的project,如下是一个例子
+;; ("Project" .
+;; ((emacs-wiki-directories . ("~/Wiki/project"))
+;; (emacs-wiki-project-server-prefix . "../project/")
+;; (emacs-wiki-publishing-directory . "/data/myweb/public_html/project")))
+ ))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; * 其它 *
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; 加入对Emacs可视化表格编辑模块table.el的支持
+;; 请参考Emacs-wiki文档Tables一节以及contrib目录中table.el
+(require 'emacs-wiki-table)
+
+;; 加入自动生成menu的支持,具体配置请看后面的emacs-wiki-menu配置部分
+(require 'emacs-wiki-menu)
+
+;; 启动faq-mode支持,一个编辑faq页面的minor mode
+;;(require 'faq-mode)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; * Hack *
+;;
+;; 一些Hack函数,更改一些东西,解决一些问题
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+
+;; 解决Emacs-wiki当前存在的与mule-gbk不兼容的问题
+;; 问题:遇到GBK字符时会将其转义,结果导致乱码
+
+;;{{{ hack emacs-wiki-escape-html-string for mule-gbk support
+(defun emacs-wiki-escape-html-string (str)
+ "Convert to character entities any non alphanumeric characters
+outside of a few punctuation symbols, that risk being
+misinterpreted if not escaped"
+ (when str
+ (let (pos code len)
+ (save-match-data
+ (while (setq pos (string-match
+ (concat "[^-"
+ emacs-wiki-regexp-alnum
+ "/:._=@\\?~#]")
+ str pos))
+ ;; Work around XEmacs differentiation of char and int
+ (setq code (if (fboundp 'char-to-int)
+ (int-to-string (char-to-int (aref str pos)))
+ (int-to-string (aref str pos))))
+ (if (string= (charset-short-name (char-charset (aref str pos)))
+ "ASCII")
+ (setq len (length code)
+ str (replace-match (concat "&#" code ";") nil nil str)
+ pos (+ 3 len pos))
+ (cond ((string= (string (char-syntax (aref str pos))) "w")
+ (setq pos (+ 1 pos)))
+ ((string= (string (char-syntax (aref str pos))) "_")
+ (setq pos (+ 1 pos)))
+ ((string= (string (char-syntax (aref str pos))) "(")
+ (setq pos (+ 1 pos)))
+ ((string= (string (char-syntax (aref str pos))) ")")
+ (setq pos (+ 1 pos)))
+ (t
+ (setq len (length code)
+ str (replace-match (concat "&#" code ";") nil nil str)
+ pos (+ 3 len pos))))))
+ str))))
+;;}}}
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; .emacs-wiki.el ends here
diff --git a/emacs.d/lisp/erc-tab.el b/emacs.d/lisp/erc-tab.el
new file mode 100644
index 0000000..50f5db7
--- /dev/null
+++ b/emacs.d/lisp/erc-tab.el
@@ -0,0 +1,269 @@
+;;; erc-tab.el --- Provide a tab-style interface to erc buffers.
+
+;; Copyright (C) 2003 David Edmondson <dme@dme.org>
+
+;; Author: David Edmondson <dme@dme.org>
+;; Keywords: tabs, faces
+;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErcTabs
+
+;; 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:
+
+;; Provides tabs in the header-line to access different erc buffers.
+;; This only works if your emacs supports a header line (emacs 21
+;; does). Add to your ~/.emacs:
+
+;; (require 'erc-tab)
+;; (erc-tab-mode 1)
+
+;; The ideas and implementation here are taken from emacs-w3m.
+
+;; Todo:
+;;
+;; * change the colour of the text in a tab to reflect activity and
+;; the type of activity (a combination of erc-track and xchat
+;; behaviour). DONE: not as complex as erc-track, but useful for
+;; discussion.
+
+(require 'erc)
+; anything else?
+
+;;; Code:
+
+(defconst erc-tab-version "$Revision$"
+ "ERC tab mode revision")
+
+(defgroup erc-tab nil
+ "Provide a tab interface to ERC buffers.")
+
+(defcustom erc-tab-topic-format
+ '(" " nick " " channel-modes " " topic)
+ "Format of the topic in the header-line in erc-mode.
+Only used in Emacs 21. This variable is processed using
+`erc-prepare-mode-line-format'."
+ :group 'erc-tab
+ :type 'sexp)
+
+(defcustom erc-tab-max-width 16
+ "Maximum width of any one channel tab."
+ :group 'erc-tab
+ :type 'number)
+
+; this removes server buffers for me
+(defcustom erc-tab-interesting-buffers-regexp "^[^:]*$"
+ "Regular expression used to look for interesting buffers. Buffers whose
+names match this expression will have a tab created in erc buffers."
+ :group 'erc-tab
+ :type 'regexp)
+
+(defface erc-tab-unselected-face
+ '((((type x w32 mac) (class color))
+ :background "Gray50" :foreground "Gray20"
+ :underline "Gray85" :box (:line-width -1 :style released-button))
+ (((class color))
+ (:background "cyan" :foreground "black" :underline "blue")))
+ "*Face to fontify unselected tabs."
+ :group 'erc-tab)
+
+; TODO: use `:inherit' from `erc-tab-unselected-face' and then
+; change the foreground.
+(defface erc-tab-unselected-active-face
+ '((((type x w32 mac) (class color))
+ :background "Gray50" :foreground "blue"
+ :underline "Gray85" :box (:line-width -1 :style released-button))
+ (((class color))
+ (:background "cyan" :foreground "yellow" :underline "blue")))
+ "*Face to fontify unselected tabs."
+ :group 'erc-tab)
+
+(defface erc-tab-selected-face
+ '((((type x w32 mac) (class color))
+ :background "Gray85" :foreground "black"
+ :underline "Gray85" :box (:line-width -1 :style released-button))
+ (((class color))
+ (:background "blue" :foreground "black" :underline "blue"))
+ (t (:underline t)))
+ "*Face to fontify selected tab."
+ :group 'erc-tab)
+
+(defface erc-tab-topic-face
+ '((((type x w32 mac) (class color))
+ :foreground "Grey85"
+ :underline "Gray85" :box (:line-width -1 :style released-button))
+ (((class color))
+ (:background "cyan" :foreground "black" :underline "blue"))
+ (t (:underline t)))
+ "*Face to fontify the tab gutter, which contains the topic."
+ :group 'erc-tab)
+
+;;;
+
+(defun erc-tab-buffer-list ()
+ "Return all erc buffers."
+ (mapcar
+ 'buffer-name
+ (erc-buffer-list)))
+
+(defun erc-tab-all-visible-buffer-names ()
+ "Return all visible channel or query buffer names."
+ (mapcar
+ 'buffer-name
+ (erc-buffer-filter
+ (lambda () (get-buffer-window (current-buffer) 'visible)))))
+
+(defun erc-tab-all-interesting-buffer-names ()
+ "Return all interesting erc buffer names."
+ (mapcar
+ 'buffer-name
+ (erc-buffer-filter
+ (lambda ()
+ (string-match erc-tab-interesting-buffers-regexp
+ (buffer-name (current-buffer)))))))
+
+(defun erc-tab-make-keymap (buffer)
+ (let ((map (make-sparse-keymap))
+ (fn `(lambda (e) (interactive "e")
+ (select-window (car (event-start e)))
+ (switch-to-buffer ,buffer))))
+ (define-key map [header-line down-mouse-1] 'ignore)
+ (define-key map [header-line drag-mouse-1] fn)
+ (define-key map [header-line mouse-1] fn)
+ map))
+
+(defun erc-tab-update ()
+ "Update all tabs, as necessary."
+ ; buffers which are visible don't belong in erc-tab-modified-buffers
+ (mapcar (lambda (b)
+ (setq erc-tab-modified-buffers
+ (remove b erc-tab-modified-buffers)))
+ (erc-tab-all-visible-buffer-names))
+
+ (mapcar 'erc-tab-update-buffer (erc-tab-buffer-list)))
+
+(defun erc-tab-update-buffer (buffer)
+ "Update the tabs in erc buffer `buffer'."
+ (save-excursion
+ (set-buffer buffer)
+ (setq header-line-format
+ (append
+ (mapcar
+ (lambda (b)
+ (propertize
+ (concat " " (truncate-string-to-width
+ b (- erc-tab-max-width 2)) " ")
+ 'face (cond
+ ((eq b buffer)
+ 'erc-tab-selected-face)
+ ((member b erc-tab-modified-buffers)
+ 'erc-tab-unselected-active-face)
+ (t
+ 'erc-tab-unselected-face))
+ 'local-map (erc-tab-make-keymap b)))
+ (erc-sort-strings (erc-tab-all-interesting-buffer-names)))
+ (list
+ (let* ((topic-text
+ (mapconcat 'identity
+ (erc-prepare-mode-line-format
+ erc-tab-topic-format) ""))
+ (help-text
+ (with-temp-buffer
+ (insert topic-text)
+ (fill-region (point-min) (point-max))
+ (buffer-string))))
+ (propertize topic-text
+ 'help-echo help-text
+ 'face 'erc-tab-topic-face)))))))
+
+(defvar erc-tab-modified-buffers nil)
+
+(defun erc-tab-buffer-updated ()
+ "Hook for `erc-insert-post-hook'."
+ (let ((this-channel (erc-default-target)))
+ (if (and (not (get-buffer-window (current-buffer) 'visible))
+ (not (memq this-channel erc-tab-modified-buffers)))
+ (setq erc-tab-modified-buffers
+ (cons this-channel erc-tab-modified-buffers)))))
+
+(defun erc-tab-JOIN (proc parsed)
+ (erc-tab-update)
+ nil)
+
+; TODO: only really needs to update the buffer that changed.
+(defun erc-tab-TOPIC (proc parsed)
+ (erc-tab-update)
+ nil)
+
+(defun erc-tab-remove ()
+ "Unset the header line for all erc buffers."
+ (save-excursion
+ (mapcar
+ (lambda (b) (set-buffer b) (setq header-line-format nil))
+ (erc-tab-buffer-list))))
+
+;;; Module;
+
+(setq erc-tab-server-hooks '("JOIN" "TOPIC"))
+
+;;;###autoload (autoload 'erc-tab-mode "erc-tab" nil t)
+(define-erc-module tab nil
+ "This mode provides a tab interface to ERC buffers."
+
+ ; enable:
+ ((if (featurep 'xemacs)
+ (defadvice switch-to-buffer (after erc-update (&rest args) activate)
+ (erc-tab-update))
+ (add-hook 'window-configuration-change-hook
+ 'erc-tab-update))
+ (mapcar
+ (lambda (message)
+ (add-hook (intern (concat "erc-server-" message "-hook"))
+ (intern (concat "erc-tab-" message))
+ t))
+ erc-tab-server-hooks)
+
+ (add-hook 'erc-kill-server-hook 'erc-tab-update t)
+ (add-hook 'erc-kill-channel-hook 'erc-tab-update t)
+ (add-hook 'erc-kill-buffer-hook 'erc-tab-update t)
+
+ (add-hook 'erc-insert-post-hook 'erc-tab-buffer-updated)
+
+ ; stop the normal header-line updates
+ (remove-hook 'erc-update-mode-line-hooks 'erc-update-header-line)
+
+ (erc-tab-update))
+
+ ; disable:
+ ; re-enable normal header-line updates
+ ((add-hook 'erc-update-mode-line-hooks 'erc-update-header-line)
+
+ (remove-hook 'erc-insert-post-hook 'erc-tab-buffer-updated)
+
+ (remove-hook 'erc-kill-buffer-hook 'erc-tab-update)
+ (remove-hook 'erc-kill-channel-hook 'erc-tab-update)
+ (remove-hook 'erc-kill-server-hook 'erc-tab-update)
+
+ (mapcar
+ (lambda (message)
+ (remove-hook (intern (concat "erc-server-" message "-hook"))
+ (intern (concat "erc-tab-" message))))
+ (reverse erc-tab-server-hooks))
+
+ (if (featurep 'xemacs)
+ (ad-disable-advice 'switch-to-buffer 'after 'erc-update)
+ (remove-hook 'window-configuration-change-hook
+ 'erc-tab-update))
+ (erc-tab-remove)))
diff --git a/emacs.d/lisp/guess-offset.el b/emacs.d/lisp/guess-offset.el
new file mode 100644
index 0000000..007848f
--- /dev/null
+++ b/emacs.d/lisp/guess-offset.el
@@ -0,0 +1,382 @@
+;;; guess-offset.el -- Automatically determine c-basic-offset
+
+;; Copyright (C) 2003 Julian Scheid
+
+;; Version: 0.1.1
+;; Author: Julian Scheid <julian@sektor37.de>
+;; Keywords: indent c-mode c-basic-offset
+
+;; 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:
+
+;; A hook for C, C++ and Java modes that guesses the indentation
+;; offset used in an existing C-like source code.
+
+;; To install, add this file to one of your load directories,
+;; byte-compile it and put the following at the very end of your
+;; .emacs file:
+
+;; (require 'guess-offset)
+
+;; When installed, guess-offset will briefly analyze every visited C
+;; or C-like source code (C++ and Java, at the time) and make a
+;; "guess" what indentation offset was used for creating this source.
+;; If the guess is considered reliable, c-basic-offset is overridden
+;; to reflect the proposed offset.
+
+;; Guess-offset doesn't add anything to your Emacs environment, but it
+;; removes something you won't miss - the hassle to manually deal with
+;; source codes that are formatted with a different indentation
+;; offset. With guess-offset, Emacs will transparently adapt to
+;; foreign indentation offsets.
+
+;; It doesn't work perfectly for every possible source file. In
+;; particular, it won't work with source codes that use a single space
+;; per level, and not with those that use varying indentation
+;; depending on the outer construct.
+
+;; Still, it will make dealing with a heap of source codes much
+;; easier, and leave you no worse off with the remainder than before.
+;; Remember, the c-basic-offset setting will only be tinkered with if
+;; there is enough evidence that the guessed offset is the right one.
+
+;; GuessOffset relies on heuristics and has a couple of variables you
+;; can play with. Please tune these settings if you are not satisfied
+;; with the current behaviour. If you think your settings are better
+;; than the defaults, please send me a copy.
+
+;; Note to users of other languages: the only reason guess-offset is
+;; currently limited to C-like languages is that it can only deal with
+;; C comments and expressions ("/*...*/" and "(...)", resp.). It
+;; shouldn't be too hard to extend this to work with other languages.
+;; Please send a patch to the author if you do.
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Code:
+
+;;;-----------------------------------------------------------------
+;;; Dependencies
+
+(require 'cc-vars)
+
+;;;-----------------------------------------------------------------
+;;; Customization Definitions:
+
+(defgroup guess-offset nil
+ "Functions for automatically determining the indentation offset
+used in a buffer."
+ :version "21.1"
+ :group 'tools)
+
+(defcustom guess-offset-minimum-tab-width 2
+ "*The minimum offset that can be guessed for a buffer."
+ :type 'number
+ :group 'guess-offset)
+
+(defcustom guess-offset-maximum-tab-width 8
+ "*The maximum offset that can be guessed for a buffer."
+ :type 'number
+ :group 'guess-offset)
+
+(defcustom guess-offset-minimum-line-count 8
+ "*The minimum count of non-empty, indented lines a buffer must
+contain for guess-offset to readjust the offset. If there are
+less lines, guess-offset will leave the buffer alone."
+ :type 'number
+ :group 'guess-offset)
+
+(defcustom guess-offset-minimum-probability 0.5
+ "*The minimum probability a guess must have for guess-offset to
+readjust the offset. If the best guess is less probably than this
+number, guess-offset will leave the buffer alone."
+ :type 'number
+ :group 'guess-offset)
+
+(defcustom guess-offset-minimum-superiority 2.0
+ "*The minimum factor the best guess must be better than the second
+best guess for guess-offset to readjust the offset. If the best guess
+is not significantly better than the second best guess, guess-offset
+will leave the buffer alone. Note that guesses with equal (or similar)
+probability are treated as one guess in this context. This avoids
+problems with offsets that are multiples of other valid offsets (like
+2, 4 and 8.)"
+ :type 'number
+ :group 'guess-offset)
+
+(defcustom guess-offset-probability-gravity 0.01
+ "*The difference between two probability values (percentages) below
+which both values are considered equal. This tolerance is necessary to
+avoid a fractional offset of the real offset being preferred over the
+actual offset used in the buffer. For example, if an offset of two has
+the probability 64.2% and an offset of four has the probability 64.9%,
+then guess-offset will assume an offset of four instead of two when
+the gravity is set to 0.007 (0.7 percent) or more."
+ :type 'number
+ :group 'guess-offset)
+
+(defcustom guess-offset-quiet-p nil
+ "*Whether guess-offset should refrain from outputting any messages."
+ :type 'boolean
+ :group 'guess-offset)
+
+(defcustom guess-offset-debug-p nil
+ "*Whether guess-offset should output lots of debugging
+information."
+ :type 'boolean
+ :group 'guess-offset)
+
+;; The function to use for detecting the start of a multi-line
+;; comment.
+(defvar guess-offset-skip-comment-start
+ 'guess-offset-skip-c-comment-start)
+
+;; The function to use for detecting the end of a multi-line comment.
+(defvar guess-offset-skip-comment-end
+ 'guess-offset-skip-c-comment-end)
+
+;;;-----------------------------------------------------------------
+;;; Function Definitions:
+
+(defun guess-offset-skip-c-comment-start (eol)
+ "Skip to the next C/C++/Java comment start in this line."
+ (re-search-forward "/[*]" eol t))
+
+(defun guess-offset-skip-c-comment-end (eol)
+ "Skip to the next C/C++/Java comment end in this line."
+ (re-search-forward "[*]/" eol t))
+
+(defun guess-offset-collect-indent-widths ()
+ "Return a indentation histogram for the current buffer."
+ (let ((tab-positions nil)
+ (line-count 0)
+ go-in-comment)
+ (save-excursion
+ (beginning-of-buffer)
+ (while (re-search-forward "[^\t\r\n ]" nil t)
+ (let ((column (- (current-column) 1)))
+ (when (and (> column 0)
+ (not go-in-comment))
+ (let ((tabinfo (assoc column tab-positions)))
+ (if (null tabinfo)
+ (setq tab-positions (cons (cons column 1)
+ tab-positions))
+ (setcdr tabinfo
+ (+ 1 (cdr tabinfo)))))
+ (setq line-count (+ line-count 1))))
+ ;; check whether a comment begins or ends on this line
+ (let ((eol (save-excursion (end-of-line) (point))))
+ (beginning-of-line)
+ (while
+ (or
+ (and (not go-in-comment)
+ (funcall guess-offset-skip-comment-start eol)
+ (setq go-in-comment t))
+ (and (not go-in-comment)
+ (re-search-forward "(" eol t)
+ (let ((bracket-level 1))
+ (while (and (/= bracket-level 0)
+ (re-search-forward "[()]" nil t))
+ (if (eq ?\( (char-before))
+ (setq bracket-level (+ 1 bracket-level))
+ (setq bracket-level (- 1 bracket-level))))))
+ (and go-in-comment
+ (funcall guess-offset-skip-comment-end eol)
+ (not (setq go-in-comment nil))))))
+ (beginning-of-line 2)))
+ (cons line-count tab-positions)))
+
+(defun guess-offset-get-tab-width-linecount (tab-positions try-offset)
+ "Return the number of lines the given offset is used for."
+ (let ((result 0))
+ (while (not (null tab-positions))
+ (let ((tab-size (car (car tab-positions)))
+ (line-count (cdr (car tab-positions))))
+ (when (eq 0 (mod tab-size try-offset))
+ (setq result (+ result line-count))))
+ (setq tab-positions (cdr tab-positions)))
+ result))
+
+
+(defun guess-offset-purge-suboffsets (offset-probability-list)
+ "Return a modified version of the list passed in with all offsets
+removed that are dividends of another offset and have a similar
+probability."
+ ;; sort the list by offsets in descending order, largest offset
+ ;; first.
+ (setq offset-probability-list
+ (sort offset-probability-list
+ '(lambda (list1 list2)
+ (> (car list1) (car list2)))))
+
+ ;; for each offset in this list, starting with the largest...
+ (let ((offset-probability-iterator offset-probability-list))
+ (while offset-probability-iterator
+
+ ;; ... remove all possible sub-offsets from the remaining part
+ ;; of the list:
+ (let ((offset (car (car offset-probability-iterator))))
+
+ ;; for each `sub-offset' between `offset' - 1 and
+ ;; `guess-offset-minimum-tab-width', including, check whether
+ ;; `offset' is a multiple of `sub-offset' (in decending order)
+ (let ((sub-offset (- offset 1)))
+
+ (while (>= sub-offset guess-offset-minimum-tab-width)
+ (let ((sub-offset-probability-pair
+ (assoc sub-offset offset-probability-list)))
+ (and sub-offset-probability-pair
+ (= 0 (mod offset sub-offset))
+
+ ;; if so, check whether its probability is near the
+ ;; probability of the current outer offset
+ ;; iterator.
+ (< (abs (- (cdr (car offset-probability-iterator))
+ (cdr sub-offset-probability-pair)))
+ guess-offset-probability-gravity)
+
+ ;; if this is the case, merge both entries. set the
+ ;; probability of the current entry to the mean
+ ;; value of both probabilities ...
+ (setcdr
+ (car offset-probability-iterator)
+ (/ (+ (cdr (car offset-probability-iterator))
+ (cdr sub-offset-probability-pair))
+ 2))
+
+ ;; ... and throw away the other.
+ (setq offset-probability-list
+ (delq sub-offset-probability-pair
+ offset-probability-list)))
+ (setq sub-offset (- sub-offset 1))))))
+ (setq offset-probability-iterator
+ (cdr offset-probability-iterator))))
+
+ ;; result is the modified list
+ offset-probability-list)
+
+(defun guess-offset-get-guess ()
+ "Guess the indentation offset used by the current buffer. Return the
+offest or nil if the offset could not be guessed reliably."
+ (let ((collect-result (guess-offset-collect-indent-widths))
+ offset-probabilities)
+ (let ((tab-positions
+ (sort (cdr collect-result)
+ '(lambda (list1 list2)
+ (> (cdr list1) (cdr list2)))))
+ (try-tab-width guess-offset-minimum-tab-width)
+ (line-count (car collect-result)))
+ (when guess-offset-debug-p
+ (message (concat "Indentation histogram:\n"
+ (mapconcat
+ '(lambda (pair)
+ (concat " "
+ (number-to-string (car pair))
+ "->"
+ (number-to-string (cdr pair))))
+ tab-positions
+ "\n"))))
+ (when (> line-count guess-offset-minimum-line-count)
+ (while (<= try-tab-width guess-offset-maximum-tab-width)
+ (let ((probability (/ (float
+ (guess-offset-get-tab-width-linecount
+ tab-positions try-tab-width))
+ line-count)))
+ (setq offset-probabilities
+ (cons (cons try-tab-width probability)
+ offset-probabilities))
+ (setq try-tab-width (+ 1 try-tab-width))))
+ (let ((sorted-probabilities
+ (sort (guess-offset-purge-suboffsets
+ offset-probabilities)
+ '(lambda (list1 list2)
+ (let ((prob1 (cdr list1))
+ (offs1 (car list1))
+ (prob2 (cdr list2))
+ (offs2 (car list2)))
+
+ ;; two probabilities are considered equal
+ ;; when their difference is below
+ ;; guess-offset-probability-gravity
+ ;;
+ ;; if they are equal,
+ (or (> prob1 prob2)
+ (and (= prob1 prob2)
+ (> offs1 offs2))))))))
+
+ (when guess-offset-debug-p
+ (message
+ (concat "Probable offsets:\n"
+ (mapconcat
+ '(lambda (pair)
+ (concat " Offset "
+ (number-to-string (car pair))
+ " has probability "
+ (format "%f" (cdr pair))))
+ sorted-probabilities
+ "\n"))))
+
+ (let ((gold-offset
+ (car (nth 0 sorted-probabilities)))
+ (gold-probability
+ (cdr (nth 0 sorted-probabilities)))
+ (silver-probability
+ (cdr (nth 1 sorted-probabilities))))
+
+ (when (and (>= gold-probability
+ guess-offset-minimum-probability)
+ (or (null silver-probability)
+ (= 0 silver-probability)
+ (>= (/ (float gold-probability)
+ (float silver-probability) )
+ guess-offset-minimum-superiority)))
+ gold-offset)))))))
+
+(defun guess-offset-set-c-basic-offset ()
+ "Guess the proper c-basic-offset for the current buffer and change
+it if a reliable guess could be made."
+ (let ((guessed-tab-width (guess-offset-get-guess)))
+ (when (not (or (null guessed-tab-width)
+ (eq guessed-tab-width c-basic-offset)))
+ (setq c-basic-offset guessed-tab-width)
+ (unless guess-offset-quiet-p
+ (message (concat "Note: c-basic-offset adjusted to "
+ (number-to-string guessed-tab-width)
+ " for buffer "
+ (buffer-name)
+ "."))))))
+
+;;;-----------------------------------------------------------------
+;;; Installation
+
+(defvar guess-offset-hooks
+ (list 'c-mode-hook
+ 'c++-mode-hook
+ (if (featurep 'jde)
+ 'jde-mode-hook
+ 'java-mode-hook)))
+
+(mapcar '(lambda (hook-name)
+ (add-hook hook-name
+ 'guess-offset-set-c-basic-offset
+ t))
+ guess-offset-hooks)
+
+(provide 'guess-offset)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; guess-offset.el ends here
diff --git a/emacs.d/lisp/tabbar.el b/emacs.d/lisp/tabbar.el
new file mode 100644
index 0000000..9f7b5d2
--- /dev/null
+++ b/emacs.d/lisp/tabbar.el
@@ -0,0 +1,1336 @@
+;;; tabbar.el --- Display a tab bar in the header line
+
+;; Copyright (C) 2003 David Ponce
+
+;; Author: David Ponce <david@dponce.com>
+;; Maintainer: David Ponce <david@dponce.com>
+;; Created: 25 February 2003
+;; Keywords: convenience
+;; Revision: $Id: tabbar.el,v 1.20 2003/06/05 08:15:49 ponced Exp $
+
+(defconst tabbar-version "1.3")
+
+;; This file is not part of GNU Emacs.
+
+;; This program is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation; either version 2, or (at
+;; your option) any later version.
+
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program; see the file COPYING. If not, write to
+;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+;;
+;; This library provides a minor mode to display tabs in the header
+;; line. It works only on GNU Emacs 21.
+;;
+;; M-x `tabbar-mode' toggle the display of the tab bar, globally.
+;;
+;; M-x `tabbar-local-mode' toggle the display of the tab bar, locally
+;; in the current buffer, when the global mode in on. This mode
+;; permit to see the tab bar in a buffer where the header line is
+;; already used by another mode (like `info' buffers). That command
+;; is particularly useful when it is given a keyboard shortcut, like
+;; this:
+;;
+;; (global-set-key [(control f10)] 'tabbar-local-mode)
+;;
+;; It is possible to navigate through tabs using commands (that is,
+;; using the keyboard). The main commands to cycle through tabs are:
+;;
+;; - `tabbar-forward' select the next available tab.
+;; - `tabbar-backward' select the previous available tab.
+;;
+;; It is worth defining keys for them. For example:
+;;
+;; (global-set-key [(control shift tab)] 'tabbar-backward)
+;; (global-set-key [(control tab)] 'tabbar-forward)
+;;
+;; The default cycle is to first try to select the tab just
+;; after/before the selected tab. If this is the last/first tab, then
+;; the first/last tab of the next/previous group of tabs is selected.
+;; That behavior is controlled by the `tabbar-cycling-scope' option.
+;;
+;; The following specialized commands can be useful too:
+;;
+;; - `tabbar-forward-tab'/`tabbar-backward-tab'
+;; Navigate through visible tabs only.
+;;
+;; - `tabbar-forward-group'/`tabbar-backward-group'
+;; Navigate through tab groups only.
+;;
+;; Core
+;; ----
+;;
+;; The content of the tab bar is represented by an internal data
+;; structure: a tab set. A tab set is a collection of tabs,
+;; identified by an unique name. In a tab set, at any time, one and
+;; only one tab is designated as selected within the tab set.
+;;
+;; A tab is a simple data structure giving: the value of the tab, and
+;; a reference to its tab set container. A tab value can be any Lisp
+;; object, even if the most common value is probably a string. Each
+;; tab object is guaranteed to be unique.
+;;
+;; A tab set is displayed on the tab bar through a "view" defined by
+;; the index of the leftmost tab shown. Thus, it is possible to
+;; scroll the tab bar horizontally, by changing the start index of the
+;; tab set view.
+;;
+;; The visual representation of a tab set is a list a
+;; `header-line-format' template elements. Each template element is
+;; the visual representation of a tab. When the visual representation
+;; of a tab is required, the function specified in the variable
+;; `tabbar-tab-label-function' is called to obtain a label (a text
+;; representation) for that tab. Also, the function specified in the
+;; variable `tabbar-help-on-tab-function' is called when the mouse is
+;; on a tab. That function is passed the tab and can return a help
+;; string to display. Finally, when a tab is selected by clicking on
+;; it, the function specified in the variable
+;; `tabbar-select-tab-function' is called with the mouse event
+;; received, and the tab.
+;;
+;; To increase performance, the tab set automatically maintains its
+;; visual representation in a cache. As far as possible, that cache
+;; is used to display the tab set, and refreshed only when necessary.
+;;
+;; Several tab sets can be maintained at the same time. Only one is
+;; displayed on the tab bar, it is obtained by calling the function
+;; specified in the variable `tabbar-current-tabset-function'.
+;;
+;; A special tab set is maintained, that contains the list of
+;; currently selected tabs, in existing tab sets. For example, a such
+;; tab set can be used to display a tab bar with a tab for each
+;; created tab set, allowing to switch to another tab set by clicking
+;; on the corresponding tab.
+;;
+;; Three buttons are displayed to the left, on the tab bar: the "home"
+;; button, the "scroll left" and the "scroll right" buttons. The
+;; "home" button is a general purpose button used to change something
+;; on the tab bar. The scroll left and scroll right buttons are used
+;; to scroll tabs horizontally. The following variables are
+;; available, for respectively the `home', `scroll-left' and
+;; `scroll-right' value of `<button>':
+;;
+;; `tabbar-<button>-function'
+;; Specify a function called when clicking on the button. The
+;; function is passed the mouse event received.
+;;
+;; `tabbar-<button>-help-function'
+;; Specify a function to obtain a help string displayed when the
+;; mouse is onto the button. The function is called with no
+;; arguments.
+;;
+;; The appearance of tabs and buttons is also customizable (see the
+;; code for more details).
+;;
+;; Buffer tabs
+;; -----------
+;;
+;; The default tab bar implementation provided, displays buffers in
+;; dedicated tabs. Selecting a tab, switch (mouse-1), or pop
+;; (mouse-2), to the buffer it contains.
+;;
+;; The list of buffers put in tabs is provided by the function
+;; specified in the variable `tabbar-buffer-list-function'. The
+;; default function: `tabbar-buffer-list', excludes buffers whose name
+;; starts with a space, when they are not visiting a file.
+;;
+;; Buffers are organized in groups, each one represented by a tab set.
+;; A buffer can have no group, or belong to more than one group. The
+;; function specified by the variable `tabbar-buffer-groups-function'
+;; is called for each buffer to obtain its groups. The default
+;; function provided: `tabbar-buffer-groups' organizes buffers
+;; depending on their major mode (see that function for details).
+;;
+;; The "home" button toggles display of buffer groups on the tab bar,
+;; allowing to easily choose another buffer group by clicking on its
+;; tab.
+;;
+;; The scroll buttons permit to scroll tabs when some of them are
+;; outside the tab bar visible area.
+
+;;; History:
+;;
+
+;;; Code:
+
+;;; Options
+;;
+(defgroup tabbar nil
+ "Display a tab bar in the header line."
+ :group 'convenience)
+
+(defcustom tabbar-cycling-scope nil
+ "*Specify the scope of cyclic navigation through tabs.
+The following scopes are possible:
+
+- `tabs'
+ Navigate through visible tabs only.
+- `groups'
+ Navigate through tab groups only.
+- default
+ Navigate through visible tabs, then through tab groups."
+ :group 'tabbar
+ :type '(choice :tag "Cycle through..."
+ (const :tag "Visible Tabs Only" tabs)
+ (const :tag "Tab Groups Only" groups)
+ (const :tag "Visible Tabs then Tab Groups" nil)))
+
+(defcustom tabbar-inhibit-functions
+ '(tabbar-default-inhibit-function)
+ "List of functions to be called before displaying the tab bar.
+Those functions are called one by one, with no arguments, until one of
+them returns a non-nil value, and thus, prevent to display the tab
+bar."
+ :group 'tabbar
+ :type 'hook)
+
+(defcustom tabbar-current-tabset-function
+ 'tabbar-buffer-tabs
+ "Function called with no argument to obtain the current tab set.
+This is the tab set displayed on the tab bar."
+ :group 'tabbar
+ :type 'function)
+
+(defcustom tabbar-tab-label-function
+ 'tabbar-buffer-tab-label
+ "Function that obtains a tab label displayed on the tab bar.
+The function is passed a tab and should return a string."
+ :group 'tabbar
+ :type 'function)
+
+(defcustom tabbar-select-tab-function
+ 'tabbar-buffer-select-tab
+ "Function that select a tab.
+The function is passed a mouse event and a tab, and should make it the
+selected tab."
+ :group 'tabbar
+ :type 'function)
+
+(defcustom tabbar-help-on-tab-function
+ 'tabbar-buffer-help-on-tab
+ "Function to obtain a help string for a tab.
+The help string is displayed when the mouse is onto the button. The
+function is passed the tab and should return a help string or nil for
+none."
+ :group 'tabbar
+ :type 'function)
+
+(defcustom tabbar-home-function
+ 'tabbar-buffer-toggle-group-mode
+ "Function called when clicking on the tab bar home button.
+The function is passed the mouse event received."
+ :group 'tabbar
+ :type 'function)
+
+(defcustom tabbar-home-help-function
+ 'tabbar-buffer-toggle-group-mode-help
+ "Function to obtain a help string for the tab bar home button.
+The help string is displayed when the mouse is onto the button.
+The function is called with no arguments."
+ :group 'tabbar
+ :type 'function)
+
+(defcustom tabbar-scroll-left-function
+ 'tabbar-scroll-left
+ "Function that scrolls tabs on left.
+The function is passed the mouse event received when clicking on the
+scroll left button. It should scroll the current tab set."
+ :group 'tabbar
+ :type 'function)
+
+(defcustom tabbar-scroll-left-help-function
+ 'tabbar-scroll-left-help
+ "Function to obtain a help string for the scroll left button.
+The help string is displayed when the mouse is onto the button.
+The function is called with no arguments."
+ :group 'tabbar
+ :type 'function)
+
+(defcustom tabbar-scroll-right-function
+ 'tabbar-scroll-right
+ "Function that scrolls tabs on right.
+The function is passed the mouse event received when clicking on the
+scroll right button. It should scroll the current tab set."
+ :group 'tabbar
+ :type 'function)
+
+(defcustom tabbar-scroll-right-help-function
+ 'tabbar-scroll-right-help
+ "Function to obtain a help string for the scroll right button.
+The help string is displayed when the mouse is onto the button.
+The function is called with no arguments."
+ :group 'tabbar
+ :type 'function)
+
+;;; Tab and tab set
+;;
+(defconst tabbar-tabsets-tabset-name "tabbar-tabsets-tabset"
+ "Name of the special tab set of existing tab sets.")
+
+(defsubst tabbar-make-tab (object tabset)
+ "Return a new tab with value OBJECT.
+TABSET is the tab set the tab belongs to."
+ (cons object tabset))
+
+(defsubst tabbar-tab-value (tab)
+ "Return the value of tab TAB."
+ (car tab))
+
+(defsubst tabbar-tab-tabset (tab)
+ "Return the tab set TAB belongs to."
+ (cdr tab))
+
+(defvar tabbar-tabsets nil
+ "The tab sets store.")
+
+(defvar tabbar-current-tabset nil
+ "The tab set currently displayed on the tab bar.")
+(make-variable-buffer-local 'tabbar-current-tabset)
+
+(defvar tabbar-last-selected-tab nil
+ "The last selected tab.")
+
+(defsubst tabbar-free-tabsets-store ()
+ "Free the tab set store."
+ (setq tabbar-tabsets nil
+ tabbar-current-tabset nil
+ tabbar-last-selected-tab nil))
+
+(defsubst tabbar-init-tabsets-store ()
+ "Initialize the tab set store."
+ (tabbar-free-tabsets-store)
+ (setq tabbar-tabsets (make-vector 31 0)))
+
+(defmacro tabbar-map-tabsets (function)
+ "Apply FUNCTION to each existing tab set.
+Return the list of the results."
+ (let ((result (make-symbol "result"))
+ (tabset (make-symbol "tabset")))
+ `(let (,result)
+ (mapatoms #'(lambda (,tabset)
+ (setq ,result
+ (cons (funcall ,function ,tabset)
+ ,result)))
+ tabbar-tabsets)
+ (nreverse ,result))))
+
+(defun tabbar-make-tabset (name &rest objects)
+ "Make a new tab set whose name is the string NAME.
+It is initialized with tabs build from the list of OBJECTS."
+ (let* ((tabset (intern name tabbar-tabsets))
+ (tabs (mapcar #'(lambda (object)
+ (tabbar-make-tab object tabset))
+ objects)))
+ (set tabset tabs)
+ (put tabset 'select (car tabs))
+ (put tabset 'start 0)
+ tabset))
+
+(defsubst tabbar-get-tabset (name)
+ "Return the tab set whose name is the string NAME.
+Return nil if not found."
+ (intern-soft name tabbar-tabsets))
+
+(defsubst tabbar-delete-tabset (tabset)
+ "Delete the tab set TABSET.
+That is, remove it from the tab sets store."
+ (unintern tabset tabbar-tabsets))
+
+(defsubst tabbar-tabs (tabset)
+ "Return the list of tabs in TABSET."
+ (symbol-value tabset))
+
+(defsubst tabbar-tab-values (tabset)
+ "Return the list of tab values in TABSET."
+ (mapcar 'tabbar-tab-value (tabbar-tabs tabset)))
+
+(defsubst tabbar-get-tab (object tabset)
+ "Search for a tab with value OBJECT in TABSET.
+Return the tab found, or nil if not found."
+ (assoc object (tabbar-tabs tabset)))
+
+(defsubst tabbar-member (tab tabset)
+ "Return non-nil if TAB is in TABSET."
+ (or (eq (tabbar-tab-tabset tab) tabset)
+ (memq tab (tabbar-tabs tabset))))
+
+(defsubst tabbar-template (tabset)
+ "Return the template to display TABSET in the header line."
+ (get tabset 'template))
+
+(defsubst tabbar-set-template (tabset template)
+ "Set the TABSET's header line format with TEMPLATE."
+ (put tabset 'template template))
+
+(defsubst tabbar-selected-tab (tabset)
+ "Return the tab selected in TABSET."
+ (get tabset 'select))
+
+(defsubst tabbar-selected-value (tabset)
+ "Return the value of the tab selected in TABSET."
+ (tabbar-tab-value (tabbar-selected-tab tabset)))
+
+(defsubst tabbar-selected-p (tab tabset)
+ "Return non-nil if TAB is the selected tab in TABSET."
+ (eq tab (tabbar-selected-tab tabset)))
+
+(defsubst tabbar-select-tab (tab tabset)
+ "Make TAB the selected tab in TABSET.
+Does nothing if TAB is not found in TABSET.
+Return TAB if selected, nil if not."
+ (when (tabbar-member tab tabset)
+ (or (tabbar-selected-p tab tabset)
+ (tabbar-set-template tabset nil))
+ (put tabset 'select tab)))
+
+(defsubst tabbar-select-tab-value (object tabset)
+ "Make the tab with value OBJECT, the selected tab in TABSET.
+Does nothing if a tab with value OBJECT is not found in TABSET.
+Return the tab selected, or nil if nothing was selected."
+ (tabbar-select-tab (tabbar-get-tab object tabset) tabset))
+
+(defsubst tabbar-start (tabset)
+ "Return the index of the first tab in the TABSET's view."
+ (get tabset 'start))
+
+(defsubst tabbar-view (tabset)
+ "Return the list of tabs in the TABSET's view."
+ (nthcdr (tabbar-start tabset) (tabbar-tabs tabset)))
+
+(defun tabbar-add-tab (tabset object &optional append)
+ "Add to TABSET a tab with value OBJECT if there isn't one there yet.
+If the tab is added, it is added at the beginning of the tab list,
+unless the optional argument APPEND is non-nil, in which case it is
+added at the end."
+ (let ((tabs (tabbar-tabs tabset)))
+ (if (tabbar-get-tab object tabset)
+ tabs
+ (let ((tab (tabbar-make-tab object tabset)))
+ (tabbar-set-template tabset nil)
+ (set tabset (if append
+ (append tabs (list tab))
+ (cons tab tabs)))))))
+
+(defun tabbar-delete-tab (tab)
+ "Remove TAB from its TABSET."
+ (let* ((tabset (tabbar-tab-tabset tab))
+ (tabs (tabbar-tabs tabset)))
+ (tabbar-set-template tabset nil)
+ (when (eq tab (tabbar-selected-tab tabset))
+ (tabbar-select-tab (car (or (cdr (memq tab tabs)) (last tabs)))
+ tabset))
+ (set tabset (delq tab tabs))))
+
+(defun tabbar-scroll (tabset count)
+ "Scroll the TABSET's view of COUNT tabs.
+If COUNT is positive move the view on right. If COUNT is negative,
+move the view on left."
+ (let ((start (min (max 0 (+ (tabbar-start tabset) count))
+ (1- (length (tabbar-tabs tabset))))))
+ (when (/= start (tabbar-start tabset))
+ (tabbar-set-template tabset nil)
+ (put tabset 'start start))))
+
+(defun tabbar-tab-next (tabset tab &optional before)
+ "Search in TABSET for the tab after TAB.
+If optional argument BEFORE is non-nil, search for the tab before
+TAB. Return the tab found, or nil otherwise."
+ (let* (last (tabs (tabbar-tabs tabset)))
+ (while (and tabs (not (eq tab (car tabs))))
+ (setq last (car tabs)
+ tabs (cdr tabs)))
+ (and tabs (if before last (nth 1 tabs)))))
+
+(defun tabbar-current-tabset (&optional update)
+ "Return the current tab set, that will be displayed on the tab bar.
+If optional argument UPDATE is non-nil, call the user defined function
+`tabbar-current-tabset-function' to obtain it. Otherwise return the
+current cached copy."
+ (when (and update tabbar-current-tabset-function)
+ (setq tabbar-current-tabset
+ (funcall tabbar-current-tabset-function))
+ (or tabbar-last-selected-tab
+ (setq tabbar-last-selected-tab
+ (tabbar-selected-tab tabbar-current-tabset))))
+ tabbar-current-tabset)
+
+(defun tabbar-get-tabsets-tabset ()
+ "Return the tab set of selected tabs in existing tab sets."
+ (let ((tabsets-tabset
+ (or (tabbar-get-tabset tabbar-tabsets-tabset-name)
+ (tabbar-make-tabset tabbar-tabsets-tabset-name))))
+ (set tabsets-tabset
+ (delq t
+ (tabbar-map-tabsets
+ #'(lambda (tabset)
+ (or (eq tabset tabsets-tabset)
+ (tabbar-selected-tab tabset))))))
+ (tabbar-scroll tabsets-tabset 0)
+ (tabbar-set-template tabsets-tabset nil)
+ tabsets-tabset))
+
+;;; Buttons and separators
+;;
+(defun tabbar-find-image (specs)
+ "Find an image, choosing one of a list of image specifications.
+SPECS is a list of image specifications. See also `find-image'."
+ (when (display-images-p)
+ (condition-case nil
+ (find-image specs)
+ (error nil))))
+
+(defconst tabbar-separator-widget
+ '(cons (string)
+ (repeat :tag "Image"
+ :extra-offset 2
+ (restricted-sexp :tag "Spec"
+ :match-alternatives (listp))))
+ "Widget for editing a tab bar separator.
+A separator is specified as a pair (STRING . IMAGE) where STRING is a
+string value, and IMAGE a list of image specifications.
+If IMAGE is non-nil, try to use that image, else use STRING.
+The value (\"\") hide separators.")
+
+(defun tabbar-setup-separator (variable value)
+ "Set VARIABLE with specification of tab separator in VALUE.
+Initialize `VARIABLE-value' with the template element to use in header
+line, to display a separator on the tab bar."
+ (let ((text (intern (format "%s-value" variable)))
+ (image (tabbar-find-image (cdr value))))
+ (set text (propertize (if image " " (car value))
+ 'face 'tabbar-separator-face
+ 'display image))
+ (custom-set-default variable value)
+ ))
+
+(defvar tabbar-separator-value nil
+ "Text of the separator used between tabs.")
+
+(defcustom tabbar-separator (list " ")
+ "Separator used between tabs.
+See the variable `tabbar-separator-widget' for details."
+ :group 'tabbar
+ :type tabbar-separator-widget
+ :set 'tabbar-setup-separator)
+
+(defconst tabbar-button-widget
+ '(cons
+ (cons :tag "Enabled"
+ (string)
+ (repeat :tag "Image"
+ :extra-offset 2
+ (restricted-sexp :tag "Spec"
+ :match-alternatives (listp))))
+ (cons :tag "Disabled"
+ (string)
+ (repeat :tag "Image"
+ :extra-offset 2
+ (restricted-sexp :tag "Spec"
+ :match-alternatives (listp))))
+ )
+ "Widget for editing a tab bar button.
+A button is specified as a pair (ENABLED-BUTTON . DISABLED-BUTTON),
+where ENABLED-BUTTON and DISABLED-BUTTON specify the value used when
+the button is respectively enabled and disabled. Each button value is
+a pair (STRING . IMAGE) where STRING is a string value, and IMAGE a
+list of image specifications.
+If IMAGE is non-nil, try to use that image, else use STRING.")
+
+(defun tabbar-setup-button (variable value)
+ "Set VARIABLE with the button specification in VALUE.
+Initialize `VARIABLE-enable' and `VARIABLE-disable' with the template
+elements to use in the header line, to respectively display an enabled
+and a disabled button on the tab bar.
+The variable `VARIABLE-keymap' must be set with the keymap used for the
+enabled button.
+The function `VARIABLE-help' must be defined to return the `help-echo'
+string shown when the mouse is on the button."
+ (let ((enabled (intern (format "%s-enabled" variable)))
+ (disabled (intern (format "%s-disabled" variable)))
+ (keymap (intern (format "%s-keymap" variable)))
+ (help (intern (format "%s-help" variable)))
+ (image-en (tabbar-find-image (cdar value)))
+ (image-di (tabbar-find-image (cddr value))))
+ (set enabled (propertize (if image-en " " (caar value))
+ 'display image-en
+ 'face 'tabbar-button-face
+ 'local-map (symbol-value keymap)
+ 'help-echo help))
+ (set disabled (propertize (if image-di " " (cadr value))
+ 'display image-di
+ 'face 'tabbar-button-face))
+ (custom-set-default variable value)
+ ))
+
+(defun tabbar-make-button-keymap (callback)
+ "Return a button keymap that call CALLBACK on mouse events.
+CALLBACK is passed the received mouse event."
+ (let ((keymap (make-sparse-keymap)))
+ ;; Pass mouse-1, mouse-2 and mouse-3 events to CALLBACK.
+ (define-key keymap [header-line down-mouse-1] 'ignore)
+ (define-key keymap [header-line mouse-1] callback)
+ (define-key keymap [header-line down-mouse-2] 'ignore)
+ (define-key keymap [header-line mouse-2] callback)
+ (define-key keymap [header-line down-mouse-3] 'ignore)
+ (define-key keymap [header-line mouse-3] callback)
+ keymap))
+
+(defvar tabbar-home-button-enabled nil
+ "Text of the enabled home button.")
+
+(defvar tabbar-home-button-disabled nil
+ "Text of the disabled home button.")
+
+(defconst tabbar-home-button-keymap
+ (tabbar-make-button-keymap 'tabbar-home-button-callback)
+ "Keymap of the home button.")
+
+(defun tabbar-home-button-callback (event)
+ "Handle a mouse EVENT on the home button.
+Call `tabbar-home-function'."
+ (interactive "e")
+ (when tabbar-home-function
+ (save-selected-window
+ (select-window (posn-window (event-start event)))
+ (funcall tabbar-home-function event)
+ (force-mode-line-update)
+ (sit-for 0)
+ )))
+
+(defun tabbar-home-button-help (window object position)
+ "Return a help string or nil for none, for the home button.
+Call `tabbar-home-help-function'.
+Arguments WINDOW, OBJECT and POSITION, are not used."
+ (when tabbar-home-help-function
+ (funcall tabbar-home-help-function)))
+
+(defconst tabbar-home-button-enabled-image
+ '((:type pbm :ascent center :data "\
+P2
+10 10
+255
+184 184 184 184 0 184 184 184 184 184 184 184 184 0 0 0 184 184 184 184
+184 184 0 0 0 0 0 184 184 184 184 0 0 0 0 0 0 0 184 184 184 184 255 0 0
+0 255 255 255 184 184 0 0 0 0 0 0 0 184 184 184 184 0 0 0 0 0 255 255 184
+184 184 184 0 0 0 255 255 184 184 184 184 184 184 0 255 255 184 184 184
+184 184 184 184 184 255 184 184 184 184
+"))
+ "Default image for the enabled home button.")
+
+(defconst tabbar-home-button-disabled-image
+ '((:type pbm :ascent center :data "\
+P2
+10 10
+255
+184 184 184 184 120 184 184 184 184 184 184 184 184 120 120 120 184 184
+184 184 184 184 120 184 184 184 120 184 184 184 184 120 120 160 184 160
+120 120 184 184 184 184 255 120 184 120 255 255 255 184 184 120 120 160
+184 160 120 120 184 184 184 184 120 184 184 184 120 255 255 184 184 184
+184 120 120 120 255 255 184 184 184 184 184 184 120 255 255 184 184 184
+184 184 184 184 184 255 184 184 184 184
+"))
+ "Default image for the disabled home button.")
+
+(defcustom tabbar-home-button
+ (cons (cons "[o]" tabbar-home-button-enabled-image)
+ (cons "[x]" tabbar-home-button-disabled-image))
+ "The home button.
+See the variable `tabbar-button-widget' for details."
+ :group 'tabbar
+ :type tabbar-button-widget
+ :set 'tabbar-setup-button)
+
+(defvar tabbar-scroll-left-button-enabled nil
+ "Text of the enabled scroll left button.")
+
+(defvar tabbar-scroll-left-button-disabled nil
+ "Text of the disabled scroll left button.")
+
+(defconst tabbar-scroll-left-button-keymap
+ (tabbar-make-button-keymap 'tabbar-scroll-left-button-callback)
+ "Keymap of the scroll left button.")
+
+(defun tabbar-scroll-left-button-callback (event)
+ "Handle a mouse EVENT on the scroll left button.
+Call `tabbar-scroll-left-function'."
+ (interactive "e")
+ (when tabbar-scroll-left-function
+ (save-selected-window
+ (select-window (posn-window (event-start event)))
+ (funcall tabbar-scroll-left-function event)
+ (force-mode-line-update)
+ (sit-for 0)
+ )))
+
+(defun tabbar-scroll-left-button-help (window object position)
+ "Return a help string or nil for none, for the scroll left button.
+Call `tabbar-scroll-left-help-function'.
+Arguments WINDOW, OBJECT and POSITION, are not used."
+ (when tabbar-scroll-left-help-function
+ (funcall tabbar-scroll-left-help-function)))
+
+(defconst tabbar-scroll-left-button-enabled-image
+ '((:type pbm :ascent center :data "\
+P2
+8 10
+255
+184 184 184 184 184 184 184 184 184 184 184 184 184 0 184 184 184 184 184
+184 0 0 255 184 184 184 184 0 0 0 255 184 184 184 0 0 0 0 255 184 184 184
+184 0 0 0 255 184 184 184 184 184 0 0 255 184 184 184 184 184 184 0 255
+184 184 184 184 184 184 184 255 184 184 184 184 184 184 184 184 184
+"))
+ "Default image for the enabled scroll left button.")
+
+(defconst tabbar-scroll-left-button-disabled-image
+ '((:type pbm :ascent center :data "\
+P2
+8 10
+255
+184 184 184 184 184 184 184 184 184 184 184 184 184 120 184 184 184 184
+184 184 120 120 255 184 184 184 184 120 184 120 255 184 184 184 120 184
+184 120 255 184 184 184 184 120 184 120 255 184 184 184 184 184 120 120
+255 184 184 184 184 184 184 120 255 184 184 184 184 184 184 184 255 184
+184 184 184 184 184 184 184 184
+"))
+ "Default image for the disabled scroll left button.")
+
+(defcustom tabbar-scroll-left-button
+ (cons (cons " <" tabbar-scroll-left-button-enabled-image)
+ (cons " =" tabbar-scroll-left-button-disabled-image))
+ "The scroll left button.
+See the variable `tabbar-button-widget' for details."
+ :group 'tabbar
+ :type tabbar-button-widget
+ :set 'tabbar-setup-button)
+
+(defvar tabbar-scroll-right-button-enabled nil
+ "Text of the enabled scroll right button.")
+
+(defvar tabbar-scroll-right-button-disabled nil
+ "Text of the disabled scroll right button.")
+
+(defconst tabbar-scroll-right-button-keymap
+ (tabbar-make-button-keymap 'tabbar-scroll-right-button-callback)
+ "Keymap of the scroll right button.")
+
+(defun tabbar-scroll-right-button-callback (event)
+ "Handle a mouse EVENT on the scroll right button.
+Call `tabbar-scroll-right-function'."
+ (interactive "e")
+ (when tabbar-scroll-right-function
+ (save-selected-window
+ (select-window (posn-window (event-start event)))
+ (funcall tabbar-scroll-right-function event)
+ (force-mode-line-update)
+ (sit-for 0)
+ )))
+
+(defun tabbar-scroll-right-button-help (window object position)
+ "Return a help string or nil for none, for the scroll right button.
+Call `tabbar-scroll-right-help-function'.
+Arguments WINDOW, OBJECT and POSITION, are not used."
+ (when tabbar-scroll-right-help-function
+ (funcall tabbar-scroll-right-help-function)))
+
+(defconst tabbar-scroll-right-button-enabled-image
+ '((:type pbm :ascent center :data "\
+P2
+8 10
+255
+184 184 184 184 184 184 184 184 184 0 184 184 184 184 184 184 184 0 0 184
+184 184 184 184 184 0 0 0 184 184 184 184 184 0 0 0 0 184 184 184 184 0
+0 0 255 255 184 184 184 0 0 255 255 184 184 184 184 0 255 255 184 184 184
+184 184 184 255 184 184 184 184 184 184 184 184 184 184 184 184 184
+"))
+ "Default image for the enabled scroll right button.")
+
+(defconst tabbar-scroll-right-button-disabled-image
+ '((:type pbm :ascent center :data "\
+P2
+8 10
+255
+184 184 184 184 184 184 184 184 184 120 184 184 184 184 184 184 184 120
+120 184 184 184 184 184 184 120 184 120 184 184 184 184 184 120 184 184
+120 184 184 184 184 120 184 120 255 255 184 184 184 120 120 255 255 184
+184 184 184 120 255 255 184 184 184 184 184 184 255 184 184 184 184 184
+184 184 184 184 184 184 184 184
+"))
+ "Default image for the disabled scroll right button.")
+
+(defcustom tabbar-scroll-right-button
+ (cons (cons " >" tabbar-scroll-right-button-enabled-image)
+ (cons " =" tabbar-scroll-right-button-disabled-image))
+ "The scroll right button.
+See the variable `tabbar-button-widget' for details."
+ :group 'tabbar
+ :type tabbar-button-widget
+ :set 'tabbar-setup-button)
+
+;;; Faces
+;;
+(defface tabbar-default-face
+ '(
+ (t
+ (:inherit variable-pitch
+ :height 0.8
+ :foreground "gray60"
+ :background "gray72"
+ )
+ )
+ )
+ "Default face used in the tab bar."
+ :group 'tabbar)
+
+(defface tabbar-unselected-face
+ '(
+ (t
+ (:inherit tabbar-default-face
+ :box (:line-width 2 :color "white" :style pressed-button)
+ )
+ )
+ )
+ "Face used for uselected tabs."
+ :group 'tabbar)
+
+(defface tabbar-selected-face
+ '(
+ (t
+ (:inherit tabbar-default-face
+ :box (:line-width 2 :color "white" :style released-button)
+ :foreground "blue"
+ )
+ )
+ )
+ "Face used for the selected tab."
+ :group 'tabbar)
+
+(defface tabbar-separator-face
+ '(
+ (t
+ (:inherit tabbar-default-face
+ :height 0.2
+ )
+ )
+ )
+ "Face used for the select mode button."
+ :group 'tabbar)
+
+(defface tabbar-button-face
+ '(
+ (t
+ (:inherit tabbar-default-face
+ :box (:line-width 2 :color "white" :style released-button)
+ :foreground "dark red"
+ )
+ )
+ )
+ "Face used for the select mode button."
+ :group 'tabbar)
+
+;;; Wrappers
+;;
+(defun tabbar-scroll-left (event)
+ "On mouse EVENT, scroll current tab set on left."
+ (when (eq (event-basic-type event) 'mouse-1)
+ (tabbar-scroll (tabbar-current-tabset) -1)
+ ))
+
+(defun tabbar-scroll-left-help ()
+ "Return the help string shown when mouse is onto the scroll left button."
+ "mouse-1: scroll tabs left.")
+
+(defun tabbar-scroll-right (event)
+ "On mouse EVENT, scroll current tab set on right."
+ (when (eq (event-basic-type event) 'mouse-1)
+ (tabbar-scroll (tabbar-current-tabset) 1)
+ ))
+
+(defun tabbar-scroll-right-help ()
+ "Return the help string shown when mouse is onto the scroll right button."
+ "mouse-1: scroll tabs right.")
+
+ ;; These functions can be called at compilation time.
+(eval-and-compile
+
+ (defun tabbar-make-select-tab-command (tab)
+ "Return a command to handle TAB selection.
+That command calls `tabbar-select-tab-function' with the received
+mouse event and TAB."
+ (let ((event (make-symbol "event")))
+ `(lambda (,event)
+ (interactive "e")
+ (setq tabbar-last-selected-tab ,tab)
+ (when tabbar-select-tab-function
+ (select-window (posn-window (event-start ,event)))
+ (funcall tabbar-select-tab-function ,event ,tab)
+ (force-mode-line-update)
+ (sit-for 0)))))
+
+ (defun tabbar-make-help-on-tab-function (tab)
+ "Return a function that return a help string on TAB.
+That command calls `tabbar-help-on-tab-function' with TAB."
+ (let ((window (make-symbol "window"))
+ (object (make-symbol "object"))
+ (position (make-symbol "position"))
+ )
+ `(lambda (,window ,object ,position)
+ (when tabbar-help-on-tab-function
+ (funcall tabbar-help-on-tab-function ,tab)))))
+
+ )
+
+(defun tabbar-line-element (tab)
+ "Return an `header-line-format' template element from TAB.
+Call `tabbar-tab-label-function' to obtain a label for TAB."
+ (let* ((keymap (make-sparse-keymap))
+ (qtab (list 'quote tab))
+ (select (tabbar-make-select-tab-command qtab))
+ (help (tabbar-make-help-on-tab-function qtab))
+ (label (if tabbar-tab-label-function
+ (funcall tabbar-tab-label-function tab)
+ tab)))
+ ;; Call `tabbar-select-tab-function' on mouse events.
+ (define-key keymap [header-line down-mouse-1] 'ignore)
+ (define-key keymap [header-line mouse-1] select)
+ (define-key keymap [header-line down-mouse-2] 'ignore)
+ (define-key keymap [header-line mouse-2] select)
+ (define-key keymap [header-line down-mouse-3] 'ignore)
+ (define-key keymap [header-line mouse-3] select)
+ ;; Return the tab followed by a separator.
+ (list (propertize label 'local-map keymap 'help-echo help
+ 'face (if (tabbar-selected-p
+ tab(tabbar-current-tabset))
+ 'tabbar-selected-face
+ 'tabbar-unselected-face))
+ tabbar-separator-value)))
+
+(defun tabbar-line ()
+ "Return the header line templates that represent the tab bar.
+Call `tabbar-current-tabset-function' to obtain the current tab set to
+display. Then call `tabbar-line-element' on each tab in current tab
+set's view to build a list of template elements for
+`header-line-format'."
+ (if (run-hook-with-args-until-success 'tabbar-inhibit-functions)
+ (setq header-line-format nil)
+ (let ((tabset (tabbar-current-tabset t))
+ (padcolor (face-background 'tabbar-default-face)))
+ (when tabset
+ (list (format "%s%s%s"
+ (if tabbar-home-function
+ tabbar-home-button-enabled
+ tabbar-home-button-disabled)
+ (if (> (tabbar-start tabset) 0)
+ tabbar-scroll-left-button-enabled
+ tabbar-scroll-left-button-disabled)
+ (if (< (tabbar-start tabset)
+ (1- (length (tabbar-tabs tabset))))
+ tabbar-scroll-right-button-enabled
+ tabbar-scroll-right-button-disabled))
+ tabbar-separator-value
+ (or
+ ;; If a cached template exists, use it.
+ (tabbar-template tabset)
+ ;; Otherwise use a refeshed value.
+ (tabbar-set-template tabset
+ (mapcar 'tabbar-line-element
+ (tabbar-view tabset))))
+ (propertize "%-" 'face (list :background padcolor
+ :foreground padcolor))))
+ )))
+
+;;; Cyclic navigation through tabs
+;;
+(defsubst tabbar-make-mouse-event (&optional type)
+ "Return a basic mouse event.
+Optional argument TYPE is a mouse event type. That is one of the
+symbols `mouse-1', `mouse-2' or `mouse-3'. The default is `mouse-1'."
+ (list (or (memq type '(mouse-2 mouse-3)) 'mouse-1)
+ (or (event-start nil) ;; Emacs 21.4
+ (list (selected-window) (point) '(0 . 0) 0))))
+
+(defmacro tabbar-click-on-tab (tab &optional type)
+ "Simulate a mouse click event on tab TAB.
+Optional argument TYPE is a mouse event type (see the function
+`tabbar-make-mouse-event' for details)."
+ `(,(tabbar-make-select-tab-command tab)
+ (tabbar-make-mouse-event ,type)))
+
+(defun tabbar-cycle (&optional backward)
+ "Cycle to the next available tab.
+If optional argument BACKWARD is non-nil, cycle to the previous tab
+instead.
+The scope of the cyclic navigation through tabs is specified by the
+option `tabbar-cycling-scope'."
+ (let ((tabset (tabbar-current-tabset t))
+ selected tab)
+ (when tabset
+ (setq selected (tabbar-selected-tab tabset))
+ (cond
+ ;; Cycle through visible tabs only.
+ ((eq tabbar-cycling-scope 'tabs)
+ (setq tab (tabbar-tab-next tabset selected backward))
+ ;; When there is no tab after/before the selected one, cycle
+ ;; to the first/last visible tab.
+ (unless tab
+ (setq tabset (tabbar-tabs tabset)
+ tab (car (if backward (last tabset) tabset))))
+ )
+ ;; Cycle through tab groups only.
+ ((eq tabbar-cycling-scope 'groups)
+ (setq tabset (tabbar-get-tabsets-tabset)
+ tab (tabbar-tab-next tabset selected backward))
+ ;; When there is no group after/before the selected one, cycle
+ ;; to the first/last available group.
+ (unless tab
+ (setq tabset (tabbar-tabs tabset)
+ tab (car (if backward (last tabset) tabset))))
+ )
+ (t
+ ;; Cycle through visible tabs then tab groups.
+ (setq tab (tabbar-tab-next tabset selected backward))
+ ;; When there is no visible tab after/before the selected one,
+ ;; cycle to the next/previous available group.
+ (unless tab
+ (setq tabset (tabbar-get-tabsets-tabset)
+ tab (tabbar-tab-next tabset selected backward))
+ ;; When there is no next/previous group, cycle to the
+ ;; first/last available group.
+ (unless tab
+ (setq tabset (tabbar-tabs tabset)
+ tab (car (if backward (last tabset) tabset))))
+ ;; Select the first/last visible tab of the new group.
+ (setq tabset (tabbar-tabs (tabbar-tab-tabset tab))
+ tab (car (if backward (last tabset) tabset))))
+ ))
+ (tabbar-click-on-tab tab))))
+
+;;;###autoload
+(defun tabbar-backward ()
+ "Select the previous available tab.
+Depend on the setting of the option `tabbar-cycling-scope'."
+ (interactive)
+ (tabbar-cycle t))
+
+;;;###autoload
+(defun tabbar-forward ()
+ "Select the next available tab.
+Depend on the setting of the option `tabbar-cycling-scope'."
+ (interactive)
+ (tabbar-cycle))
+
+;;;###autoload
+(defun tabbar-backward-group ()
+ "Go to selected tab in the previous available group."
+ (interactive)
+ (let ((tabbar-cycling-scope 'groups))
+ (tabbar-cycle t)))
+
+;;;###autoload
+(defun tabbar-forward-group ()
+ "Go to selected tab in the next available group."
+ (interactive)
+ (let ((tabbar-cycling-scope 'groups))
+ (tabbar-cycle)))
+
+;;;###autoload
+(defun tabbar-backward-tab ()
+ "Select the previous visible tab."
+ (interactive)
+ (let ((tabbar-cycling-scope 'tabs))
+ (tabbar-cycle t)))
+
+;;;###autoload
+(defun tabbar-forward-tab ()
+ "Select the next visible tab."
+ (interactive)
+ (let ((tabbar-cycling-scope 'tabs))
+ (tabbar-cycle)))
+
+;;; Minor modes
+;;
+(defvar tabbar-old-global-hlf nil
+ "Global value of the header line when entering tab bar mode.")
+
+(defconst tabbar-header-line-format '(:eval (tabbar-line))
+ "The tab bar header line format.")
+
+;;;###autoload
+(define-minor-mode tabbar-mode
+ "Toggle display of a tab bar in the header line.
+With prefix argument ARG, turn on if positive, otherwise off.
+Returns non-nil if the new state is enabled."
+ :global t
+ :group 'tabbar
+ (if tabbar-mode
+;;; ON
+ (unless (eq header-line-format tabbar-header-line-format)
+ ;; Save current default value of `header-line-format'.
+ (setq tabbar-old-global-hlf (default-value 'header-line-format))
+ (add-hook 'kill-buffer-hook 'tabbar-buffer-kill-buffer-hook)
+ (tabbar-init-tabsets-store)
+ (setq-default header-line-format tabbar-header-line-format))
+;;; OFF
+ ;; Restore previous `header-line-format', if it has not changed.
+ (when (eq (default-value 'header-line-format)
+ tabbar-header-line-format)
+ (setq-default header-line-format tabbar-old-global-hlf))
+ (remove-hook 'kill-buffer-hook 'tabbar-buffer-kill-buffer-hook)
+ (tabbar-free-tabsets-store)
+ ;; Turn off locals tab bar mode
+ (mapc #'(lambda (b)
+ (with-current-buffer b
+ (tabbar-local-mode -1)))
+ (buffer-list))
+ ))
+
+(defvar tabbar-old-local-hlf nil
+ "Local value of the header line when entering tab bar local mode.")
+(make-variable-buffer-local 'tabbar-old-local-hlf)
+
+;;;###autoload
+(define-minor-mode tabbar-local-mode
+ "Toggle local display of the tab bar.
+With prefix argument ARG, turn on if positive, otherwise off.
+Returns non-nil if the new state is enabled.
+When on and tab bar global mode is on, if a buffer local value of
+`header-line-format' exists, it is saved, then the local header line
+is killed to show the tab bar. When off, the saved local value of the
+header line is restored, hiding the tab bar."
+ :global nil
+ :group 'tabbar
+;;; ON
+ (if tabbar-local-mode
+ (if (and tabbar-mode (local-variable-p 'header-line-format)
+ (not (local-variable-p 'tabbar-old-local-hlf)))
+ (progn
+ (setq tabbar-old-local-hlf header-line-format)
+ (kill-local-variable 'header-line-format))
+ (setq tabbar-local-mode nil))
+;;; OFF
+ (when (local-variable-p 'tabbar-old-local-hlf)
+ (setq header-line-format tabbar-old-local-hlf)
+ (kill-local-variable 'tabbar-old-local-hlf))
+ ))
+
+;;; Hooks
+;;
+(defun tabbar-default-inhibit-function ()
+ "Inhibit display of the tab bar in specified windows.
+That is dedicated windows, and `checkdoc' status windows."
+ (or (window-dedicated-p (selected-window))
+ (member (buffer-name)
+ '(" *Checkdoc Status*"))))
+
+(defun tabbar-buffer-kill-buffer-hook ()
+ "Hook run just before actually killing a buffer.
+In tab bar mode, try to switch to a buffer in the current tab bar,
+after the current buffer has been killed. Try first the buffer in tab
+after the current one, then the buffer in tab before. On success, put
+the sibling buffer in front of the buffer list, so it will be selected
+first."
+ (and tabbar-mode
+ (eq tabbar-current-tabset-function 'tabbar-buffer-tabs)
+ (eq (current-buffer) (window-buffer (selected-window)))
+ (let ((bl (tabbar-tab-values (tabbar-current-tabset)))
+ (bn (buffer-name))
+ found sibling)
+ (while (and bl (not found))
+ (if (equal bn (car bl))
+ (setq found t)
+ (setq sibling (car bl)))
+ (setq bl (cdr bl)))
+ (when (setq sibling (or (car bl) sibling))
+ ;; Move sibling buffer in front of the buffer list.
+ (save-current-buffer
+ (switch-to-buffer sibling))))))
+
+;;; Buffer tabs
+;;
+(defcustom tabbar-buffer-list-function
+ 'tabbar-buffer-list
+ "*Function that returns the list of buffers to show in tabs.
+That function is called with no arguments and must return a list of
+buffers."
+ :group 'tabbar
+ :type 'function)
+
+(defcustom tabbar-buffer-groups-function
+ 'tabbar-buffer-groups
+ "*Function that gives the group names a buffer belongs to.
+That function is passed a buffer and must return a list of group
+names, or nil if the buffer has no group.
+Notice that it is better that a buffer belongs to one group."
+ :group 'tabbar
+ :type 'function)
+
+(defun tabbar-buffer-list ()
+ "Return the list of buffers to show in tabs.
+Exclude buffers whose name starts with a space, when they are not
+visiting a file."
+ (delq t
+ (mapcar #'(lambda (b)
+ (cond
+ ((buffer-file-name b) b)
+ ((char-equal ?\ (aref (buffer-name b) 0)))
+ (b)))
+ (buffer-list))))
+
+(defun tabbar-buffer-groups (buffer)
+ "Return the list of group names BUFFER belongs to.
+Return only one group for each buffer."
+ (with-current-buffer (get-buffer buffer)
+ (cond
+ ((or (get-buffer-process (current-buffer))
+ (memq major-mode
+ '(comint-mode compilation-mode)))
+ '("Process")
+ )
+ ((member (buffer-name)
+ '("*scratch*" "*Messages*"))
+ '("Common")
+ )
+ ((eq major-mode 'dired-mode)
+ '("Dired")
+ )
+ ((memq major-mode
+ '(help-mode apropos-mode Info-mode Man-mode))
+ '("Help")
+ )
+ ((memq major-mode
+ '(rmail-mode
+ rmail-edit-mode vm-summary-mode vm-mode mail-mode
+ mh-letter-mode mh-show-mode mh-folder-mode
+ gnus-summary-mode message-mode gnus-group-mode
+ gnus-article-mode score-mode gnus-browse-killed-mode))
+ '("Mail")
+ )
+ (t
+ (list
+ (if (and (stringp mode-name) (string-match "[^ ]" mode-name))
+ mode-name
+ (symbol-name major-mode)))
+ )
+ )))
+
+;;; Group buffers in tab sets.
+;;
+(defun tabbar-buffer-cleanup-tabsets (buffers)
+ "Remove obsolete tabs from existing tab sets.
+That is tabs whose value is a killed buffer or a buffer not in
+BUFFERS. Delete tab sets that no more contain tabs."
+ (mapc 'tabbar-delete-tabset
+ (tabbar-map-tabsets
+ #'(lambda (tabset)
+ (mapc #'(lambda (tab)
+ (let ((b (get-buffer (tabbar-tab-value tab))))
+ (unless (and b (memq b buffers))
+ (tabbar-delete-tab tab))))
+ (tabbar-tabs tabset))
+ (unless (tabbar-tabs tabset)
+ tabset)))))
+
+(defun tabbar-buffer-update-groups ()
+ "Update group of buffers.
+Return the the first group where the current buffer is."
+ ;; Ensure that the current buffer will always have a tab!
+ (let ((buffers (cons (current-buffer)
+ (funcall tabbar-buffer-list-function)))
+ current-group)
+ (mapc
+ #'(lambda (buffer)
+ (let* ((name (buffer-name buffer))
+ (groups (funcall tabbar-buffer-groups-function name)))
+ (when (eq buffer (current-buffer))
+ (setq current-group (car groups)))
+ (mapc #'(lambda (group)
+ (let ((tabset (tabbar-get-tabset group)))
+ (if tabset
+ (tabbar-add-tab tabset name t)
+ (tabbar-make-tabset group name))))
+ groups)))
+ buffers)
+ (tabbar-buffer-cleanup-tabsets buffers)
+ current-group))
+
+;;; Tab bar callbacks
+;;
+(defvar tabbar-buffer-group-mode nil
+ "Display tabs for group of buffers, when non-nil.")
+(make-variable-buffer-local 'tabbar-buffer-group-mode)
+
+(defun tabbar-buffer-tabs ()
+ "Return the buffers to display on the tab bar, in a tab set."
+ (let ((group (tabbar-buffer-update-groups))
+ (buffer (buffer-name))
+ tabset curtab)
+ (if tabbar-buffer-group-mode
+ (progn
+ (setq tabset (tabbar-get-tabsets-tabset)
+ curtab (tabbar-selected-tab (tabbar-current-tabset)))
+ (unless (and (equal buffer (tabbar-tab-value curtab))
+ (tabbar-select-tab curtab tabset))
+ (tabbar-select-tab-value buffer tabset)))
+ (setq tabset (tabbar-tab-tabset tabbar-last-selected-tab))
+ (unless (and tabset (tabbar-get-tab buffer tabset))
+ (setq tabset (tabbar-get-tabset group)))
+ (tabbar-select-tab-value buffer tabset))
+ tabset))
+
+(defun tabbar-buffer-tab-label (tab)
+ "Return the label to display TAB.
+Must be a valid `header-line-format' template element."
+ (if tabbar-buffer-group-mode
+ (format "[%s]" (tabbar-tab-tabset tab))
+ (format " %s " (tabbar-tab-value tab))))
+
+(defun tabbar-buffer-help-on-tab (tab)
+ "Return the help string shown when mouse is onto TAB."
+ (if tabbar-buffer-group-mode
+ "mouse-1: switch to selected tab in group"
+ "\
+mouse-1: switch to buffer, \
+mouse-2: pop to buffer, \
+mouse-3: delete other windows"
+ ))
+
+(defun tabbar-buffer-select-tab (event tab)
+ "On mouse EVENT, select TAB."
+ (let ((mouse-button (event-basic-type event))
+ (buffer (tabbar-tab-value tab)))
+ (cond
+ ((eq mouse-button 'mouse-1)
+ (switch-to-buffer buffer))
+ ((eq mouse-button 'mouse-2)
+ (pop-to-buffer buffer t))
+ ((eq mouse-button 'mouse-3)
+ (delete-other-windows)))
+ ;; Disable group mode.
+ (setq tabbar-buffer-group-mode nil)
+ ))
+
+(defun tabbar-buffer-toggle-group-mode (event)
+ "On mouse EVENT, toggle group mode.
+When enabled, display tabs for group of buffers, instead of buffer
+tabs."
+ (setq tabbar-buffer-group-mode (not tabbar-buffer-group-mode)))
+
+(defun tabbar-buffer-toggle-group-mode-help ()
+ "Return the help string shown when mouse is onto the toggle button."
+ (if tabbar-buffer-group-mode
+ "mouse-1: show buffers in selected group"
+ "mouse-1: show groups of buffers"
+ ))
+
+(provide 'tabbar)
+
+;;; tabbar.el ends here