From 978a5fdaa35e8945920ab194213715e6f1f0bc20 Mon Sep 17 00:00:00 2001 From: Ted Zlatanov Date: Fri, 13 Dec 2013 13:18:19 -0500 Subject: [PATCH] Improve CFEngine 3 parsing and eldoc support, with syntax fallbacks * progmodes/cfengine.el (cfengine-cf-promises): Add more default locations for cf-promises. (cfengine-mode-syntax-functions-regex): New caching variable. (cfengine3-fallback-syntax): Fallback syntax for cases where cf-promises doesn't run. (cfengine3--current-word): Reimplement using `cfengine-mode-syntax-functions-regex'. (cfengine3-completion-function, cfengine3--current-function): Use `cfengine3-make-syntax-cache' directly. (cfengine3-clear-syntax-cache): New function. (cfengine3-make-syntax-cache): Simplify and create `cfengine-mode-syntax-functions-regex' on demand. (cfengine3-format-function-docstring): Don't call `cfengine3-make-syntax-cache' explicitly. --- lisp/ChangeLog | 17 ++ lisp/progmodes/cfengine.el | 726 ++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 703 insertions(+), 40 deletions(-) diff --git a/lisp/ChangeLog b/lisp/ChangeLog index b48563761c4..8bd026470d1 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,20 @@ +2013-12-13 Teodor Zlatanov + + * progmodes/cfengine.el (cfengine-cf-promises): Add more default + locations for cf-promises. + (cfengine-mode-syntax-functions-regex): New caching variable. + (cfengine3-fallback-syntax): Fallback syntax for cases where + cf-promises doesn't run. + (cfengine3--current-word): Reimplement using + `cfengine-mode-syntax-functions-regex'. + (cfengine3-completion-function, cfengine3--current-function): Use + `cfengine3-make-syntax-cache' directly. + (cfengine3-clear-syntax-cache): New function. + (cfengine3-make-syntax-cache): Simplify and create + `cfengine-mode-syntax-functions-regex' on demand. + (cfengine3-format-function-docstring): Don't call + `cfengine3-make-syntax-cache' explicitly. + 2013-12-13 Martin Rudalics Fix windmove-find-other-window broken after pixelwise resizing diff --git a/lisp/progmodes/cfengine.el b/lisp/progmodes/cfengine.el index a5cd863f2e1..83eec8bde62 100644 --- a/lisp/progmodes/cfengine.el +++ b/lisp/progmodes/cfengine.el @@ -55,6 +55,9 @@ ;;; Code: +(autoload 'json-read "json") +(autoload 'regexp-opt "regexp-opt") + (defgroup cfengine () "Editing CFEngine files." :group 'languages) @@ -68,11 +71,15 @@ (or (executable-find "cf-promises") (executable-find "/var/cfengine/bin/cf-promises") (executable-find "/usr/bin/cf-promises") + (executable-find "/usr/sbin/cf-promises") (executable-find "/usr/local/bin/cf-promises") - (executable-find "~/bin/cf-promises")) + (executable-find "/usr/local/sbin/cf-promises") + (executable-find "~/bin/cf-promises") + (executable-find "~/sbin/cf-promises")) "The location of the cf-promises executable. Used for syntax discovery and checking. Set to nil to disable -the `compile-command' override and the ElDoc support." +the `compile-command' override. In that case, the ElDoc support +will use a fallback syntax definition." :group 'cfengine :type 'file) @@ -146,6 +153,640 @@ bundle agent rcfiles (defvar cfengine-mode-syntax-cache nil "Cache for `cfengine-mode' syntax trees obtained from 'cf-promises -s json'.") +(defvar cfengine-mode-syntax-functions-regex nil) + +(defconst cfengine3-fallback-syntax + '((functions + (userexists + (category . "system") (variadic . :json-false) + (parameters . [((range . ".*") (type . "string"))]) + (returnType . "context") (status . "normal")) + (usemodule + (category . "utils") (variadic . :json-false) + (parameters . [((range . ".*") (type . "string")) + ((range . ".*") (type . "string"))]) + (returnType . "context") (status . "normal")) + (unique + (category . "data") (variadic . :json-false) + (parameters . [((range . "[a-zA-Z0-9_$(){}\\[\\].:]+") (type . "string"))]) + (returnType . "slist") (status . "normal")) + (translatepath + (category . "files") (variadic . :json-false) + (parameters . [((range . "\"?(/.*)") (type . "string"))]) + (returnType . "string") (status . "normal")) + (sum + (category . "data") (variadic . :json-false) + (parameters . [((range . "[a-zA-Z0-9_$(){}\\[\\].:]+") (type . "string"))]) + (returnType . "real") (status . "normal")) + (sublist + (category . "data") (variadic . :json-false) + (parameters . [((range . "[a-zA-Z0-9_$(){}\\[\\].:]+") (type . "string")) + ((range . "head,tail") (type . "option")) + ((range . "0,99999999999") (type . "int"))]) + (returnType . "slist") (status . "normal")) + (strftime + (category . "data") (variadic . :json-false) + (parameters . [((range . "gmtime,localtime") (type . "option")) + ((range . ".*") (type . "string")) + ((range . "0,99999999999") (type . "int"))]) + (returnType . "string") (status . "normal")) + (strcmp + (category . "data") (variadic . :json-false) + (parameters . [((range . ".*") (type . "string")) + ((range . ".*") (type . "string"))]) + (returnType . "context") (status . "normal")) + (splitstring + (category . "data") (variadic . :json-false) + (parameters . [((range . ".*") (type . "string")) + ((range . ".*") (type . "string")) + ((range . "0,99999999999") (type . "int"))]) + (returnType . "slist") (status . "normal")) + (splayclass + (category . "utils") (variadic . :json-false) + (parameters . [((range . ".*") (type . "string")) + ((range . "daily,hourly") (type . "option"))]) + (returnType . "context") (status . "normal")) + (sort + (category . "data") (variadic . :json-false) + (parameters . [((range . "[a-zA-Z0-9_$(){}\\[\\].:]+") (type . "string")) + ((range . "lex") (type . "string"))]) + (returnType . "slist") (status . "normal")) + (some + (category . "data") (variadic . :json-false) + (parameters . [((range . ".*") (type . "string")) + ((range . "[a-zA-Z0-9_$(){}\\[\\].:]+") (type . "string"))]) + (returnType . "context") (status . "normal")) + (shuffle + (category . "data") (variadic . :json-false) + (parameters . [((range . "[a-zA-Z0-9_$(){}\\[\\].:]+") (type . "string")) + ((range . ".*") (type . "string"))]) + (returnType . "slist") (status . "normal")) + (selectservers + (category . "communication") (variadic . :json-false) + (parameters . [((range . "@[(][a-zA-Z0-9]+[)]") (type . "string")) + ((range . "0,99999999999") (type . "int")) + ((range . ".*") (type . "string")) + ((range . ".*") (type . "string")) + ((range . "0,99999999999") (type . "int")) + ((range . "[a-zA-Z0-9_$(){}\\[\\].:]+") (type . "string"))]) + (returnType . "int") (status . "normal")) + (reverse + (category . "data") (variadic . :json-false) + (parameters . [((range . "[a-zA-Z0-9_$(){}\\[\\].:]+") (type . "string"))]) + (returnType . "slist") (status . "normal")) + (rrange + (category . "data") (variadic . :json-false) + (parameters . [((range . "-9.99999E100,9.99999E100") (type . "real")) + ((range . "-9.99999E100,9.99999E100") (type . "real"))]) + (returnType . "rrange") (status . "normal")) + (returnszero + (category . "utils") (variadic . :json-false) + (parameters . [((range . "\"?(/.*)") (type . "string")) + ((range . "useshell,noshell,powershell") (type . "option"))]) + (returnType . "context") (status . "normal")) + (remoteclassesmatching + (category . "communication") (variadic . :json-false) + (parameters . [((range . ".*") (type . "string")) + ((range . ".*") (type . "string")) + ((range . "true,false,yes,no,on,off") (type . "option")) + ((range . "[a-zA-Z0-9_$(){}\\[\\].:]+") (type . "string"))]) + (returnType . "context") (status . "normal")) + (remotescalar + (category . "communication") (variadic . :json-false) + (parameters . [((range . "[a-zA-Z0-9_$(){}\\[\\].:]+") (type . "string")) + ((range . ".*") (type . "string")) + ((range . "true,false,yes,no,on,off") (type . "option"))]) + (returnType . "string") (status . "normal")) + (regldap + (category . "communication") (variadic . :json-false) + (parameters . [((range . ".*") (type . "string")) + ((range . ".*") (type . "string")) + ((range . ".*") (type . "string")) + ((range . ".*") (type . "string")) + ((range . "subtree,onelevel,base") (type . "option")) + ((range . ".*") (type . "string")) + ((range . "none,ssl,sasl") (type . "option"))]) + (returnType . "context") (status . "normal")) + (reglist + (category . "data") (variadic . :json-false) + (parameters . [((range . "@[(][a-zA-Z0-9]+[)]") (type . "string")) + ((range . ".*") (type . "string"))]) + (returnType . "context") (status . "normal")) + (regline + (category . "io") (variadic . :json-false) + (parameters . [((range . ".*") (type . "string")) + ((range . ".*") (type . "string"))]) + (returnType . "context") (status . "normal")) + (registryvalue + (category . "system") (variadic . :json-false) + (parameters . [((range . ".*") (type . "string")) + ((range . ".*") (type . "string"))]) + (returnType . "string") (status . "normal")) + (regextract + (category . "data") (variadic . :json-false) + (parameters . [((range . ".*") (type . "string")) + ((range . ".*") (type . "string")) + ((range . "[a-zA-Z0-9_$(){}\\[\\].:]+") (type . "string"))]) + (returnType . "context") (status . "normal")) + (regcmp + (category . "data") (variadic . :json-false) + (parameters . [((range . ".*") (type . "string")) + ((range . ".*") (type . "string"))]) + (returnType . "context") (status . "normal")) + (regarray + (category . "data") (variadic . :json-false) + (parameters . [((range . "[a-zA-Z0-9_$(){}\\[\\].:]+") (type . "string")) + ((range . ".*") (type . "string"))]) + (returnType . "context") (status . "normal")) + (readtcp + (category . "communication") (variadic . :json-false) + (parameters . [((range . ".*") (type . "string")) + ((range . "0,99999999999") (type . "int")) + ((range . ".*") (type . "string")) + ((range . "0,99999999999") (type . "int"))]) + (returnType . "string") (status . "normal")) + (readstringlist + (category . "io") (variadic . :json-false) + (parameters . [((range . "\"?(/.*)") (type . "string")) + ((range . ".*") (type . "string")) + ((range . ".*") (type . "string")) + ((range . "0,99999999999") (type . "int")) + ((range . "0,99999999999") (type . "int"))]) + (returnType . "slist") (status . "normal")) + (readstringarrayidx + (category . "io") (variadic . :json-false) + (parameters . [((range . "[a-zA-Z0-9_$(){}\\[\\].:]+") (type . "string")) + ((range . "\"?(/.*)") (type . "string")) + ((range . ".*") (type . "string")) + ((range . ".*") (type . "string")) + ((range . "0,99999999999") (type . "int")) + ((range . "0,99999999999") (type . "int"))]) + (returnType . "int") (status . "normal")) + (readstringarray + (category . "io") (variadic . :json-false) + (parameters . [((range . "[a-zA-Z0-9_$(){}\\[\\].:]+") (type . "string")) + ((range . "\"?(/.*)") (type . "string")) + ((range . ".*") (type . "string")) + ((range . ".*") (type . "string")) + ((range . "0,99999999999") (type . "int")) + ((range . "0,99999999999") (type . "int"))]) + (returnType . "int") (status . "normal")) + (readreallist + (category . "io") (variadic . :json-false) + (parameters . [((range . "\"?(/.*)") (type . "string")) + ((range . ".*") (type . "string")) + ((range . ".*") (type . "string")) + ((range . "0,99999999999") (type . "int")) + ((range . "0,99999999999") (type . "int"))]) + (returnType . "rlist") (status . "normal")) + (readrealarray + (category . "io") (variadic . :json-false) + (parameters . [((range . "[a-zA-Z0-9_$(){}\\[\\].:]+") (type . "string")) + ((range . "\"?(/.*)") (type . "string")) + ((range . ".*") (type . "string")) + ((range . ".*") (type . "string")) + ((range . "0,99999999999") (type . "int")) + ((range . "0,99999999999") (type . "int"))]) + (returnType . "int") (status . "normal")) + (readintlist + (category . "io") (variadic . :json-false) + (parameters . [((range . "\"?(/.*)") (type . "string")) + ((range . ".*") (type . "string")) + ((range . ".*") (type . "string")) + ((range . "0,99999999999") (type . "int")) + ((range . "0,99999999999") (type . "int"))]) + (returnType . "ilist") (status . "normal")) + (readintarray + (category . "io") (variadic . :json-false) + (parameters . [((range . "[a-zA-Z0-9_$(){}\\[\\].:]+") (type . "string")) + ((range . "\"?(/.*)") (type . "string")) + ((range . ".*") (type . "string")) + ((range . ".*") (type . "string")) + ((range . "0,99999999999") (type . "int")) + ((range . "0,99999999999") (type . "int"))]) + (returnType . "int") (status . "normal")) + (readfile + (category . "io") (variadic . :json-false) + (parameters . [((range . "\"?(/.*)") (type . "string")) + ((range . "0,99999999999") (type . "int"))]) + (returnType . "string") (status . "normal")) + (randomint + (category . "data") (variadic . :json-false) + (parameters . [((range . "-99999999999,9999999999") (type . "int")) + ((range . "-99999999999,9999999999") (type . "int"))]) + (returnType . "int") (status . "normal")) + (product + (category . "data") (variadic . :json-false) + (parameters . [((range . "[a-zA-Z0-9_$(){}\\[\\].:]+") (type . "string"))]) + (returnType . "real") (status . "normal")) + (peerleaders + (category . "communication") (variadic . :json-false) + (parameters . [((range . "\"?(/.*)") (type . "string")) + ((range . ".*") (type . "string")) + ((range . "0,99999999999") (type . "int"))]) + (returnType . "slist") (status . "normal")) + (peerleader + (category . "communication") (variadic . :json-false) + (parameters . [((range . "\"?(/.*)") (type . "string")) + ((range . ".*") (type . "string")) + ((range . "0,99999999999") (type . "int"))]) + (returnType . "string") (status . "normal")) + (peers + (category . "communication") (variadic . :json-false) + (parameters . [((range . "\"?(/.*)") (type . "string")) + ((range . ".*") (type . "string")) + ((range . "0,99999999999") (type . "int"))]) + (returnType . "slist") (status . "normal")) + (parsestringarrayidx + (category . "io") (variadic . :json-false) + (parameters . [((range . "[a-zA-Z0-9_$(){}\\[\\].:]+") (type . "string")) + ((range . "\"?(/.*)") (type . "string")) + ((range . ".*") (type . "string")) + ((range . ".*") (type . "string")) + ((range . "0,99999999999") (type . "int")) + ((range . "0,99999999999") (type . "int"))]) + (returnType . "int") (status . "normal")) + (parsestringarray + (category . "io") (variadic . :json-false) + (parameters . [((range . "[a-zA-Z0-9_$(){}\\[\\].:]+") (type . "string")) + ((range . "\"?(/.*)") (type . "string")) + ((range . ".*") (type . "string")) + ((range . ".*") (type . "string")) + ((range . "0,99999999999") (type . "int")) + ((range . "0,99999999999") (type . "int"))]) + (returnType . "int") (status . "normal")) + (parserealarray + (category . "io") (variadic . :json-false) + (parameters . [((range . "[a-zA-Z0-9_$(){}\\[\\].:]+") (type . "string")) + ((range . "\"?(/.*)") (type . "string")) + ((range . ".*") (type . "string")) + ((range . ".*") (type . "string")) + ((range . "0,99999999999") (type . "int")) + ((range . "0,99999999999") (type . "int"))]) + (returnType . "int") (status . "normal")) + (parseintarray + (category . "io") (variadic . :json-false) + (parameters . [((range . "[a-zA-Z0-9_$(){}\\[\\].:]+") (type . "string")) + ((range . "\"?(/.*)") (type . "string")) + ((range . ".*") (type . "string")) + ((range . ".*") (type . "string")) + ((range . "0,99999999999") (type . "int")) + ((range . "0,99999999999") (type . "int"))]) + (returnType . "int") (status . "normal")) + (or + (category . "data") (variadic . t) + (parameters . []) + (returnType . "string") (status . "normal")) + (on + (category . "data") (variadic . :json-false) + (parameters . [((range . "1970,3000") (type . "int")) + ((range . "1,12") (type . "int")) + ((range . "1,31") (type . "int")) + ((range . "0,23") (type . "int")) + ((range . "0,59") (type . "int")) + ((range . "0,59") (type . "int"))]) + (returnType . "int") (status . "normal")) + (nth + (category . "data") (variadic . :json-false) + (parameters . [((range . "[a-zA-Z0-9_$(){}\\[\\].:]+") (type . "string")) + ((range . "0,99999999999") (type . "int"))]) + (returnType . "string") (status . "normal")) + (now + (category . "system") (variadic . :json-false) + (parameters . []) + (returnType . "int") (status . "normal")) + (not + (category . "data") (variadic . :json-false) + (parameters . [((range . ".*") (type . "string"))]) + (returnType . "string") (status . "normal")) + (none + (category . "data") (variadic . :json-false) + (parameters . [((range . ".*") (type . "string")) + ((range . "[a-zA-Z0-9_$(){}\\[\\].:]+") (type . "string"))]) + (returnType . "context") (status . "normal")) + (maplist + (category . "data") (variadic . :json-false) + (parameters . [((range . ".*") (type . "string")) + ((range . "[a-zA-Z0-9_$(){}\\[\\].:]+") (type . "string"))]) + (returnType . "slist") (status . "normal")) + (maparray + (category . "data") (variadic . :json-false) + (parameters . [((range . ".*") (type . "string")) + ((range . "[a-zA-Z0-9_$(){}\\[\\].:]+") (type . "string"))]) + (returnType . "slist") (status . "normal")) + (lsdir + (category . "files") (variadic . :json-false) + (parameters . [((range . ".+") (type . "string")) + ((range . ".*") (type . "string")) + ((range . "true,false,yes,no,on,off") (type . "option"))]) + (returnType . "slist") (status . "normal")) + (length + (category . "data") (variadic . :json-false) + (parameters . [((range . "[a-zA-Z0-9_$(){}\\[\\].:]+") (type . "string"))]) + (returnType . "int") (status . "normal")) + (ldapvalue + (category . "communication") (variadic . :json-false) + (parameters . [((range . ".*") (type . "string")) + ((range . ".*") (type . "string")) + ((range . ".*") (type . "string")) + ((range . ".*") (type . "string")) + ((range . "subtree,onelevel,base") (type . "option")) + ((range . "none,ssl,sasl") (type . "option"))]) + (returnType . "string") (status . "normal")) + (ldaplist + (category . "communication") (variadic . :json-false) + (parameters . [((range . ".*") (type . "string")) + ((range . ".*") (type . "string")) + ((range . ".*") (type . "string")) + ((range . ".*") (type . "string")) + ((range . "subtree,onelevel,base") (type . "option")) + ((range . "none,ssl,sasl") (type . "option"))]) + (returnType . "slist") (status . "normal")) + (ldaparray + (category . "communication") (variadic . :json-false) + (parameters . [((range . ".*") (type . "string")) + ((range . ".*") (type . "string")) + ((range . ".*") (type . "string")) + ((range . ".*") (type . "string")) + ((range . "subtree,onelevel,base") (type . "option")) + ((range . "none,ssl,sasl") (type . "option"))]) + (returnType . "context") (status . "normal")) + (laterthan + (category . "files") (variadic . :json-false) + (parameters . [((range . "0,1000") (type . "int")) + ((range . "0,1000") (type . "int")) + ((range . "0,1000") (type . "int")) + ((range . "0,1000") (type . "int")) + ((range . "0,1000") (type . "int")) + ((range . "0,40000") (type . "int"))]) + (returnType . "context") (status . "normal")) + (lastnode + (category . "data") (variadic . :json-false) + (parameters . [((range . ".*") (type . "string")) + ((range . ".*") (type . "string"))]) + (returnType . "string") (status . "normal")) + (join + (category . "data") (variadic . :json-false) + (parameters . [((range . ".*") (type . "string")) + ((range . "[a-zA-Z0-9_$(){}\\[\\].:]+") (type . "string"))]) + (returnType . "string") (status . "normal")) + (isvariable + (category . "utils") (variadic . :json-false) + (parameters . [((range . "[a-zA-Z0-9_$(){}\\[\\].:]+") (type . "string"))]) + (returnType . "context") (status . "normal")) + (isplain + (category . "files") (variadic . :json-false) + (parameters . [((range . "\"?(/.*)") (type . "string"))]) + (returnType . "context") (status . "normal")) + (isnewerthan + (category . "files") (variadic . :json-false) + (parameters . [((range . "\"?(/.*)") (type . "string")) + ((range . "\"?(/.*)") (type . "string"))]) + (returnType . "context") (status . "normal")) + (islink + (category . "files") (variadic . :json-false) + (parameters . [((range . "\"?(/.*)") (type . "string"))]) + (returnType . "context") (status . "normal")) + (islessthan + (category . "data") (variadic . :json-false) + (parameters . [((range . ".*") (type . "string")) + ((range . ".*") (type . "string"))]) + (returnType . "context") (status . "normal")) + (isgreaterthan + (category . "data") (variadic . :json-false) + (parameters . [((range . ".*") (type . "string")) + ((range . ".*") (type . "string"))]) + (returnType . "context") (status . "normal")) + (isexecutable + (category . "files") (variadic . :json-false) + (parameters . [((range . "\"?(/.*)") (type . "string"))]) + (returnType . "context") (status . "normal")) + (isdir + (category . "files") (variadic . :json-false) + (parameters . [((range . "\"?(/.*)") (type . "string"))]) + (returnType . "context") (status . "normal")) + (irange + (category . "data") (variadic . :json-false) + (parameters . [((range . "-99999999999,9999999999") (type . "int")) + ((range . "-99999999999,9999999999") (type . "int"))]) + (returnType . "irange") (status . "normal")) + (iprange + (category . "communication") (variadic . :json-false) + (parameters . [((range . ".*") (type . "string"))]) + (returnType . "context") (status . "normal")) + (intersection + (category . "data") (variadic . :json-false) + (parameters . [((range . "[a-zA-Z0-9_$(){}\\[\\].:]+") (type . "string")) + ((range . "[a-zA-Z0-9_$(){}\\[\\].:]+") (type . "string"))]) + (returnType . "slist") (status . "normal")) + (ifelse + (category . "data") (variadic . t) + (parameters . []) + (returnType . "string") (status . "normal")) + (hubknowledge + (category . "communication") (variadic . :json-false) + (parameters . [((range . "[a-zA-Z0-9_$(){}\\[\\].:]+") (type . "string"))]) + (returnType . "string") (status . "normal")) + (hostswithclass + (category . "communication") (variadic . :json-false) + (parameters . [((range . "[a-zA-Z0-9_]+") (type . "string")) + ((range . "name,address") (type . "option"))]) + (returnType . "slist") (status . "normal")) + (hostsseen + (category . "communication") (variadic . :json-false) + (parameters . [((range . "0,99999999999") (type . "int")) + ((range . "lastseen,notseen") (type . "option")) + ((range . "name,address") (type . "option"))]) + (returnType . "slist") (status . "normal")) + (hostrange + (category . "communication") (variadic . :json-false) + (parameters . [((range . ".*") (type . "string")) + ((range . ".*") (type . "string"))]) + (returnType . "context") (status . "normal")) + (hostinnetgroup + (category . "system") (variadic . :json-false) + (parameters . [((range . ".*") (type . "string"))]) + (returnType . "context") (status . "normal")) + (ip2host + (category . "communication") (variadic . :json-false) + (parameters . [((range . ".*") (type . "string"))]) + (returnType . "string") (status . "normal")) + (host2ip + (category . "communication") (variadic . :json-false) + (parameters . [((range . ".*") (type . "string"))]) + (returnType . "string") (status . "normal")) + (hashmatch + (category . "data") (variadic . :json-false) + (parameters . [((range . "\"?(/.*)") (type . "string")) + ((range . "md5,sha1,crypt,cf_sha224,cf_sha256,cf_sha384,cf_sha512") (type . "option")) + ((range . "[a-zA-Z0-9_$(){}\\[\\].:]+") (type . "string"))]) + (returnType . "context") (status . "normal")) + (hash + (category . "data") (variadic . :json-false) + (parameters . [((range . ".*") (type . "string")) + ((range . "md5,sha1,sha256,sha512,sha384,crypt") (type . "option"))]) + (returnType . "string") (status . "normal")) + (groupexists + (category . "system") (variadic . :json-false) + (parameters . [((range . ".*") (type . "string"))]) + (returnType . "context") (status . "normal")) + (grep + (category . "data") (variadic . :json-false) + (parameters . [((range . ".*") (type . "string")) + ((range . "[a-zA-Z0-9_$(){}\\[\\].:]+") (type . "string"))]) + (returnType . "slist") (status . "normal")) + (getvalues + (category . "data") (variadic . :json-false) + (parameters . [((range . "[a-zA-Z0-9_$(){}\\[\\].:]+") (type . "string"))]) + (returnType . "slist") (status . "normal")) + (getusers + (category . "system") (variadic . :json-false) + (parameters . [((range . ".*") (type . "string")) + ((range . ".*") (type . "string"))]) + (returnType . "slist") (status . "normal")) + (getuid + (category . "system") (variadic . :json-false) + (parameters . [((range . ".*") (type . "string"))]) + (returnType . "int") (status . "normal")) + (getindices + (category . "data") (variadic . :json-false) + (parameters . [((range . "[a-zA-Z0-9_$(){}\\[\\].:]+") (type . "string"))]) + (returnType . "slist") (status . "normal")) + (getgid + (category . "data") (variadic . :json-false) + (parameters . [((range . ".*") (type . "string"))]) + (returnType . "int") (status . "normal")) + (getfields + (category . "data") (variadic . :json-false) + (parameters . [((range . ".*") (type . "string")) + ((range . "\"?(/.*)") (type . "string")) + ((range . ".*") (type . "string")) + ((range . ".*") (type . "string"))]) + (returnType . "int") (status . "normal")) + (getenv + (category . "system") (variadic . :json-false) + (parameters . [((range . "[a-zA-Z0-9_$(){}\\[\\].:]+") (type . "string")) + ((range . "0,99999999999") (type . "int"))]) + (returnType . "string") (status . "normal")) + (format + (category . "data") (variadic . t) + (parameters . [((range . ".*") (type . "string"))]) + (returnType . "string") (status . "normal")) + (filter + (category . "data") (variadic . :json-false) + (parameters . [((range . ".*") (type . "string")) + ((range . "[a-zA-Z0-9_$(){}\\[\\].:]+") (type . "string")) + ((range . "true,false,yes,no,on,off") (type . "option")) + ((range . "true,false,yes,no,on,off") (type . "option")) + ((range . "0,99999999999") (type . "int"))]) + (returnType . "slist") (status . "normal")) + (filestat + (category . "files") (variadic . :json-false) + (parameters . [((range . "\"?(/.*)") (type . "string")) + ((range . "size,gid,uid,ino,nlink,ctime,atime,mtime,mode,modeoct,permstr,permoct,type,devno,dev_minor,dev_major,basename,dirname") (type . "option"))]) + (returnType . "string") (status . "normal")) + (filesize + (category . "files") (variadic . :json-false) + (parameters . [((range . "\"?(/.*)") (type . "string"))]) + (returnType . "int") (status . "normal")) + (filesexist + (category . "files") (variadic . :json-false) + (parameters . [((range . "@[(][a-zA-Z0-9]+[)]") (type . "string"))]) + (returnType . "context") (status . "normal")) + (fileexists + (category . "files") (variadic . :json-false) + (parameters . [((range . "\"?(/.*)") (type . "string"))]) + (returnType . "context") (status . "normal")) + (execresult + (category . "utils") (variadic . :json-false) + (parameters . [((range . ".+") (type . "string")) + ((range . "useshell,noshell,powershell") (type . "option"))]) + (returnType . "string") (status . "normal")) + (every + (category . "data") (variadic . :json-false) + (parameters . [((range . ".*") (type . "string")) + ((range . "[a-zA-Z0-9_$(){}\\[\\].:]+") (type . "string"))]) + (returnType . "context") (status . "normal")) + (escape + (category . "data") (variadic . :json-false) + (parameters . [((range . ".*") (type . "string"))]) + (returnType . "string") (status . "normal")) + (diskfree + (category . "files") (variadic . :json-false) + (parameters . [((range . "\"?(/.*)") (type . "string"))]) + (returnType . "int") (status . "normal")) + (dirname + (category . "files") (variadic . :json-false) + (parameters . [((range . ".*") (type . "string"))]) + (returnType . "string") (status . "normal")) + (difference + (category . "data") (variadic . :json-false) + (parameters . [((range . "[a-zA-Z0-9_$(){}\\[\\].:]+") (type . "string")) + ((range . "[a-zA-Z0-9_$(){}\\[\\].:]+") (type . "string"))]) + (returnType . "slist") (status . "normal")) + (countlinesmatching + (category . "io") (variadic . :json-false) + (parameters . [((range . ".*") (type . "string")) + ((range . "\"?(/.*)") (type . "string"))]) + (returnType . "int") (status . "normal")) + (countclassesmatching + (category . "utils") (variadic . :json-false) + (parameters . [((range . ".*") (type . "string"))]) + (returnType . "int") (status . "normal")) + (classesmatching + (category . "utils") (variadic . :json-false) + (parameters . [((range . ".*") (type . "string"))]) + (returnType . "slist") (status . "normal")) + (classmatch + (category . "utils") (variadic . :json-false) + (parameters . [((range . ".*") (type . "string"))]) + (returnType . "context") (status . "normal")) + (classify + (category . "data") (variadic . :json-false) + (parameters . [((range . ".*") (type . "string"))]) + (returnType . "context") (status . "normal")) + (changedbefore + (category . "files") (variadic . :json-false) + (parameters . [((range . "\"?(/.*)") (type . "string")) + ((range . "\"?(/.*)") (type . "string"))]) + (returnType . "context") (status . "normal")) + (concat + (category . "data") (variadic . t) + (parameters . []) + (returnType . "string") (status . "normal")) + (canonify + (category . "data") (variadic . :json-false) + (parameters . [((range . ".*") (type . "string"))]) + (returnType . "string") (status . "normal")) + (and + (category . "data") (variadic . t) + (parameters . []) + (returnType . "string") (status . "normal")) + (ago + (category . "data") (variadic . :json-false) + (parameters . [((range . "0,1000") (type . "int")) + ((range . "0,1000") (type . "int")) + ((range . "0,1000") (type . "int")) + ((range . "0,1000") (type . "int")) + ((range . "0,1000") (type . "int")) + ((range . "0,40000") (type . "int"))]) + (returnType . "int") (status . "normal")) + (accumulated + (category . "data") (variadic . :json-false) + (parameters . [((range . "0,1000") (type . "int")) + ((range . "0,1000") (type . "int")) + ((range . "0,1000") (type . "int")) + ((range . "0,1000") (type . "int")) + ((range . "0,1000") (type . "int")) + ((range . "0,40000") (type . "int"))]) + (returnType . "int") (status . "normal")) + (accessedbefore + (category . "files") (variadic . :json-false) + (parameters . [((range . "\"?(/.*)") (type . "string")) + ((range . "\"?(/.*)") (type . "string"))]) + (returnType . "context") (status . "normal")))) + "Fallback CFEngine syntax, containing just function definitions.") + (defcustom cfengine-mode-abbrevs nil "Abbrevs for CFEngine2 mode." :group 'cfengine @@ -520,31 +1161,24 @@ Intended as the value of `indent-line-function'." ;; CLASS: [.|&!()a-zA-Z0-9_\200-\377]+:: ;; CATEGORY: [a-zA-Z_]+: -(defun cfengine3--current-word (&optional bounds) +(defun cfengine3--current-word (flist &optional bounds) "Propose a word around point in the current CFEngine 3 buffer." - (let ((c (char-after (point))) - (s (syntax-ppss))) - (when (not (nth 3 s)) ; not inside a string + (save-excursion + (skip-syntax-forward "w_") + (when (search-backward-regexp + cfengine-mode-syntax-functions-regex + (point-at-bol) + t) (if bounds - (save-excursion - (let ((oldpoint (point)) - start end) - (skip-syntax-backward "w_") (setq start (point)) - (goto-char oldpoint) - (skip-syntax-forward "w_") (setq end (point)) - (when (not (and (eq start oldpoint) - (eq end oldpoint))) - (list start (point))))) - (and c - (memq (char-syntax c) '(?_ ?w)) - (current-word)))))) + (list (point) (match-end 1)) + (match-string 1))))) (defun cfengine3--current-function () "Look up current CFEngine 3 function" - (let* ((syntax (assoc cfengine-cf-promises cfengine-mode-syntax-cache)) + (let* ((syntax (cfengine3-make-syntax-cache)) (flist (assoc 'functions syntax))) (when flist - (let ((w (cfengine3--current-word))) + (let ((w (cfengine3--current-word flist))) (and w (assq (intern w) flist)))))) ;; format from "cf-promises -s json", e.g. "sort" function: @@ -590,33 +1224,45 @@ Intended as the value of `indent-line-function'." (if has-some-parameters ", ..." "...") "")))) +(defun cfengine3-clear-syntax-cache () + (interactive) + (setq cfengine-mode-syntax-functions-regex nil) + (setq cfengine-mode-syntax-cache nil)) + (defun cfengine3-make-syntax-cache () "Build the CFEngine 3 syntax cache. Calls `cfengine-cf-promises' with \"-s json\"" - (when cfengine-cf-promises - (let ((loaded-json-lib (require 'json nil t)) - (syntax (assoc cfengine-cf-promises cfengine-mode-syntax-cache))) - (if (not loaded-json-lib) - (message "JSON library could not be loaded!") - (unless syntax - (with-demoted-errors - (with-temp-buffer - (call-process-shell-command cfengine-cf-promises - nil ; no input - t ; current buffer - nil ; no redisplay - "-s" "json") - (goto-char (point-min)) - (setq syntax (json-read)) - (setq cfengine-mode-syntax-cache - (cons (cons cfengine-cf-promises syntax) - cfengine-mode-syntax-cache))))))))) + (let ((ret (if cfengine-cf-promises + (let ((loaded-json-lib (require 'json nil t)) + (syntax (cfengine3-make-syntax-cache))) + (if (not loaded-json-lib) + (message "JSON library could not be loaded!") + (unless syntax + (with-demoted-errors + (with-temp-buffer + (call-process-shell-command cfengine-cf-promises + nil ; no input + t ; current buffer + nil ; no redisplay + "-s" "json") + (goto-char (point-min)) + (setq syntax (json-read)) + (setq cfengine-mode-syntax-cache + (cons (cons cfengine-cf-promises syntax) + cfengine-mode-syntax-cache))))))) + cfengine3-fallback-syntax))) + (unless cfengine-mode-syntax-functions-regex + (setq cfengine-mode-syntax-functions-regex + (regexp-opt (mapcar (lambda (def) + (format "%s" (car def))) + (cdr (assoc 'functions ret))) + 'symbols))) + ret)) (defun cfengine3-documentation-function () "Document CFengine 3 functions around point. Intended as the value of `eldoc-documentation-function', which see. Use it by executing `turn-on-eldoc-mode'." - (cfengine3-make-syntax-cache) (let ((fdef (cfengine3--current-function))) (when fdef (cfengine3-format-function-docstring fdef)))) @@ -625,7 +1271,7 @@ see. Use it by executing `turn-on-eldoc-mode'." "Return completions for function name around or before point." (cfengine3-make-syntax-cache) (let* ((bounds (cfengine3--current-word t)) - (syntax (assoc cfengine-cf-promises cfengine-mode-syntax-cache)) + (syntax (cfengine3-make-syntax-cache)) (flist (assoc 'functions syntax))) (when bounds (append bounds (list (cdr flist)))))) -- 2.11.4.GIT