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) |
