miekg / cf Goto Github PK
View Code? Open in Web Editor NEWCFEngine formatter
License: GNU General Public License v3.0
CFEngine formatter
License: GNU General Public License v3.0
You should be able to place comments anywhere, but a comment after the bundle keyword causes parsing error.
$ cat > test.cf
bundle # foo
agent test{}
$ cf-promises test.cf; echo $? # Does cf-promises accept it? Exit 0 means yes.
0
$ cffmt test.cf
2023/03/28 13:48:50 Failed to parse: parsing error
Policies that use namespaces cause parsing errors.
This example uses a bundle in a non-default namespace and that bundle uses a body from the default namespace:
bundle agent __main__
{
methods:
"Actuate a bundle in another namespace"
usebundle => myNamespace:hello_world,
action => nolock;
}
body action nolock
{
ifelapsed => "0";
}
body file control
{
namespace => "myNamespace";
}
bundle agent hello_world
{
reports:
"$(this.namespace):$(this.bundle): Hello World!"
action => default:nolock;
}
# cf-agent --file /tmp/example.cf
R: myNamespace:hello_world: Hello World!
~/go/bin/cffmt -d /tmp/example.cf
2023/04/28 10:58:52 chroma.Token {Keyword bundle}
2023/04/28 10:58:52 chroma.Token {Keyword agent}
2023/04/28 10:58:52 chroma.Token {NameFunction __main__}
2023/04/28 10:58:52 chroma.Token {Punctuation {}
2023/04/28 10:58:52 chroma.Token {KeywordDeclaration methods}
2023/04/28 10:58:52 chroma.Token {Punctuation :}
2023/04/28 10:58:52 chroma.Token {TokenType(-994) "Actuate a bundle in another namespace"}
2023/04/28 10:58:52 chroma.Token {KeywordReserved usebundle}
2023/04/28 10:58:52 chroma.Token {TokenType(-996) =>}
2023/04/28 10:58:52 chroma.Token {KeywordDeclaration myNamespace}
2023/04/28 10:58:52 chroma.Token {Punctuation :}
2023/04/28 10:58:52 chroma.Token {NameFunction hello_world}
2023/04/28 10:58:52 chroma.Token {Punctuation ,}
2023/04/28 10:58:52 chroma.Token {KeywordReserved action}
2023/04/28 10:58:52 chroma.Token {TokenType(-996) =>}
2023/04/28 10:58:52 chroma.Token {NameFunction nolock}
2023/04/28 10:58:52 chroma.Token {Punctuation ;}
2023/04/28 10:58:52 chroma.Token {Punctuation }}
2023/04/28 10:58:52 chroma.Token {Keyword body}
2023/04/28 10:58:52 chroma.Token {Keyword action}
2023/04/28 10:58:52 chroma.Token {NameFunction nolock}
2023/04/28 10:58:52 chroma.Token {Punctuation {}
2023/04/28 10:58:52 chroma.Token {KeywordReserved ifelapsed}
2023/04/28 10:58:52 chroma.Token {TokenType(-996) =>}
2023/04/28 10:58:52 chroma.Token {TokenType(-994) "0"}
2023/04/28 10:58:52 chroma.Token {Punctuation ;}
2023/04/28 10:58:52 chroma.Token {Punctuation }}
2023/04/28 10:58:52 chroma.Token {Keyword body}
2023/04/28 10:58:52 chroma.Token {Keyword file}
2023/04/28 10:58:52 chroma.Token {Keyword control}
2023/04/28 10:58:52 chroma.Token {Punctuation {}
2023/04/28 10:58:52 chroma.Token {KeywordReserved namespace}
2023/04/28 10:58:52 chroma.Token {TokenType(-996) =>}
2023/04/28 10:58:52 chroma.Token {TokenType(-994) "myNamespace"}
2023/04/28 10:58:52 chroma.Token {Punctuation ;}
2023/04/28 10:58:52 chroma.Token {Punctuation }}
2023/04/28 10:58:52 chroma.Token {Keyword bundle}
2023/04/28 10:58:52 chroma.Token {Keyword agent}
2023/04/28 10:58:52 chroma.Token {NameFunction hello_world}
2023/04/28 10:58:52 chroma.Token {Punctuation {}
2023/04/28 10:58:52 chroma.Token {KeywordDeclaration reports}
2023/04/28 10:58:52 chroma.Token {Punctuation :}
2023/04/28 10:58:52 chroma.Token {TokenType(-994) "$(this.namespace):$(this.bundle): Hello World!"}
2023/04/28 10:58:52 chroma.Token {KeywordReserved action}
2023/04/28 10:58:52 chroma.Token {TokenType(-996) =>}
2023/04/28 10:58:52 chroma.Token {KeywordDeclaration default}
2023/04/28 10:58:52 chroma.Token {Punctuation :}
2023/04/28 10:58:52 chroma.Token {NameFunction nolock}
2023/04/28 10:58:52 chroma.Token {Punctuation ;}
2023/04/28 10:58:52 chroma.Token {Punctuation }}
2023/04/28 10:58:52 Debug Tree:
Specification(false)
├─ Comment(false)
├─ Bundle(false)
│ ├─ Comment(false)
│ ├─ BundleBody(true)
│ │ ├─ Comment(false)
│ │ ├─ PromiseGuard(true)
│ │ └─ ClassPromises(true)
│ │ ├─ ClassGuardPromises(false)
│ │ ├─ Comment(false)
│ │ ├─ Macro(false)
│ │ └─ Promise(false)
│ │ ├─ Promisee(false)
│ │ │ └─ ThinArrow(false)
│ │ ├─ Comment(false)
│ │ ├─ PromiseConstraints(false)
│ │ ├─ Constraint(false)
│ │ │ ├─ Comment(false)
│ │ │ ├─ FatArrow(true)
│ │ │ └─ Rval(false)
│ │ │ ├─ Qstring(false)
│ │ │ ├─ Function(false)
│ │ │ ├─ List(false)
│ │ │ └─ NakedVar(false)
│ │ ├─ Comment(false)
│ │ └─ {KeywordReserved usebundle} ≠ {Punctuation ,}
│ └─ Comment(false)
└─ Body(false)
2023/04/28 10:58:52 Parse Tree:
<nil>
2023/04/28 10:58:52 Failed to parse: parsing error
b.Enter
takes an interface, now we just use with a plain string. We could actually insert a (fake) chroma.Token with the correct type and value of the non-terminal node we're looking at. This would vastly improve how the AST looks
this causes a loop, the semicolon is not found and the closing brace isn't eaten
body common control
{
bundlesequence => {
@(update_def.bundlesequence_end),
"hi",
}
}
I would suggest that comments that are grouped together, stay together. In the example below I have a file header that I don't want to be associated with the body below it. This followed by a comment that explains the body, which I want to be associated with the body.
input:
# Licensed under the MIT License
# Copyright (c) 2023 Lars Erik Wik
# Run the bogus bundle first, then doofus
body common control {
bundlesequence => { "bogus", "doofus" };
}
actual:
# Licensed under the MIT License
# Copyright (c) 2023 Lars Erik Wik
# Run the bogus bundle first, then doofus
body common control
{
bundlesequence => { "bogus", "doofus" };
}
expected:
# Licensed under the MIT License
# Copyright (c) 2023 Lars Erik Wik
# Run the bogus bundle first, then doofus
body common control
{
bundlesequence => { "bogus", "doofus" };
}
When using comments inside slists, three leading spaces are printed in front of all comments trailing an element, except for the comment trailing the last element. I would expect two leading spaces to be printed for all elements.
$ cat > test.cf
body common control {
bundlesequence => {
"bogus", # first
"doofus", # last
};
}
$ cffmt test.cf | sed "s/ /./g" # Swap spaces with dots
body.common.control
{
..bundlesequence.=>.{."bogus",...#.first
......................"doofus"..#.last
.......................};
}
When temporarily commenting out bundles from a bundle sequence, they appear on the line above. It would be more convenient if they stayed on the same line, so that I could easily uncomment them.
$ cat > test.cf
body common control {
bundlesequence => {
# "foo",
"bogus",
# "bar",
"doofus",
};
}
$ cffmt test.cf
body common control
{
bundlesequence => { "# foo",
"bogus", "# bar",
"doofus" };
}
These are parsed, but not printed correctly:
"exec_prefix" string => ifelse(isexecutable("/bin/systemd-run"), "/bin/systemd-run --unit=cfengine-upgrade --scope ", # trailing space in commands important
isexecutable("/usr/bin/systemd-run"), "/usr/bin/systemd-run --unit=cfengine-upgrade --scope ", "");
is not indented correctly
input:
bundle agent bogus {
# Hello
}
actual:
bundle agent bogus
# Hello
{
}
expected:
bundle agent bogus
{
# Hello
}
Support cfengine macro's so at least the std lib of cfengine3 parses completely.
input:
bundle agent bogus {
reports:
"Hello CFEngine" -> { "foo", "bar", "baz" };
}
actual:
bundle agent bogus
{
reports:
"Hello CFEngine" -> { "foo", "bar", "baz" }
;
}
expected:
bundle agent bogus
{
reports:
"Hello CFEngine" -> { "foo", "bar", "baz" };
}
This is a bigger issue, where some comments aren't aligned "just right". Also hooks into multiline comments that sometimes have the same problem.
i.e:
# define the prome stuff that we care about
IsPrometheusServer::
"/etc/prometheus/sd_configs/node_servers.json" # picked up automatically by prometheus
copy_from => no_backup_rdcp("$(def.distr_files_dir)/etc/prometheus/sd_configs/node_servers.json",$(sys.policy_hub)),
perms => mog(0444, root, bin);
prints:
# define the prome stuff that we care about
IsPrometheusServer::
"/etc/prometheus/sd_configs/node_servers.json" # picked up automatically by prometheus
copy_from => no_backup_rdcp("$(def.distr_files_dir)/etc/prometheus/sd_configs/node_servers.json", $(sys.policy_hub)),
perms => mog(0444, root, bin);
Note the newline after 'picked up .....', which in that particular case should be suppressed.
In other cases, like multiple comments in a list, things work out beautifully. The comments printing in print.go is already a bit hazy, so this should be done properly.
This file causes infinite loop:
body common control
{
bundlesequence => {
@(update_def.bundlesequence_end),
# Define control_common_update_bundlesequnce_end via augments
};
}
We dump the token and the AST when parsing files, maybe a 1-line error is nicer
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.