blob: 34efba804b1a75240b7bb01ed1fd3f59420ddc65 [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
163(load "/<path/to/chromium>/src/buildtools/clang_format/script/clang-format.el")
164(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
andybons22afb312015-08-31 02:24:51181## Highlight long lines
andybons3322f762015-08-24 21:37:09182
183One nice way to highlight long lines and other style issues:
andybons22afb312015-08-31 02:24:51184
185```el
andybons3322f762015-08-24 21:37:09186(require 'whitespace)
187(setq whitespace-style '(face indentation trailing empty lines-tail))
188(setq whitespace-line-column nil)
189(set-face-attribute 'whitespace-line nil
190 :background "purple"
191 :foreground "white"
192 :weight 'bold)
193(global-whitespace-mode 1)
194```
195
andybons22afb312015-08-31 02:24:51196Note: You might need to grab the latest version of
197[whitespace.el](http://www.emacswiki.org/emacs-en/download/whitespace.el).
andybons3322f762015-08-24 21:37:09198
Daniel Bratellf73f0df2018-09-24 13:52:49199## deep nesting
andybons3322f762015-08-24 21:37:09200
andybons22afb312015-08-31 02:24:51201A couple of helpers that show a summary of where you are; the first by tracing
202the indentation hierarchy upwards, the second by only showing `#if`s and
203`#else`s that are relevant to the current line:
andybons3322f762015-08-24 21:37:09204
205```el
andybons3322f762015-08-24 21:37:09206(defun ami-summarize-indentation-at-point ()
andybons22afb312015-08-31 02:24:51207 "Echo a summary of how one gets from the left-most column to
208 POINT in terms of indentation changes."
209 (interactive)
210 (save-excursion
211 (let ((cur-indent most-positive-fixnum)
212 (trace '()))
213 (while (not (bobp))
214 (let ((current-line (buffer-substring (line-beginning-position)
215 (line-end-position))))
216 (when (and (not (string-match "^\\s-*$" current-line))
217 (< (current-indentation) cur-indent))
218 (setq cur-indent (current-indentation))
219 (setq trace (cons current-line trace))
220 (if (or (string-match "^\\s-*}" current-line)
221 (string-match "^\\s-*else " current-line)
222 (string-match "^\\s-*elif " current-line))
223 (setq cur-indent (1+ cur-indent)))))
224 (forward-line -1))
225 (message "%s" (mapconcat 'identity trace "\n")))))
andybons3322f762015-08-24 21:37:09226
227(require 'cl)
andybons22afb312015-08-31 02:24:51228 (defun ami-summarize-preprocessor-branches-at-point ()
229 "Summarize the C preprocessor branches needed to get to point."
230 (interactive)
231 (flet ((current-line-text ()
232 (buffer-substring (line-beginning-position) (line-end-position))))
233 (save-excursion
234 (let ((eol (or (end-of-line) (point)))
235 deactivate-mark directives-stack)
236 (goto-char (point-min))
237 (while (re-search-forward "^#\\(if\\|else\\|endif\\)" eol t)
238 (if (or (string-prefix-p "#if" (match-string 0))
239 (string-prefix-p "#else" (match-string 0)))
240 (push (current-line-text) directives-stack)
241 (if (string-prefix-p "#endif" (match-string 0))
242 (while (string-prefix-p "#else" (pop directives-stack)) t))))
243 (message "%s" (mapconcat 'identity (reverse directives-stack) "\n"))))))
andybons3322f762015-08-24 21:37:09244```
245
246## find-things-fast
247
andybons22afb312015-08-31 02:24:51248erg wrote a suite of tools that do common operations from the root of your
249repository, called
250[Find Things Fast](https://github.com/eglaysher/find-things-fast). It contains
251ido completion over `git ls-files` (or the svn find equivalent) and `grepsource`
252that only git greps files with extensions we care about (or the equivalent the
253`find | xargs grep` statement in non-git repos.)
andybons3322f762015-08-24 21:37:09254
255## vc-mode and find-file performance
256
andybons22afb312015-08-31 02:24:51257When you first open a file under git control, vc mode kicks in and does a high
258level stat of your git repo. For huge repos, especially WebKit and Chromium,
259this makes opening a file take literally seconds. This snippet disables VC git
260for chrome directories:
andybons3322f762015-08-24 21:37:09261
andybons22afb312015-08-31 02:24:51262```el
andybons3322f762015-08-24 21:37:09263; Turn off VC git for chrome
264(when (locate-library "vc")
265(defadvice vc-registered (around nochrome-vc-registered (file))
266(message (format "nochrome-vc-registered %s" file))
267(if (string-match ".*chrome/src.*" file)
268(progn
269(message (format "Skipping VC mode for %s" % file))
270(setq ad-return-value nil)
271)
272ad-do-it)
273)
274(ad-activate 'vc-registered)
275)
276```
277
278## git tools
andybons3322f762015-08-24 21:37:09279
andybons22afb312015-08-31 02:24:51280We're collecting Chrome-specific tools under `tools/emacs`. See the files there
281for details.
282
283* `trybot.el`: import Windows trybot output into a `compilation-mode` buffer.
andybons3322f762015-08-24 21:37:09284
285## ERC for IRC
286
asargent4adb8112015-12-07 19:42:02287See [ErcIrc](erc_irc.md).
andybons3322f762015-08-24 21:37:09288
Junichi Uekawa75d91cad2021-06-15 05:54:42289## Compilation with M-x compile
andybons3322f762015-08-24 21:37:09290
Junichi Uekawa75d91cad2021-06-15 05:54:42291It's usually useful to first find the top directory with locate-dominating-file,
292and run `M-x compile`
293
294```lisp
295(defun chromium-compile ()
296 "Run compile for chromium."
297 (interactive)
298 (let ((chrome-dir (locate-dominating-file "." "chrome/BUILD.gn")))
299 (when chrome-dir
300 (let* ((default-directory chrome-dir))
301 (compile "ninja -C out/Debug chrome chrome_sandbox ")))))
302```