diff options
author | Luo Jinghua <sunmoon1997@gmail.com> | 2010-01-03 19:58:20 +0800 |
---|---|---|
committer | Luo Jinghua <sunmoon1997@gmail.com> | 2010-01-03 19:58:20 +0800 |
commit | bd43daeed39aff3f6d64252ef2d32083f9d52c96 (patch) | |
tree | a8c683cedee463d030030beff29e4075beeee46f |
Initial commit of my emacs configuration
-rw-r--r-- | emacs | 332 | ||||
-rw-r--r-- | emacs.d/lisp/emacs-wiki.el | 333 | ||||
-rw-r--r-- | emacs.d/lisp/erc-tab.el | 269 | ||||
-rw-r--r-- | emacs.d/lisp/guess-offset.el | 382 | ||||
-rw-r--r-- | emacs.d/lisp/tabbar.el | 1336 |
5 files changed, 2652 insertions, 0 deletions
@@ -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 |