blob: 434d325260ebd803f782ad836069af73cab16da8 [file] [log] [blame] [view]
andybons22afb312015-08-31 02:24:511# Emacs
2
3[TOC]
4
andybons3322f762015-08-24 21:37:095## Debugging
6
Alan Bram06b277682017-10-04 19:32:327[Linux Debugging](linux_debugging.md) has some Emacs-specific debugging tips.
andybons3322f762015-08-24 21:37:098
andybons3322f762015-08-24 21:37:099## Syntax-error Highlighting
andybons22afb312015-08-31 02:24:5110
11[Ninja](ninja_build.md) users get in-line highlighting of syntax errors using
12`flymake.el` on each buffer-save:
13
14
15 (load-file "src/tools/emacs/flymake-chromium.el")
16
andybons3322f762015-08-24 21:37:0917## [ycmd](https://github.com/Valloric/ycmd) (YouCompleteMe) + flycheck
18
andybons22afb312015-08-31 02:24:5119[emacs-ycmd](https://github.com/abingham/emacs-ycmd) in combination with
20flycheck provides:
andybons3322f762015-08-24 21:37:0921
andybons22afb312015-08-31 02:24:5122* advanced code completion
23* syntax checking
24* navigation to declarations and definitions (using `ycmd-goto`) based on
25 on-the-fly processing using clang. A quick demo video showing code
26 completion and flycheck highlighting a missing semicolon syntax error:
andybons3322f762015-08-24 21:37:0927
andybons22afb312015-08-31 02:24:5128[![video preview][img]][video]
29
30[img]: http://img.youtube.com/vi/a0zMbm4jACk/0.jpg
31[video]: http://www.youtube.com/watch?feature=player_embedded&v=a0zMbm4jACk
32
33### Requirements
34
andybons3322f762015-08-24 21:37:0935 * Your build system is set up for building with clang or wrapper+clang
36
andybons22afb312015-08-31 02:24:5137### Setup
andybons3322f762015-08-24 21:37:0938
andybons22afb312015-08-31 02:24:51391. Clone, update external git repositories and build.sh ycmd from
40 https://github.com/Valloric/ycmd into a directory, e.g. `~/dev/ycmd`
411. Test `ycmd` by running `~/dev/ycmd$ python ycmd/__main__.py` You should see
42 `KeyError: 'hmac_secret'`
431. Install the following packages to emacs, for example from melpa:
44 * `ycmd`
45 * `company-ycmd`
46 * `flycheck-ycmd`
471. [More info on configuring emacs-ycmd](https://github.com/abingham/emacs-ycmd#quickstart)
48 1. Assuming your checkout of Chromium is in `~/dev/blink`, i.e. this is the
49 directory in which you find the `src`folder, create a symbolic link as
50 follows:
andybons3322f762015-08-24 21:37:0951
andybons22afb312015-08-31 02:24:5152 ```shell
53 cd ~/dev/blink
54 ln -s src/tools/vim/chromium.ycm_extra_conf.py .ycm_extra_conf.py
55 ```
56
57 1. Add something like the following to your `init.el`
58
59```el
andybons3322f762015-08-24 21:37:0960;; ycmd
61
62;;; Googlers can replace a lot of this with (require 'google-ycmd).
63
64(require 'ycmd)
65(require 'company-ycmd)
66(require 'flycheck-ycmd)
67
68(company-ycmd-setup)
69(flycheck-ycmd-setup)
70
71;; Show completions after 0.15 seconds
72(setq company-idle-delay 0.15)
73
74;; Activate for editing C++ files
75(add-hook 'c++-mode-hook 'ycmd-mode)
76(add-hook 'c++-mode-hook 'company-mode)
77(add-hook 'c++-mode-hook 'flycheck-mode)
78
79;; Replace the directory information with where you downloaded ycmd to
80(set-variable 'ycmd-server-command (list "python" (substitute-in-file-name "$HOME/dev/ycmd/ycmd/__main__.py")))
81
82;; Edit according to where you have your Chromium/Blink checkout
83(add-to-list 'ycmd-extra-conf-whitelist (substitute-in-file-name "$HOME/dev/blink/.ycm_extra_conf.py"))
84
85;; Show flycheck errors in idle-mode as well
86(setq ycmd-parse-conditions '(save new-line mode-enabled idle-change))
87
88;; Makes emacs-ycmd less verbose
89(setq url-show-status nil)
90```
91
andybons22afb312015-08-31 02:24:5192### Troubleshooting
andybons3322f762015-08-24 21:37:0993
andybons22afb312015-08-31 02:24:5194* If no completions show up or emacs reports errors, you can check the
95 `*ycmd-server*` buffer for errors. See the next bullet point for how to
96 handle "OS Error: No such file or directory"
97* Launching emacs from an OS menu might result in a different environment so
98 that `ycmd` does not find ninja. In that case, you can use a package like
99 [exec-path from shell](https://github.com/purcell/exec-path-from-shell) and
100 add the following to your `init.el`:
101
102```el
andybons3322f762015-08-24 21:37:09103(require 'exec-path-from-shell)
104(when (memq window-system '(mac ns x))
105 (exec-path-from-shell-initialize))
106```
107
andybons3322f762015-08-24 21:37:09108## ff-get-other-file
109
andybons22afb312015-08-31 02:24:51110There's a builtin function called `ff-get-other-file` which will get the "other
111file" based on file extension. I have this bound to C-o in c-mode
112(`(local-set-key "\C-o" 'ff-get-other-file)`). While "other file" is per-mode
113defined, in c-like languages it means jumping between the header and the source
114file. So I switch back and forth between the header and the source with C-o. If
115we had separate include/ and src/ directories, this would be a pain to setup,
116but this might just work out of the box for you. See the documentation for the
117variable `cc-other-file-alist` for more information.
andybons3322f762015-08-24 21:37:09118
andybons22afb312015-08-31 02:24:51119One drawback of ff-get-other-file is that it will always switch to a matching
120buffer, even if the other file is in a different directory, so if you have
121A.cc,A.h,A.cc(2) then ff-get-other-file will switch to A.h from A.cc(2) rather
122than load A.h(2) from the appropriate directory. If you prefer something (C
123specific) that always finds, try this:
124
125```el
andybons3322f762015-08-24 21:37:09126(defun cc-other-file()
127 "Toggles source/header file"
128 (interactive)
129 (let ((buf (current-buffer))
130 (name (file-name-sans-extension (buffer-file-name)))
andybons22afb312015-08-31 02:24:51131 (other-extens
132 (cadr (assoc (concat "\\."
andybons3322f762015-08-24 21:37:09133 (file-name-extension (buffer-file-name))
andybons22afb312015-08-31 02:24:51134 "\\'")
andybons3322f762015-08-24 21:37:09135 cc-other-file-alist))))
136 (dolist (e other-extens)
137 (if (let ((f (concat name e)))
138 (and (file-exists-p f) (find-file f)))
139 (return)))
140 )
141 )
142```
andybons22afb312015-08-31 02:24:51143
144_Note: if you know an easy way to change the ff-get-other-file behavior, please
145replace this hack with that solution! - [email protected]_
andybons3322f762015-08-24 21:37:09146
147## Use Google's C++ style!
148
andybons22afb312015-08-31 02:24:51149We have an emacs module,
150[google-c-style.el](http://google-styleguide.googlecode.com/svn/trunk/google-c-style.el),
151which adds c-mode formatting. Then add to your .emacs:
152
153```el
154(load "/<path/to/chromium>/src/buildtools/clang_format/script/clang-format.el")
155(add-hook 'c-mode-common-hook
156 (function (lambda () (local-set-key (kbd "TAB") 'clang-format-region))))
andybons3322f762015-08-24 21:37:09157```
andybons22afb312015-08-31 02:24:51158
159Now, you can use the
andybons3322f762015-08-24 21:37:09160
161&lt;Tab&gt;
162
andybons22afb312015-08-31 02:24:51163key to format the current line (even a long line) or region.
andybons3322f762015-08-24 21:37:09164
Daniel Bratellad5d0992018-09-21 16:35:18165## BUILD.gn and .gni files
166
167BUILD.gn and gni files are supported by the official gn-mode which can
168be enabled with:
169
170 (load-file "src/tools/emacs/gn.el")
171
andybons22afb312015-08-31 02:24:51172## Highlight long lines
andybons3322f762015-08-24 21:37:09173
174One nice way to highlight long lines and other style issues:
andybons22afb312015-08-31 02:24:51175
176```el
andybons3322f762015-08-24 21:37:09177(require 'whitespace)
178(setq whitespace-style '(face indentation trailing empty lines-tail))
179(setq whitespace-line-column nil)
180(set-face-attribute 'whitespace-line nil
181 :background "purple"
182 :foreground "white"
183 :weight 'bold)
184(global-whitespace-mode 1)
185```
186
andybons22afb312015-08-31 02:24:51187Note: You might need to grab the latest version of
188[whitespace.el](http://www.emacswiki.org/emacs-en/download/whitespace.el).
andybons3322f762015-08-24 21:37:09189
190## gyp
191
192### `gyp` style
andybons22afb312015-08-31 02:24:51193There is a gyp mode that provides basic indentation and font-lock (syntax
194highlighting) support. The mode derives from python.el (bundled with newer
195emacsen).
andybons3322f762015-08-24 21:37:09196
andybons22afb312015-08-31 02:24:51197You can find it in /src/tools/gyp/tools/emacs
andybons3322f762015-08-24 21:37:09198
199See the README file there for installation instructions.
200
andybons22afb312015-08-31 02:24:51201**Important**: the mode is only tested with `python.el` (bundled with newer
202emacsen), not with `python-mode.el` (outdated and less maintained these days).
andybons3322f762015-08-24 21:37:09203
204### deep nesting
205
andybons22afb312015-08-31 02:24:51206A couple of helpers that show a summary of where you are; the first by tracing
207the indentation hierarchy upwards, the second by only showing `#if`s and
208`#else`s that are relevant to the current line:
andybons3322f762015-08-24 21:37:09209
210```el
andybons3322f762015-08-24 21:37:09211(defun ami-summarize-indentation-at-point ()
andybons22afb312015-08-31 02:24:51212 "Echo a summary of how one gets from the left-most column to
213 POINT in terms of indentation changes."
214 (interactive)
215 (save-excursion
216 (let ((cur-indent most-positive-fixnum)
217 (trace '()))
218 (while (not (bobp))
219 (let ((current-line (buffer-substring (line-beginning-position)
220 (line-end-position))))
221 (when (and (not (string-match "^\\s-*$" current-line))
222 (< (current-indentation) cur-indent))
223 (setq cur-indent (current-indentation))
224 (setq trace (cons current-line trace))
225 (if (or (string-match "^\\s-*}" current-line)
226 (string-match "^\\s-*else " current-line)
227 (string-match "^\\s-*elif " current-line))
228 (setq cur-indent (1+ cur-indent)))))
229 (forward-line -1))
230 (message "%s" (mapconcat 'identity trace "\n")))))
andybons3322f762015-08-24 21:37:09231
232(require 'cl)
andybons22afb312015-08-31 02:24:51233 (defun ami-summarize-preprocessor-branches-at-point ()
234 "Summarize the C preprocessor branches needed to get to point."
235 (interactive)
236 (flet ((current-line-text ()
237 (buffer-substring (line-beginning-position) (line-end-position))))
238 (save-excursion
239 (let ((eol (or (end-of-line) (point)))
240 deactivate-mark directives-stack)
241 (goto-char (point-min))
242 (while (re-search-forward "^#\\(if\\|else\\|endif\\)" eol t)
243 (if (or (string-prefix-p "#if" (match-string 0))
244 (string-prefix-p "#else" (match-string 0)))
245 (push (current-line-text) directives-stack)
246 (if (string-prefix-p "#endif" (match-string 0))
247 (while (string-prefix-p "#else" (pop directives-stack)) t))))
248 (message "%s" (mapconcat 'identity (reverse directives-stack) "\n"))))))
andybons3322f762015-08-24 21:37:09249```
250
251## find-things-fast
252
andybons22afb312015-08-31 02:24:51253erg wrote a suite of tools that do common operations from the root of your
254repository, called
255[Find Things Fast](https://github.com/eglaysher/find-things-fast). It contains
256ido completion over `git ls-files` (or the svn find equivalent) and `grepsource`
257that only git greps files with extensions we care about (or the equivalent the
258`find | xargs grep` statement in non-git repos.)
andybons3322f762015-08-24 21:37:09259
260## vc-mode and find-file performance
261
andybons22afb312015-08-31 02:24:51262When you first open a file under git control, vc mode kicks in and does a high
263level stat of your git repo. For huge repos, especially WebKit and Chromium,
264this makes opening a file take literally seconds. This snippet disables VC git
265for chrome directories:
andybons3322f762015-08-24 21:37:09266
andybons22afb312015-08-31 02:24:51267```el
andybons3322f762015-08-24 21:37:09268; Turn off VC git for chrome
269(when (locate-library "vc")
270(defadvice vc-registered (around nochrome-vc-registered (file))
271(message (format "nochrome-vc-registered %s" file))
272(if (string-match ".*chrome/src.*" file)
273(progn
274(message (format "Skipping VC mode for %s" % file))
275(setq ad-return-value nil)
276)
277ad-do-it)
278)
279(ad-activate 'vc-registered)
280)
281```
282
283## git tools
andybons3322f762015-08-24 21:37:09284
andybons22afb312015-08-31 02:24:51285We're collecting Chrome-specific tools under `tools/emacs`. See the files there
286for details.
287
288* `trybot.el`: import Windows trybot output into a `compilation-mode` buffer.
andybons3322f762015-08-24 21:37:09289
290## ERC for IRC
291
asargent4adb8112015-12-07 19:42:02292See [ErcIrc](erc_irc.md).
andybons3322f762015-08-24 21:37:09293
294## TODO
295
andybons22afb312015-08-31 02:24:51296* Figure out how to make `M-x compile` default to
297 `cd /path/to/chrome/root; make -r chrome`.