Mercurial > dotfiles
comparison .elisp/textmate.el @ 152:a24d5587386f
textmate.el: update to latest version
author | Augie Fackler <durin42@gmail.com> |
---|---|
date | Fri, 09 Oct 2009 21:48:03 -0400 |
parents | e30655eb7050 |
children | 668268f29a88 |
comparison
equal
deleted
inserted
replaced
151:bf6b5a0dc1f3 | 152:a24d5587386f |
---|---|
1 ;; textmate.el --- TextMate minor mode for Emacs | 1 ;; textmate.el --- TextMate minor mode for Emacs |
2 | 2 |
3 ;; Copyright (C) 2008 Chris Wanstrath <chris@ozmm.org> and others | 3 ;; Copyright (C) 2008, 2009 Chris Wanstrath <chris@ozmm.org> and others |
4 | 4 |
5 ;; Licensed under the same terms as Emacs. | 5 ;; Licensed under the same terms as Emacs. |
6 | 6 |
7 ;; Version: 0.1.0 | |
8 ;; Keywords: textmate osx mac | 7 ;; Keywords: textmate osx mac |
9 ;; Created: 22 Nov 2008 | 8 ;; Created: 22 Nov 2008 |
10 ;; Author: Chris Wanstrath <chris@ozmm.org> and others | 9 ;; Author: Chris Wanstrath <chris@ozmm.org> and others |
11 | 10 |
12 ;; This file is NOT part of GNU Emacs. | 11 ;; This file is NOT part of GNU Emacs. |
28 ;; ⌥⌘T - Reset File Cache (for Go to File, cache unused if using git/hg root, | 27 ;; ⌥⌘T - Reset File Cache (for Go to File, cache unused if using git/hg root, |
29 ;; but resets cached root location, useful if roots | 28 ;; but resets cached root location, useful if roots |
30 ;; are nested) | 29 ;; are nested) |
31 | 30 |
32 ;; A "project" in textmate-mode is determined by the presence of | 31 ;; A "project" in textmate-mode is determined by the presence of |
33 ;; a .git directory. If no .git directory is found in your current | 32 ;; a .git directory, an .hg directory, a Rakefile, or a Makefile. |
34 ;; directory, textmate-mode will traverse upwards until one (or none) | 33 |
35 ;; is found. The directory housing the .git directory is presumed | 34 ;; You can configure what makes a project root by appending a file |
36 ;; to be the project's root. | 35 ;; or directory name onto the `*textmate-project-roots*' list. |
36 | |
37 ;; If no project root indicator is found in your current directory, | |
38 ;; textmate-mode will traverse upwards until one (or none) is found. | |
39 ;; The directory housing the project root indicator (e.g. a .git or .hg | |
40 ;; directory) is presumed to be the project's root. | |
37 | 41 |
38 ;; In other words, calling Go to File from | 42 ;; In other words, calling Go to File from |
39 ;; ~/Projects/fieldrunners/app/views/towers/show.html.erb will use | 43 ;; ~/Projects/fieldrunners/app/views/towers/show.html.erb will use |
40 ;; ~/Projects/fieldrunners/ as the root if ~/Projects/fieldrunners/.git | 44 ;; ~/Projects/fieldrunners/ as the root if ~/Projects/fieldrunners/.git |
41 ;; exists. | 45 ;; exists. |
46 | |
47 ;; In the event that the project root was defined by either .git or .hg, | |
48 ;; fast file-listing with no caching is provided by the version control | |
49 ;; system. | |
50 | |
51 ;; Not bound to keys, but available are textmate-find-in-project and | |
52 ;; textmate-find-in-project-type, which use grep, the file listing, | |
53 ;; and grep-mode to provide excellent (and blindingly fast with git and | |
54 ;; hg!) grep integration with emacs and your project. | |
55 | |
56 ;; Also available (and unbound) is textmate-compile, which is like | |
57 ;; compile but prepends a cd to the project root to the command. It is | |
58 ;; used to build the find-in-project commands, but has other possible | |
59 ;; uses as well (eg, a test runner or some kind of compile command). | |
42 | 60 |
43 ;;; Installation | 61 ;;; Installation |
44 | 62 |
45 ;; $ cd ~/.emacs.d/vendor | 63 ;; $ cd ~/.emacs.d/vendor |
46 ;; $ git clone git://github.com/defunkt/textmate.el.git | 64 ;; $ git clone git://github.com/defunkt/textmate.el.git |
58 (eval-when-compile | 76 (eval-when-compile |
59 (require 'cl)) | 77 (require 'cl)) |
60 | 78 |
61 ;;; Minor mode | 79 ;;; Minor mode |
62 | 80 |
81 (defvar *textmate-gf-exclude* | |
82 "/\\.|vendor|fixtures|tmp|log|build|\\.xcodeproj|\\.nib|\\.framework|\\.app|\\.pbproj|\\.pbxproj|\\.xcode|\\.xcodeproj|\\.bundle|\\.pyc" | |
83 "Regexp of files to exclude from `textmate-goto-file'.") | |
84 | |
85 (defvar *textmate-project-roots* | |
86 '(".git" ".hg" "Rakefile" "Makefile" "README" "build.xml") | |
87 "The presence of any file/directory in this list indicates a project root.") | |
88 | |
63 (defvar textmate-use-file-cache t | 89 (defvar textmate-use-file-cache t |
64 "* Should `textmate-goto-file' keep a local cache of files?") | 90 "Should `textmate-goto-file' keep a local cache of files?") |
65 | 91 |
66 (defvar textmate-completing-library 'ido | 92 (defvar textmate-completing-library 'ido |
67 "The library `textmade-goto-symbol' and `textmate-goto-file' should use for completing filenames and symbols (`ido' by default)") | 93 "The library `textmade-goto-symbol' and `textmate-goto-file' should use for |
94 completing filenames and symbols (`ido' by default)") | |
68 | 95 |
69 (defvar *textmate-completing-function-alist* '((ido ido-completing-read) | 96 (defvar *textmate-completing-function-alist* '((ido ido-completing-read) |
70 (icicles icicle-completing-read) | 97 (icicles icicle-completing-read) |
71 (none completing-read)) | 98 (none completing-read)) |
72 "The function to call to read file names and symbols from the user") | 99 "The function to call to read file names and symbols from the user") |
118 (define-key map [(control c)(control k)] 'comment-or-uncomment-region-or-line) | 145 (define-key map [(control c)(control k)] 'comment-or-uncomment-region-or-line) |
119 (define-key map [(meta t)] 'textmate-goto-file) | 146 (define-key map [(meta t)] 'textmate-goto-file) |
120 (define-key map [(meta shift t)] 'textmate-goto-symbol))) | 147 (define-key map [(meta shift t)] 'textmate-goto-symbol))) |
121 map)) | 148 map)) |
122 | 149 |
123 | 150 (defvar *textmate-project-root* nil |
124 (defvar *textmate-project-root* nil) | 151 "Used internally to cache the project root.") |
125 (defvar *textmate-project-files* '()) | 152 (defvar *textmate-project-files* '() |
126 | 153 "Used internally to cache the files in a project.") |
127 (defvar *textmate-gf-exclude* | |
128 "/\\.|vendor|fixtures|tmp|log|build|\\.xcodeproj|\\.nib|\\.framework|\\.app|\\.pbproj|\\.pbxproj|\\.xcode|\\.xcodeproj|\\.bundle|\\.pyc") | |
129 | |
130 (defvar *textmate-project-roots* | |
131 '(".git" ".hg" "Rakefile" "Makefile" "README" "build.xml")) | |
132 | 154 |
133 (defvar *textmate-vcs-exclude* nil | 155 (defvar *textmate-vcs-exclude* nil |
134 "string to give to grep -V to exclude some VCS paths from being grepped." | 156 "string to give to grep -V to exclude some VCS paths from being grepped." |
135 ) | 157 ) |
136 | 158 |
137 (defvar *textmate-find-in-project-default* nil) | 159 (defvar *textmate-find-in-project-default* nil) |
138 | 160 |
139 (defvar *textmate-find-in-project-type-default* nil) | 161 (defvar *textmate-find-in-project-type-default* nil) |
162 | |
163 (defvar *textmate-compile-default* nil) | |
140 | 164 |
141 ;;; Bindings | 165 ;;; Bindings |
142 | 166 |
143 (defun textmate-ido-fix () | 167 (defun textmate-ido-fix () |
144 "Add up/down keybindings for ido." | 168 "Add up/down keybindings for ido." |
145 (define-key ido-completion-map [up] 'ido-prev-match) | 169 (define-key ido-completion-map [up] 'ido-prev-match) |
146 (define-key ido-completion-map [down] 'ido-next-match)) | 170 (define-key ido-completion-map [down] 'ido-next-match)) |
147 | 171 |
148 (defun textmate-completing-read (&rest args) | 172 (defun textmate-completing-read (&rest args) |
149 (let ((reading-fn (cadr (assoc textmate-completing-library *textmate-completing-function-alist*)))) | 173 "Uses `*textmate-completing-function-alist*' to call the appropriate completing |
174 function." | |
175 (let ((reading-fn | |
176 (cadr (assoc textmate-completing-library | |
177 *textmate-completing-function-alist*)))) | |
150 (apply (symbol-function reading-fn) args))) | 178 (apply (symbol-function reading-fn) args))) |
151 | 179 |
152 ;;; allow-line-as-region-for-function adds an "-or-line" version of | 180 ;;; allow-line-as-region-for-function adds an "-or-line" version of |
153 ;;; the given comment function which (un)comments the current line is | 181 ;;; the given comment function which (un)comments the current line is |
154 ;;; the mark is not active. This code comes from Aquamac's osxkeys.el | 182 ;;; the mark is not active. This code comes from Aquamac's osxkeys.el |
174 (allow-line-as-region-for-function comment-or-uncomment-region))) | 202 (allow-line-as-region-for-function comment-or-uncomment-region))) |
175 | 203 |
176 ;;; Commands | 204 ;;; Commands |
177 | 205 |
178 (defun textmate-next-line () | 206 (defun textmate-next-line () |
207 "Inserts an indented newline after the current line and moves the point to it." | |
179 (interactive) | 208 (interactive) |
180 (end-of-line) | 209 (end-of-line) |
181 (newline-and-indent)) | 210 (newline-and-indent)) |
182 | 211 |
183 ;; http://chopmo.blogspot.com/2008/09/quickly-jumping-to-symbols.html | 212 ;; http://chopmo.blogspot.com/2008/09/quickly-jumping-to-symbols.html |
222 (let* ((selected-symbol (ido-completing-read "Symbol? " symbol-names)) | 251 (let* ((selected-symbol (ido-completing-read "Symbol? " symbol-names)) |
223 (position (cdr (assoc selected-symbol name-and-pos)))) | 252 (position (cdr (assoc selected-symbol name-and-pos)))) |
224 (goto-char position)))) | 253 (goto-char position)))) |
225 | 254 |
226 (defun textmate-goto-file () | 255 (defun textmate-goto-file () |
256 "Uses your completing read to quickly jump to a file in a project." | |
227 (interactive) | 257 (interactive) |
228 (let ((root (textmate-project-root))) | 258 (let ((root (textmate-project-root))) |
229 (when (null root) | 259 (when (null root) |
230 (error | 260 (error |
231 (concat | 261 (concat |
232 "Can't find a sutiable project root (" | 262 "Can't find a suitable project root (" |
233 (string-join " " *textmate-project-roots* ) | 263 (string-join " " *textmate-project-roots* ) |
234 ")"))) | 264 ")"))) |
235 (find-file | 265 (find-file |
236 (concat | 266 (concat |
237 (expand-file-name root) "/" | 267 (expand-file-name root) "/" |
238 (textmate-completing-read | 268 (textmate-completing-read |
239 "Find file: " | 269 "Find file: " |
240 (textmate-project-files root)))))) | 270 (textmate-project-files root)))))) |
241 | 271 |
242 (defun textmate-find-in-project-type () | 272 (defun textmate-find-in-project-type () |
273 "Run grep over project files of a specific type and put the results | |
274 in a grep-mode buffer." | |
243 (interactive) | 275 (interactive) |
244 (let ((pat (read-string (concat "Suffix" | 276 (let ((pat (read-string (concat "Suffix" |
245 (if *textmate-find-in-project-type-default* | 277 (if *textmate-find-in-project-type-default* |
246 (format " [\"%s\"]" *textmate-find-in-project-type-default*) | 278 (format " [\"%s\"]" *textmate-find-in-project-type-default*) |
247 "") | 279 "") |
248 ": " | 280 ": " |
249 ) nil nil *textmate-find-in-project-type-default*))) | 281 ) nil nil *textmate-find-in-project-type-default*))) |
250 (setq *textmate-find-in-project-type-default* pat) | 282 (setq *textmate-find-in-project-type-default* pat) |
251 (textmate-find-in-project (concat "*." pat)))) | 283 (textmate-find-in-project (concat "*." pat)))) |
252 | 284 |
253 (defun textmate-find-in-project (&optional pattern) | 285 (defun textmate-start-compile-in-root (command &optional mode |
254 (interactive) | 286 name-function |
255 (let ((root (textmate-project-root)) | 287 highlight-regexp) |
256 (default *textmate-find-in-project-default*) | 288 "Idential to compilation-start, except it automatically changes to the |
257 ) | 289 project root directory before starting the command." |
290 (let ((root (textmate-project-root))) | |
258 (when (null root) | 291 (when (null root) |
259 (error "Not in a project area.")) | 292 (error "Not in a project area.")) |
260 (let ((re (read-string (concat "Search for " | 293 (let ((realcommand (concat "cd " root " ; " command))) |
294 (compilation-start realcommand mode name-function highlight-regexp)))) | |
295 | |
296 (defun textmate-compile () | |
297 "Run a command in compilation-mode rooted at the project root." | |
298 (interactive) | |
299 (let* ((default *textmate-compile-default*) | |
300 (command (read-string | |
301 (concat "Command" | |
302 (if default (format " [\"%s\"]" default) "") | |
303 ": ") nil 'textmate-compile-history default))) | |
304 (setq *textmate-compile-default* command) | |
305 (textmate-start-compile-in-root command))) | |
306 | |
307 (defun textmate-find-in-project (&optional pattern) | |
308 "Run grep over project files with results in grep-mode. | |
309 | |
310 Takes an optional argument (see also textmate-find-in-project-type) | |
311 of a file extension to limit the search. Useful for finding results in only a | |
312 specific type of file." | |
313 (interactive) | |
314 (let* ((default *textmate-find-in-project-default*) | |
315 (re (read-string (concat "Search for " | |
261 (if (and default (> (length default) 0)) | 316 (if (and default (> (length default) 0)) |
262 (format "[\"%s\"]" default)) ": ") | 317 (format "[\"%s\"]" default)) ": ") |
263 nil 'textmate-find-in-project-history default) | 318 nil 'textmate-find-in-project-history default)) |
264 ) | 319 (incpat (if pattern pattern "*")) |
265 (incpat (if pattern pattern "*"))) | 320 (type (textmate-project-root-type (textmate-project-root))) |
266 (append textmate-find-in-project-history (list re)) | 321 (command |
267 (setq *textmate-find-in-project-default* re) | 322 (cond ((not (string= type "unknown")) |
268 (let ((type (textmate-project-root-type root))) | 323 (concat (cond ((string= type "git") "git ls-files") |
269 (let ((command | |
270 (cond ((not (string= type "unknown")) | |
271 (concat "cd " | |
272 root | |
273 " ; " | |
274 (cond ((string= type "git") "git ls-files") | |
275 ((string= type "hg") "hg manifest")) | 324 ((string= type "hg") "hg manifest")) |
276 (if *textmate-vcs-exclude* | 325 (if *textmate-vcs-exclude* |
277 (concat " | grep -v " (shell-quote-argument *textmate-vcs-exclude*)) | 326 (concat " | grep -v " |
327 (shell-quote-argument *textmate-vcs-exclude*)) | |
278 "") | 328 "") |
279 " | xargs grep -nR " | 329 " | xargs grep -nR " |
280 (if pattern (concat " --include='" pattern "' ") "") | 330 (if pattern (concat " --include='" pattern "' ") "") |
281 " -- " | 331 " -- " |
282 (shell-quote-argument re))) | 332 (shell-quote-argument re))) |
283 (t (concat "cd " root "; egrep -nR --exclude='" | 333 (t (concat "egrep -nR --exclude='" |
284 *textmate-gf-exclude* | 334 *textmate-gf-exclude* |
285 "' --include='" | 335 "' --include='" |
286 incpat | 336 incpat |
287 "' -- " | 337 "' -- " |
288 (shell-quote-argument re) | 338 (shell-quote-argument re) |
289 " . | grep -vE '" | 339 " . | grep -vE '" |
290 *textmate-gf-exclude* | 340 *textmate-gf-exclude* |
291 "' | sed s:./::" | 341 "' | sed s:./::" |
292 ))))) | 342 ))))) |
293 (compilation-start command 'grep-mode))) | 343 (setq *textmate-find-in-project-default* re) |
294 ))) | 344 (textmate-start-compile-in-root command 'grep-mode))) |
295 | 345 |
296 (defun textmate-clear-cache () | 346 (defun textmate-clear-cache () |
347 "Clears the project root and project files cache. Use after adding files." | |
297 (interactive) | 348 (interactive) |
298 (setq *textmate-project-root* nil) | 349 (setq *textmate-project-root* nil) |
299 (setq *textmate-project-files* nil) | 350 (setq *textmate-project-files* nil) |
300 (message "textmate-mode cache cleared.")) | 351 (message "textmate-mode cache cleared.")) |
301 | 352 |
333 ((member ".hg" (directory-files root)) "hg") | 384 ((member ".hg" (directory-files root)) "hg") |
334 (t "unknown") | 385 (t "unknown") |
335 )) | 386 )) |
336 | 387 |
337 (defun textmate-project-files (root) | 388 (defun textmate-project-files (root) |
389 "Finds all files in a given project using either hg, git, or find." | |
338 (let ((type (textmate-project-root-type root))) | 390 (let ((type (textmate-project-root-type root))) |
339 (cond ((string= type "git") (split-string | 391 (cond ((string= type "git") (split-string |
340 (shell-command-to-string | 392 (shell-command-to-string |
341 (concat "cd " root " && git ls-files")) "\n" t)) | 393 (concat "cd " root " && git ls-files")) "\n" t)) |
342 ((string= type "hg") (split-string | 394 ((string= type "hg") (split-string |
344 (concat "cd " root " && hg manifest")) "\n" t)) | 396 (concat "cd " root " && hg manifest")) "\n" t)) |
345 ((string= type "unknown") (textmate-cached-project-files-find root)) | 397 ((string= type "unknown") (textmate-cached-project-files-find root)) |
346 ))) | 398 ))) |
347 | 399 |
348 (defun textmate-project-files-find (root) | 400 (defun textmate-project-files-find (root) |
401 "Finds all files in a given project using find." | |
349 (split-string | 402 (split-string |
350 (shell-command-to-string | 403 (shell-command-to-string |
351 (concat | 404 (concat |
352 "find " | 405 "find " |
353 root | 406 root |
356 "' | sed 's:" | 409 "' | sed 's:" |
357 *textmate-project-root* | 410 *textmate-project-root* |
358 "/::'")) "\n" t)) | 411 "/::'")) "\n" t)) |
359 | 412 |
360 (defun textmate-cached-project-files-find (&optional root) | 413 (defun textmate-cached-project-files-find (&optional root) |
414 "Finds and caches all files in a given project using find." | |
361 (cond | 415 (cond |
362 ((null textmate-use-file-cache) (textmate-project-files root)) | 416 ((null textmate-use-file-cache) (textmate-project-files root)) |
363 ((equal (textmate-project-root) (car *textmate-project-files*)) | 417 ((equal (textmate-project-root) (car *textmate-project-files*)) |
364 (cdr *textmate-project-files*)) | 418 (cdr *textmate-project-files*)) |
365 (t (cdr (setq *textmate-project-files* | 419 (t (cdr (setq *textmate-project-files* |
366 `(,root . ,(textmate-project-files-find root))))))) | 420 `(,root . ,(textmate-project-files-find root))))))) |
367 | 421 |
368 (defun textmate-project-root () | 422 (defun textmate-project-root () |
423 "Returns the current project root." | |
369 (when (or | 424 (when (or |
370 (null *textmate-project-root*) | 425 (null *textmate-project-root*) |
371 (not (string-match *textmate-project-root* default-directory))) | 426 (not (string-match *textmate-project-root* default-directory))) |
372 (let ((root (textmate-find-project-root))) | 427 (let ((root (textmate-find-project-root))) |
373 (if root | 428 (if root |
385 'nil | 440 'nil |
386 (root-matches root (cdr names)) | 441 (root-matches root (cdr names)) |
387 ))) | 442 ))) |
388 | 443 |
389 (defun textmate-find-project-root (&optional root) | 444 (defun textmate-find-project-root (&optional root) |
445 "Determines the current project root by recursively searching for an indicator." | |
390 (when (null root) (setq root default-directory)) | 446 (when (null root) (setq root default-directory)) |
391 (cond | 447 (cond |
392 ((root-matches root *textmate-project-roots*) | 448 ((root-matches root *textmate-project-roots*) |
393 (expand-file-name root)) | 449 (expand-file-name root)) |
394 ((equal (expand-file-name root) "/") nil) | 450 ((equal (expand-file-name root) "/") nil) |