blob: f20958741e033a027947f8a8e54a6dbc0afd8b13 [file] [log] [blame] [view]
andybons22afb312015-08-31 02:24:511# Emacs
2
3[TOC]
4
andybons3322f762015-08-24 21:37:095## Debugging
6
andybons22afb312015-08-31 02:24:517[Linux Debugging](linux_debugging.md) has some emacs-specific debugging tips.
andybons3322f762015-08-24 21:37:098
9
10## Blink Style (WebKit)
11
andybons22afb312015-08-31 02:24:5112Chrome and Blink/WebKit style differ. You can use
13[directory-local variables](http://www.gnu.org/software/emacs/manual/html_node/emacs/Directory-Variables.html)
14to make the tab key do the right thing. E.g., in `third_party/WebKit`, add a
15`.dir-locals.el` that contains
andybons3322f762015-08-24 21:37:0916
andybons22afb312015-08-31 02:24:5117```el
andybons3322f762015-08-24 21:37:0918((nil . ((indent-tabs-mode . nil)
19 (c-basic-offset . 4)
20 (fill-column . 120))))
21```
22
andybons22afb312015-08-31 02:24:5123This turns off tabs, sets your indent to four spaces, and makes `M-q` wrap at
24120 columns (WebKit doesn't define a wrap column, but there's a soft limit
25somewhere in that area for comments. Some reviewers do enforce the no wrap
26limit, which Emacs can deal with gracefully; see below.)
andybons3322f762015-08-24 21:37:0927
andybons22afb312015-08-31 02:24:5128Be sure to `echo .dir-locals.el >> .git/info/exclude` so `git clean` doesn't
29delete your file.
andybons3322f762015-08-24 21:37:0930
andybons22afb312015-08-31 02:24:5131It can be useful to set up a WebKit specific indent style. It's not too much
32different so it's easy to base off of the core Google style. Somewhere after
33you've loaded google.el (most likely in your .emacs file), add:
andybons3322f762015-08-24 21:37:0934
andybons22afb312015-08-31 02:24:5135```el
36(c-add-style "WebKit" '("Google"
andybons3322f762015-08-24 21:37:0937 (c-basic-offset . 4)
38 (c-offsets-alist . ((innamespace . 0)
39 (access-label . -)
40 (case-label . 0)
41 (member-init-intro . +)
42 (topmost-intro . 0)
43 (arglist-cont-nonempty . +)))))
44```
45
46then you can add
47
andybons22afb312015-08-31 02:24:5148```el
49(c-mode . ((c-file-style . "WebKit")))
50(c++-mode . ((c-file-style . "WebKit"))))
andybons3322f762015-08-24 21:37:0951```
52
andybons22afb312015-08-31 02:24:5153to the end of the .dir-locals.el file you created above. Note that this style
54may not yet be complete, but it covers the most common differences.
andybons3322f762015-08-24 21:37:0955
andybons22afb312015-08-31 02:24:5156Now that you have a WebKit specific style being applied, and assuming you have
57font locking and it's default jit locking turned on, you can also get Emacs 23
58to wrap long lines more intelligently by adding the following to your .emacs
59file:
andybons3322f762015-08-24 21:37:0960
andybons22afb312015-08-31 02:24:5161```el
andybons3322f762015-08-24 21:37:0962;; For dealing with WebKit long lines and word wrapping.
andybons22afb312015-08-31 02:24:5163(defun c-mode-adaptive-indent (beg end)
qyearsleyc0dc6f42016-12-02 22:13:3964 "Set the wrap-prefix for the region between BEG and END with adaptive filling."
andybons22afb312015-08-31 02:24:5165 (goto-char beg)
66 (while
67 (let ((lbp (line-beginning-position))
68 (lep (line-end-position)))
andybons3322f762015-08-24 21:37:0969 (put-text-property lbp lep 'wrap-prefix (concat (fill-context-prefix lbp lep) (make-string c-basic-offset ? )))
70 (search-forward "\n" end t))))
71
andybons22afb312015-08-31 02:24:5172(define-minor-mode c-adaptive-wrap-mode
73 "Wrap the buffer text with adaptive filling for c-mode."
74 :lighter ""
75 (save-excursion
76 (save-restriction
77 (widen)
78 (let ((buffer-undo-list t)
79 (inhibit-read-only t)
80 (mod (buffer-modified-p)))
81 (if c-adaptive-wrap-mode
andybons3322f762015-08-24 21:37:0982 (jit-lock-register 'c-mode-adaptive-indent)
andybons22afb312015-08-31 02:24:5183 (jit-lock-unregister 'c-mode-adaptive-indent)
andybons3322f762015-08-24 21:37:0984 (remove-text-properties (point-min) (point-max) '(wrap-prefix pref)))
85 (restore-buffer-modified-p mod)))))
86
87(defun c-adaptive-wrap-mode-for-webkit ()
88 "Turn on visual line mode and adaptive wrapping for WebKit source files."
89 (if (or (string-equal "webkit" c-indentation-style)
90 (string-equal "WebKit" c-indentation-style))
91 (progn
92 (visual-line-mode t)
93 (c-adaptive-wrap-mode t))))
94
95(add-hook 'c-mode-common-hook 'c-adaptive-wrap-mode-for-webkit)
96(add-hook 'hack-local-variables-hook 'c-adaptive-wrap-mode-for-webkit)
97```
98
andybons22afb312015-08-31 02:24:5199This turns on visual wrap mode for files using the WebKit c style, and sets up a
100hook to dynamically set the indent on the wrapped lines. It's not quite as
101intelligent as it could be (e.g., what would the wrap be if there really were a
102newline there?), but it's very fast. It makes dealing with long code lines
103anywhere much more tolerable (not just in WebKit).
andybons3322f762015-08-24 21:37:09104
105## Syntax-error Highlighting
andybons22afb312015-08-31 02:24:51106
107[Ninja](ninja_build.md) users get in-line highlighting of syntax errors using
108`flymake.el` on each buffer-save:
109
110
111 (load-file "src/tools/emacs/flymake-chromium.el")
112
andybons3322f762015-08-24 21:37:09113
114## [ycmd](https://github.com/Valloric/ycmd) (YouCompleteMe) + flycheck
115
andybons22afb312015-08-31 02:24:51116[emacs-ycmd](https://github.com/abingham/emacs-ycmd) in combination with
117flycheck provides:
andybons3322f762015-08-24 21:37:09118
andybons22afb312015-08-31 02:24:51119* advanced code completion
120* syntax checking
121* navigation to declarations and definitions (using `ycmd-goto`) based on
122 on-the-fly processing using clang. A quick demo video showing code
123 completion and flycheck highlighting a missing semicolon syntax error:
andybons3322f762015-08-24 21:37:09124
andybons22afb312015-08-31 02:24:51125[![video preview][img]][video]
126
127[img]: http://img.youtube.com/vi/a0zMbm4jACk/0.jpg
128[video]: http://www.youtube.com/watch?feature=player_embedded&v=a0zMbm4jACk
129
130### Requirements
131
andybons3322f762015-08-24 21:37:09132 * Your build system is set up for building with clang or wrapper+clang
133
andybons22afb312015-08-31 02:24:51134### Setup
andybons3322f762015-08-24 21:37:09135
andybons22afb312015-08-31 02:24:511361. Clone, update external git repositories and build.sh ycmd from
137 https://github.com/Valloric/ycmd into a directory, e.g. `~/dev/ycmd`
1381. Test `ycmd` by running `~/dev/ycmd$ python ycmd/__main__.py` You should see
139 `KeyError: 'hmac_secret'`
1401. Install the following packages to emacs, for example from melpa:
141 * `ycmd`
142 * `company-ycmd`
143 * `flycheck-ycmd`
1441. [More info on configuring emacs-ycmd](https://github.com/abingham/emacs-ycmd#quickstart)
145 1. Assuming your checkout of Chromium is in `~/dev/blink`, i.e. this is the
146 directory in which you find the `src`folder, create a symbolic link as
147 follows:
andybons3322f762015-08-24 21:37:09148
andybons22afb312015-08-31 02:24:51149 ```shell
150 cd ~/dev/blink
151 ln -s src/tools/vim/chromium.ycm_extra_conf.py .ycm_extra_conf.py
152 ```
153
154 1. Add something like the following to your `init.el`
155
156```el
andybons3322f762015-08-24 21:37:09157;; ycmd
158
159;;; Googlers can replace a lot of this with (require 'google-ycmd).
160
161(require 'ycmd)
162(require 'company-ycmd)
163(require 'flycheck-ycmd)
164
165(company-ycmd-setup)
166(flycheck-ycmd-setup)
167
168;; Show completions after 0.15 seconds
169(setq company-idle-delay 0.15)
170
171;; Activate for editing C++ files
172(add-hook 'c++-mode-hook 'ycmd-mode)
173(add-hook 'c++-mode-hook 'company-mode)
174(add-hook 'c++-mode-hook 'flycheck-mode)
175
176;; Replace the directory information with where you downloaded ycmd to
177(set-variable 'ycmd-server-command (list "python" (substitute-in-file-name "$HOME/dev/ycmd/ycmd/__main__.py")))
178
179;; Edit according to where you have your Chromium/Blink checkout
180(add-to-list 'ycmd-extra-conf-whitelist (substitute-in-file-name "$HOME/dev/blink/.ycm_extra_conf.py"))
181
182;; Show flycheck errors in idle-mode as well
183(setq ycmd-parse-conditions '(save new-line mode-enabled idle-change))
184
185;; Makes emacs-ycmd less verbose
186(setq url-show-status nil)
187```
188
andybons22afb312015-08-31 02:24:51189### Troubleshooting
andybons3322f762015-08-24 21:37:09190
andybons22afb312015-08-31 02:24:51191* If no completions show up or emacs reports errors, you can check the
192 `*ycmd-server*` buffer for errors. See the next bullet point for how to
193 handle "OS Error: No such file or directory"
194* Launching emacs from an OS menu might result in a different environment so
195 that `ycmd` does not find ninja. In that case, you can use a package like
196 [exec-path from shell](https://github.com/purcell/exec-path-from-shell) and
197 add the following to your `init.el`:
198
199```el
andybons3322f762015-08-24 21:37:09200(require 'exec-path-from-shell)
201(when (memq window-system '(mac ns x))
202 (exec-path-from-shell-initialize))
203```
204
andybons3322f762015-08-24 21:37:09205## ff-get-other-file
206
andybons22afb312015-08-31 02:24:51207There's a builtin function called `ff-get-other-file` which will get the "other
208file" based on file extension. I have this bound to C-o in c-mode
209(`(local-set-key "\C-o" 'ff-get-other-file)`). While "other file" is per-mode
210defined, in c-like languages it means jumping between the header and the source
211file. So I switch back and forth between the header and the source with C-o. If
212we had separate include/ and src/ directories, this would be a pain to setup,
213but this might just work out of the box for you. See the documentation for the
214variable `cc-other-file-alist` for more information.
andybons3322f762015-08-24 21:37:09215
andybons22afb312015-08-31 02:24:51216One drawback of ff-get-other-file is that it will always switch to a matching
217buffer, even if the other file is in a different directory, so if you have
218A.cc,A.h,A.cc(2) then ff-get-other-file will switch to A.h from A.cc(2) rather
219than load A.h(2) from the appropriate directory. If you prefer something (C
220specific) that always finds, try this:
221
222```el
andybons3322f762015-08-24 21:37:09223(defun cc-other-file()
224 "Toggles source/header file"
225 (interactive)
226 (let ((buf (current-buffer))
227 (name (file-name-sans-extension (buffer-file-name)))
andybons22afb312015-08-31 02:24:51228 (other-extens
229 (cadr (assoc (concat "\\."
andybons3322f762015-08-24 21:37:09230 (file-name-extension (buffer-file-name))
andybons22afb312015-08-31 02:24:51231 "\\'")
andybons3322f762015-08-24 21:37:09232 cc-other-file-alist))))
233 (dolist (e other-extens)
234 (if (let ((f (concat name e)))
235 (and (file-exists-p f) (find-file f)))
236 (return)))
237 )
238 )
239```
andybons22afb312015-08-31 02:24:51240
241_Note: if you know an easy way to change the ff-get-other-file behavior, please
242replace this hack with that solution! - [email protected]_
andybons3322f762015-08-24 21:37:09243
244## Use Google's C++ style!
245
andybons22afb312015-08-31 02:24:51246We have an emacs module,
247[google-c-style.el](http://google-styleguide.googlecode.com/svn/trunk/google-c-style.el),
248which adds c-mode formatting. Then add to your .emacs:
249
250```el
251(load "/<path/to/chromium>/src/buildtools/clang_format/script/clang-format.el")
252(add-hook 'c-mode-common-hook
253 (function (lambda () (local-set-key (kbd "TAB") 'clang-format-region))))
andybons3322f762015-08-24 21:37:09254```
andybons22afb312015-08-31 02:24:51255
256Now, you can use the
andybons3322f762015-08-24 21:37:09257
258&lt;Tab&gt;
259
andybons22afb312015-08-31 02:24:51260key to format the current line (even a long line) or region.
andybons3322f762015-08-24 21:37:09261
andybons22afb312015-08-31 02:24:51262## Highlight long lines
andybons3322f762015-08-24 21:37:09263
264One nice way to highlight long lines and other style issues:
andybons22afb312015-08-31 02:24:51265
266```el
andybons3322f762015-08-24 21:37:09267(require 'whitespace)
268(setq whitespace-style '(face indentation trailing empty lines-tail))
269(setq whitespace-line-column nil)
270(set-face-attribute 'whitespace-line nil
271 :background "purple"
272 :foreground "white"
273 :weight 'bold)
274(global-whitespace-mode 1)
275```
276
andybons22afb312015-08-31 02:24:51277Note: You might need to grab the latest version of
278[whitespace.el](http://www.emacswiki.org/emacs-en/download/whitespace.el).
andybons3322f762015-08-24 21:37:09279
280## gyp
281
282### `gyp` style
andybons22afb312015-08-31 02:24:51283There is a gyp mode that provides basic indentation and font-lock (syntax
284highlighting) support. The mode derives from python.el (bundled with newer
285emacsen).
andybons3322f762015-08-24 21:37:09286
andybons22afb312015-08-31 02:24:51287You can find it in /src/tools/gyp/tools/emacs
andybons3322f762015-08-24 21:37:09288
289See the README file there for installation instructions.
290
andybons22afb312015-08-31 02:24:51291**Important**: the mode is only tested with `python.el` (bundled with newer
292emacsen), not with `python-mode.el` (outdated and less maintained these days).
andybons3322f762015-08-24 21:37:09293
294### deep nesting
295
andybons22afb312015-08-31 02:24:51296A couple of helpers that show a summary of where you are; the first by tracing
297the indentation hierarchy upwards, the second by only showing `#if`s and
298`#else`s that are relevant to the current line:
andybons3322f762015-08-24 21:37:09299
300```el
andybons3322f762015-08-24 21:37:09301(defun ami-summarize-indentation-at-point ()
andybons22afb312015-08-31 02:24:51302 "Echo a summary of how one gets from the left-most column to
303 POINT in terms of indentation changes."
304 (interactive)
305 (save-excursion
306 (let ((cur-indent most-positive-fixnum)
307 (trace '()))
308 (while (not (bobp))
309 (let ((current-line (buffer-substring (line-beginning-position)
310 (line-end-position))))
311 (when (and (not (string-match "^\\s-*$" current-line))
312 (< (current-indentation) cur-indent))
313 (setq cur-indent (current-indentation))
314 (setq trace (cons current-line trace))
315 (if (or (string-match "^\\s-*}" current-line)
316 (string-match "^\\s-*else " current-line)
317 (string-match "^\\s-*elif " current-line))
318 (setq cur-indent (1+ cur-indent)))))
319 (forward-line -1))
320 (message "%s" (mapconcat 'identity trace "\n")))))
andybons3322f762015-08-24 21:37:09321
322(require 'cl)
andybons22afb312015-08-31 02:24:51323 (defun ami-summarize-preprocessor-branches-at-point ()
324 "Summarize the C preprocessor branches needed to get to point."
325 (interactive)
326 (flet ((current-line-text ()
327 (buffer-substring (line-beginning-position) (line-end-position))))
328 (save-excursion
329 (let ((eol (or (end-of-line) (point)))
330 deactivate-mark directives-stack)
331 (goto-char (point-min))
332 (while (re-search-forward "^#\\(if\\|else\\|endif\\)" eol t)
333 (if (or (string-prefix-p "#if" (match-string 0))
334 (string-prefix-p "#else" (match-string 0)))
335 (push (current-line-text) directives-stack)
336 (if (string-prefix-p "#endif" (match-string 0))
337 (while (string-prefix-p "#else" (pop directives-stack)) t))))
338 (message "%s" (mapconcat 'identity (reverse directives-stack) "\n"))))))
andybons3322f762015-08-24 21:37:09339```
340
341## find-things-fast
342
andybons22afb312015-08-31 02:24:51343erg wrote a suite of tools that do common operations from the root of your
344repository, called
345[Find Things Fast](https://github.com/eglaysher/find-things-fast). It contains
346ido completion over `git ls-files` (or the svn find equivalent) and `grepsource`
347that only git greps files with extensions we care about (or the equivalent the
348`find | xargs grep` statement in non-git repos.)
andybons3322f762015-08-24 21:37:09349
350## vc-mode and find-file performance
351
andybons22afb312015-08-31 02:24:51352When you first open a file under git control, vc mode kicks in and does a high
353level stat of your git repo. For huge repos, especially WebKit and Chromium,
354this makes opening a file take literally seconds. This snippet disables VC git
355for chrome directories:
andybons3322f762015-08-24 21:37:09356
andybons22afb312015-08-31 02:24:51357```el
andybons3322f762015-08-24 21:37:09358; Turn off VC git for chrome
359(when (locate-library "vc")
360(defadvice vc-registered (around nochrome-vc-registered (file))
361(message (format "nochrome-vc-registered %s" file))
362(if (string-match ".*chrome/src.*" file)
363(progn
364(message (format "Skipping VC mode for %s" % file))
365(setq ad-return-value nil)
366)
367ad-do-it)
368)
369(ad-activate 'vc-registered)
370)
371```
372
373## git tools
andybons3322f762015-08-24 21:37:09374
andybons22afb312015-08-31 02:24:51375We're collecting Chrome-specific tools under `tools/emacs`. See the files there
376for details.
377
378* `trybot.el`: import Windows trybot output into a `compilation-mode` buffer.
andybons3322f762015-08-24 21:37:09379
380## ERC for IRC
381
asargent4adb8112015-12-07 19:42:02382See [ErcIrc](erc_irc.md).
andybons3322f762015-08-24 21:37:09383
384## TODO
385
andybons22afb312015-08-31 02:24:51386* Figure out how to make `M-x compile` default to
387 `cd /path/to/chrome/root; make -r chrome`.