Mercurial > dotfiles
comparison .elisp/textmate.el @ 22:8715ccb6f61b
Start using textmate.el.
author | Augie Fackler <durin42@gmail.com> |
---|---|
date | Fri, 12 Dec 2008 09:38:16 -0600 |
parents | |
children | d6fd2964258c |
comparison
equal
deleted
inserted
replaced
21:b465892f75e4 | 22:8715ccb6f61b |
---|---|
1 ;; textmate.el --- TextMate minor mode for Emacs | |
2 | |
3 ;; Copyright (C) 2008 Chris Wanstrath <chris@ozmm.org> | |
4 | |
5 ;; Licensed under the same terms as Emacs. | |
6 | |
7 ;; Version: 0.1.0 | |
8 ;; Keywords: textmate osx mac | |
9 ;; Created: 22 Nov 2008 | |
10 ;; Author: Chris Wanstrath <chris@ozmm.org> | |
11 | |
12 ;; This file is NOT part of GNU Emacs. | |
13 | |
14 ;; Licensed under the same terms as Emacs. | |
15 | |
16 ;;; Commentary: | |
17 | |
18 ;; This minor mode exists to mimick TextMate's awesome | |
19 ;; features. | |
20 | |
21 ;; ⌘T - Go to File | |
22 ;; ⇧⌘T - Go to Symbol | |
23 ;; ⌘L - Go to Line | |
24 ;; ⌘/ - Comment Line (or Selection/Region) | |
25 ;; ⌘] - Shift Right (currently indents region) | |
26 ;; ⌘[ - Shift Left (not yet implemented) | |
27 ;; ⌥⌘] - Align Assignments | |
28 ;; ⌥⌘[ - Indent Line | |
29 ;; ⌘RET - Insert Newline at Line's End | |
30 ;; ⌥⌘T - Reset File Cache (for Go to File) | |
31 | |
32 ;; A "project" in textmate-mode is determined by the presence of | |
33 ;; a .git directory. If no .git directory is found in your current | |
34 ;; directory, textmate-mode will traverse upwards until one (or none) | |
35 ;; is found. The directory housing the .git directory is presumed | |
36 ;; to be the project's root. | |
37 | |
38 ;; In other words, calling Go to File from | |
39 ;; ~/Projects/fieldrunners/app/views/towers/show.html.erb will use | |
40 ;; ~/Projects/fieldrunners/ as the root if ~/Projects/fieldrunners/.git | |
41 ;; exists. | |
42 | |
43 ;;; Installation | |
44 | |
45 ;; $ cd ~/.emacs.d/vendor | |
46 ;; $ git clone git://github.com/defunkt/textmate.el.git | |
47 ;; | |
48 ;; In your emacs config: | |
49 ;; | |
50 ;; (add-to-list 'load-path "~/.emacs.d/vendor/textmate.el") | |
51 ;; (require 'textmate) | |
52 ;; (textmate-mode) | |
53 | |
54 ;;; Depends on imenu | |
55 (require 'imenu) | |
56 | |
57 ;;; Minor mode | |
58 | |
59 (defvar textmate-use-file-cache t | |
60 "* Should `textmate-goto-file' keep a local cache of files?") | |
61 | |
62 (defvar textmate-completing-library 'ido | |
63 "The library `textmade-goto-symbol' and `textmate-goto-file' should use for completing filenames and symbols (`ido' by default)") | |
64 | |
65 (defvar *textmate-completing-function-alist* '((ido ido-completing-read) | |
66 (icicles icicle-completing-read) | |
67 (none completing-read)) | |
68 "The function to call to read file names and symbols from the user") | |
69 | |
70 (defvar *textmate-completing-minor-mode-alist* | |
71 `((ido ,(lambda (a) (progn (ido-mode a) (setq ido-enable-flex-matching t)))) | |
72 (icicles ,(lambda (a) (icy-mode a))) | |
73 (none ,(lambda (a) ()))) | |
74 "The list of functions to enable and disable completing minor modes") | |
75 | |
76 (defvar *textmate-mode-map* (make-sparse-keymap)) | |
77 (defvar *textmate-project-root* nil) | |
78 (defvar *textmate-project-files* '()) | |
79 (defvar *textmate-gf-exclude* | |
80 "/\\.|vendor|fixtures|tmp|log|build|\\.xcodeproj|\\.nib|\\.framework|\\.app|\\.pbproj|\\.pbxproj|\\.xcode|\\.xcodeproj|\\.bundle") | |
81 | |
82 (defvar *textmate-keybindings-list* `((textmate-next-line | |
83 [A-return] [M-return]) | |
84 (textmate-clear-cache | |
85 ,(kbd "A-M-t") [(control c)(control t)]) | |
86 (align | |
87 ,(kbd "A-M-]") [(control c)(control a)]) | |
88 (indent-according-to-mode | |
89 ,(kbd "A-M-[") nil) | |
90 (indent-region | |
91 ,(kbd "A-]") [(control tab)]) | |
92 (comment-or-uncomment-region-or-line | |
93 ,(kbd "A-/") [(control c)(control k)]) | |
94 (textmate-goto-file | |
95 ,(kbd "A-t") [(meta t)]) | |
96 (textmate-goto-symbol | |
97 ,(kbd "A-T") [(meta T)]))) | |
98 | |
99 (defvar *textmate-project-root-p* | |
100 #'(lambda (coll) (or (member ".git" coll) | |
101 (member ".hg" coll) | |
102 )) | |
103 "*Lambda that, given a collection of directory entries, returns | |
104 non-nil if it represents the project root.") | |
105 | |
106 ;;; Bindings | |
107 | |
108 (defun textmate-ido-fix () | |
109 "Add up/down keybindings for ido." | |
110 (define-key ido-completion-map [up] 'ido-prev-match) | |
111 (define-key ido-completion-map [down] 'ido-next-match)) | |
112 | |
113 (defun textmate-bind-keys () | |
114 (add-hook 'ido-setup-hook 'textmate-ido-fix) | |
115 | |
116 ; weakness until i figure out how to do this right | |
117 (when (boundp 'osx-key-mode-map) | |
118 (define-key osx-key-mode-map (kbd "A-t") 'textmate-goto-file) | |
119 (define-key osx-key-mode-map (kbd "A-T") 'textmate-goto-symbol)) | |
120 | |
121 (let ((member) (i 0) (access (if (boundp 'aquamacs-version) 'cadr 'caddr))) | |
122 (setq member (nth i *textmate-keybindings-list*)) | |
123 (while member | |
124 (if (funcall access member) | |
125 (define-key *textmate-mode-map* (funcall access member) (car member))) | |
126 (setq member (nth i *textmate-keybindings-list*)) | |
127 (setq i (+ i 1))))) | |
128 | |
129 (defun textmate-completing-read (&rest args) | |
130 (let ((reading-fn (cadr (assoc textmate-completing-library *textmate-completing-function-alist*)))) | |
131 (apply (symbol-function reading-fn) args))) | |
132 | |
133 ;;; Commands | |
134 | |
135 (defun textmate-next-line () | |
136 (interactive) | |
137 (end-of-line) | |
138 (newline-and-indent)) | |
139 | |
140 ;; http://chopmo.blogspot.com/2008/09/quickly-jumping-to-symbols.html | |
141 (defun textmate-goto-symbol () | |
142 "Will update the imenu index and then use ido to select a symbol to navigate to" | |
143 (interactive) | |
144 (imenu--make-index-alist) | |
145 (let ((name-and-pos '()) | |
146 (symbol-names '())) | |
147 (flet ((addsymbols (symbol-list) | |
148 (when (listp symbol-list) | |
149 (dolist (symbol symbol-list) | |
150 (let ((name nil) (position nil)) | |
151 (cond | |
152 ((and (listp symbol) (imenu--subalist-p symbol)) | |
153 (addsymbols symbol)) | |
154 | |
155 ((listp symbol) | |
156 (setq name (car symbol)) | |
157 (setq position (cdr symbol))) | |
158 | |
159 ((stringp symbol) | |
160 (setq name symbol) | |
161 (setq position (get-text-property 1 'org-imenu-marker symbol)))) | |
162 | |
163 (unless (or (null position) (null name)) | |
164 (add-to-list 'symbol-names name) | |
165 (add-to-list 'name-and-pos (cons name position)))))))) | |
166 (addsymbols imenu--index-alist)) | |
167 (let* ((selected-symbol (textmate-completing-read "Symbol: " symbol-names)) | |
168 (position (cdr (assoc selected-symbol name-and-pos)))) | |
169 (goto-char position)))) | |
170 | |
171 (defun textmate-goto-file () | |
172 (interactive) | |
173 (let ((root (textmate-project-root))) | |
174 (when (null root) | |
175 (error "Can't find any .git directory")) | |
176 (find-file | |
177 (concat | |
178 (expand-file-name root) "/" | |
179 (textmate-completing-read | |
180 "Find file: " | |
181 (textmate-cached-project-files root)))))) | |
182 | |
183 (defun textmate-clear-cache () | |
184 (interactive) | |
185 (setq *textmate-project-root* nil) | |
186 (setq *textmate-project-files* nil) | |
187 (message "textmate-mode cache cleared.")) | |
188 | |
189 ;;; Utilities | |
190 | |
191 (defun textmate-also-ignore (pattern) | |
192 "Also ignore PATTERN in project files." | |
193 (setq *textmate-gf-exclude* | |
194 (concat *textmate-gf-exclude* "|" pattern))) | |
195 | |
196 (defun textmate-project-files (root) | |
197 (split-string | |
198 (shell-command-to-string | |
199 (concat | |
200 "find " | |
201 root | |
202 " -type f | grep -vE '" | |
203 *textmate-gf-exclude* | |
204 "' | sed 's:" | |
205 *textmate-project-root* | |
206 "/::'")) "\n" t)) | |
207 | |
208 (defun textmate-cached-project-files (&optional root) | |
209 (cond | |
210 ((null textmate-use-file-cache) (textmate-project-files root)) | |
211 ((equal (textmate-project-root) (car *textmate-project-files*)) | |
212 (cdr *textmate-project-files*)) | |
213 (t (cdr (setq *textmate-project-files* | |
214 `(,root . ,(textmate-project-files root))))))) | |
215 | |
216 (defun textmate-project-root () | |
217 (when (or | |
218 (null *textmate-project-root*) | |
219 (not (string-match *textmate-project-root* default-directory))) | |
220 (let ((root (textmate-find-project-root))) | |
221 (if root | |
222 (setq *textmate-project-root* (expand-file-name (concat root "/"))) | |
223 (setq *textmate-project-root* nil)))) | |
224 *textmate-project-root*) | |
225 | |
226 (defun textmate-find-project-root (&optional root) | |
227 (when (null root) (setq root default-directory)) | |
228 (cond | |
229 ((funcall *textmate-project-root-p* (directory-files root)) | |
230 (expand-file-name root)) | |
231 ((equal (expand-file-name root) "/") nil) | |
232 (t (textmate-find-project-root (concat (file-name-as-directory root) ".."))))) | |
233 | |
234 ;;;###autoload | |
235 (define-minor-mode textmate-mode "TextMate Emulation Minor Mode" | |
236 :lighter " mate" :global t :keymap *textmate-mode-map* | |
237 (textmate-bind-keys) | |
238 ; activate preferred completion library | |
239 (dolist (mode *textmate-completing-minor-mode-alist*) | |
240 (if (eq (car mode) textmate-completing-library) | |
241 (funcall (cadr mode) t) | |
242 (when (fboundp | |
243 (cadr (assoc (car mode) *textmate-completing-function-alist*))) | |
244 (funcall (cadr mode) -1))))) | |
245 | |
246 (provide 'textmate) | |
247 ;;; textmate.el ends here |