blob: 82f536cd3ef025e97fdb3dd6d13009062cca8d9e [file] [log] [blame] [view]
andybons22afb312015-08-31 02:24:511# Emacs
2
3[TOC]
4
andybons3322f762015-08-24 21:37:095## Debugging
6
Tom Anderson93e49e492019-12-23 19:55:377[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
Benoit Lizee27b6742020-07-30 14:43:1540 https://github.com/ycm-core/YouCompleteMe into a directory, e.g. `~/dev/ycmd`
41 * The ycmd packaging changed, the server is in a different location. To
42 build it, run:
43 ```shell
44 cd ~/dev/ycmd
45 git submodule update --init --recursive
46 python3 install.py --clang-completer
47 ```
481. Test `ycmd` by running `~/dev/ycmd$ python third_party/ycmd/__main__.py --options_file /tmp/test.json`. The options file can be created with e.g. `echo '{"hmac_secret": "1234567812345678"}' > /tmp/test.json`. The server should start normally.
andybons22afb312015-08-31 02:24:51491. Install the following packages to emacs, for example from melpa:
50 * `ycmd`
51 * `company-ycmd`
52 * `flycheck-ycmd`
531. [More info on configuring emacs-ycmd](https://github.com/abingham/emacs-ycmd#quickstart)
54 1. Assuming your checkout of Chromium is in `~/dev/blink`, i.e. this is the
55 directory in which you find the `src`folder, create a symbolic link as
56 follows:
andybons3322f762015-08-24 21:37:0957
andybons22afb312015-08-31 02:24:5158 ```shell
59 cd ~/dev/blink
60 ln -s src/tools/vim/chromium.ycm_extra_conf.py .ycm_extra_conf.py
61 ```
62
63 1. Add something like the following to your `init.el`
64
65```el
andybons3322f762015-08-24 21:37:0966;; ycmd
67
68;;; Googlers can replace a lot of this with (require 'google-ycmd).
69
70(require 'ycmd)
71(require 'company-ycmd)
72(require 'flycheck-ycmd)
73
74(company-ycmd-setup)
75(flycheck-ycmd-setup)
76
77;; Show completions after 0.15 seconds
78(setq company-idle-delay 0.15)
79
80;; Activate for editing C++ files
81(add-hook 'c++-mode-hook 'ycmd-mode)
82(add-hook 'c++-mode-hook 'company-mode)
83(add-hook 'c++-mode-hook 'flycheck-mode)
84
85;; Replace the directory information with where you downloaded ycmd to
Benoit Lizee27b6742020-07-30 14:43:1586(set-variable 'ycmd-server-command (list "python3" (substitute-in-file-name "$HOME/dev/ycmd/third_party/ycmd/ycmd/__main__.py")))
andybons3322f762015-08-24 21:37:0987
88;; Edit according to where you have your Chromium/Blink checkout
89(add-to-list 'ycmd-extra-conf-whitelist (substitute-in-file-name "$HOME/dev/blink/.ycm_extra_conf.py"))
90
91;; Show flycheck errors in idle-mode as well
92(setq ycmd-parse-conditions '(save new-line mode-enabled idle-change))
93
94;; Makes emacs-ycmd less verbose
95(setq url-show-status nil)
96```
97
andybons22afb312015-08-31 02:24:5198### Troubleshooting
andybons3322f762015-08-24 21:37:0999
andybons22afb312015-08-31 02:24:51100* If no completions show up or emacs reports errors, you can check the
101 `*ycmd-server*` buffer for errors. See the next bullet point for how to
102 handle "OS Error: No such file or directory"
103* Launching emacs from an OS menu might result in a different environment so
104 that `ycmd` does not find ninja. In that case, you can use a package like
105 [exec-path from shell](https://github.com/purcell/exec-path-from-shell) and
106 add the following to your `init.el`:
107
108```el
andybons3322f762015-08-24 21:37:09109(require 'exec-path-from-shell)
110(when (memq window-system '(mac ns x))
111 (exec-path-from-shell-initialize))
112```
Benoit Lizee27b6742020-07-30 14:43:15113* ycmd depends on the installed version of python. For googlers running gLinux,
114 a system update may have changed the python version. In this case, you need to
115 recompile ycmd first.
andybons3322f762015-08-24 21:37:09116
andybons3322f762015-08-24 21:37:09117## ff-get-other-file
118
andybons22afb312015-08-31 02:24:51119There's a builtin function called `ff-get-other-file` which will get the "other
120file" based on file extension. I have this bound to C-o in c-mode
121(`(local-set-key "\C-o" 'ff-get-other-file)`). While "other file" is per-mode
122defined, in c-like languages it means jumping between the header and the source
123file. So I switch back and forth between the header and the source with C-o. If
124we had separate include/ and src/ directories, this would be a pain to setup,
125but this might just work out of the box for you. See the documentation for the
126variable `cc-other-file-alist` for more information.
andybons3322f762015-08-24 21:37:09127
andybons22afb312015-08-31 02:24:51128One drawback of ff-get-other-file is that it will always switch to a matching
129buffer, even if the other file is in a different directory, so if you have
130A.cc,A.h,A.cc(2) then ff-get-other-file will switch to A.h from A.cc(2) rather
131than load A.h(2) from the appropriate directory. If you prefer something (C
132specific) that always finds, try this:
133
134```el
andybons3322f762015-08-24 21:37:09135(defun cc-other-file()
136 "Toggles source/header file"
137 (interactive)
138 (let ((buf (current-buffer))
139 (name (file-name-sans-extension (buffer-file-name)))
andybons22afb312015-08-31 02:24:51140 (other-extens
141 (cadr (assoc (concat "\\."
andybons3322f762015-08-24 21:37:09142 (file-name-extension (buffer-file-name))
andybons22afb312015-08-31 02:24:51143 "\\'")
andybons3322f762015-08-24 21:37:09144 cc-other-file-alist))))
145 (dolist (e other-extens)
146 (if (let ((f (concat name e)))
147 (and (file-exists-p f) (find-file f)))
148 (return)))
149 )
150 )
151```
andybons22afb312015-08-31 02:24:51152
153_Note: if you know an easy way to change the ff-get-other-file behavior, please
154replace this hack with that solution! - [email protected]_
andybons3322f762015-08-24 21:37:09155
156## Use Google's C++ style!
157
andybons22afb312015-08-31 02:24:51158We have an emacs module,
159[google-c-style.el](http://google-styleguide.googlecode.com/svn/trunk/google-c-style.el),
160which adds c-mode formatting. Then add to your .emacs:
161
162```el
Joanna Wang3aafdb22023-05-26 15:03:31163(load "/<path/to/chromium>/src/third_party/clang-format/script/clang-format.el")
andybons22afb312015-08-31 02:24:51164(add-hook 'c-mode-common-hook
165 (function (lambda () (local-set-key (kbd "TAB") 'clang-format-region))))
andybons3322f762015-08-24 21:37:09166```
andybons22afb312015-08-31 02:24:51167
168Now, you can use the
andybons3322f762015-08-24 21:37:09169
170&lt;Tab&gt;
171
andybons22afb312015-08-31 02:24:51172key to format the current line (even a long line) or region.
andybons3322f762015-08-24 21:37:09173
Daniel Bratellad5d0992018-09-21 16:35:18174## BUILD.gn and .gni files
175
176BUILD.gn and gni files are supported by the official gn-mode which can
177be enabled with:
178
179 (load-file "src/tools/emacs/gn.el")
180
Dan McArdle50bc621f02023-11-29 10:32:30181## Mojom IDL (.mojom files)
182
183[Mojom](/mojo/public/tools/bindings/README.md)
184files are supported by mojom-mode, which can be enabled with:
185
186```el
187(load-file "/<path/to/chromium>/src/tools/emacs/mojom-mode.el")
188```
189
190Alternatively, you can `require` the feature.
191(See emacs documentation on
192[Named Features](https://www.gnu.org/software/emacs/manual/html_node/elisp/Named-Features.html).)
193
194```el
195(add-to-list 'load-path "/<path/to/chromium>/src/tools/emacs/")
196(require 'mojom-mode)
197```
198
andybons22afb312015-08-31 02:24:51199## Highlight long lines
andybons3322f762015-08-24 21:37:09200
201One nice way to highlight long lines and other style issues:
andybons22afb312015-08-31 02:24:51202
203```el
andybons3322f762015-08-24 21:37:09204(require 'whitespace)
205(setq whitespace-style '(face indentation trailing empty lines-tail))
206(setq whitespace-line-column nil)
207(set-face-attribute 'whitespace-line nil
208 :background "purple"
209 :foreground "white"
210 :weight 'bold)
211(global-whitespace-mode 1)
212```
213
andybons22afb312015-08-31 02:24:51214Note: You might need to grab the latest version of
215[whitespace.el](http://www.emacswiki.org/emacs-en/download/whitespace.el).
andybons3322f762015-08-24 21:37:09216
Daniel Bratellf73f0df2018-09-24 13:52:49217## deep nesting
andybons3322f762015-08-24 21:37:09218
andybons22afb312015-08-31 02:24:51219A couple of helpers that show a summary of where you are; the first by tracing
220the indentation hierarchy upwards, the second by only showing `#if`s and
221`#else`s that are relevant to the current line:
andybons3322f762015-08-24 21:37:09222
223```el
andybons3322f762015-08-24 21:37:09224(defun ami-summarize-indentation-at-point ()
andybons22afb312015-08-31 02:24:51225 "Echo a summary of how one gets from the left-most column to
226 POINT in terms of indentation changes."
227 (interactive)
228 (save-excursion
229 (let ((cur-indent most-positive-fixnum)
230 (trace '()))
231 (while (not (bobp))
232 (let ((current-line (buffer-substring (line-beginning-position)
233 (line-end-position))))
234 (when (and (not (string-match "^\\s-*$" current-line))
235 (< (current-indentation) cur-indent))
236 (setq cur-indent (current-indentation))
237 (setq trace (cons current-line trace))
238 (if (or (string-match "^\\s-*}" current-line)
239 (string-match "^\\s-*else " current-line)
240 (string-match "^\\s-*elif " current-line))
241 (setq cur-indent (1+ cur-indent)))))
242 (forward-line -1))
243 (message "%s" (mapconcat 'identity trace "\n")))))
andybons3322f762015-08-24 21:37:09244
245(require 'cl)
andybons22afb312015-08-31 02:24:51246 (defun ami-summarize-preprocessor-branches-at-point ()
247 "Summarize the C preprocessor branches needed to get to point."
248 (interactive)
249 (flet ((current-line-text ()
250 (buffer-substring (line-beginning-position) (line-end-position))))
251 (save-excursion
252 (let ((eol (or (end-of-line) (point)))
253 deactivate-mark directives-stack)
254 (goto-char (point-min))
255 (while (re-search-forward "^#\\(if\\|else\\|endif\\)" eol t)
256 (if (or (string-prefix-p "#if" (match-string 0))
257 (string-prefix-p "#else" (match-string 0)))
258 (push (current-line-text) directives-stack)
259 (if (string-prefix-p "#endif" (match-string 0))
260 (while (string-prefix-p "#else" (pop directives-stack)) t))))
261 (message "%s" (mapconcat 'identity (reverse directives-stack) "\n"))))))
andybons3322f762015-08-24 21:37:09262```
263
264## find-things-fast
265
andybons22afb312015-08-31 02:24:51266erg wrote a suite of tools that do common operations from the root of your
267repository, called
268[Find Things Fast](https://github.com/eglaysher/find-things-fast). It contains
269ido completion over `git ls-files` (or the svn find equivalent) and `grepsource`
270that only git greps files with extensions we care about (or the equivalent the
271`find | xargs grep` statement in non-git repos.)
andybons3322f762015-08-24 21:37:09272
273## vc-mode and find-file performance
274
andybons22afb312015-08-31 02:24:51275When you first open a file under git control, vc mode kicks in and does a high
276level stat of your git repo. For huge repos, especially WebKit and Chromium,
277this makes opening a file take literally seconds. This snippet disables VC git
278for chrome directories:
andybons3322f762015-08-24 21:37:09279
andybons22afb312015-08-31 02:24:51280```el
andybons3322f762015-08-24 21:37:09281; Turn off VC git for chrome
282(when (locate-library "vc")
283(defadvice vc-registered (around nochrome-vc-registered (file))
284(message (format "nochrome-vc-registered %s" file))
285(if (string-match ".*chrome/src.*" file)
286(progn
287(message (format "Skipping VC mode for %s" % file))
288(setq ad-return-value nil)
289)
290ad-do-it)
291)
292(ad-activate 'vc-registered)
293)
294```
295
296## git tools
andybons3322f762015-08-24 21:37:09297
andybons22afb312015-08-31 02:24:51298We're collecting Chrome-specific tools under `tools/emacs`. See the files there
299for details.
300
301* `trybot.el`: import Windows trybot output into a `compilation-mode` buffer.
andybons3322f762015-08-24 21:37:09302
303## ERC for IRC
304
asargent4adb8112015-12-07 19:42:02305See [ErcIrc](erc_irc.md).
andybons3322f762015-08-24 21:37:09306
Junichi Uekawa75d91cad2021-06-15 05:54:42307## Compilation with M-x compile
andybons3322f762015-08-24 21:37:09308
Junichi Uekawa75d91cad2021-06-15 05:54:42309It's usually useful to first find the top directory with locate-dominating-file,
310and run `M-x compile`
311
312```lisp
313(defun chromium-compile ()
314 "Run compile for chromium."
315 (interactive)
316 (let ((chrome-dir (locate-dominating-file "." "chrome/BUILD.gn")))
317 (when chrome-dir
318 (let* ((default-directory chrome-dir))
319 (compile "ninja -C out/Debug chrome chrome_sandbox ")))))
320```