Mercurial > dotfiles
annotate .elisp/textmate.el @ 25:c7ff220bba9f
Bad merge on my end.
| author | Augie Fackler <durin42@gmail.com> |
|---|---|
| date | Tue, 16 Dec 2008 16:10:40 -0600 |
| parents | d6fd2964258c |
| children | 260deb14fbc8 |
| rev | line source |
|---|---|
| 22 | 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 | |
|
24
d6fd2964258c
New version of textmate.el
Augie Fackler <durin42@gmail.com>
parents:
22
diff
changeset
|
97 ,(kbd "A-T") [(meta T)]) |
|
d6fd2964258c
New version of textmate.el
Augie Fackler <durin42@gmail.com>
parents:
22
diff
changeset
|
98 (textmate-toggle-camel-case |
| 25 | 99 ,(kbd "C-_") [(control _)]))) |
| 22 | 100 |
| 101 (defvar *textmate-project-root-p* | |
| 102 #'(lambda (coll) (or (member ".git" coll) | |
| 103 (member ".hg" coll) | |
| 104 )) | |
| 105 "*Lambda that, given a collection of directory entries, returns | |
| 106 non-nil if it represents the project root.") | |
| 107 | |
| 108 ;;; Bindings | |
| 109 | |
| 110 (defun textmate-ido-fix () | |
| 111 "Add up/down keybindings for ido." | |
| 112 (define-key ido-completion-map [up] 'ido-prev-match) | |
| 113 (define-key ido-completion-map [down] 'ido-next-match)) | |
| 114 | |
| 115 (defun textmate-bind-keys () | |
| 116 (add-hook 'ido-setup-hook 'textmate-ido-fix) | |
| 117 | |
| 118 ; weakness until i figure out how to do this right | |
| 119 (when (boundp 'osx-key-mode-map) | |
| 120 (define-key osx-key-mode-map (kbd "A-t") 'textmate-goto-file) | |
| 121 (define-key osx-key-mode-map (kbd "A-T") 'textmate-goto-symbol)) | |
| 122 | |
| 123 (let ((member) (i 0) (access (if (boundp 'aquamacs-version) 'cadr 'caddr))) | |
| 124 (setq member (nth i *textmate-keybindings-list*)) | |
| 125 (while member | |
| 126 (if (funcall access member) | |
| 127 (define-key *textmate-mode-map* (funcall access member) (car member))) | |
| 128 (setq member (nth i *textmate-keybindings-list*)) | |
| 129 (setq i (+ i 1))))) | |
| 130 | |
| 131 (defun textmate-completing-read (&rest args) | |
| 132 (let ((reading-fn (cadr (assoc textmate-completing-library *textmate-completing-function-alist*)))) | |
| 133 (apply (symbol-function reading-fn) args))) | |
| 134 | |
| 135 ;;; Commands | |
| 136 | |
| 137 (defun textmate-next-line () | |
| 138 (interactive) | |
| 139 (end-of-line) | |
| 140 (newline-and-indent)) | |
| 141 | |
| 142 ;; http://chopmo.blogspot.com/2008/09/quickly-jumping-to-symbols.html | |
| 143 (defun textmate-goto-symbol () | |
| 144 "Will update the imenu index and then use ido to select a symbol to navigate to" | |
| 145 (interactive) | |
| 146 (imenu--make-index-alist) | |
| 147 (let ((name-and-pos '()) | |
| 148 (symbol-names '())) | |
| 149 (flet ((addsymbols (symbol-list) | |
| 150 (when (listp symbol-list) | |
| 151 (dolist (symbol symbol-list) | |
| 152 (let ((name nil) (position nil)) | |
| 153 (cond | |
| 154 ((and (listp symbol) (imenu--subalist-p symbol)) | |
| 155 (addsymbols symbol)) | |
| 156 | |
| 157 ((listp symbol) | |
| 158 (setq name (car symbol)) | |
| 159 (setq position (cdr symbol))) | |
| 160 | |
| 161 ((stringp symbol) | |
| 162 (setq name symbol) | |
| 163 (setq position (get-text-property 1 'org-imenu-marker symbol)))) | |
| 164 | |
| 165 (unless (or (null position) (null name)) | |
| 166 (add-to-list 'symbol-names name) | |
| 167 (add-to-list 'name-and-pos (cons name position)))))))) | |
| 168 (addsymbols imenu--index-alist)) | |
| 169 (let* ((selected-symbol (textmate-completing-read "Symbol: " symbol-names)) | |
| 170 (position (cdr (assoc selected-symbol name-and-pos)))) | |
| 171 (goto-char position)))) | |
| 172 | |
| 173 (defun textmate-goto-file () | |
| 174 (interactive) | |
| 175 (let ((root (textmate-project-root))) | |
| 176 (when (null root) | |
| 177 (error "Can't find any .git directory")) | |
| 178 (find-file | |
| 179 (concat | |
| 180 (expand-file-name root) "/" | |
| 181 (textmate-completing-read | |
| 182 "Find file: " | |
| 183 (textmate-cached-project-files root)))))) | |
| 184 | |
| 185 (defun textmate-clear-cache () | |
| 186 (interactive) | |
| 187 (setq *textmate-project-root* nil) | |
| 188 (setq *textmate-project-files* nil) | |
| 189 (message "textmate-mode cache cleared.")) | |
| 190 | |
|
24
d6fd2964258c
New version of textmate.el
Augie Fackler <durin42@gmail.com>
parents:
22
diff
changeset
|
191 (defun textmate-toggle-camel-case () |
|
d6fd2964258c
New version of textmate.el
Augie Fackler <durin42@gmail.com>
parents:
22
diff
changeset
|
192 "Toggle current sexp between camelCase and snake_case, like TextMate C-_." |
|
d6fd2964258c
New version of textmate.el
Augie Fackler <durin42@gmail.com>
parents:
22
diff
changeset
|
193 (interactive) |
|
d6fd2964258c
New version of textmate.el
Augie Fackler <durin42@gmail.com>
parents:
22
diff
changeset
|
194 (if (thing-at-point 'word) |
|
d6fd2964258c
New version of textmate.el
Augie Fackler <durin42@gmail.com>
parents:
22
diff
changeset
|
195 (progn |
|
d6fd2964258c
New version of textmate.el
Augie Fackler <durin42@gmail.com>
parents:
22
diff
changeset
|
196 (unless (looking-at "\\<") (backward-sexp)) |
|
d6fd2964258c
New version of textmate.el
Augie Fackler <durin42@gmail.com>
parents:
22
diff
changeset
|
197 (let ((case-fold-search nil) |
|
d6fd2964258c
New version of textmate.el
Augie Fackler <durin42@gmail.com>
parents:
22
diff
changeset
|
198 (start (point)) |
|
d6fd2964258c
New version of textmate.el
Augie Fackler <durin42@gmail.com>
parents:
22
diff
changeset
|
199 (end (save-excursion (forward-sexp) (point)))) |
|
d6fd2964258c
New version of textmate.el
Augie Fackler <durin42@gmail.com>
parents:
22
diff
changeset
|
200 (if (and (looking-at "[a-z0-9_]+") (= end (match-end 0))) ; snake-case |
|
d6fd2964258c
New version of textmate.el
Augie Fackler <durin42@gmail.com>
parents:
22
diff
changeset
|
201 (progn |
|
d6fd2964258c
New version of textmate.el
Augie Fackler <durin42@gmail.com>
parents:
22
diff
changeset
|
202 (goto-char start) |
|
d6fd2964258c
New version of textmate.el
Augie Fackler <durin42@gmail.com>
parents:
22
diff
changeset
|
203 (while (re-search-forward "_[a-z]" end t) |
|
d6fd2964258c
New version of textmate.el
Augie Fackler <durin42@gmail.com>
parents:
22
diff
changeset
|
204 (goto-char (1- (point))) |
|
d6fd2964258c
New version of textmate.el
Augie Fackler <durin42@gmail.com>
parents:
22
diff
changeset
|
205 (delete-char -1) |
|
d6fd2964258c
New version of textmate.el
Augie Fackler <durin42@gmail.com>
parents:
22
diff
changeset
|
206 (upcase-region (point) (1+ (point))) |
|
d6fd2964258c
New version of textmate.el
Augie Fackler <durin42@gmail.com>
parents:
22
diff
changeset
|
207 (setq end (1- end)))) |
|
d6fd2964258c
New version of textmate.el
Augie Fackler <durin42@gmail.com>
parents:
22
diff
changeset
|
208 (downcase-region (point) (1+ (point))) |
|
d6fd2964258c
New version of textmate.el
Augie Fackler <durin42@gmail.com>
parents:
22
diff
changeset
|
209 (while (re-search-forward "[A-Z][a-z]" end t) |
|
d6fd2964258c
New version of textmate.el
Augie Fackler <durin42@gmail.com>
parents:
22
diff
changeset
|
210 (forward-char -2) |
|
d6fd2964258c
New version of textmate.el
Augie Fackler <durin42@gmail.com>
parents:
22
diff
changeset
|
211 (insert "_") |
|
d6fd2964258c
New version of textmate.el
Augie Fackler <durin42@gmail.com>
parents:
22
diff
changeset
|
212 (downcase-region (point) (1+ (point))) |
|
d6fd2964258c
New version of textmate.el
Augie Fackler <durin42@gmail.com>
parents:
22
diff
changeset
|
213 (forward-char 1) |
|
d6fd2964258c
New version of textmate.el
Augie Fackler <durin42@gmail.com>
parents:
22
diff
changeset
|
214 (setq end (1+ end))) |
|
d6fd2964258c
New version of textmate.el
Augie Fackler <durin42@gmail.com>
parents:
22
diff
changeset
|
215 (downcase-region start end) |
|
d6fd2964258c
New version of textmate.el
Augie Fackler <durin42@gmail.com>
parents:
22
diff
changeset
|
216 ))))) |
|
d6fd2964258c
New version of textmate.el
Augie Fackler <durin42@gmail.com>
parents:
22
diff
changeset
|
217 |
| 22 | 218 ;;; Utilities |
| 219 | |
| 220 (defun textmate-also-ignore (pattern) | |
| 221 "Also ignore PATTERN in project files." | |
| 222 (setq *textmate-gf-exclude* | |
| 223 (concat *textmate-gf-exclude* "|" pattern))) | |
| 224 | |
| 225 (defun textmate-project-files (root) | |
| 226 (split-string | |
| 227 (shell-command-to-string | |
| 228 (concat | |
| 229 "find " | |
| 230 root | |
| 231 " -type f | grep -vE '" | |
| 232 *textmate-gf-exclude* | |
| 233 "' | sed 's:" | |
| 234 *textmate-project-root* | |
| 235 "/::'")) "\n" t)) | |
| 236 | |
| 237 (defun textmate-cached-project-files (&optional root) | |
| 238 (cond | |
| 239 ((null textmate-use-file-cache) (textmate-project-files root)) | |
| 240 ((equal (textmate-project-root) (car *textmate-project-files*)) | |
| 241 (cdr *textmate-project-files*)) | |
| 242 (t (cdr (setq *textmate-project-files* | |
| 243 `(,root . ,(textmate-project-files root))))))) | |
| 244 | |
| 245 (defun textmate-project-root () | |
| 246 (when (or | |
| 247 (null *textmate-project-root*) | |
| 248 (not (string-match *textmate-project-root* default-directory))) | |
| 249 (let ((root (textmate-find-project-root))) | |
| 250 (if root | |
| 251 (setq *textmate-project-root* (expand-file-name (concat root "/"))) | |
| 252 (setq *textmate-project-root* nil)))) | |
| 253 *textmate-project-root*) | |
| 254 | |
| 255 (defun textmate-find-project-root (&optional root) | |
| 256 (when (null root) (setq root default-directory)) | |
| 257 (cond | |
| 258 ((funcall *textmate-project-root-p* (directory-files root)) | |
| 259 (expand-file-name root)) | |
| 260 ((equal (expand-file-name root) "/") nil) | |
| 261 (t (textmate-find-project-root (concat (file-name-as-directory root) ".."))))) | |
| 262 | |
| 263 ;;;###autoload | |
| 264 (define-minor-mode textmate-mode "TextMate Emulation Minor Mode" | |
| 265 :lighter " mate" :global t :keymap *textmate-mode-map* | |
| 266 (textmate-bind-keys) | |
| 267 ; activate preferred completion library | |
| 268 (dolist (mode *textmate-completing-minor-mode-alist*) | |
| 269 (if (eq (car mode) textmate-completing-library) | |
| 270 (funcall (cadr mode) t) | |
| 271 (when (fboundp | |
| 272 (cadr (assoc (car mode) *textmate-completing-function-alist*))) | |
| 273 (funcall (cadr mode) -1))))) | |
| 274 | |
| 275 (provide 'textmate) | |
| 276 ;;; textmate.el ends here |
