diff --git a/M2/Macaulay2/editors/Macaulay2Web/M2-symbols.ts.in b/M2/Macaulay2/editors/Macaulay2Web/M2-symbols.ts.in index 6ed5cdf49d4..37cb8fd06e1 100644 --- a/M2/Macaulay2/editors/Macaulay2Web/M2-symbols.ts.in +++ b/M2/Macaulay2/editors/Macaulay2Web/M2-symbols.ts.in @@ -1 +1,3 @@ +// @M2BANNER@ + export default [@M2SYMBOLS@]; diff --git a/M2/Macaulay2/editors/Makefile.in b/M2/Macaulay2/editors/Makefile.in index 1a7ba38d65c..fb34e8f8c55 100644 --- a/M2/Macaulay2/editors/Makefile.in +++ b/M2/Macaulay2/editors/Makefile.in @@ -38,7 +38,8 @@ highlightjs/%: @srcdir@/highlightjs/% highlightjs cp $< $@ clean: - rm -rf @pre_emacsdir@/* atom emacs highlightjs prism pygments vim + rm -rf @pre_emacsdir@/* atom emacs highlightjs prism pygments vim \ + Macaulay2Web textmate else clean: diff --git a/M2/Macaulay2/editors/atom/macaulay2.cson.in b/M2/Macaulay2/editors/atom/macaulay2.cson.in index 5a9309e579e..a2178339431 100644 --- a/M2/Macaulay2/editors/atom/macaulay2.cson.in +++ b/M2/Macaulay2/editors/atom/macaulay2.cson.in @@ -1,3 +1,5 @@ +## @M2BANNER@ + # If this is your first time writing a language grammar, check out: # - https://flight-manual.atom.io/hacking-atom/sections/creating-a-grammar/ # - https://flight-manual.atom.io/hacking-atom/sections/creating-a-legacy-textmate-grammar/ diff --git a/M2/Macaulay2/editors/emacs b/M2/Macaulay2/editors/emacs index 830ef641cea..084b0fa4f53 160000 --- a/M2/Macaulay2/editors/emacs +++ b/M2/Macaulay2/editors/emacs @@ -1 +1 @@ -Subproject commit 830ef641ceaab0c7f847d7399ed735d2da8975e4 +Subproject commit 084b0fa4f53194fb18d6178af2fe097d68e065c4 diff --git a/M2/Macaulay2/editors/make-M2-symbols.m2 b/M2/Macaulay2/editors/make-M2-symbols.m2 index 53c7a4189b3..df3ff49eadd 100644 --- a/M2/Macaulay2/editors/make-M2-symbols.m2 +++ b/M2/Macaulay2/editors/make-M2-symbols.m2 @@ -3,201 +3,35 @@ -- as keywords, types, etc. and substituting them in grammar files for various -- editors and syntax highlighting engines. Grammar file templates are assumed -- to be located in the same directory as this script. --- Currently: --- - Emacs --- - Atom & Linguist: https://github.com/Macaulay2/language-macaulay2 --- - Rouge --- - Pygments --- - highlight.js - -------------------------------------------------------------------------------- -exportFrom_Core "sortBy" - --- TODO: Move these two elsewhere: -Function and Function := (f, g) -> s -> f s and g s -Function or Function := (f, g) -> s -> f s or g s - -is := X -> (name, symb) -> instance(value symb, X) - -isAlpha := s -> match("^[[:alpha:]]+$", s) -isAlphaNumeric := s -> match("^[[:alnum:]]+$", s) - --- Things we want to highlight: -isType := is Type -isKeyword := is Keyword -isFunction := is Function -isConst := (name, symb) -> (isAlphaNumeric name - and not (isFunction or isType or isKeyword) (name, symb) - and (symb === symbol null or value symb =!= null)) - -okay := method() -okay(String, Keyword) := -okay(String, Symbol) := (name, pkg) -> length name > 1 and isAlphaNumeric name - -------------------------------------------------------------------------------- --- Get a list of all symbols visible just after loading preloaded packages -allPkgNames := separate(" ", version#"packages") | {"Core"} -loadedPkgNames := Core#"preloaded packages" | {"Core", "Text", "Parsing", "SimpleDoc"} -symbols := unique (sortBy ascii @@ first) join( - apply(allPkgNames, pkgname -> (pkgname, symbol Core)), - flatten apply(loadedPkgNames, pkgname -> ( - pkg := needsPackage pkgname; - select(pairs pkg.Dictionary, okay)))) - -if length symbols < 1500 then error "expected more entries for M2-symbols" - --- Check for invalid symbols -bad := select(symbols, (name, symb) -> not okay(name, symb)) -if #bad > 0 then error( - "encountered symbol(s) that are not alphanumeric or have less than 2 characters:", - concatenate apply(bad, (name, symb) -> - {"\n\t", -* TODO: symbolLocation name, ": here is the first use of ", *- toString name})) - -------------------------------------------------------------------------------- --- Put the symbols into bins -SYMBOLS = first \ select(symbols, (name, symb) -> isAlphaNumeric name) -KEYWORDS = first \ select(symbols, isKeyword) -DATATYPES = first \ select(symbols, isType) -FUNCTIONS = first \ select(symbols, isFunction) -CONSTANTS = first \ select(symbols, isConst) -CONSTANTS = CONSTANTS | {"Node", "Item", "Example", "CannedExample", "Pre", "Code", "Tree", "Synopsis"} -- SimpleDoc words -CONSTANTS = sort CONSTANTS -STRINGS = format "///\\\\(/?/?[^/]\\\\|\\\\(//\\\\)*////[^/]\\\\)*\\\\(//\\\\)*///" - ------------------------------------------------------------------------------- --- Substitute symbols, keywords, types, functions, and constants --- This banner is added to the top of generated grammars -banner := "Auto-generated for Macaulay2-@M2VERSION@. Do not modify this file manually." - -symbolsForVim = template -> ( - output := concatenate("\"\" ", banner, newline, newline, template); - output = replace("@M2VERSION@", version#"VERSION", output); - output = replace("@M2SYMBOLS@", demark(" ", SYMBOLS), output); - output = replace("@M2KEYWORDS@", demark(" ", KEYWORDS), output); - output = replace("@M2DATATYPES@", demark(" ", DATATYPES), output); - output = replace("@M2FUNCTIONS@", demark(" ", FUNCTIONS), output); - output = replace("@M2CONSTANTS@", demark(" ", CONSTANTS), output); - output = replace("@M2STRINGS@", STRINGS, output); - output) - -symbolsForEmacs = template -> ( - output := concatenate(";; ", banner, newline, newline, template); - output = replace("@M2VERSION@", version#"VERSION", output); - output = replace("@M2SYMBOLS@", demark(" ", format \ SYMBOLS), output); - output = replace("@M2KEYWORDS@", demark(" ", format \ KEYWORDS), output); - output = replace("@M2DATATYPES@", demark(" ", format \ DATATYPES), output); - output = replace("@M2FUNCTIONS@", demark(" ", format \ FUNCTIONS), output); - output = replace("@M2CONSTANTS@", demark(" ", format \ CONSTANTS), output); - output = replace("@M2STRINGS@", STRINGS, output); - output) - -symbolsForAtom = template -> ( - output := concatenate("## ", banner, newline, newline, template); - output = replace("@M2VERSION@", version#"VERSION", output); - --output = replace("@M2SYMBOLS@", demark("|", SYMBOLS), output); - output = replace("@M2KEYWORDS@", demark("|", KEYWORDS), output); - output = replace("@M2DATATYPES@", demark("|", DATATYPES), output); - output = replace("@M2FUNCTIONS@", demark("|", FUNCTIONS), output); - output = replace("@M2CONSTANTS@", demark("|", CONSTANTS), output); - output = replace("@M2STRINGS@", STRINGS, output); - output) - -symbolsForPrism = template -> ( - output := concatenate("// ", banner, newline, newline, template); - output = replace("@M2VERSION@", version#"VERSION", output); - output = replace("@M2SYMBOLS@", demark(",", format \ SYMBOLS), output); - output = replace("@M2KEYWORDS@", demark("|", KEYWORDS), output); - output = replace("@M2DATATYPES@", demark("|", DATATYPES), output); - output = replace("@M2FUNCTIONS@", demark("|", FUNCTIONS), output); - output = replace("@M2CONSTANTS@", demark("|", CONSTANTS), output); - output = replace("@M2STRINGS@", STRINGS, output); - output) - -symbolsForRouge = template -> ( - output := concatenate("## ", banner, newline, newline, template); - output = replace("@M2VERSION@", version#"VERSION", output); - --output = replace("@M2SYMBOLS@", demark("|", SYMBOLS), output); - output = replace("@M2KEYWORDS@", demark(" ", KEYWORDS), output); - output = replace("@M2DATATYPES@", demark("|", DATATYPES), output); - output = replace("@M2FUNCTIONS@", demark("|", FUNCTIONS), output); - output = replace("@M2CONSTANTS@", demark("|", CONSTANTS), output); - output = replace("@M2STRINGS@", STRINGS, output); - output) - -pygmentsformat = symlist -> demark("," | newline | " ", format \ symlist) -symbolsForPygments = template -> ( - output := replace("@M2BANNER@", "# " | banner, template); - output = replace("@M2VERSION@", version#"VERSION", output); - output = replace("@M2KEYWORDS@", pygmentsformat KEYWORDS, output); - output = replace("@M2DATATYPES@", pygmentsformat DATATYPES, output); - output = replace("@M2FUNCTIONS@", pygmentsformat FUNCTIONS, output); - output = replace("@M2CONSTANTS@", pygmentsformat CONSTANTS, output); - output = replace("@M2STRINGS@", STRINGS, output); - output) - -hljsformat = symlist -> demark("," | newline | " ", format \ symlist) -symbolsForHighlightJS = template -> ( - output := replace("@M2BANNER@", banner, template); - output = replace("@M2VERSION@", version#"VERSION", output); - output = replace("@M2KEYWORDS@", hljsformat KEYWORDS, output); - output = replace("@M2DATATYPES@", hljsformat DATATYPES, output); - output = replace("@M2FUNCTIONS@", hljsformat FUNCTIONS, output); - output = replace("@M2CONSTANTS@", hljsformat CONSTANTS, output); - output) - -symbolsForTextMate = template -> ( - output = replace("@M2KEYWORDS@", demark("|", KEYWORDS), template); - output = replace("@M2DATATYPES@", demark("|", DATATYPES), output); - output = replace("@M2FUNCTIONS@", demark("|", FUNCTIONS), output); - output = replace("@M2CONSTANTS@", demark("|", CONSTANTS), output); - output) - -symbolsForMacaulay2Web = template -> ( - output := concatenate("// ", banner, newline, newline, template); - output = replace("@M2VERSION@", version#"VERSION", output); - output = replace("@M2SYMBOLS@", demark(",", format \ SYMBOLS), output); - output) - -------------------------------------------------------------------------------- --- Generate syntax files from templates in the same directory - -generateGrammar := (grammarFile, grammarFunction) -> ( - template := currentFileDirectory | grammarFile | ".in"; - if fileExists template then ( - stdio << "-- Generating " << grammarFile << endl; - directory := replace("/[^/].*$", "", grammarFile); - if not isDirectory directory then makeDirectory directory; - grammarFile << grammarFunction get(template) << close) - else stderr << "Skipping generation of " << grammarFile << " as it does not exist." << endl;) +needsPackage "Style" -- Emacs: Write M2-symbols.el -generateGrammar("emacs/M2-symbols.el", symbolsForEmacs) +generateGrammar("emacs/M2-symbols.el", x -> demark(" ", format \ x)) -- Atom & Linguist: Write macaulay2.cson -generateGrammar("atom/macaulay2.cson", symbolsForAtom); +generateGrammar("atom/macaulay2.cson", x -> demark("|", x)) -- Prism: Write macaulay2.js -generateGrammar("prism/macaulay2.js", symbolsForPrism); +generateGrammar("prism/macaulay2.js", x -> demark("|", x)) -- Vim: Write m2.vim.syntax and m2.vim.dict -generateGrammar("vim/m2.vim.syntax", symbolsForVim); -generateGrammar("vim/m2.vim.dict", symbolsForVim); -- TODO: is this necessary? - --- Rouge: Write macaulay2.rb ---generateGrammar("rouge/macaulay2.rb", symbolsForRouge); +generateGrammar("vim/m2.vim.syntax", x -> demark(" ", x)) +generateGrammar("vim/m2.vim.dict", x -> demark(" ", x)) -- TODO: is this necessary? -- Pygments: Write macaulay2.py -generateGrammar("pygments/macaulay2.py", symbolsForPygments) +generateGrammar("pygments/macaulay2.py", + x -> demark("," | newline | " ", format \ x)) -- highlight.js: Write macaulay2.js -generateGrammar("highlightjs/macaulay2.js", symbolsForHighlightJS) +generateGrammar("highlightjs/macaulay2.js", + x -> demark("," | newline | " ", format \ x)) -generateGrammar("textmate/macaulay2.tmLanguage.json", symbolsForTextMate) +generateGrammar("textmate/macaulay2.tmLanguage.json", x -> demark("|", x)) -- Macaulay2Web: Write M2-symbols.ts -generateGrammar("Macaulay2Web/M2-symbols.ts", symbolsForMacaulay2Web) - +generateGrammar("Macaulay2Web/M2-symbols.ts", x -> demark(",", format \ x)) -- Local Variables: -- compile-command: "make -C $M2BUILDDIR/Macaulay2/emacs M2-symbols " diff --git a/M2/Macaulay2/editors/prism/macaulay2.js.in b/M2/Macaulay2/editors/prism/macaulay2.js.in index 3181ad3f587..1196d13f309 100644 --- a/M2/Macaulay2/editors/prism/macaulay2.js.in +++ b/M2/Macaulay2/editors/prism/macaulay2.js.in @@ -1,3 +1,5 @@ +// @M2BANNER@ + Prism.languages.m2 = Prism.languages.macaulay2 = { 'comment': [ diff --git a/M2/Macaulay2/editors/vim/m2.vim.dict.in b/M2/Macaulay2/editors/vim/m2.vim.dict.in index bdbc0a80239..b5ffa3bd230 100644 --- a/M2/Macaulay2/editors/vim/m2.vim.dict.in +++ b/M2/Macaulay2/editors/vim/m2.vim.dict.in @@ -1,3 +1,5 @@ +"" @M2BANNER@ + " Vim dictionary file " Language: Macaulay2 diff --git a/M2/Macaulay2/editors/vim/m2.vim.syntax.in b/M2/Macaulay2/editors/vim/m2.vim.syntax.in index f9b00004905..7dad405f876 100644 --- a/M2/Macaulay2/editors/vim/m2.vim.syntax.in +++ b/M2/Macaulay2/editors/vim/m2.vim.syntax.in @@ -1,3 +1,5 @@ +"" @M2BANNER@ + " Vim syntax file " Language: Macaulay2 diff --git a/M2/Macaulay2/m2/integers.m2 b/M2/Macaulay2/m2/integers.m2 index 32575b61efa..1cb1eeb4a00 100644 --- a/M2/Macaulay2/m2/integers.m2 +++ b/M2/Macaulay2/m2/integers.m2 @@ -92,6 +92,11 @@ ZZ & ZZ := ZZ => lookup(symbol &, ZZ, ZZ) ZZ ^^ ZZ := bitxorfun Boolean xor Boolean := (x, y) -> x and not y or not x and y +Function and Function := (f, g) -> s -> f s and g s +Function or Function := (f, g) -> s -> f s or g s +Function xor Function := (f, g) -> s -> f s xor g s +not Function := f -> s -> not f s + ZZ~ := bitnotfun changeBase = method() diff --git a/M2/Macaulay2/packages/Macaulay2Doc/operators.m2 b/M2/Macaulay2/packages/Macaulay2Doc/operators.m2 index 9a5c72f7dff..05a69e37de0 100644 --- a/M2/Macaulay2/packages/Macaulay2Doc/operators.m2 +++ b/M2/Macaulay2/packages/Macaulay2Doc/operators.m2 @@ -250,7 +250,7 @@ document { -- TODO: implement or/and for ZZ document { - Key => "or", + Key => {"or", (symbol or, Function, Function)}, Headline => "disjunction", TT "t or u", " -- returns true if ", TT "t", " is true or ", TT "u", " is true.", @@ -260,7 +260,7 @@ document { } document { - Key => "and", + Key => {"and", (symbol and, Function, Function)}, Headline => "conjunction", TT "t and u", " -- returns true if ", TT "t", " is true and ", TT "u", " is true.", @@ -270,7 +270,7 @@ document { } document { - Key => "not", + Key => {"not", (symbol not, Function)}, Headline => "negation", TT "not x", " -- yields the negation of x, which must be true or false.", SeeAlso =>{ "and", "or" } @@ -280,6 +280,7 @@ doc /// Key symbol xor (symbol xor, Boolean, Boolean) + (symbol xor, Function, Function) Headline exclusive disjunction Usage diff --git a/M2/Macaulay2/packages/SimpleDoc.m2 b/M2/Macaulay2/packages/SimpleDoc.m2 index e1e0f4626bb..61de5952ade 100644 --- a/M2/Macaulay2/packages/SimpleDoc.m2 +++ b/M2/Macaulay2/packages/SimpleDoc.m2 @@ -66,6 +66,8 @@ applySplit = (functionTable, textlines) -> apply(splitByIndent(textlines, false) functionTable#key(textlines_{s+1..e}, getLinenum textlines#s))) -- Mapping tables for evaluating docstring keywords +-- When adding a new keyword that isn't already an exported symbol, +-- add it to the list of constants for syntax highlighting in Style.m2 NodeFunctions = new HashTable from { "Node" => (textlines, keylinenum) -> new Node from nodeCheck(applySplit(NodeFunctions, textlines), keylinenum), "Key" => (textlines, keylinenum) -> Key => getKeys(textlines, keylinenum), diff --git a/M2/Macaulay2/packages/Style.m2 b/M2/Macaulay2/packages/Style.m2 index a3019f09d69..f8bd81e469c 100644 --- a/M2/Macaulay2/packages/Style.m2 +++ b/M2/Macaulay2/packages/Style.m2 @@ -3,16 +3,182 @@ newPackage( "Style", AuxiliaryFiles => true, Headline => "style sheets and images for the documentation", Keywords => {"Documentation"}, - Version => "1.0" + Version => "1.1" ) +--------------------------------------------- +-- grammar generation code adapted from -- +-- M2/Macaulay2/editors/make-M2-symbols.m2 -- +--------------------------------------------- + +export {"generateGrammar"} + +importFrom(Core, "sortBy") + +is := X -> (name, symb) -> instance(value symb, X) + +isAlpha := s -> match("^[[:alpha:]]+$", s) +isAlphaNumeric := s -> match("^[[:alnum:]]+$", s) + +-- Things we want to highlight: +isType := is Type +isKeyword := is Keyword +isFunction := is Function +isConst := (name, symb) -> (isAlphaNumeric name + and not (isFunction or isType or isKeyword) (name, symb) + and (symb === symbol null or value symb =!= null)) + +okay := method() +okay(String, Keyword) := +okay(String, Symbol) := (name, pkg) -> length name > 1 and isAlphaNumeric name + +cachedSymbols = new CacheTable +STRINGS = format "///\\\\(/?/?[^/]\\\\|\\\\(//\\\\)*////[^/]\\\\)*\\\\(//\\\\)*///" + +-- This banner is added to the top of generated grammars +banner := "Auto-generated for Macaulay2-@M2VERSION@. Do not modify this file manually." + +generateSymbols = () -> ( + ---------------------------------------------------------------------------- + -- Get a list of all symbols visible just after loading preloaded packages + allPkgNames := separate(" ", version#"packages") | {"Core"}; + loadedPkgNames := join(Core#"preloaded packages", + {"Core", "Text", "Parsing", "SimpleDoc"}); + symbols := unique (sortBy ascii @@ first) join( + apply(allPkgNames, pkgname -> (pkgname, symbol Core)), + flatten apply(loadedPkgNames, pkgname -> ( + pkg := needsPackage pkgname; + select(pairs pkg.Dictionary, okay)))); + + if length symbols < 1500 then error "expected more entries for M2-symbols"; + + ------------------------------------------------------------------------------- + -- Put the symbols into bins + cachedSymbols.Symbol = first \ select(symbols, + (name, symb) ->isAlphaNumeric name); + cachedSymbols.Keyword = first \ select(symbols, isKeyword); + cachedSymbols.Type = first \ select(symbols, isType); + cachedSymbols.Function = first \ select(symbols, isFunction); + cachedSymbols.Constant = sort join( + first \ select(symbols, isConst), { + -- SimpleDoc docstring keywords -- keep updated + -- NodeFunctions + "Node", + "Synopsis", + -- DescriptionFunctions + "CannedExample", + "Code", + "Example", + "Pre", + "Tree", + -- ConsequenceFunctions + "Item" + }); + ) + +------------------------------------------------------------------------------- +-- Generate syntax files from templates in the same directory + +generateGrammar = method() +generateGrammar(String, String, Function) := (template, outfile, demarkf) -> ( + if not fileExists template + then ( + printerr("warning: ", template, + " does not exist; skipping generation of ", outfile); + return); + printerr("generating ", outfile); + directory := replace("/[^/].*$", "", outfile); + if not isDirectory directory then makeDirectory directory; + output := get template; + if #cachedSymbols == 0 then generateSymbols(); + output = replace("@M2BANNER@", banner, output); + output = replace("@M2VERSION@", version#"VERSION", output); + output = replace("@M2SYMBOLS@", demarkf cachedSymbols.Symbol, output); + output = replace("@M2KEYWORDS@", demarkf cachedSymbols.Keyword, output); + output = replace("@M2DATATYPES@", demarkf cachedSymbols.Type, output); + output = replace("@M2FUNCTIONS@", demarkf cachedSymbols.Function, output); + output = replace("@M2CONSTANTS@", demarkf cachedSymbols.Constant, output); + output = replace("@M2STRINGS@", STRINGS, output); + outfile << output << close;) +generateGrammar(String, Function) := (outfile, demarkf) -> ( + generateGrammar(currentFileDirectory | outfile | ".in", outfile, demarkf)) + beginDocumentation() -document { Key => "Style", - Headline => "style sheets and images for the documentation", - "This package is simply a repository for the style sheets and images used by the - html pages in the documentation." - } +doc /// + Key + Style + Headline + style sheets and images for the documentation + Description + Text + This package is primarily a repository for the style sheets and images + used by the html pages in the documentation. + + It exports one method, @TO generateGrammar@, for generating grammar files + used for syntax highlighting and/or auto-completion in Macaulay2 code + editors and in the html documentation. +/// + +doc /// + Key + generateGrammar + (generateGrammar, String, Function) + (generateGrammar, String, String, Function) + Headline + generate a grammar file from a template + Usage + generateGrammar(template, outfile, demarkf) + generateGrammar(outfile, demarkf) + Inputs + template:String -- the filename of the template file + outfile:String -- the filename of the output file + demarkf:Function -- how to demark a list of symbols + Description + Text + This method generates a grammar file for use in syntax highlighting + Macaulay2 code in a text editor or web browser. + + The file @SAMP "template"@ may contain any of the following special + strings: + + @UL { + LI {SAMP "\100M2BANNER\100", ", for placing a banner mentioning that + the resulting file was automatically generated."}, + LI {SAMP "\100M2VERSION\100", ", for the current version of ", + "Macaulay2."}, + LI {SAMP "\100M2SYMBOLS\100", ", for a list of all Macaulay2 symbols", + ", e.g., for automatic completion."}, + LI {SAMP "\100M2KEYWORDS\100", ", for a list of Macaulay2 keywords."}, + LI {SAMP "\100M2DATATYPES\100", ", for a list of Macaulay2 types."}, + LI {SAMP "\100M2FUNCTIONS\100", ", for a list of Macaulay2 ", + "functions."}, + LI {SAMP "\100M2CONSTANTS\100", ", for a list of Macaulay2 symbols ", + "and packages."}, + LI {SAMP "\100M2STRINGS\100", ", for a regular expression that ", + "matches Macaulay2 strings."}}@ + + The function @SAMP "demarkf"@ indicates how the elements of each of the + lists will be demarked in the resulting file. The file @SAMP "outfile"@ + will then be generated, replacing each of these strings as indicated + above. + Example + outfile = temporaryFileName() + template = outfile | ".in" + template << "@M2BANNER@" << endl << endl; + template << "This is an example file for the generateGrammar method!"; + template << endl; + template << "String regex: @M2STRINGS@" << endl; + template << "List of keywords: {" << endl; + template << " @M2KEYWORDS@" << endl; + template << "}" << endl << close; + get template + generateGrammar(template, outfile, x -> demark(",\n ", x)) + get outfile + Text + If @SAMP "template"@ is omitted, then it defaults to + @M2CODE "currentFileDirectory | outfile | \".in\""@. +/// -- Local Variables: -- compile-command: "make -C $M2BUILDDIR/Macaulay2/packages PACKAGES=Style "