15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles);; Copyright (c) 2011 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles);; Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles);; found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles);; Set up flymake for use with chromium code. Uses ninja (since none of the 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles);; other chromium build systems have latency that allows interactive use). 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles);; 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles);; Requires a modern emacs (GNU Emacs >= 23) and that gyp has already generated 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles);; the build.ninja file(s). See defcustoms below for settable knobs. 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)(require 'flymake) 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)(defcustom cr-flymake-ninja-build-file "out/Debug/build.ninja" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Relative path from chromium's src/ directory to the 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) build.ninja file to use.") 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)(defcustom cr-flymake-ninja-executable "ninja" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Ninja executable location; either in $PATH or explicitly given.") 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)(defun cr-flymake-absbufferpath () 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Return the absolute path to the current buffer, or nil if the 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current buffer has no path." 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (when buffer-file-truename 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (expand-file-name buffer-file-truename))) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)(defun cr-flymake-chromium-src () 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Return chromium's src/ directory, or nil on failure." 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (let ((srcdir (locate-dominating-file 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (cr-flymake-absbufferpath) cr-flymake-ninja-build-file))) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (when srcdir (expand-file-name srcdir)))) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)(defun cr-flymake-string-prefix-p (prefix str) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Return non-nil if PREFIX is a prefix of STR (23.2 has string-prefix-p but 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) that's case insensitive and also 23.1 doesn't have it)." 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (string= prefix (substring str 0 (length prefix)))) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)(defun cr-flymake-current-file-name () 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Return the relative path from chromium's src/ directory to the 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file backing the current buffer or nil if it doesn't look like 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) we're under chromium/src/." 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (when (and (cr-flymake-chromium-src) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (cr-flymake-string-prefix-p 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (cr-flymake-chromium-src) (cr-flymake-absbufferpath))) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (substring (cr-flymake-absbufferpath) (length (cr-flymake-chromium-src))))) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)(defun cr-flymake-from-build-to-src-root () 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Return a path fragment for getting from the build.ninja file to src/." 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (replace-regexp-in-string 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "[^/]+" ".." 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (substring 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (file-name-directory 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (file-truename (or (and (cr-flymake-string-prefix-p 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "/" cr-flymake-ninja-build-file) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cr-flymake-ninja-build-file) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (concat (cr-flymake-chromium-src) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cr-flymake-ninja-build-file)))) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (length (cr-flymake-chromium-src))))) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)(defun cr-flymake-getfname (file-name-from-error-message) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Strip cruft from the passed-in filename to help flymake find the real file." 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (file-name-nondirectory file-name-from-error-message)) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)(defun cr-flymake-ninja-command-line () 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Return the command-line for running ninja, as a list of strings, or nil if 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) we're not during a save" 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (unless (buffer-modified-p) 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (list cr-flymake-ninja-executable 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (list "-C" 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (concat (cr-flymake-chromium-src) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (file-name-directory cr-flymake-ninja-build-file)) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (concat (cr-flymake-from-build-to-src-root) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (cr-flymake-current-file-name) "^"))))) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)(defun cr-flymake-kick-off-check-after-save () 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Kick off a syntax check after file save, if flymake-mode is on." 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (when flymake-mode (flymake-start-syntax-check))) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)(defadvice next-error (around cr-flymake-next-error activate) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "If flymake has something to say, let it say it; otherwise 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) revert to normal next-error behavior." 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (if (not flymake-err-info) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (condition-case msg 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ad-do-it 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (error (message "%s" (prin1-to-string msg)))) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (flymake-goto-next-error) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ;; copy/pasted from flymake-display-err-menu-for-current-line because I 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ;; couldn't find a way to have it tell me what the relevant error for this 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ;; line was in a single call: 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (let* ((line-no (flymake-current-line-no)) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (line-err-info-list 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (nth 0 (flymake-find-err-info flymake-err-info line-no))) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (menu-data (flymake-make-err-menu-data line-no line-err-info-list))) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (prin1 (car (car (car (cdr menu-data)))) t)))) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)(defun cr-flymake-find-file () 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Enable flymake, but only if it makes sense, and immediately 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) disable timer-based execution." 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (when (and (not flymake-mode) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (not buffer-read-only) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (cr-flymake-current-file-name)) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ;; Since flymake-allowed-file-name-masks requires static regexps to match 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ;; against, can't use cr-flymake-chromium-src here. Instead we add a 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ;; generic regexp, but only to a buffer-local version of the variable. 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (set (make-local-variable 'flymake-allowed-file-name-masks) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (list (list "\\.c\\(\\|c\\|pp\\)" 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'cr-flymake-ninja-command-line 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'ignore 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'cr-flymake-getfname))) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (flymake-find-file-hook) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (if flymake-mode 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (cancel-timer flymake-timer) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (kill-local-variable 'flymake-allowed-file-name-masks)))) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)(add-hook 'find-file-hook 'cr-flymake-find-file 'append) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)(add-hook 'after-save-hook 'cr-flymake-kick-off-check-after-save) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles);; Show flymake infrastructure ERRORs in hopes of fixing them. Set to 3 for 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles);; DEBUG-level output from flymake.el. 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)(setq flymake-log-level 0) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)(provide 'flymake-chromium) 123