| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275 | 
							- ;;; gyp.el - font-lock-mode support for gyp files.
 
- ;; Copyright (c) 2012 Google Inc. All rights reserved.
 
- ;; Use of this source code is governed by a BSD-style license that can be
 
- ;; found in the LICENSE file.
 
- ;; Put this somewhere in your load-path and
 
- ;; (require 'gyp)
 
- (require 'python)
 
- (require 'cl)
 
- (when (string-match "python-mode.el" (symbol-file 'python-mode 'defun))
 
-   (error (concat "python-mode must be loaded from python.el (bundled with "
 
-                  "recent emacsen), not from the older and less maintained "
 
-                  "python-mode.el")))
 
- (defadvice python-indent-calculate-levels (after gyp-outdent-closing-parens
 
-                                                  activate)
 
-   "De-indent closing parens, braces, and brackets in gyp-mode."
 
-   (when (and (eq major-mode 'gyp-mode)
 
-              (string-match "^ *[])}][],)}]* *$"
 
-                            (buffer-substring-no-properties
 
-                             (line-beginning-position) (line-end-position))))
 
-     (setf (first python-indent-levels)
 
-           (- (first python-indent-levels) python-continuation-offset))))
 
- (defadvice python-indent-guess-indent-offset (around
 
-                                               gyp-indent-guess-indent-offset
 
-                                               activate)
 
-   "Guess correct indent offset in gyp-mode."
 
-   (or (and (not (eq major-mode 'gyp-mode))
 
-            ad-do-it)
 
-       (save-excursion
 
-         (save-restriction
 
-           (widen)
 
-           (goto-char (point-min))
 
-           ;; Find first line ending with an opening brace that is not a comment.
 
-           (or (and (re-search-forward "\\(^[[{]$\\|^.*[^#].*[[{]$\\)")
 
-                    (forward-line)
 
-                    (/= (current-indentation) 0)
 
-                    (set (make-local-variable 'python-indent-offset)
 
-                         (current-indentation))
 
-                    (set (make-local-variable 'python-continuation-offset)
 
-                         (current-indentation)))
 
-               (message "Can't guess gyp indent offset, using default: %s"
 
-                        python-continuation-offset))))))
 
- (define-derived-mode gyp-mode python-mode "Gyp"
 
-   "Major mode for editing .gyp files. See http://code.google.com/p/gyp/"
 
-   ;; gyp-parse-history is a stack of (POSITION . PARSE-STATE) tuples,
 
-   ;; with greater positions at the top of the stack. PARSE-STATE
 
-   ;; is a list of section symbols (see gyp-section-name and gyp-parse-to)
 
-   ;; with most nested section symbol at the front of the list.
 
-   (set (make-local-variable 'gyp-parse-history) '((1 . (list))))
 
-   (gyp-add-font-lock-keywords))
 
- (defun gyp-set-indentation ()
 
-   "Hook function to configure python indentation to suit gyp mode."
 
-   (set (make-local-variable 'python-indent-offset) 2)
 
-   (set (make-local-variable 'python-continuation-offset) 2)
 
-   (set (make-local-variable 'python-indent-guess-indent-offset) t)
 
-   (python-indent-guess-indent-offset))
 
- (add-hook 'gyp-mode-hook 'gyp-set-indentation)
 
- (add-to-list 'auto-mode-alist '("\\.gyp\\'" . gyp-mode))
 
- (add-to-list 'auto-mode-alist '("\\.gypi\\'" . gyp-mode))
 
- (add-to-list 'auto-mode-alist '("/\\.gclient\\'" . gyp-mode))
 
- ;;; Font-lock support
 
- (defconst gyp-dependencies-regexp
 
-   (regexp-opt (list "dependencies" "export_dependent_settings"))
 
-   "Regular expression to introduce 'dependencies' section")
 
- (defconst gyp-sources-regexp
 
-   (regexp-opt (list "action" "files" "include_dirs" "includes" "inputs"
 
-                     "libraries" "outputs" "sources"))
 
-   "Regular expression to introduce 'sources' sections")
 
- (defconst gyp-conditions-regexp
 
-   (regexp-opt (list "conditions" "target_conditions"))
 
-   "Regular expression to introduce conditions sections")
 
- (defconst gyp-variables-regexp
 
-   "^variables"
 
-   "Regular expression to introduce variables sections")
 
- (defconst gyp-defines-regexp
 
-   "^defines"
 
-   "Regular expression to introduce 'defines' sections")
 
- (defconst gyp-targets-regexp
 
-   "^targets"
 
-   "Regular expression to introduce 'targets' sections")
 
- (defun gyp-section-name (section)
 
-   "Map the sections we are interested in from SECTION to symbol.
 
-    SECTION is a string from the buffer that introduces a section.  The result is
 
-    a symbol representing the kind of section.
 
-    This allows us to treat (for the purposes of font-lock) several different
 
-    section names as the same kind of section. For example, a 'sources section
 
-    can be introduced by the 'sources', 'inputs', 'outputs' keyword.
 
-    'other is the default section kind when a more specific match is not made."
 
-   (cond ((string-match-p gyp-dependencies-regexp section) 'dependencies)
 
-         ((string-match-p gyp-sources-regexp section) 'sources)
 
-         ((string-match-p gyp-variables-regexp section) 'variables)
 
-         ((string-match-p gyp-conditions-regexp section) 'conditions)
 
-         ((string-match-p gyp-targets-regexp section) 'targets)
 
-         ((string-match-p gyp-defines-regexp section) 'defines)
 
-         (t 'other)))
 
- (defun gyp-invalidate-parse-states-after (target-point)
 
-   "Erase any parse information after target-point."
 
-   (while (> (caar gyp-parse-history) target-point)
 
-     (setq gyp-parse-history (cdr gyp-parse-history))))
 
- (defun gyp-parse-point ()
 
-   "The point of the last parse state added by gyp-parse-to."
 
-   (caar gyp-parse-history))
 
- (defun gyp-parse-sections ()
 
-   "A list of section symbols holding at the last parse state point."
 
-   (cdar gyp-parse-history))
 
- (defun gyp-inside-dictionary-p ()
 
-   "Predicate returning true if the parser is inside a dictionary."
 
-   (not (eq (cadar gyp-parse-history) 'list)))
 
- (defun gyp-add-parse-history (point sections)
 
-   "Add parse state SECTIONS to the parse history at POINT so that parsing can be
 
-    resumed instantly."
 
-   (while (>= (caar gyp-parse-history) point)
 
-     (setq gyp-parse-history (cdr gyp-parse-history)))
 
-   (setq gyp-parse-history (cons (cons point sections) gyp-parse-history)))
 
- (defun gyp-parse-to (target-point)
 
-   "Parses from (point) to TARGET-POINT adding the parse state information to
 
-    gyp-parse-state-history. Parsing stops if TARGET-POINT is reached or if a
 
-    string literal has been parsed. Returns nil if no further parsing can be
 
-    done, otherwise returns the position of the start of a parsed string, leaving
 
-    the point at the end of the string."
 
-   (let ((parsing t)
 
-         string-start)
 
-     (while parsing
 
-       (setq string-start nil)
 
-       ;; Parse up to a character that starts a sexp, or if the nesting
 
-       ;; level decreases.
 
-       (let ((state (parse-partial-sexp (gyp-parse-point)
 
-                                        target-point
 
-                                        -1
 
-                                        t))
 
-             (sections (gyp-parse-sections)))
 
-         (if (= (nth 0 state) -1)
 
-             (setq sections (cdr sections)) ; pop out a level
 
-           (cond ((looking-at-p "['\"]") ; a string
 
-                  (setq string-start (point))
 
-                  (goto-char (scan-sexps (point) 1))
 
-                  (if (gyp-inside-dictionary-p)
 
-                      ;; Look for sections inside a dictionary
 
-                      (let ((section (gyp-section-name
 
-                                      (buffer-substring-no-properties
 
-                                       (+ 1 string-start)
 
-                                       (- (point) 1)))))
 
-                        (setq sections (cons section (cdr sections)))))
 
-                  ;; Stop after the string so it can be fontified.
 
-                  (setq target-point (point)))
 
-                 ((looking-at-p "{")
 
-                  ;; Inside a dictionary. Increase nesting.
 
-                  (forward-char 1)
 
-                  (setq sections (cons 'unknown sections)))
 
-                 ((looking-at-p "\\[")
 
-                  ;; Inside a list. Increase nesting
 
-                  (forward-char 1)
 
-                  (setq sections (cons 'list sections)))
 
-                 ((not (eobp))
 
-                  ;; other
 
-                  (forward-char 1))))
 
-         (gyp-add-parse-history (point) sections)
 
-         (setq parsing (< (point) target-point))))
 
-     string-start))
 
- (defun gyp-section-at-point ()
 
-   "Transform the last parse state, which is a list of nested sections and return
 
-    the section symbol that should be used to determine font-lock information for
 
-    the string. Can return nil indicating the string should not have any attached
 
-    section."
 
-   (let ((sections (gyp-parse-sections)))
 
-     (cond
 
-      ((eq (car sections) 'conditions)
 
-       ;; conditions can occur in a variables section, but we still want to
 
-       ;; highlight it as a keyword.
 
-       nil)
 
-      ((and (eq (car sections) 'list)
 
-            (eq (cadr sections) 'list))
 
-       ;; conditions and sources can have items in [[ ]]
 
-       (caddr sections))
 
-      (t (cadr sections)))))
 
- (defun gyp-section-match (limit)
 
-   "Parse from (point) to LIMIT returning by means of match data what was
 
-    matched. The group of the match indicates what style font-lock should apply.
 
-    See also `gyp-add-font-lock-keywords'."
 
-   (gyp-invalidate-parse-states-after (point))
 
-   (let ((group nil)
 
-         (string-start t))
 
-     (while (and (< (point) limit)
 
-                 (not group)
 
-                 string-start)
 
-       (setq string-start (gyp-parse-to limit))
 
-       (if string-start
 
-           (setq group (case (gyp-section-at-point)
 
-                         ('dependencies 1)
 
-                         ('variables 2)
 
-                         ('conditions 2)
 
-                         ('sources 3)
 
-                         ('defines 4)
 
-                         (nil nil)))))
 
-     (if group
 
-         (progn
 
-           ;; Set the match data to indicate to the font-lock mechanism the
 
-           ;; highlighting to be performed.
 
-           (set-match-data (append (list string-start (point))
 
-                                   (make-list (* (1- group) 2) nil)
 
-                                   (list (1+ string-start) (1- (point)))))
 
-           t))))
 
- ;;; Please see http://code.google.com/p/gyp/wiki/GypLanguageSpecification for
 
- ;;; canonical list of keywords.
 
- (defun gyp-add-font-lock-keywords ()
 
-   "Add gyp-mode keywords to font-lock mechanism."
 
-   ;; TODO(jknotten): Move all the keyword highlighting into gyp-section-match
 
-   ;; so that we can do the font-locking in a single font-lock pass.
 
-   (font-lock-add-keywords
 
-    nil
 
-    (list
 
-     ;; Top-level keywords
 
-     (list (concat "['\"]\\("
 
-               (regexp-opt (list "action" "action_name" "actions" "cflags"
 
-                                 "cflags_cc" "conditions" "configurations"
 
-                                 "copies" "defines" "dependencies" "destination"
 
-                                 "direct_dependent_settings"
 
-                                 "export_dependent_settings" "extension" "files"
 
-                                 "include_dirs" "includes" "inputs" "ldflags" "libraries"
 
-                                 "link_settings" "mac_bundle" "message"
 
-                                 "msvs_external_rule" "outputs" "product_name"
 
-                                 "process_outputs_as_sources" "rules" "rule_name"
 
-                                 "sources" "suppress_wildcard"
 
-                                 "target_conditions" "target_defaults"
 
-                                 "target_defines" "target_name" "toolsets"
 
-                                 "targets" "type" "variables" "xcode_settings"))
 
-               "[!/+=]?\\)") 1 'font-lock-keyword-face t)
 
-     ;; Type of target
 
-     (list (concat "['\"]\\("
 
-               (regexp-opt (list "loadable_module" "static_library"
 
-                                 "shared_library" "executable" "none"))
 
-               "\\)") 1 'font-lock-type-face t)
 
-     (list "\\(?:target\\|action\\)_name['\"]\\s-*:\\s-*['\"]\\([^ '\"]*\\)" 1
 
-           'font-lock-function-name-face t)
 
-     (list 'gyp-section-match
 
-           (list 1 'font-lock-function-name-face t t) ; dependencies
 
-           (list 2 'font-lock-variable-name-face t t) ; variables, conditions
 
-           (list 3 'font-lock-constant-face t t) ; sources
 
-           (list 4 'font-lock-preprocessor-face t t)) ; preprocessor
 
-     ;; Variable expansion
 
-     (list "<@?(\\([^\n )]+\\))" 1 'font-lock-variable-name-face t)
 
-     ;; Command expansion
 
-     (list "<!@?(\\([^\n )]+\\))" 1 'font-lock-variable-name-face t)
 
-     )))
 
- (provide 'gyp)
 
 
  |