1788 lines
78 KiB
EmacsLisp
1788 lines
78 KiB
EmacsLisp
;;; cmake-font-lock.el --- Advanced, type aware, highlight support for CMake
|
|
|
|
;; Copyright (C) 2012-2015 Anders Lindgren
|
|
|
|
;; Author: Anders Lindgren
|
|
;; Keywords: faces, languages
|
|
;; Package-Version: 20200103.1702
|
|
;; Created: 2012-12-05
|
|
;; Version: 0.1.6
|
|
;; Package-Requires: ((cmake-mode "0.0"))
|
|
;; URL: https://github.com/Lindydancer/cmake-font-lock
|
|
|
|
;; This program is free software: you can redistribute it and/or modify
|
|
;; it under the terms of the GNU General Public License as published by
|
|
;; the Free Software Foundation, either version 3 of the License, or
|
|
;; (at your option) any later version.
|
|
;;
|
|
;; This program is distributed in the hope that it will be useful,
|
|
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
;; GNU General Public License for more details.
|
|
;;
|
|
;; You should have received a copy of the GNU General Public License
|
|
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
;;; Commentary:
|
|
|
|
;; Advanced syntax coloring support for CMake scripts.
|
|
;;
|
|
;; The major feature of this package is to highlighting function
|
|
;; arguments according to their use. For example:
|
|
;;
|
|
;; 
|
|
;;
|
|
;; CMake, as a programming language, has a very simple syntax.
|
|
;; Unfortunately, this makes it hard to read CMake scripts. CMake
|
|
;; supports function calls, but they may not be nested. In addition,
|
|
;; the functions do not support return values like normal programming
|
|
;; languages, instead a function is capable of setting variables in
|
|
;; the scope of the parent. In other words, a parameter could be
|
|
;; anything like the name of a variable, a keyword, a property, or
|
|
;; even a plain string.
|
|
;;
|
|
;; By highlighting each argument, CMake scripts becomes much easier to
|
|
;; read, and also to write.
|
|
;;
|
|
;; This package is aware of all built-in CMake functions. In addition,
|
|
;; it allows you to add function signatures for your own functions.
|
|
|
|
;; The following is colored:
|
|
;;
|
|
;; * Function arguments are colored according to it's use, An argument
|
|
;; can be colored as a *keyword*, a *variable*, a *property*, or a
|
|
;; *target*. This package provides information on all built-in CMake
|
|
;; functions. Information on user-defined functions can be added.
|
|
;;
|
|
;; * All function names are colored, however, special functions like
|
|
;; `if', `while', `function', and `include' are colored using a
|
|
;; different color.
|
|
;;
|
|
;; * The constants `true', `false', `yes', `no', `y', `n', `on', and
|
|
;; `off'.
|
|
;;
|
|
;; * The constructs `${...}', `$ENV{...}', and `$<name:...>'.
|
|
;;
|
|
;; * In preprocessor definitions like `-DNAME', `NAME' is colored.
|
|
;;
|
|
;; * Comments and quoted strings.
|
|
;;
|
|
|
|
;; Installation:
|
|
;;
|
|
;; Place the file in a directory in Emacs' load path.
|
|
;;
|
|
;; Add the following lines to a suitable init file, like ~/.emacs, to
|
|
;; enable this package:
|
|
;;
|
|
;; (autoload 'cmake-font-lock-activate "cmake-font-lock" nil t)
|
|
;; (add-hook 'cmake-mode-hook 'cmake-font-lock-activate)
|
|
;;
|
|
;; This package is designed to be used together with a major mode for
|
|
;; editing CMake files. Once such package is `cmake-mode.el'
|
|
;; distributed by Kitware, however this package is not dependent upon
|
|
;; or associated with any specific CMake major mode. (Note that the
|
|
;; Kitware package contains rudimentary syntax coloring support.)
|
|
|
|
;; Customizing:
|
|
;;
|
|
;; In order to perform syntax coloring correctly, this package has to
|
|
;; be aware of the keywords and types of the CMake functions used. To
|
|
;; add information about non-standard CMake function, the following
|
|
;; functions can be used:
|
|
;;
|
|
;; `cmake-font-lock-add-keywords' -- Add keyword information:
|
|
;;
|
|
;; Adding the list of keywords to a function is a simple way to get
|
|
;; basic coloring correct. For most functions, this is sufficient.
|
|
;; For example:
|
|
;;
|
|
;; (cmake-font-lock-add-keywords
|
|
;; "my-func" '("FILE" "RESULT" "OTHER"))
|
|
;;
|
|
;; `cmake-font-lock-set-signature' -- Set full function type:
|
|
;;
|
|
;; Set the signature (the type of the arguments) for a function. For
|
|
;; example:
|
|
;;
|
|
;; (cmake-font-lock-set-signature
|
|
;; "my-func" '(:var nil :prop) '(("FILE" :file) ("RESULT" :var)))
|
|
;;
|
|
;; Custom types:
|
|
;;
|
|
;; The signatures of CMake functions provided by this package use a
|
|
;; number of types (see `cmake-font-lock-function-signatures'
|
|
;; for details). However, when adding new signatures, it's possible to
|
|
;; use additional types. In that case, the variable
|
|
;; `cmake-font-lock-argument-kind-face-alist' must be modified
|
|
;; to map the CMake type to a concrete Emacs face. For example:
|
|
;;
|
|
;; (cmake-font-lock-set-signature "my_warn" (:warning))
|
|
;; (add-to-list '(:warning . font-lock-warning-face)
|
|
;; cmake-font-lock-argument-kind-face-alist)
|
|
;;
|
|
|
|
;; Problems:
|
|
;;
|
|
;; * In CMake, function taking expressions, like `if' and `while',
|
|
;; treat any string as the name of a variable, if one exists. This
|
|
;; mode fontifies all such as variables, whether or not they
|
|
;; actually refer to variable. You can quote the arguments to
|
|
;; fontify them as strings (even though that will not prevent CMake
|
|
;; from interpreting them as variables).
|
|
;;
|
|
;; * Normally, keywords are written explicitly when calling a
|
|
;; function. However, it is legal to assigning them to a variable,
|
|
;; which is expanded at the time the function is called. In this
|
|
;; case, remaining arguments will not be colored correctly. For
|
|
;; example:
|
|
;;
|
|
;; set(def DEFINITION var2)
|
|
;; get_directory_property(var1 ${def} my_property)
|
|
|
|
;;; Code:
|
|
|
|
;; Naming:
|
|
;;
|
|
;; The package `cmake-mode' use the prefix `cmake-', this package use
|
|
;; the prefix `cmake-font-lock'. The only indentifier where this could
|
|
;; have been a problem is the constant `cmake-font-lock-keywords',
|
|
;; provided by `cmake-mode'. To avoid a collision, this package
|
|
;; provide `cmake-font-lock-advanced-keywords' instead.
|
|
|
|
;; Ideas for the future:
|
|
;;
|
|
;; - rename "cmake-font-lock-xxx" to "cmfl-xxx"?
|
|
;;
|
|
;; - Join keywords and signature datastructures? (Hard work for the
|
|
;; generator.)
|
|
;;
|
|
;; - Grey-out the arguments to the "endxxx()" functions?
|
|
;;
|
|
;; - Highlight misplaced arguments using warning face?
|
|
;;
|
|
;; - Better logger.
|
|
;;
|
|
;; - Use consistent naming (keyword).
|
|
;;
|
|
;; - Allow `cmake-font-lock-function-signatures' to contain a
|
|
;; function to call for the cases where a signature isn't powerful
|
|
;; enough to describe a function.
|
|
|
|
|
|
|
|
(defvar cmake-font-lock-function-keywords-alist
|
|
'(("add_custom_command" . ("APPEND"
|
|
"ARGS"
|
|
"BYPRODUCTS"
|
|
"COMMAND"
|
|
"COMMAND_EXPAND_LISTS"
|
|
"COMMENT"
|
|
"DEPENDS"
|
|
"DEPFILE"
|
|
"IMPLICIT_DEPENDS"
|
|
"JOB_POOL"
|
|
"MAIN_DEPENDENCY"
|
|
"OUTPUT"
|
|
"POST_BUILD"
|
|
"PRE_BUILD"
|
|
"PRE_LINK"
|
|
"TARGET"
|
|
"USES_TERMINAL"
|
|
"VERBATIM"
|
|
"WORKING_DIRECTORY"))
|
|
("add_custom_target" . ("ALL"
|
|
"BYPRODUCTS"
|
|
"COMMAND"
|
|
"COMMAND_EXPAND_LISTS"
|
|
"COMMENT"
|
|
"DEPENDS"
|
|
"JOB_POOL"
|
|
"SOURCES"
|
|
"USES_TERMINAL"
|
|
"VERBATIM"
|
|
"WORKING_DIRECTORY"))
|
|
("add_executable" . ("ALIAS"
|
|
"EXCLUDE_FROM_ALL"
|
|
"GLOBAL"
|
|
"IMPORTED"
|
|
"MACOSX_BUNDLE"
|
|
"WIN32"))
|
|
("add_library" . ("ALIAS"
|
|
"EXCLUDE_FROM_ALL"
|
|
"GLOBAL"
|
|
"IMPORTED"
|
|
"INTERFACE"
|
|
"MODULE"
|
|
"OBJECT"
|
|
"SHARED"
|
|
"STATIC"
|
|
"UNKNOWN"))
|
|
("add_subdirectory" . ("EXCLUDE_FROM_ALL"))
|
|
("add_test" . ("COMMAND"
|
|
"COMMAND_EXPAND_LISTS"
|
|
"CONFIGURATIONS"
|
|
"NAME"
|
|
"WORKING_DIRECTORY"))
|
|
("build_command" . ("CONFIGURATION"
|
|
"PROJECT_NAME"
|
|
"TARGET"))
|
|
("cmake_host_system_information" . ("QUERY"
|
|
"RESULT"))
|
|
("cmake_minimum_required" . ("FATAL_ERROR"
|
|
"VERSION"))
|
|
("cmake_parse_arguments" . ("PARSE_ARGV"))
|
|
("cmake_policy" . ("GET"
|
|
"NEW"
|
|
"OLD"
|
|
"POP"
|
|
"PUSH"
|
|
"SET"
|
|
"VERSION"))
|
|
("configure_file" . ("@ONLY"
|
|
"COPYONLY"
|
|
"CRLF"
|
|
"DOS"
|
|
"ESCAPE_QUOTES"
|
|
"LF"
|
|
"NEWLINE_STYLE"
|
|
"UNIX"
|
|
"WIN32"))
|
|
("create_test_sourcelist" . ("EXTRA_INCLUDE"
|
|
"FUNCTION"))
|
|
("define_property" . ("BRIEF_DOCS"
|
|
"CACHED_VARIABLE"
|
|
"DIRECTORY"
|
|
"FULL_DOCS"
|
|
"GLOBAL"
|
|
"INHERITED"
|
|
"PROPERTY"
|
|
"SOURCE"
|
|
"TARGET"
|
|
"TEST"
|
|
"VARIABLE"))
|
|
("enable_language" . ("OPTIONAL"))
|
|
("exec_program" . ("ARGS"
|
|
"OUTPUT_VARIABLE"
|
|
"RETURN_VALUE"))
|
|
("execute_process" . ("ANSI"
|
|
"AUTO"
|
|
"COMMAND"
|
|
"COMMAND_ECHO"
|
|
"ENCODING"
|
|
"ERROR_FILE"
|
|
"ERROR_QUIET"
|
|
"ERROR_STRIP_TRAILING_WHITESPACE"
|
|
"ERROR_VARIABLE"
|
|
"INPUT_FILE"
|
|
"NONE"
|
|
"OEM"
|
|
"OUTPUT_FILE"
|
|
"OUTPUT_QUIET"
|
|
"OUTPUT_STRIP_TRAILING_WHITESPACE"
|
|
"OUTPUT_VARIABLE"
|
|
"RESULT_VARIABLE"
|
|
"RESULTS_VARIABLE"
|
|
"STDERR"
|
|
"STDOUT"
|
|
"TIMEOUT"
|
|
"UTF8"
|
|
"UTF-8"
|
|
"WORKING_DIRECTORY"))
|
|
("export" . ("ANDROID_MK"
|
|
"APPEND"
|
|
"EXPORT"
|
|
"EXPORT_LINK_INTERFACE_LIBRARIES"
|
|
"FILE"
|
|
"NAMESPACE"
|
|
"PACKAGE"
|
|
"TARGETS"))
|
|
("export_library_dependencies" . ("APPEND"))
|
|
("file" . ("APPEND"
|
|
"BUNDLE_EXECUTABLE"
|
|
"CONDITION"
|
|
"CONFLICTING_DEPENDENCIES_PREFIX"
|
|
"CONFIGURE_DEPENDS"
|
|
"CONTENT"
|
|
"COPY"
|
|
"COPY_ON_ERROR"
|
|
"CREATE_SYMLINK"
|
|
"DESTINATION"
|
|
"DIRECTORIES"
|
|
"DIRECTORY"
|
|
"DIRECTORY_PERMISSIONS"
|
|
"DOWNLOAD"
|
|
"ENCODING"
|
|
"EXCLUDE"
|
|
"EXECUTABLES"
|
|
"EXPECTED_HASH"
|
|
"EXPECTED_MD5"
|
|
"FILE"
|
|
"FILES_MATCHING"
|
|
"FILE_PERMISSIONS"
|
|
"FOLLOW_SYMLINKS"
|
|
"FOLLOW_SYMLINK_CHAIN"
|
|
"FUNCTION"
|
|
"GENERATE"
|
|
"GET_RUNTIME_DEPENDENCIES"
|
|
"GLOB"
|
|
"GLOB_RECURSE"
|
|
"GUARD"
|
|
"HEX"
|
|
"HTTPHEADER"
|
|
"INACTIVITY_TIMEOUT"
|
|
"IGNORED"
|
|
"INSTALL"
|
|
"INPUT"
|
|
"LENGTH_MAXIMUM"
|
|
"LENGTH_MINIMUM"
|
|
"LIBRARIES"
|
|
"LIMIT"
|
|
"LIMIT_COUNT"
|
|
"LIMIT_INPUT"
|
|
"LIMIT_OUTPUT"
|
|
"LIST_DIRECTORIES"
|
|
"LOCK"
|
|
"LOG"
|
|
"MAKE_DIRECTORY"
|
|
"MD5"
|
|
"MODULES"
|
|
"NETRC"
|
|
"NETRC_FILE"
|
|
"NEWLINE_CONSUME"
|
|
"NO_HEX_CONVERSION"
|
|
"NO_SOURCE_PERMISSIONS"
|
|
"OFFSET"
|
|
"OPTIONAL"
|
|
"OUTPUT"
|
|
"PATTERN"
|
|
"PERMISSIONS"
|
|
"POST_EXCLUDE_REGEXES"
|
|
"POST_INCLUDE_REGEXES"
|
|
"PRE_EXCLUDE_REGEXES"
|
|
"PRE_INCLUDE_REGEXES"
|
|
"PROCESS"
|
|
"READ"
|
|
"READ_SYMLINK"
|
|
"REGEX"
|
|
"RELATIVE"
|
|
"RELATIVE_PATH"
|
|
"RELEASE"
|
|
"REMOVE"
|
|
"REMOVE_RECURSE"
|
|
"RENAME"
|
|
"REQUIRED"
|
|
"RESOLVED_DEPENDENCIES_VAR"
|
|
"RESULT"
|
|
"RESULT_VARIABLE"
|
|
"SHA1"
|
|
"SHA224"
|
|
"SHA256"
|
|
"SHA384"
|
|
"SHA512"
|
|
"SHOW_PROGRESS"
|
|
"SIZE"
|
|
"STATUS"
|
|
"STRINGS"
|
|
"SYMBOLIC"
|
|
"TIMEOUT"
|
|
"TIMESTAMP"
|
|
"TLS_VERIFY"
|
|
"TLS_CAINFO"
|
|
"TO_CMAKE_PATH"
|
|
"TO_NATIVE_PATH"
|
|
"TOUCH"
|
|
"TOUCH_NOCREATE"
|
|
"UNRESOLVED_DEPENDENCIES_VAR"
|
|
"UPLOAD"
|
|
"USE_SOURCE_PERMISSIONS"
|
|
"USERPWD"
|
|
"UTC"
|
|
"WRITE"))
|
|
("find_file" . ("CMAKE_FIND_ROOT_PATH_BOTH"
|
|
"DOC"
|
|
"ENV"
|
|
"HINTS"
|
|
"NAMES"
|
|
"NO_CMAKE_ENVIRONMENT_PATH"
|
|
"NO_CMAKE_FIND_ROOT_PATH"
|
|
"NO_CMAKE_PATH"
|
|
"NO_CMAKE_SYSTEM_PATH"
|
|
"NO_DEFAULT_PATH"
|
|
"NO_PACKAGE_ROOT_PATH"
|
|
"NO_SYSTEM_ENVIRONMENT_PATH"
|
|
"ONLY_CMAKE_FIND_ROOT_PATH"
|
|
"PATHS"
|
|
"PATH_SUFFIXES"))
|
|
("find_library" . ("CMAKE_FIND_ROOT_PATH_BOTH"
|
|
"DOC"
|
|
"ENV"
|
|
"HINTS"
|
|
"NAMES"
|
|
"NAMES_PER_DIR"
|
|
"NO_CMAKE_ENVIRONMENT_PATH"
|
|
"NO_CMAKE_FIND_ROOT_PATH"
|
|
"NO_CMAKE_PATH"
|
|
"NO_CMAKE_SYSTEM_PATH"
|
|
"NO_DEFAULT_PATH"
|
|
"NO_PACKAGE_ROOT_PATH"
|
|
"NO_SYSTEM_ENVIRONMENT_PATH"
|
|
"ONLY_CMAKE_FIND_ROOT_PATH"
|
|
"PATHS"
|
|
"PATH_SUFFIXES"))
|
|
("find_package" . ("CMAKE_FIND_ROOT_PATH_BOTH"
|
|
"COMPONENTS"
|
|
"CONFIG"
|
|
"CONFIGS"
|
|
"EXACT"
|
|
"HINTS"
|
|
"MODULE"
|
|
"NAMES"
|
|
"NO_CMAKE_BUILDS_PATH"
|
|
"NO_CMAKE_ENVIRONMENT_PATH"
|
|
"NO_CMAKE_FIND_ROOT_PATH"
|
|
"NO_CMAKE_PACKAGE_REGISTRY"
|
|
"NO_CMAKE_PATH"
|
|
"NO_CMAKE_SYSTEM_PACKAGE_REGISTRY"
|
|
"NO_CMAKE_SYSTEM_PATH"
|
|
"NO_DEFAULT_PATH"
|
|
"NO_MODULE"
|
|
"NO_PACKAGE_ROOT_PATH"
|
|
"NO_POLICY_SCOPE"
|
|
"NO_SYSTEM_ENVIRONMENT_PATH"
|
|
"ONLY_CMAKE_FIND_ROOT_PATH"
|
|
"OPTIONAL_COMPONENTS"
|
|
"PATHS"
|
|
"PATH_SUFFIXES"
|
|
"QUIET"
|
|
"REQUIRED"))
|
|
("find_path" . ("CMAKE_FIND_ROOT_PATH_BOTH"
|
|
"DOC"
|
|
"ENV"
|
|
"HINTS"
|
|
"NAMES"
|
|
"NO_CMAKE_ENVIRONMENT_PATH"
|
|
"NO_CMAKE_FIND_ROOT_PATH"
|
|
"NO_CMAKE_PATH"
|
|
"NO_CMAKE_SYSTEM_PATH"
|
|
"NO_DEFAULT_PATH"
|
|
"NO_PACKAGE_ROOT_PATH"
|
|
"NO_SYSTEM_ENVIRONMENT_PATH"
|
|
"ONLY_CMAKE_FIND_ROOT_PATH"
|
|
"PATHS"
|
|
"PATH_SUFFIXES"))
|
|
("find_program" . ("CMAKE_FIND_ROOT_PATH_BOTH"
|
|
"DOC"
|
|
"ENV"
|
|
"HINTS"
|
|
"NAMES"
|
|
"NAMES_PER_DIR"
|
|
"NO_CMAKE_ENVIRONMENT_PATH"
|
|
"NO_CMAKE_FIND_ROOT_PATH"
|
|
"NO_CMAKE_PATH"
|
|
"NO_CMAKE_SYSTEM_PATH"
|
|
"NO_DEFAULT_PATH"
|
|
"NO_PACKAGE_ROOT_PATH"
|
|
"NO_SYSTEM_ENVIRONMENT_PATH"
|
|
"ONLY_CMAKE_FIND_ROOT_PATH"
|
|
"PATHS"
|
|
"PATH_SUFFIXES"))
|
|
("foreach" . ("IN"
|
|
"ITEMS"
|
|
"LISTS"
|
|
"RANGE"))
|
|
("get_directory_property" . ("DEFINITION"
|
|
"DIRECTORY"))
|
|
("get_filename_component" . ("ABSOLUTE"
|
|
"BASE_DIR"
|
|
"CACHE"
|
|
"DIRECTORY"
|
|
"EXT"
|
|
"LAST_EXT"
|
|
"NAME"
|
|
"NAME_WE"
|
|
"NAME_WLE"
|
|
"PATH"
|
|
"PROGRAM"
|
|
"PROGRAM_ARGS"
|
|
"REALPATH"))
|
|
("get_property" . ("BRIEF_DOCS"
|
|
"CACHE"
|
|
"DEFINED"
|
|
"DIRECTORY"
|
|
"FULL_DOCS"
|
|
"GLOBAL"
|
|
"INSTALL"
|
|
"PROPERTY"
|
|
"SET"
|
|
"SOURCE"
|
|
"TARGET"
|
|
"TEST"
|
|
"VARIABLE"))
|
|
("include" . ("NO_POLICY_SCOPE"
|
|
"OPTIONAL"
|
|
"RESULT_VARIABLE"))
|
|
("include_directories" . ("AFTER"
|
|
"BEFORE"
|
|
"SYSTEM"))
|
|
("include_external_msproject" . ("GUID"
|
|
"PLATFORM"
|
|
"TYPE"))
|
|
("include_guard" . ("DIRECTORY"
|
|
"GLOBAL"))
|
|
("install" . ("ARCHIVE"
|
|
"BUNDLE"
|
|
"CODE"
|
|
"COMPONENT"
|
|
"CONFIGURATIONS"
|
|
"DESTINATION"
|
|
"DIRECTORY"
|
|
"DIRECTORY_PERMISSIONS"
|
|
"EXCLUDE"
|
|
"EXCLUDE_FROM_ALL"
|
|
"EXPORT"
|
|
"EXPORT_ANDROID_MK"
|
|
"EXPORT_LINK_INTERFACE_LIBRARIES"
|
|
"FILE"
|
|
"FILES"
|
|
"FILES_MATCHING"
|
|
"FILE_PERMISSIONS"
|
|
"FRAMEWORK"
|
|
"GROUP_EXECUTE"
|
|
"GROUP_READ"
|
|
"GROUP_WRITE"
|
|
"INCLUDES"
|
|
"LIBRARY"
|
|
"MESSAGE"
|
|
"MESSAGE_NEVER"
|
|
"NAMELINK_COMPONENT"
|
|
"NAMELINK_ONLY"
|
|
"NAMELINK_SKIP"
|
|
"NAMESPACE"
|
|
"OBJECTS"
|
|
"OPTIONAL"
|
|
"OWNER_EXECUTE"
|
|
"OWNER_READ"
|
|
"OWNER_WRITE"
|
|
"PATTERN"
|
|
"PERMISSIONS"
|
|
"PRIVATE_HEADER"
|
|
"PROGRAMS"
|
|
"PUBLIC_HEADER"
|
|
"REGEX"
|
|
"RENAME"
|
|
"RESOURCE"
|
|
"RUNTIME"
|
|
"SETGID"
|
|
"SETUID"
|
|
"SCRIPT"
|
|
"TARGETS"
|
|
"TYPE"
|
|
"USE_SOURCE_PERMISSIONS"
|
|
"WORLD_EXECUTE"
|
|
"WORLD_READ"
|
|
"WORLD_WRITE"))
|
|
("install_files" . ("FILES"))
|
|
("install_programs" . ("FILES"))
|
|
("install_targets" . ("RUNTIME_DIRECTORY"))
|
|
("link_directories" . ("AFTER"
|
|
"BEFORE"))
|
|
("link_libraries" . ("debug"
|
|
"general"
|
|
"optimized"))
|
|
("list" . ("APPEND"
|
|
"ASCENDING"
|
|
"AT"
|
|
"CASE"
|
|
"COMPARE"
|
|
"DESCENDING"
|
|
"EXCLUDE"
|
|
"FILE_BASENAME"
|
|
"FILTER"
|
|
"FIND"
|
|
"FOR"
|
|
"GENEX_STRIP"
|
|
"GET"
|
|
"INCLUDE"
|
|
"INSENSITIVE"
|
|
"INSERT"
|
|
"JOIN"
|
|
"LENGTH"
|
|
"ORDER"
|
|
"POP_BACK"
|
|
"POP_FRONT"
|
|
"PREPEND"
|
|
"REGEX"
|
|
"REMOVE_AT"
|
|
"REMOVE_DUPLICATES"
|
|
"REMOVE_ITEM"
|
|
"REPLACE"
|
|
"REVERSE"
|
|
"SENSITIVE"
|
|
"SORT"
|
|
"STRING"
|
|
"STRIP"
|
|
"SUBLIST"
|
|
"TOLOWER"
|
|
"TOUPPER"
|
|
"TRANSFORM"
|
|
"OUTPUT_VARIABLE"))
|
|
("load_cache" . ("EXCLUDE"
|
|
"INCLUDE_INTERNALS"
|
|
"READ_WITH_PREFIX"))
|
|
("load_command" . ("COMMAND_NAME"))
|
|
("mark_as_advanced" . ("CLEAR"
|
|
"FORCE"))
|
|
("math" . ("EXPR"
|
|
"DECIMAL"
|
|
"HEXADECIMAL"
|
|
"INPUT_FORMAT"
|
|
"OUTPUT_FORMAT"))
|
|
("message" . ("AUTHOR_WARNING"
|
|
"DEPRECATION"
|
|
"DEBUG"
|
|
"FATAL_ERROR"
|
|
"NOTICE"
|
|
"SEND_ERROR"
|
|
"STATUS"
|
|
"TRACE"
|
|
"VERBOSE"
|
|
"WARNING"))
|
|
("project" . ("DESCRIPTION"
|
|
"HOMEPAGE_URL"
|
|
"LANGUAGES"
|
|
"VERSION"))
|
|
("separate_arguments" . ("NATIVE_COMMAND"
|
|
"UNIX_COMMAND"
|
|
"WINDOWS_COMMAND"))
|
|
("set" . ("BOOL"
|
|
"CACHE"
|
|
"FILEPATH"
|
|
"FORCE"
|
|
"INTERNAL"
|
|
"PARENT_SCOPE"
|
|
"PATH"
|
|
"STRING"))
|
|
("set_directory_properties" . ("PROPERTIES"))
|
|
("set_property" . ("APPEND"
|
|
"APPEND_STRING"
|
|
"CACHE"
|
|
"DIRECTORY"
|
|
"GLOBAL"
|
|
"INSTALL"
|
|
"PROPERTY"
|
|
"SOURCE"
|
|
"TARGET"
|
|
"TEST"))
|
|
("set_source_files_properties" . ("PROPERTIES"))
|
|
("set_target_properties" . ("PROPERTIES"))
|
|
("set_tests_properties" . ("PROPERTIES"))
|
|
("source_group" . ("FILES"
|
|
"PREFIX"
|
|
"REGULAR_EXPRESSION"
|
|
"TREE"))
|
|
("string" . ("@ONLY"
|
|
"ALPHABET"
|
|
"APPEND"
|
|
"ASCII"
|
|
"COMPARE"
|
|
"CONCAT"
|
|
"CONFIGURE"
|
|
"EQUAL"
|
|
"ESCAPE_QUOTES"
|
|
"FIND"
|
|
"GENEX_STRIP"
|
|
"GREATER"
|
|
"GREATER_EQUAL"
|
|
"JOIN"
|
|
"LENGTH"
|
|
"LESS"
|
|
"LESS_EQUAL"
|
|
"MAKE_C_IDENTIFIER"
|
|
"MATCH"
|
|
"MATCHALL"
|
|
"MATCHES"
|
|
"MD5"
|
|
"NAME"
|
|
"NAMESPACE"
|
|
"NOTEQUAL"
|
|
"PREPEND"
|
|
"RANDOM"
|
|
"RANDOM_SEED"
|
|
"REGEX"
|
|
"REPEAT"
|
|
"REPLACE"
|
|
"REVERSE"
|
|
"SHA1"
|
|
"SHA224"
|
|
"SHA256"
|
|
"SHA384"
|
|
"SHA512"
|
|
"SHA3_224"
|
|
"SHA3_256"
|
|
"SHA3_384"
|
|
"SHA3_512"
|
|
"STRIP"
|
|
"SUBSTRING"
|
|
"TIMESTAMP"
|
|
"TOLOWER"
|
|
"TOUPPER"
|
|
"TYPE"
|
|
"UPPER"
|
|
"UTC"
|
|
"UUID"))
|
|
("subdirs" . ("EXCLUDE_FROM_ALL"
|
|
"PREORDER"))
|
|
("target_compile_definitions" . ("INTERFACE"
|
|
"PRIVATE"
|
|
"PUBLIC"))
|
|
("target_compile_features" . ("INTERFACE"
|
|
"PRIVATE"
|
|
"PUBLIC"))
|
|
("target_compile_options" . ("BEFORE"
|
|
"INTERFACE"
|
|
"PRIVATE"
|
|
"PUBLIC"))
|
|
("target_include_directories" . ("BEFORE"
|
|
"INTERFACE"
|
|
"PRIVATE"
|
|
"PUBLIC"
|
|
"SYSTEM"))
|
|
("target_link_directories" . ("BEFORE"
|
|
"INTERFACE"
|
|
"PRIVATE"
|
|
"PUBLIC"))
|
|
("target_link_libraries" . ("INTERFACE"
|
|
"LINK_INTERFACE_LIBRARIES"
|
|
"LINK_PRIVATE"
|
|
"LINK_PUBLIC"
|
|
"PRIVATE"
|
|
"PUBLIC"
|
|
"debug"
|
|
"general"
|
|
"optimized"))
|
|
("target_link_options" . ("BEFORE"
|
|
"INTERFACE"
|
|
"PRIVATE"
|
|
"PUBLIC"))
|
|
("target_precompile_headers" . ("INTERFACE"
|
|
"PRIVATE"
|
|
"PUBLIC"
|
|
"REUSE_FROM"))
|
|
("target_sources" . ("INTERFACE"
|
|
"PRIVATE"
|
|
"PUBLIC"))
|
|
("try_compile" . ("CMAKE_FLAGS"
|
|
"COMPILE_DEFINITIONS"
|
|
"COPY_FILE"
|
|
"COPY_FILE_ERROR"
|
|
"CXX_EXTENSIONS"
|
|
"CXX_STANDARD"
|
|
"CXX_STANDARD_REQUIRED"
|
|
"C_EXTENSIONS"
|
|
"C_STANDARD"
|
|
"C_STANDARD_REQUIRED"
|
|
"INCLUDE_DIRECTORIES"
|
|
"LINK_DIRECTORIES"
|
|
"LINK_LIBRARIES"
|
|
"LINK_OPTIONS"
|
|
"OUTPUT_VARIABLE"
|
|
"SOURCES"))
|
|
("try_run" . ("ARGS"
|
|
"CMAKE_FLAGS"
|
|
"COMPILE_DEFINITIONS"
|
|
"COMPILE_OUTPUT_VARIABLE"
|
|
"LINK_LIBRARIES"
|
|
"LINK_OPTIONS"
|
|
"OUTPUT_VARIABLE"
|
|
"RUN_OUTPUT_VARIABLE"))
|
|
("unset" . ("CACHE"
|
|
"PARENT_SCOPE"))
|
|
("use_mangled_mesa" . ("OUTPUT_DIRECTORY"
|
|
"PATH_TO_MESA"))
|
|
("variable_requires" . ("REQUIRED_VARIABLE1"
|
|
"REQUIRED_VARIABLE2"
|
|
"RESULT_VARIABLE"
|
|
"TEST_VARIABLE"))
|
|
("write_file" . ("APPEND"))))
|
|
|
|
|
|
|
|
|
|
(defvar cmake-font-lock-function-alias-alist
|
|
'(("else" . "if")
|
|
("elseif" . "if")
|
|
("endif" . "if")
|
|
("while" . "if")
|
|
("endwhile" . "if")
|
|
("endforeach" . "foreach")
|
|
("endfunction" . "function")
|
|
("endmacro" . "macro"))
|
|
"*Alias function names.
|
|
|
|
This is used to keep down the size of
|
|
`cmake-font-lock-function-keywords-alist' and
|
|
`cmake-font-lock-function-signatures'.")
|
|
|
|
|
|
(defvar cmake-font-lock-function-signatures
|
|
'(("add_custom_command" () (("BYPRODUCTS" :repeat :path)
|
|
("DEPENDS" :repeat :path)
|
|
("DEPFILE" :path)
|
|
("IMPLICIT_DEPENDS" :repeat nil :path)
|
|
("MAIN_DEPENDENCY" :path)
|
|
("TARGET" :tgt)))
|
|
("add_custom_target" (:tgt) (("BYPRODUCTS" :repeat :path)
|
|
("DEPENDS" :repeat :path)
|
|
("SOURCES" :repeat :path)))
|
|
("add_dependencies" (:repeat :tgt))
|
|
("add_executable" (:tgt) (("ALIAS" :tgt)))
|
|
("add_library" (:tgt) (("ALIAS" :tgt)))
|
|
("aux_source_directory" (nil :var))
|
|
("build_command" (:var) (("TARGET" :tgt)))
|
|
("cmake_host_system_information" () (("RESULT" :var)))
|
|
("cmake_policy" () (("GET" :policy :var)
|
|
("SET" :policy)))
|
|
("define_property" () (("PROPERTY" :prop)))
|
|
("execute_process" () (("RESULT_VARIABLE" :var)
|
|
("RESULTS_VARIABLE" :var)
|
|
("OUTPUT_VARIABLE" :var)
|
|
("ERROR_VARIABLE" :var)
|
|
("INPUT_FILE" :path)
|
|
("OUTPUT_FILE" :path)
|
|
("ERROR_FILE" :path)))
|
|
("export" () (("TARGETS" :repeat :tgt)))
|
|
("file" () (("LOCK" :path)
|
|
("READ" :path :var)
|
|
("MD5" :path :var)
|
|
("SHA1" :path :var)
|
|
("SHA224" :path :var)
|
|
("SHA256" :path :var)
|
|
("SHA384" :path :var)
|
|
("SHA512" :path :var)
|
|
("SHA3_224" :path :var)
|
|
("SHA3_256" :path :var)
|
|
("SHA3_384" :path :var)
|
|
("SHA3_512" :path :var)
|
|
("STRINGS" :path :var)
|
|
("TIMESTAMP" :path :var)
|
|
("RESOLVED_DEPENDENCIES_VAR" :var)
|
|
("UNRESOLVED_DEPENDENCIES_VAR" :var)
|
|
("CONFLICTING_DEPENDENCIES_PREFIX" nil)
|
|
("EXECUTABLES" :repeat :path)
|
|
("LIBRARIES" :repeat :path)
|
|
("MODULES" :repeat :path)
|
|
("DIRECTORIES" :repeat :path)
|
|
("BUNDLE_EXECUTABLE" :path)
|
|
("GLOB" :var)
|
|
("GLOB_RECURSE" :var)
|
|
("RESULT_VARIABLE" :var)
|
|
("RELATIVE_PATH" :var :path :path)
|
|
("TO_CMAKE_PATH" :path :var)
|
|
("TO_NATIVE_PATH" :path :var)))
|
|
("find_file" (:var :optional nil :repeat :path))
|
|
("find_library" (:var :optional nil :repeat :path))
|
|
("find_path" (:var :optional nil :repeat :path))
|
|
("find_program" (:var :optional nil :repeat :path))
|
|
("foreach" (:var) (("LISTS" :repeat :var)))
|
|
("function" (:func :repeat :var))
|
|
("get_cmake_property" (:var :prop))
|
|
;; Note: This falls outside the standard form, as "DIRECTORY dir"
|
|
;; can be optional in the middle of the argument list. Work-around
|
|
;; is to see :prop as an extra argument to the keywords.
|
|
("get_directory_property" (:var :optional :prop)
|
|
(("DIRECTORY" :path :optional :prop)
|
|
("DEFINITION" :var :optional :prop)))
|
|
("get_filename_component" (:var :path))
|
|
("get_property" (:var) (("PROPERTY" :prop)
|
|
("DIRECTORY" :optional :path)
|
|
("INSTALL" :path)
|
|
("SOURCE" :path)
|
|
("TARGET" :tgt)
|
|
("TEST" :tst)))
|
|
("get_source_file_property" (:var :path :prop))
|
|
("get_target_property" (:var :tgt :prop))
|
|
("get_test_property" (:test :prop :var))
|
|
;; Note: "(" is treated as a keyword, however, it will never be
|
|
;; fontified as such, thanks to
|
|
;; `cmake-font-lock-argument-kind-regexp-alist'.
|
|
;;
|
|
;; This works for all keywords except "IS_NEWER_THAN", since it is
|
|
;; the only keyword that does not take a variable on its left hand
|
|
;; side. Fortunately, file names typically don't look like a
|
|
;; variable, so in most cases it will not be fontified at all.
|
|
;;
|
|
;; The ":optional :var" is needed to match both "(x OR y)" and the
|
|
;; more complex "(x OR ( y AND z ))"
|
|
("if" (:optional :var)
|
|
(("(" :optional :var)
|
|
("AND" :optional :var)
|
|
("COMMAND" :func)
|
|
("DEFINED" :var)
|
|
("EQUAL" :var)
|
|
("EXISTS" :path)
|
|
("GREATER" :var)
|
|
("GREATER_EQUAL" :var)
|
|
("IN_LIST" :var)
|
|
("IS_ABSOLUTE" :path)
|
|
("IS_DIRECTORY" :path)
|
|
("IS_NEWER_THAN" :path)
|
|
("IS_SYMLINK" :path)
|
|
("LESS" :var)
|
|
("LESS_EQUAL" :var)
|
|
("MATCHES" :regexp)
|
|
("NOT" :optional :var)
|
|
("OR" :optional :var)
|
|
("POLICY" :policy)
|
|
("STREQUAL" :var)
|
|
("STRGREATER" :var)
|
|
("STRGREATER_EQUAL" :var)
|
|
("STRLESS" :var)
|
|
("STRLESS_EQUAL" :var)
|
|
("TARGET" :tgt)
|
|
("TEST" :tst)
|
|
("VERSION_EQUAL" :var)
|
|
("VERSION_GREATER" :var)
|
|
("VERSION_GREATER_EQUAL" :var)
|
|
("VERSION_LESS" :var)
|
|
("VERSION_LESS_EQUAL" :var)))
|
|
("include" () (("RESULT_VARIABLE" :var)))
|
|
("include_external_msproject" (:tgt :path))
|
|
("install" () (("TARGETS" :repeat :tgt)))
|
|
("list" () (("FILTER" :var)
|
|
("LENGTH" :var :var)
|
|
("GET" :var :repeat nil :var)
|
|
("APPEND" :var)
|
|
("FIND" :var nil :var)
|
|
("INSERT" :var)
|
|
("JOIN" :var nil :var)
|
|
("POP_BACK" :var)
|
|
("POP_FRONT" :var)
|
|
("PREPEND" :var)
|
|
("REMOVE_ITEM" :var)
|
|
("REMOVE_AT" :var)
|
|
("REMOVE_DUPLICATES" :var)
|
|
("REVERSE" :var)
|
|
("SORT" :var)
|
|
("SUBLIST" :var nil nil :var)
|
|
("TRANSFORM" :var)))
|
|
("macro" (:func :repeat :var))
|
|
("mark_as_advanced" (:repeat :var) (("CLEAR" :repeat :var)
|
|
("FORCE" :repeat :var)))
|
|
("math" () (("EXPR" :var)))
|
|
("option" (:var))
|
|
("separate_arguments" (:var))
|
|
("set" (:var))
|
|
("set_directory_properties" () (("PROPERTIES" :repeat (:prop nil))))
|
|
("set_property" () (("PROPERTY" :prop)
|
|
("DIRECTORY" :path)
|
|
("INSTALL" :repeat :path)
|
|
("SOURCE" :repeat :path)
|
|
("TARGET" :repeat :tgt)
|
|
("TEST" :repeat :tst)))
|
|
("set_source_files_properties" () (("PROPERTIES" :repeat (:prop nil))))
|
|
("set_target_properties" (:repeat :tgt)
|
|
(("PROPERTIES" :repeat (:prop nil))))
|
|
("set_test_properties" (:repeat :tst)
|
|
(("PROPERTIES" :repeat (:prop nil))))
|
|
("site_name" (:var))
|
|
("string" () (("CONCAT" :var)
|
|
("GENEX_STRIP" nil :var)
|
|
("MATCH" nil :var)
|
|
("MATCHALL" nil :var)
|
|
("REPLACE" nil nil :var)
|
|
("MD5" :var)
|
|
("SHA1" :var)
|
|
("SHA224" :var)
|
|
("SHA256" :var)
|
|
("SHA384" :var)
|
|
("SHA512" :var)
|
|
("SHA3_224" :var)
|
|
("SHA3_256" :var)
|
|
("SHA3_384" :var)
|
|
("SHA3_512" :var)
|
|
("EQUAL" nil nil :var)
|
|
("NOTEQUAL" nil nil :var)
|
|
("LESS" nil nil :var)
|
|
("GREATER" nil nil :var)
|
|
("ASCII" :repeat nil :var)
|
|
("CONFIGURE" nil :var)
|
|
("JOIN" nil :var)
|
|
("TOUPPER" nil :var)
|
|
("TOLOWER" nil :var)
|
|
("LENGTH" nil :var)
|
|
("REPEAT" nil nil :var)
|
|
("SUBSTRING" nil nil nil :var)
|
|
("STRIP" nil :var)
|
|
("TIMESTAMP" :var)
|
|
("MAKE_C_IDENTIFIER" nil :var)
|
|
("RANDOM" :repeat nil :var)
|
|
("FIND" nil nil :var)
|
|
("UUID" :var)))
|
|
("target_compile_features" (:tgt))
|
|
("target_compile_options" (:tgt))
|
|
("target_compile_definitions" (:tgt) (("INTERFACE" :repeat :def)
|
|
("PUBLIC" :repeat :def)
|
|
("PRIVATE" :repeat :def)))
|
|
("target_include_directories" (:tgt) (("INTERFACE" :repeat :path)
|
|
("PUBLIC" :repeat :path)
|
|
("PRIVATE" :repeat :path)))
|
|
("target_link_directories" (:tgt) (("INTERFACE" :repeat :path)
|
|
("PUBLIC" :repeat :path)
|
|
("PRIVATE" :repeat :path)))
|
|
("target_link_libraries" (:tgt))
|
|
("target_link_options" (:tgt))
|
|
("target_precompile_headers" (:tgt) (("INTERFACE" :repeat :path)
|
|
("PUBLIC" :repeat :path)
|
|
("PRIVATE" :repeat :path)
|
|
("REUSE_FROM" :tgt)))
|
|
("target_sources" (:tgt))
|
|
;; Placement of :optional is to allow "try_compile(var dir SOURCES ...)"
|
|
("try_compile" (:var nil :optional nil nil :tgt)
|
|
(("OUTPUT_VARIABLE" :var)
|
|
("COMPILE_DEFINITIONS" :repeat :def)
|
|
("COPY_FILE_ERROR" :var)))
|
|
("try_run" (:var :var)
|
|
(("COMPILE_OUTPUT_VARIABLE" :var)
|
|
("OUTPUT_VARIABLE" :var)
|
|
("RUN_OUTPUT_VARIABLE" :var)
|
|
("COMPILE_DEFINITIONS" :repeat :def)))
|
|
("unset" (:var))
|
|
("variable_watch" (:var)))
|
|
"*List of function signatures.
|
|
|
|
Each element of the list is a list with two or three elements.
|
|
The first is the (lower-case form of the) name of the function.
|
|
The second is a list of argument kinds (see below). The third,
|
|
optional, is an alist from keywords to lists of argument kinds.
|
|
|
|
An argument kind is:
|
|
|
|
- nil A plain argument that should not be fontified.
|
|
- :var A variable
|
|
- :func A function
|
|
- :prop A property
|
|
- :policy A CMake policy
|
|
- :path A file or a directory
|
|
- :tgt A target
|
|
- :def A preprocessor definition
|
|
- :optional The rest of the elements are not mandatory
|
|
- :repeat what Repeat the element `what'
|
|
- :repeat (...) Repeat the elements is the list.
|
|
- Anything else A custom type
|
|
|
|
Elements are fontified as specified by
|
|
`cmake-font-lock-argument-kind-face-alist'.")
|
|
|
|
;; Filled in by `cmake-font-lock-setup'.
|
|
(defvar cmake-font-lock-advanced-keywords nil)
|
|
|
|
;; --------------------------------------------------
|
|
;; Public functions
|
|
;;
|
|
|
|
;;;###autoload
|
|
(defun cmake-font-lock-activate ()
|
|
"Activate advanced CMake colorization.
|
|
|
|
To activate this every time a CMake file is opened, use the following:
|
|
|
|
(add-hook 'cmake-mode-hook 'cmake-font-lock-activate)"
|
|
(interactive)
|
|
(cmake-font-lock-setup)
|
|
;; If this function is called after font-lock is up and running,
|
|
;; refresh it. (This does not work on older Emacs versions.)
|
|
(if (and font-lock-mode
|
|
(fboundp 'font-lock-refresh-defaults))
|
|
(font-lock-refresh-defaults)))
|
|
|
|
|
|
;; This ensures that this package is enabled automatically when
|
|
;; installed as a package (when cmake-mode is installed).
|
|
|
|
;;;###autoload(add-hook 'cmake-mode-hook 'cmake-font-lock-activate)
|
|
|
|
|
|
(defun cmake-font-lock-add-keywords (name keywords)
|
|
"Add keywords to a CMake function."
|
|
(setq name (downcase name))
|
|
(let ((pair (assoc name cmake-font-lock-function-keywords-alist)))
|
|
(unless pair
|
|
(setq pair (cons name ()))
|
|
(push pair cmake-font-lock-function-keywords-alist))
|
|
(dolist (kw keywords)
|
|
(unless (member kw (cdr pair))
|
|
(setcdr pair (cons kw (cdr pair)))))))
|
|
|
|
(defun cmake-font-lock-set-signature (name sig
|
|
&optional keyword-sig-alist)
|
|
"Set the signature of a CMake function.
|
|
|
|
`sig' and `keyword-sig-alist' should be on the same form as the
|
|
second and third element of each entry in the list
|
|
`cmake-font-lock-function-signatures'."
|
|
(setq name (downcase name))
|
|
(let ((entry (assoc name cmake-font-lock-function-signatures)))
|
|
(if entry
|
|
(setcdr entry (list sig keyword-sig-alist))
|
|
(push (list name sig keyword-sig-alist)
|
|
cmake-font-lock-function-signatures))))
|
|
|
|
|
|
;; --------------------------------------------------
|
|
;; Font-lock support functions
|
|
;;
|
|
|
|
|
|
|
|
(defun cmake-font-lock-normalize-function-name (name)
|
|
"Normalize function name, or name alias."
|
|
(setq name (downcase name))
|
|
(let ((alias-pair (assoc name
|
|
cmake-font-lock-function-alias-alist)))
|
|
(if alias-pair
|
|
(cdr alias-pair)
|
|
name)))
|
|
|
|
|
|
(defun cmake-font-lock-is-in-comment ()
|
|
"Return non-nil if point is in a comment.
|
|
|
|
This assumes that Font Lock is active and has fontified comments."
|
|
(let ((props (text-properties-at (point)))
|
|
(faces '()))
|
|
(while props
|
|
(let ((pr (pop props))
|
|
(value (pop props)))
|
|
(if (eq pr 'face)
|
|
(setq faces value))))
|
|
(unless (listp faces)
|
|
(setq faces (list faces)))
|
|
(memq 'font-lock-comment-face faces)))
|
|
|
|
|
|
(defun cmake-font-lock-search-forward-ignore-comments (re limit)
|
|
"Search forward for regexp RE but ignore occurences in comments.
|
|
LIMIT is search limit."
|
|
(let (res)
|
|
(while
|
|
(progn
|
|
(setq res (re-search-forward re limit t))
|
|
(and res
|
|
(cmake-font-lock-is-in-comment))))
|
|
res))
|
|
|
|
|
|
;; ----------------------------------------
|
|
;; Support for ${...} constructs.
|
|
;;
|
|
;; In addition, the following is handled:
|
|
;; - $name{...} -- "name" (typically ENV)
|
|
;; - name{...} -- Used by set() and unset().
|
|
;;
|
|
|
|
(defun cmake-font-lock-skip-braces ()
|
|
"Move point past the end of a (possibly nested) ${...} construct.
|
|
Return nil if the matching closing brace was not found."
|
|
;; Skip initial optional dollar.
|
|
(if (eq (following-char) ?$)
|
|
(forward-char))
|
|
;; Skip initial identifier (typically ENV).
|
|
(skip-chars-forward "a-zA-Z@0-9_")
|
|
;; Skip a { } brace pair, possibly containing other pairs.
|
|
(and (eq (following-char) ?{)
|
|
(let ((depth 0)
|
|
(res nil)
|
|
(done nil))
|
|
(while (not done)
|
|
(cond ((eq (following-char) ?{)
|
|
(setq depth (+ depth 1))
|
|
(forward-char))
|
|
((eq (following-char) ?})
|
|
(setq depth (- depth 1))
|
|
(forward-char)
|
|
(when (equal depth 0)
|
|
(setq done t)
|
|
(setq res t)))
|
|
(t
|
|
(if (equal (skip-chars-forward "a-zA-Z@0-9_$") 0)
|
|
(setq done t)))))
|
|
res)))
|
|
|
|
(defvar cmake-font-lock-match-dollar-braces-has-name nil
|
|
"True when the current brace construct is a hash, like ENV.")
|
|
|
|
(defun cmake-font-lock-match-dollar-braces-content (lim)
|
|
"Match (part of) the content of a ${...} construct.
|
|
In the case of nested ${...} construct, repeated calls to this
|
|
match next top-level part.
|
|
|
|
If the current construct is without a name (typically a
|
|
variable), subexpression 1 of the match-data is set.
|
|
Otherwise (typically ENV), subexpression 2 is set.
|
|
|
|
For example, the numbers below indicate the parts that are
|
|
matched in subsequent call:
|
|
|
|
${abd${def}ghi}
|
|
111 222"
|
|
;; Skip embedded ${...} constructs.
|
|
(while (eq (following-char) ?$)
|
|
(cmake-font-lock-skip-braces))
|
|
(let ((p (point)))
|
|
(if (> (skip-chars-forward "a-zA-Z@0-9_") 0)
|
|
;; Create match data.
|
|
(let* ((md (list p (point)))
|
|
(md-full md))
|
|
(if cmake-font-lock-match-dollar-braces-has-name
|
|
(setq md-full (append md-full '(nil nil))))
|
|
(setq md-full (append md-full md))
|
|
(set-match-data md-full)
|
|
t)
|
|
nil)))
|
|
|
|
(defun cmake-font-lock-match-dollar-braces (lim)
|
|
"Match a $xxx{...} construct.
|
|
|
|
Place point after the opening brace, to prepare for calls to
|
|
`cmake-font-lock-match-dollar-braces-content'.
|
|
|
|
Subexpressions of the match-data are as follows:
|
|
|
|
$ 1 (if present)
|
|
xxx 2 (if present)
|
|
{ 3
|
|
} 4 (if present)"
|
|
(let ((id "[a-zA-Z@_][a-zA-Z@_0-9]*")
|
|
(ws "\\s-*"))
|
|
(if (cmake-font-lock-search-forward-ignore-comments
|
|
(concat "\\(\\$\\)?" ws "\\(" id ws "\\)?" "\\({\\)") lim)
|
|
(let ((md (list (match-beginning 0) (match-end 0)
|
|
(match-beginning 1) (match-end 1)
|
|
(match-beginning 2) (match-end 2)
|
|
(match-beginning 3) (match-end 3))))
|
|
(setq cmake-font-lock-match-dollar-braces-has-name
|
|
(match-beginning 2))
|
|
(save-excursion
|
|
(goto-char (match-end 0))
|
|
(while
|
|
(cmake-font-lock-match-dollar-braces-content lim))
|
|
(if (eq (following-char) ?})
|
|
(nconc md (list (point) (+ (point) 1))))
|
|
;; Patch slot 0.
|
|
(setcar (cdr md) (+ (point) 1))
|
|
(set-match-data md))
|
|
t)
|
|
nil)))
|
|
|
|
|
|
;; ----------------------------------------
|
|
;; Function matcher.
|
|
;;
|
|
|
|
(defvar cmake-font-lock-arguments-begin nil)
|
|
(defvar cmake-font-lock-arguments-end nil
|
|
"The point after the closing parenthesis of the current function.")
|
|
(defvar cmake-font-lock-current-function nil
|
|
"Name of function being fontified.")
|
|
|
|
(defun cmake-font-lock-match-plain-function (lim)
|
|
"Search for a CMake function and setup for argument list matching.
|
|
|
|
Point is placed after the parenthesis that starts the argument list.
|
|
Return the name of the matched function."
|
|
(let ((ws "\\s-*")
|
|
(id "\\<[a-z@_][a-z@_0-9]*\\>"))
|
|
(if (re-search-forward (concat "^" ws "\\(" id "\\)" ws "(") lim t)
|
|
(let ((name (match-string 1)))
|
|
(setq cmake-font-lock-current-function name)
|
|
(setq cmake-font-lock-arguments-begin
|
|
(match-end 0))
|
|
(setq cmake-font-lock-arguments-end
|
|
(save-excursion
|
|
;; Right before the opening parenthesis.
|
|
(goto-char (match-end 1))
|
|
;; Search limit. Pick the first of:
|
|
(or
|
|
;; Closing parethesis.
|
|
(ignore-errors
|
|
(forward-sexp)
|
|
(point))
|
|
;; Next line starting in column zero.
|
|
(save-match-data
|
|
(and (re-search-forward "^[^ \t]" lim t)
|
|
(match-beginning 0)))
|
|
;; End of buffer.
|
|
(point-max))))
|
|
;; Return function name.
|
|
name)
|
|
;; Name not found.
|
|
nil)))
|
|
|
|
(defun cmake-font-lock-arguments-bound ()
|
|
"Set point at the start of the argument list and return the end.
|
|
This is useful as a font-lock pre-match form."
|
|
(goto-char cmake-font-lock-arguments-begin)
|
|
cmake-font-lock-arguments-end)
|
|
|
|
|
|
;; ----------------------------------------
|
|
;; Argument matcher.
|
|
;;
|
|
|
|
(defun cmake-font-lock-skip-whitespace ()
|
|
(let ((spc 32))
|
|
(while (and (not (eobp))
|
|
(member (following-char) (list spc ?\t ?# ?\n)))
|
|
;; Skip comments.
|
|
(if (eq (following-char) ?#)
|
|
(forward-line))
|
|
;; Skip whitespace.
|
|
(skip-chars-forward " \t\n"))))
|
|
|
|
(defun cmake-font-lock-this-argument (&optional limit)
|
|
"Set point at the current argument and return the end.
|
|
|
|
Parameter `limit' points the before the closing parenthesis of
|
|
the function call.
|
|
|
|
Return nil if there are no more arguments.
|
|
|
|
Treats parenthesis as individual tokens. A token can contain a
|
|
${var} construct."
|
|
(cmake-font-lock-skip-whitespace)
|
|
(if (and limit
|
|
(>= (point) limit))
|
|
nil
|
|
(save-excursion
|
|
(let ((p (point)))
|
|
(if (memq (following-char) '( ?\( ?\) ))
|
|
;; Parentheses are tokens by themselves.
|
|
;;
|
|
;; set(x (y)) == set(x "(;y;)")
|
|
(forward-char)
|
|
(while
|
|
(and (not (eobp))
|
|
(cond ((memq (char-syntax (following-char))
|
|
'(?w ?. ?_))
|
|
(forward-char)
|
|
t)
|
|
((eq (following-char) ?\\)
|
|
(forward-char)
|
|
(unless (equal (point) limit)
|
|
(forward-char))
|
|
t)
|
|
((eq (following-char) ?\")
|
|
(condition-case nil
|
|
(forward-sexp)
|
|
(error (forward-char)))
|
|
t)
|
|
((memq (following-char) '(?$ ?{ ?}))
|
|
(forward-char)
|
|
t)
|
|
(t
|
|
nil)))))
|
|
(if (> (point) p)
|
|
(point)
|
|
nil)))))
|
|
|
|
(defvar cmake-font-lock-argument-kind-face-alist
|
|
'((:def . font-lock-constant-face)
|
|
(:var . font-lock-variable-name-face)
|
|
(:func . font-lock-function-name-face)
|
|
(:prop . font-lock-constant-face)
|
|
(:policy . font-lock-constant-face)
|
|
(:keyword . font-lock-type-face)
|
|
(:tgt . font-lock-constant-face)
|
|
(:tst . font-lock-constant-face))
|
|
"*Map from argument kind to face used to highlight that kind.")
|
|
|
|
|
|
(defvar cmake-font-lock-arguments-with-type '()
|
|
"Function arguments collected but not yet fontified.
|
|
|
|
Each entry is in the form `(kind beg end)', where `kind'
|
|
corresponds to the kinds described by
|
|
`cmake-font-lock-function-signatures'. `beg' and `end'
|
|
are the start and end points of the argument.")
|
|
|
|
|
|
(defun cmake-font-lock-minimun-number-of-arguments (signature)
|
|
"The least number of arguments needed to match the signature."
|
|
(let ((res 0))
|
|
(while signature
|
|
(if (eq (car signature) :optional)
|
|
(setq signature nil)
|
|
(if (eq (car signature) :repeat)
|
|
(setq signature (cdr-safe (cdr signature)))
|
|
(setq res (+ 1 res))
|
|
(pop signature))))
|
|
res))
|
|
|
|
|
|
(defun cmake-font-lock-collect-all-arguments (function-name limit)
|
|
"Find and categorize all arguments.
|
|
|
|
`function-name' is the name of the function and `limit' is the
|
|
point after the closing parenthesis of the argument list (or, if
|
|
not found, another suitable point).
|
|
|
|
The point is assumed to be positioned after the parenthesis that
|
|
start the argument list.
|
|
|
|
Return a list of `(kind beg end)', where `kind' is the type of
|
|
the argument (variable, property etc.), `beg' and `end' are the
|
|
location in the buffer where the argument is located."
|
|
(setq function-name
|
|
(cmake-font-lock-normalize-function-name function-name))
|
|
(let ((all-arguments '()))
|
|
;; ----------
|
|
;; Collect all arguments into `all-arguments'.
|
|
;;
|
|
(while
|
|
(let ((end-point (cmake-font-lock-this-argument (- limit 1))))
|
|
(if end-point
|
|
(let ((argument (buffer-substring-no-properties
|
|
(point) end-point)))
|
|
(push (list argument (point) end-point) all-arguments)
|
|
;; Continue looping
|
|
(goto-char end-point)
|
|
t)
|
|
;; else, end loop
|
|
nil)))
|
|
(setq all-arguments (nreverse all-arguments))
|
|
;; ----------
|
|
;; partition the arguments into groups, where the all except the
|
|
;; first group start with a keyword.
|
|
;;
|
|
;; Note that not all arguments that match a keyword should be
|
|
;; treated as a keyword, in case is it is in a position to mean
|
|
;; something else.
|
|
(let ((signature-to-args-alist '()))
|
|
(let ((triplet (assoc function-name
|
|
cmake-font-lock-function-signatures))
|
|
(signature '())
|
|
(keyword-signatures '())
|
|
(function-keywords
|
|
(cdr-safe
|
|
(assoc function-name
|
|
cmake-font-lock-function-keywords-alist))))
|
|
;; Start with the signature of arguments in front of any
|
|
;; keyword.
|
|
(when triplet
|
|
(setq signature (nth 1 triplet))
|
|
(setq keyword-signatures (nth 2 triplet)))
|
|
(while all-arguments
|
|
(let ((least-number-of-arguments
|
|
(cmake-font-lock-minimun-number-of-arguments
|
|
signature))
|
|
(args '()))
|
|
(while (and all-arguments
|
|
(> least-number-of-arguments 0))
|
|
(push (pop all-arguments) args)
|
|
(setq least-number-of-arguments (- least-number-of-arguments 1)))
|
|
(while (and all-arguments
|
|
;; Check keywords both in the plain list...
|
|
(not (member (nth 0 (car all-arguments))
|
|
function-keywords))
|
|
;; ...and in the function signature.
|
|
(not (assoc (nth 0 (car all-arguments))
|
|
keyword-signatures)))
|
|
(push (pop all-arguments) args))
|
|
(if args
|
|
(push (cons signature (nreverse args))
|
|
signature-to-args-alist))
|
|
;; Continue with the next keyword and its arguments (if
|
|
;; there are any left).
|
|
(if all-arguments
|
|
(let ((keyword-signature-pair
|
|
(assoc (nth 0 (car all-arguments)) keyword-signatures)))
|
|
(setq signature
|
|
(cons :keyword (cdr-safe keyword-signature-pair))))))))
|
|
(setq signature-to-args-alist (nreverse signature-to-args-alist))
|
|
;; ----------
|
|
;; Assign types to arguments. Start at the beginning of each
|
|
;; group. When a :repeat part is found, match the rest of the
|
|
;; arguments from the end, finish with matching the remaining
|
|
;; arguments with the repeat signature.
|
|
(let ((arguments-with-type '()))
|
|
(dolist (signature-args-pair signature-to-args-alist)
|
|
(let ((signature (car signature-args-pair))
|
|
(args (cdr signature-args-pair))
|
|
(repeat-signature nil))
|
|
(while (and (not repeat-signature)
|
|
args
|
|
signature)
|
|
(if (eq (car signature) :repeat)
|
|
(progn
|
|
(pop signature) ; :repeat
|
|
(setq repeat-signature (pop signature))
|
|
;; Ensure it's a list.
|
|
;;
|
|
;; Note: ":repeat nil" is a valid signature,
|
|
;; `repeat-signature' should in this case be
|
|
;; "(nil)".
|
|
(if (or (not (listp repeat-signature))
|
|
(null repeat-signature))
|
|
(setq repeat-signature (list repeat-signature))))
|
|
(if (eq (car signature) :optional)
|
|
;; Ignore :optional (it played out it's part in the
|
|
;; grouping above.
|
|
(pop signature)
|
|
;; Plain argument.
|
|
(push (cons (pop signature) (cdr (pop args)))
|
|
arguments-with-type))))
|
|
;; If there are any arguments left, we have found a repeat
|
|
;; block.
|
|
(if repeat-signature
|
|
(let ((types-from-the-back '()))
|
|
;; Match arguments with signatures from the end
|
|
(setq args (nreverse args))
|
|
(setq signature (nreverse signature))
|
|
(while (and args
|
|
signature)
|
|
(push (cons (pop signature) (cdr (pop args)))
|
|
types-from-the-back))
|
|
;; Match the middle (repeat) arguments.
|
|
(setq args (nreverse args))
|
|
(setq signature repeat-signature)
|
|
(while args
|
|
(if (null signature)
|
|
(setq signature repeat-signature))
|
|
(push (cons (pop signature) (cdr (pop args)))
|
|
arguments-with-type))
|
|
;; Combine all arguments, in the correct order.
|
|
(setq arguments-with-type
|
|
(nconc (nreverse types-from-the-back)
|
|
arguments-with-type))))))
|
|
(nreverse arguments-with-type)))))
|
|
|
|
|
|
(defun cmake-font-lock-collect-all-arguments-pre-match-form ()
|
|
"Collect all arguments of the current matched function.
|
|
|
|
Set the point to the beginning of the argument list and return
|
|
the end, making this function suitable for a font-lock
|
|
pre-match-form."
|
|
(setq cmake-font-lock-arguments-with-type
|
|
(cmake-font-lock-collect-all-arguments
|
|
cmake-font-lock-current-function
|
|
cmake-font-lock-arguments-end))
|
|
(cmake-font-lock-arguments-bound))
|
|
|
|
|
|
;; The regexp match an identifier, possibly containing an ${...}
|
|
;; constructs.
|
|
(defvar cmake-font-lock-argument-kind-regexp-alist
|
|
'((:var . "\\`[a-z@_$][a-z@_0-9${}]*\\'")
|
|
(:keyword . "\\`[a-z@_$][a-z@_0-9${}]*\\'")
|
|
(:prop . "\\`[a-z@_$][a-z@_0-9${}]*\\'")
|
|
(:policy . "\\`[a-z@_$][a-z@_0-9${}]*\\'")))
|
|
|
|
|
|
(defvar cmake-font-lock-this-argument-face nil
|
|
"The font-lock face (color) that should be used an argument.
|
|
|
|
This is set by `cmake-font-lock-next-collected-argument'
|
|
to correspond to the type of the argument.")
|
|
|
|
|
|
(defun cmake-font-lock-next-collected-argument (lim)
|
|
"Match the next argument.
|
|
|
|
When there are arguments to match, set the active match data to
|
|
correspond to the type of the argument, as specified by
|
|
`cmake-font-lock-argument-kind-face-alist', and
|
|
return non-nil. Return nil if there are no more arguments to
|
|
match."
|
|
(let ((res nil))
|
|
(while
|
|
(let ((match (and cmake-font-lock-arguments-with-type
|
|
(pop cmake-font-lock-arguments-with-type))))
|
|
; (message "next: %s" match)
|
|
(if match
|
|
(let* ((kind (nth 0 match))
|
|
(type-regexp-pair
|
|
(assoc
|
|
kind
|
|
cmake-font-lock-argument-kind-regexp-alist)))
|
|
(if (or (null type-regexp-pair)
|
|
(string-match (cdr type-regexp-pair)
|
|
(buffer-substring-no-properties
|
|
(nth 1 match)
|
|
(nth 2 match))))
|
|
(let ((type-face-pair
|
|
(assoc
|
|
kind
|
|
cmake-font-lock-argument-kind-face-alist)))
|
|
(if type-face-pair
|
|
(progn
|
|
(setq cmake-font-lock-this-argument-face
|
|
(cdr type-face-pair))
|
|
(set-match-data (list (nth 1 match)
|
|
(nth 2 match)))
|
|
(setq res t)
|
|
nil) ; Stop loop
|
|
t)) ; Uninteresting match, continue.
|
|
;; Match, argument can't possibly be of this type.
|
|
t))
|
|
;; Else, no more matches, stop loop.
|
|
nil)))
|
|
; (message "next -> %s" res)
|
|
res))
|
|
|
|
|
|
;; ----------------------------------------
|
|
;; Setup.
|
|
;;
|
|
|
|
(defvar cmake-font-lock-saved-point nil)
|
|
|
|
(defun cmake-font-lock-setup ()
|
|
"Initialize cmake font-lock rules."
|
|
|
|
;;----------
|
|
;; Syntax
|
|
;;
|
|
;; In cmake, you can write strings without quotes, for example:
|
|
;;
|
|
;; if (EXISTS /my/target/directory)
|
|
;; ..
|
|
;; endif()
|
|
;;
|
|
;; This makes font-lock see all symbols and punctuation characters
|
|
;; as parts of words. This ensures that the individual words (like
|
|
;; "target" in the example above) are not considered words (and this
|
|
;; fontified) when matching with "\\<" and "\\>".
|
|
;;
|
|
;; Keep "=" as a non-word character to allow us to match "-DFOO" in
|
|
;; "-DFOO=BAR", which is used when fontifying preprocessor definitions.
|
|
;;
|
|
;; Ensure that "_" is treated as a word by font-lock. By default,
|
|
;; cmake-mode defines this as a word, but users may (and is
|
|
;; encouraged to) redefine this to "symbol".
|
|
;;
|
|
;; Note: The cmake documentation does not include the exact syntax
|
|
;; for quote-less strings, but this seems to work for typical cases.
|
|
(let ((syntax-alist '())
|
|
(ch 0))
|
|
(while (< ch 256)
|
|
(if (and (not (equal ch ?=))
|
|
(or (equal ch ?_)
|
|
(member (char-syntax ch) '(?. ?_))))
|
|
(push (cons ch "w") syntax-alist))
|
|
(setq ch (+ ch 1)))
|
|
|
|
;; ----------
|
|
;; The third argument sets case-independent font-lock rules.
|
|
(setq font-lock-defaults
|
|
(list 'cmake-font-lock-advanced-keywords nil t syntax-alist)))
|
|
|
|
;; ----------
|
|
;; New font-lock rules.
|
|
;;
|
|
|
|
(setq font-lock-multiline t)
|
|
(let* ((keywords '("break"
|
|
"continue"
|
|
"foreach" "endforeach"
|
|
"function" "endfunction"
|
|
"else"
|
|
"elseif"
|
|
"if" "endif"
|
|
"include"
|
|
"macro" "endmacro"
|
|
"return"
|
|
"while" "endwhile"))
|
|
(constants '("true"
|
|
"false"
|
|
"yes"
|
|
"no"
|
|
"y"
|
|
"n"
|
|
"on"
|
|
"off"))
|
|
;; Regexp snippets used to make larger regexps more readable.
|
|
(id "[a-z@_][a-z@_0-9]*")
|
|
(ws "\\s-*"))
|
|
(setq
|
|
cmake-font-lock-advanced-keywords
|
|
(list
|
|
;; Keywords -- Basic language features like flow control.
|
|
(cons (concat "\\<"
|
|
(regexp-opt keywords t)
|
|
"\\>" ws "(")
|
|
'(1 'font-lock-keyword-face))
|
|
;; Constants.
|
|
(cons (concat "\\<"
|
|
(regexp-opt constants t)
|
|
"\\>")
|
|
'(1 'font-lock-constant-face))
|
|
;; Preprocessor definitions.
|
|
(cons (concat "\\<-D\\([a-z_][a-z0-9_]*\\)\\>")
|
|
'(1 'font-lock-constant-face))
|
|
;; Expression generator $<name:...>
|
|
(cons (concat "\\$<\\(" id "\\)[:>]")
|
|
'(1 'font-lock-preprocessor-face))
|
|
;; Variables embedded in ${...} and $name{...} (where "name"
|
|
;; typically is ENV).
|
|
;;
|
|
;; In the ${...} case, the interior is colored as a variable.
|
|
;;
|
|
;; In the $name{...} case, "name" is colored like a variable and
|
|
;; the content as a constant.
|
|
;;
|
|
;; The "${" and "}" are not fontified (unless as part of a
|
|
;; string).
|
|
;;
|
|
;; Nested constructs like "${abc${def}ghi}" are handled by using
|
|
;; an anchored rule, where the inner match function
|
|
;; `cmake-font-lock-match-dollar-braces-content'
|
|
;; repeatedly match the non-${} parts, in this case "abc" and
|
|
;; "ghi".
|
|
;;
|
|
;; Implementation node: The following will fontify ${ and }
|
|
;; using the face "default" (unless it's part of a string). This
|
|
;; stops it from being painted over by the arguments fontifier
|
|
;; below, which use the "keep" construct to paint the rest of
|
|
;; each argument.
|
|
;;
|
|
;; The pre- and post-match forms are used to back up the point,
|
|
;; to ensure that nested constructs work.
|
|
'(cmake-font-lock-match-dollar-braces
|
|
(1 'default nil t)
|
|
(2 'font-lock-variable-name-face nil t)
|
|
(3 'default)
|
|
(4 'default nil t)
|
|
(cmake-font-lock-match-dollar-braces-content
|
|
;; PRE-MATCH-FORM:
|
|
(setq cmake-font-lock-saved-point (point))
|
|
;; POST-MATCH-FORM:
|
|
(goto-char cmake-font-lock-saved-point)
|
|
;; Highlight.
|
|
(1 'font-lock-variable-name-face prepend t)
|
|
(2 'font-lock-constant-face prepend t)))
|
|
;; Function calls and arguments.
|
|
'(cmake-font-lock-match-plain-function
|
|
(1 'font-lock-function-name-face)
|
|
;; Arguments passed to functions, like "WARNING" in
|
|
;; "message(WARNING ...). This can fontify keywords,
|
|
;; variables, properties, and function names -- but only if
|
|
;; the function type is known.
|
|
(cmake-font-lock-next-collected-argument
|
|
;; PRE-MATCH-FORM:
|
|
(cmake-font-lock-collect-all-arguments-pre-match-form)
|
|
;; POST-MATCH-FORM:
|
|
nil
|
|
;; Highlight
|
|
(0 cmake-font-lock-this-argument-face keep t)))
|
|
))))
|
|
|
|
|
|
;; ------------------------------------------------------------
|
|
;; The end
|
|
;;
|
|
|
|
(provide 'cmake-font-lock)
|
|
|
|
;;; cmake-font-lock.el ends here
|