;; http://emacs-fu.blogspot.com/2008/12/using-packages-functions-only-if-they.html (defmacro require-maybe (feature &optional file) "*Try to require FEATURE, but don't signal an error if `require' fails." `(let ((require-result (require ,feature ,file 'noerror))) (with-current-buffer (get-buffer-create "*Startup Log*") (let* ((startup-log-format-string-prefix "%-20s--------[") (startup-log-format-string-postfix "%s") (startup-status (if require-result "LOADED" "FAILED")) (startup-status-face `(face (:foreground ,(if require-result "green" "red"))))) (insert (format startup-log-format-string-prefix ,feature)) (let ((start-pos (point))) (insert (format startup-log-format-string-postfix startup-status)) (add-text-properties start-pos (point) startup-status-face) (insert "]\n")))) require-result)) (defmacro when-available (func foo) "*Do something if FUNCTION is available." `(when (fboundp ,func) ,foo)) (when (file-exists-p "~/elisp/3rd-party-lib/emacs-w3m") (add-to-list 'load-path "~/elisp/3rd-party-lib/emacs-w3m")) (setq bookmark-save-flag 1) (setq bookmark-bmenu-file-column 50) ; wider column for doc-view auto bookmark (setq case-fold-search t) (setq read-file-name-completion-ignore-case t) (setq make-backup-files nil) (setq transient-mark-mode t) (setq current-language-environment "UTF-8") (setq default-input-method "chinese-py-punct") (size-indication-mode 1) (savehist-mode 1) (mouse-avoidance-mode 'cat-and-mouse) (require 'midnight) (setq clean-buffer-list-delay-general 4) ; survive weekend (add-to-list 'clean-buffer-list-kill-never-regexps "\\.org$") (require 'server) (defun wl-server-running-p (&optional name) "Test whether server NAME is running." (interactive (list (if current-prefix-arg (read-string "Server name: " nil nil server-name)))) (unless name (setq name server-name)) (condition-case nil (progn (delete-process (make-network-process :name "server-client-test" :family 'local :server nil :noquery t :service (expand-file-name name (or server-socket-dir (format "/tmp/emacs%d" (user-uid)))))) t) (file-error nil))) (unless (and (fboundp 'daemonp) (daemonp)) (if (and (fboundp 'server-running-p) server-socket-dir) (unless (server-running-p) (server-start)) (unless (wl-server-running-p) (server-start)))) (defun wl-revert-buffer (&optional arg) (interactive "P") (revert-buffer t t arg)) ; prefix to keep file modes (global-set-key (kbd "") 'wl-revert-buffer) (mouse-wheel-mode 1) (add-hook 'comint-output-filter-functions 'comint-watch-for-password-prompt) (add-hook 'comint-output-filter-functions 'comint-strip-ctrl-m) (setq process-coding-system-alist '(("bash" . utf-8))) (ansi-color-for-comint-mode-on) (when (file-exists-p "~/edata/diary") (setq diary-file "~/edata/diary") (require 'diary-lib) (setq diary-display-function 'diary-fancy-display) (add-hook 'diary-list-entries-hook 'diary-sort-entries t) ;; 2009年1月16日星期五 14:00-16:00 (GMT+08:00) Beijing, Chongqing, ...... (add-to-list 'diary-outlook-formats '("When: \\([0-9]+\\)[^0-9]+\\([0-9]+\\)[^0-9]+\\([0-9]+\\)[^0-9]+ \\([0-9:-]+\\) [^\n]+ \[^\n]+ \\(?:Where: \\([^\n]+\\)\n+\\)? \\*~\\*~\\*~\\*~\\*~\\*~\\*~\\*~\\*~\\*" . "\\2/\\3/\\1\n \\4 %s, Location: \\5\n"))) (require 'appt) (setq appt-display-format 'window) (appt-activate 1) ; it runs `diary' (require 'epa) (require 'printing) (pr-update-menus) (setq iswitchb-buffer-ignore (quote ("^\\*Completions\\*" "^TAGS$" "^TAGS-LISP$" "^ " "^\\*sent mail to .*\\*" "^\\*sent reply to .*\\*" "^\\*sent wide reply to .*\\*" "^\\*Clock Task Select\\*$" "^\\*Org Clock\\*$" "^\\*anything.*\\*$" "^\\*tramp/sudo .*\\*$" ))) (iswitchb-mode 1) (defun wl-iswitchb-completing-read (prompt choices &optional dummy require-match) "Use iswitchb completion functionality." (let ((iswitchb-make-buflist-hook (lambda () (setq iswitchb-temp-buflist (cond ((consp (car choices)) (mapcar 'car choices)) ((stringp (car choices)) choices) ((symbolp (car choices)) (mapcar 'symbol-name choices)) (t (error "Unknown type of choices."))))))) (iswitchb-read-buffer prompt nil require-match))) (require 'bs) (global-set-key (kbd "C-x C-b") 'bs-show) (require 'uniquify) (setq uniquify-buffer-name-style 'reverse) (setq uniquify-separator "/") (setq uniquify-after-kill-buffer-p t) ; rename after killing uniquified (setq uniquify-ignore-buffers-re "^\\*") ; don't muck with special buffers (autoload 'markdown-mode "markdown-mode.el" "Major mode for editing Markdown files" t) (eval-after-load 'markdown-mode '(add-hook 'markdown-mode-hook 'turn-on-flyspell)) (add-to-list 'load-path "~/elisp/3rd-party-lib/sdcv-mode") (require-maybe 'sdcv-mode) (eval-after-load 'sdcv-mode '(progn (global-set-key (kbd "C-c d") 'sdcv-search) (define-key sdcv-mode-map "S" 'wl-sdcv-save-word))) (setq ispell-program-name "aspell") (set-default 'ispell-local-dictionary "american") (require-maybe 'nxml-mode) (eval-after-load 'nxml-mode '(add-to-list 'auto-mode-alist '("\\.xml$" . nxml-mode))) (require-maybe 'w3m) (eval-after-load 'w3m '(progn (defun wl-w3m-browse-url-in-new-session (url &rest args) "Helper function." (w3m-browse-url url t)) (setq w3m-default-display-inline-images t) (setq browse-url-browser-function 'wl-w3m-browse-url-in-new-session) (setq w3m-use-cookies t) (setq w3m-use-title-buffer-name t))) (setq user-full-name "Liang Wang") (tool-bar-mode -1) (require-maybe 'browse-kill-ring) (when (file-exists-p "~/elisp/3rd-party-lib/yasnippet") (add-to-list 'load-path "~/elisp/3rd-party-lib/yasnippet") ;;; Workaround: do not show menu until I find a way to show menu only ;;; on certain window. (setq yas/use-menu nil) (require-maybe 'yasnippet) (eval-after-load 'yasnippet '(progn (setq yas/snippet-dirs "~/elisp/3rd-party-lib/yasnippet/snippets/") (yas/load-directory yas/snippet-dirs) (define-key global-map (kbd "") 'yas/expand) (define-key global-map (kbd "C-") 'yas/expand) (remove-hook 'after-change-major-mode-hook 'yas/global-mode-enable-in-buffers) (add-hook 'cperl-mode-hook 'yas/minor-mode-on) (add-hook 'perl-mode-hook 'yas/minor-mode-on) (add-hook 'c-mode-common-hook 'yas/minor-mode-on) (add-hook 'html-mode-hook 'yas/minor-mode-on) (add-hook 'org-mode-hook 'yas/minor-mode-on)))) (defun wl-extract-url-from-spam () (interactive) (save-excursion (goto-char (point-min)) (let ((url-list '()) (current-time (current-time-string))) (while (re-search-forward "http://\\(.*?\\)/" nil t) (add-to-list 'url-list (match-string-no-properties 1))) (with-current-buffer (get-buffer-create "*SPAM URL*") (dolist (u url-list) (insert (concat "\\b" u "\\b # " current-time)) (insert "\n")) (replace-string "." "\\." nil (point-min) (point-max))) (switch-to-buffer-other-window "*SPAM URL*")))) (when (require-maybe 'chm-view) (setq chm-view-delay 3)) (defun wl-set-srt-coding-system () "Set srt coding system to chinese-gbk-unix." (interactive) (set-buffer-file-coding-system 'chinese-gbk-unix)) (defun wl-dos2unix () "dos2unix" (interactive) (set-buffer-file-coding-system 'undecided-unix)) (defun wl-unix2dos () "unix2dos" (interactive) (set-buffer-file-coding-system 'undecided-dos)) (add-hook 'after-save-hook 'executable-make-buffer-file-executable-if-script-p) (require 'filecache) (add-to-list 'file-cache-filter-regexps "\\.svn\\>") (add-to-list 'file-cache-filter-regexps "\\.git\\>") (add-to-list 'file-cache-filter-regexps "\\.dep$") (add-to-list 'file-cache-filter-regexps "\\.obj$") ;; (file-cache-add-directory-recursively "~/elisp") (file-cache-add-directory-list '("~/elisp/" "~/elisp/customization/" "~/elisp/scripts/")) (when (and (file-exists-p "~/gtd") (file-directory-p "~/gtd")) (file-cache-add-directory-recursively "~/gtd")) ;; Install hook after setup filecache since it requires `dired'. I ;; don't want `dired-x' is loaded on startup time. (define-key global-map "\C-x\C-j" 'dired-jump) (define-key global-map "\C-x4\C-j" 'dired-jump-other-window) (add-hook 'dired-load-hook (lambda () (load "dired-x") (setq dired-x-hands-off-my-keys nil) (dired-x-bind-find-file))) (defun wl-setup-project (dir) (interactive "DProject root directory: ") (wl-setup-project-1 dir nil)) (defun wl-setup-project-recursively (dir) (interactive "DProject root directory: ") (wl-setup-project-1 dir 'recursively)) (eval-after-load 'etags '(progn (setq tags-revert-without-query t) (defun wl-etags-apropos-symbol (tagname) (interactive (find-tag-interactive "Locate tag: ")) (tags-apropos (concat "\\_<" tagname "\\_>"))) (defadvice find-tag-noselect (around wl-find-tag-noselect (tagname &optional next-p regexp-p)) (let ((case-fold-search nil)) ad-do-it)) (ad-activate 'find-tag-noselect))) (defun wl-visit-tags-table (dir &optional file replace) (unless file (setq file "TAGS")) (let ((tags-filename (expand-file-name "TAGS" dir)) (tags-add-tables (and (not replace) t))) (when (file-readable-p tags-filename) (visit-tags-table tags-filename)))) (defun wl-setup-project-1 (dir recur) (if recur (file-cache-add-directory-recursively dir) (file-cache-add-directory dir)) (wl-visit-tags-table dir)) (defun wl-anything (&optional extra) (interactive "P") (if (and extra wl-more-anything-sources) (progn (require 'info) (anything wl-more-anything-sources)) (if wl-anything-sources (anything wl-anything-sources) (anything)))) (defun wl-yank () (interactive) (let ((anything-enable-digit-shortcuts nil)) (anything-show-kill-ring))) (defun wl-regexp () (interactive) (let ((anything-enable-digit-shortcuts nil)) (anything-regexp))) (defun wl-repeat-matching-complex-command () (interactive) (anything '(anything-c-source-complex-command-history))) (defun wl-bbdb () (interactive) (if anything-c-source-bbdb (anything '(anything-c-source-bbdb)) (bbdb))) (defun wl-org-headline () (interactive) (if anything-c-source-org-headline (anything 'anything-c-source-org-headline) (error "anything-c-source-org-headline unavailable."))) (defvar wl-anything-org-agenda-headline-sources `(((name . "Org headlines in all agenda files") (candidates . (lambda () (org-map-entries (lambda () (when (org-at-heading-p) (concat (buffer-file-name) ":" (int-to-string (line-number-at-pos)) ":" (org-get-heading)))) t 'agenda))) (type . file-line) (after-jump-hook . (lambda () (org-reveal) (org-show-entry)))))) (defun wl-anything-org-agenda-headline () (interactive) (anything wl-anything-org-agenda-headline-sources nil nil nil nil "*anything for org agenda*")) (defun wl-list-tags (file) (with-current-buffer (get-file-buffer tags-file-name) (goto-char (point-min)) (when (re-search-forward (concat "\f\n" (if (< (length default-directory) (length file)) (concat "\\(.*" file "\\|" (substring file (length default-directory)) "\\)") file) ",") nil t) (let (tags) (forward-line 1) (while (not (or (eobp) (looking-at "\f"))) (add-to-list 'tags (cons (car (save-excursion (funcall snarf-tag-function t))) (save-excursion (funcall snarf-tag-function nil)))) (forward-line 1)) tags)))) (defun wl-anything-c-etags-in-current-buffer () (when (buffer-file-name) (let ((file (buffer-file-name)) (first-time t) tags tmp) (while (visit-tags-table-buffer (not first-time)) (setq first-time nil) (setq tmp (wl-list-tags file)) (when tmp (setq tags (append tmp tags)))) tags))) (defvar wl-anything-c-source-etags-in-current-buffer '((name . "Tags") (candidates . (lambda () (when (or tags-file-name tags-table-list) (with-current-buffer anything-current-buffer (wl-anything-c-etags-in-current-buffer))))) (action . (("Find tag" . (lambda (tag-info) (etags-goto-tag-location tag-info))))) (persistent-action . (("Find tag" . (lambda (tag-info) (etags-goto-tag-location tag-info))))))) (defun wl-anything-etags-in-currect-buffer () (interactive) (anything 'wl-anything-c-source-etags-in-current-buffer nil nil nil nil "*anything etags for buffer*")) (eval-after-load 'anything '(progn (setq anything-enable-digit-shortcuts t) (global-set-key (kbd "") 'wl-anything))) (eval-after-load 'anything-config '(progn (setq anything-su-or-sudo "sudo") (setq anything-c-boring-buffer-regexp (concat anything-c-boring-buffer-regexp "\\|\\*tramp/sudo ")) (setq wl-anything-sources ;; temporary remove locate since it reports error which is ;; very annoying (remove 'anything-c-source-locate (append anything-for-files-prefered-list '(anything-c-source-emacs-process anything-c-source-imenu wl-anything-c-source-etags-in-current-buffer)))) (defvar wl-more-anything-sources (remove-duplicates (append '(anything-c-source-complex-command-history anything-c-source-extended-command-history anything-c-source-emacs-functions anything-c-source-emacs-variables anything-c-source-emacs-source-defun anything-c-source-info-elisp anything-c-source-info-pages anything-c-source-elisp-library-scan anything-c-source-man-pages) wl-anything-sources) :from-end t)) (define-key anything-map (kbd "M-o") 'anything-previous-source) (global-set-key (kbd "M-y") 'wl-yank) (global-set-key (kbd "C-x M-:") 'wl-repeat-matching-complex-command))) ;;; With patch from Alan. (eval-after-load 'cc-mode '(progn (setq cc-imenu-c++-generic-expression `( ;; Try to match ::operator definitions first. Otherwise `X::operator new ()' ;; will be incorrectly recognised as function `new ()' because the regexps ;; work by backtracking from the end of the definition. (nil ,(concat "^\\<.*" "[^" c-alnum "_:<>~]" ; match any non-identifier char ; (note: this can be `\n') "\\(" "\\([" c-alnum "_:<>~]*::\\)?" ; match an operator "operator\\>[ \t]*" "\\(()\\|[^(]*\\)" ; special case for `()' operator "\\)" "[ \t]*([^)]*)[ \t]*[^ \t;]" ; followed by ws, arg list, ; require something other than ; a `;' after the (...) to ; avoid prototypes. Can't ; catch cases with () inside ; the parentheses surrounding ; the parameters. e.g.: ; `int foo(int a=bar()) {...}' ) 1) ;; Special case to match a line like `main() {}' ;; e.g. no return type, not even on the previous line. (nil ,(concat "^" "\\([" c-alpha "_][" c-alnum "_:<>~]*\\)" ; match function name "[ \t]*(" ; see above, BUT "[ \t]*\\([^ \t(*][^)]*\\)?)" ; the arg list must not start "[ \t]*[^ \t;(]" ; with an asterisk or parentheses ) 1) ;; General function name regexp (nil ,(concat "^\\<" ; line MUST start with word char ;; \n added to prevent overflow in regexp matcher. ;; http://lists.gnu.org/archive/html/emacs-pretest-bug/2007-02/msg00021.html "[^()\n]*" ; no parentheses before "[^" c-alnum "_:<>~]" ; match any non-identifier char "\\([" c-alpha "_][" c-alnum "_:<>~]*\\)" ; match function name "\\([ \t\n]\\|\\\\\n\\)*(" ; see above, BUT the arg list "\\([ \t\n]\\|\\\\\n\\)*" ; must not start "\\([^ \t\n(*]" ; with an asterisk or parentheses "[^()]*\\(([^()]*)[^()]*\\)*" ; Maybe function pointer arguments "\\)?)" "\\([ \t\n]\\|\\\\\n\\)*[^ \t\n;(]" ) 1) ;; Special case for definitions using phony prototype macros like: ;; `int main _PROTO( (int argc,char *argv[]) )'. ;; This case is only included if cc-imenu-c-prototype-macro-regexp is set. ;; Only supported in c-code, so no `:<>~' chars in function name! ,@(if cc-imenu-c-prototype-macro-regexp `((nil ,(concat "^\\<.*" ; line MUST start with word char "[^" c-alnum "_]" ; match any non-identifier char "\\([" c-alpha "_][" c-alnum "_]*\\)" ; match function name "[ \t]*" ; whitespace before macro name cc-imenu-c-prototype-macro-regexp "[ \t]*(" ; ws followed by first paren. "[ \t]*([^)]*)[ \t]*)[ \t]*[^ \t;]" ; see above ) 1))) ;; Class definitions ("Class" ,(concat "^" ; beginning of line is required "\\(template[ \t]*<[^>]+>[ \t]*\\)?" ; there may be a `template <...>' "\\(class\\|struct\\)[ \t]+" "\\(" ; the string we want to get "[" c-alnum "_]+" ; class name "\\(<[^>]+>\\)?" ; possibly explicitly specialized "\\)" "\\([ \t\n]\\|\\\\\n\\)*[:{]" ) 3))) (setq cc-imenu-c-generic-expression cc-imenu-c++-generic-expression))) (require 'imenu) (require-maybe 'anything) (setq anything-command-map-prefix-key "") (require-maybe 'anything-config) (require-maybe 'auto-complete) (eval-after-load 'auto-complete '(progn (global-auto-complete-mode t) (define-key ac-complete-mode-map "\C-n" 'ac-next) (define-key ac-complete-mode-map "\C-p" 'ac-previous) (setq ac-auto-start nil) (defun wl-ac-start () (interactive) (setq ac-auto-start 6) (ac-start)) (defadvice ac-cleanup (after wl-ac-cleanup ()) (setq ac-auto-start nil)) (ad-activate 'ac-cleanup) (define-key global-map (kbd "") 'wl-ac-start) (add-hook 'emacs-lisp-mode-hook (lambda () (make-local-variable 'ac-sources) (setq ac-sources '(ac-source-words-in-buffer ac-source-symbols)))) (defvar ac-source-etags '((candidates . (lambda () (all-completions ac-target (tags-completion-table)))))) (defun wl-add-ac-source-etags () (make-local-variable 'ac-sources) (add-to-list 'ac-sources 'ac-source-etags)) (add-hook 'c-mode-common-hook 'wl-add-ac-source-etags))) (global-set-key (kbd "M-/") 'hippie-expand) (setq hippie-expand-try-functions-list '(try-expand-all-abbrevs try-expand-dabbrev try-expand-dabbrev-all-buffers try-expand-dabbrev-from-kill try-complete-lisp-symbol-partially try-complete-lisp-symbol try-complete-file-name-partially try-complete-file-name)) (when (string-lessp "23.2" emacs-version) (setq tab-always-indent 'complete) (setq completion-styles (append completion-styles '(initials)))) (defun wl-sudo-find-file (file dir) (find-file (concat "/sudo:localhost:" (expand-file-name file dir)))) (defun wl-customize-frame () (interactive) (if window-system (progn (scroll-bar-mode -1) (setq x-select-enable-clipboard t)) (xterm-mouse-mode))) (if (and (fboundp 'daemonp) (daemonp)) (add-hook 'after-make-frame-functions (lambda (frame) (with-selected-frame frame (wl-customize-frame)))) (wl-customize-frame)) ;;; The Words (defvar wl-the-words-filename "~/gtd/words.org") (defvar wl-sdcv-current-word nil) (defun wl-sdcv-search-word () (unless (eq major-mode 'sdcv-mode) (error "Not in sdcv-mode")) (save-excursion (goto-char (point-min)) (when (re-search-forward (concat outline-regexp "\\\(.*\\\)" "\n")) (match-string 1)))) (defun wl-sdcv-handle-word (handler) (let ((word (wl-sdcv-search-word))) (if word (funcall handler word) (message "Word not found")))) (defun wl-sdcv-save-word () (interactive) (wl-sdcv-handle-word 'wl-append-word-to-file)) (defun wl-echo-sdcv-search-word () (interactive) (let ((word (wl-sdcv-search-word))) (if word (message "%s" word) (message "Word not found")))) (defun wl-append-to-file (filename content) (with-temp-buffer (insert content) (append-to-file (point-min) (point-max) filename))) (defun wl-org-current-date-inactive () (let ((now (decode-time))) (format "[%4d-%2d-%2d %s]" (nth 5 now) (nth 4 now) (nth 3 now) (cond ((= (nth 6 now) 0) "Sun") ((= (nth 6 now) 1) "Mon") ((= (nth 6 now) 2) "Tue") ((= (nth 6 now) 3) "Wed") ((= (nth 6 now) 4) "Thu") ((= (nth 6 now) 5) "Fri") ((= (nth 6 now) 6) "Sat"))))) (defun wl-append-word-to-file (word) (interactive "sWord: ") (unless (file-exists-p wl-the-words-filename) (wl-append-to-file wl-the-words-filename "-*- org -*-\n\n# This file saves list of words to remember and review\n\n")) (with-temp-buffer (insert-file-contents wl-the-words-filename) (unless (re-search-forward (concat "^\\\* " word "$") nil t) (wl-append-to-file wl-the-words-filename (concat "* " word "\n" " :PROPERTIES:\n" " :CREATED: " (wl-org-current-date-inactive) "\n" " :END:\n\n"))))) (defun wl-append-word-to-file-at-point () (interactive) (let ((word (thing-at-point 'word))) (wl-append-word-to-file word))) ;;; Search Dictionary Interface (defvar wl-search-dictionary-function (if (fboundp 'sdcv-search-word) 'sdcv-search-word nil)) (defun wl-search-word (word) (interactive "sWord: ") (funcall wl-search-dictionary-function word)) (defun wl-search-word-at-point () (interactive) (wl-search-word (thing-at-point 'word))) ;;; Dictionary in anything (defun wl-anything-search-word () (interactive) (anything '(((name . "Search Word") (candidates . (lambda () (list anything-input))) (action ("Search Word" . wl-search-word) ("Search Word in StarDict" . sdcv-search-word)) (volatile))))) (defun wl-anything-search-word-at-point () (interactive) (anything '(((name . "Search Word") (candidates . (lambda () (list anything-input))) (action ("Search Word" . wl-search-word) ("Search Word in StarDict" . sdcv-search-word)) (volatile))) (thing-at-point 'word))) ;;; Find files (defvar wl-find-file-completing-read-function 'wl-iswitchb-completing-read) (defun wl-find-file-root (filename root-list) (find-if (lambda (dir) (when (> (length filename) (length dir)) (string-equal dir (substring filename 0 (length dir))))) root-list)) (defun wl-find-file-in-other-root (filename dir root-list) (let* ((root (wl-find-file-root filename root-list)) (relative-path (substring filename (length root)))) (find-file-existing (expand-file-name relative-path dir)))) (defun wl-find-file-other-root-list (filename root-list-list) (when root-list-list (let ((root (wl-find-file-root filename (car root-list-list)))) (if root (list root (car root-list-list)) (wl-find-file-other-root-list filename (cdr root-list-list)))))) (defvar wl-find-file-gcc-root-list nil) (defvar wl-find-file-binutils-root-list nil) (defun wl-binutils-find-buffer-file-in-other-root (dir) (interactive (list (let ((completion-ignore-case t) (root (wl-find-file-root (buffer-file-name) wl-find-file-binutils-root-list))) (funcall wl-find-file-completing-read-function "Open file in: " (remove-if (lambda (elem) (string-equal elem root)) wl-find-file-binutils-root-list))))) (wl-find-file-in-other-root (buffer-file-name) dir wl-find-file-binutils-root-list)) (defun wl-gcc-find-buffer-file-in-other-root (dir) (interactive (list (let ((completion-ignore-case t) (root (wl-find-file-root (buffer-file-name) wl-find-file-gcc-root-list))) (funcall wl-find-file-completing-read-function "Open file in: " (remove-if (lambda (elem) (string-equal elem root)) wl-find-file-gcc-root-list))))) (wl-find-file-in-other-root (buffer-file-name) dir wl-find-file-gcc-root-list)) (defun wl-find-other-file-1 (filename &rest root-list-list) (let* ((root (wl-find-file-other-root-list filename root-list-list)) (relative-path (substring filename (length (car root))))) (remove-if (lambda (file) (not (file-exists-p file))) (mapcar (lambda (dir) (expand-file-name relative-path dir)) (remove-if (lambda (elem) (string-equal elem (car root))) (cadr root)))))) (defun wl-find-other-file-other-window (filename) (interactive (list (let ((completion-ignore-case t) (file-list (wl-find-other-file-1 (buffer-file-name) wl-find-file-gcc-root-list wl-find-file-binutils-root-list))) (if file-list (funcall wl-find-file-completing-read-function "Open file: " file-list) (error "%s does not exist in other directories" (file-name-nondirectory (buffer-file-name))))))) (find-file-other-window filename)) (when (file-exists-p "~/elisp/3rd-party-lib/ace-jump-mode/") (add-to-list 'load-path "~/elisp/3rd-party-lib/ace-jump-mode/") (require-maybe 'ace-jump-mode) (eval-after-load 'ace-jump-mode '(progn (define-key global-map (kbd "C-c SPC") 'ace-jump-mode)))) (defun wl-find-files (directory &optional full-name match-regexp nosort) (let (result) (wl-find-files-1 directory full-name match-regexp nosort result))) (defun wl-find-files-1 (directory full-name match-regexp nosort result) (let ((level-1-match (directory-files directory full-name match-regexp nosort))) (when (not (null level-1-match)) (setq result (append result level-1-match)))) (let ((level-1-all (directory-files directory))) (dolist (file level-1-all) (let ((file-in-dir (expand-file-name file directory))) (when (and (file-directory-p file-in-dir) (not (string-equal file ".")) (not (string-equal file ".."))) (setq result (wl-find-files-1 file-in-dir full-name match-regexp nosort result)))))) result) (require 'wl-patches) (provide 'wl-generic)