From 6a5716b662477ebb289a6512f5c29e7c978a8457 Mon Sep 17 00:00:00 2001 From: Emilien Lemaire Date: Sat, 6 May 2023 19:37:45 +0200 Subject: [PATCH] Add menhir table for packages --- sphinx/commands.rst | 364 +++++++++++++++++++++++++++------------- sphinx/conf.py | 2 +- sphinx/reference.rst | 16 ++ sphinx/usecases.rst | 50 +++++- src/drom_lib/dune.ml | 80 +++++++-- src/drom_lib/globals.ml | 2 + src/drom_lib/package.ml | 72 ++++++++ src/drom_lib/project.ml | 23 +++ src/drom_lib/types.ml | 24 +++ 9 files changed, 493 insertions(+), 140 deletions(-) diff --git a/sphinx/commands.rst b/sphinx/commands.rst index ec593074..81e64920 100644 --- a/sphinx/commands.rst +++ b/sphinx/commands.rst @@ -34,11 +34,14 @@ Overview of sub-commands:: fmt Format sources with ocamlformat + headers + Check all headers in project + install Build & install the project in the project opam switch - lock (since version 0.2.1) - Generate a .locked file for the project + list (since version 0.4.0) + List available project or packages skeletons new Create a new project @@ -70,6 +73,12 @@ Overview of sub-commands:: test Run tests + toml + Read TOML files and print them back on stdout + + top + Run the ocaml toplevel + tree Display a tree of dependencies @@ -80,8 +89,8 @@ Overview of sub-commands:: Update packages in switch -drom build -~~~~~~~~~~~~ +main.exe build +~~~~~~~~~~~~~~~~ Build a project @@ -110,7 +119,7 @@ This command performs the following actions: **USAGE** :: - drom build [OPTIONS] + main.exe build [OPTIONS] Where options are: @@ -119,8 +128,6 @@ Where options are: * :code:`--local` Create a local switch instead of using a global switch -* :code:`--locked` (since version 0.2.1) Use .locked file if it exists - * :code:`--profile PROFILE` Build profile to use * :code:`--switch OPAM_SWITCH` Use global switch SWITCH instead of creating a local switch @@ -130,8 +137,8 @@ Where options are: * :code:`-y` or :code:`--yes` Reply yes to all questions -drom build-deps -~~~~~~~~~~~~~~~~~ +main.exe build-deps +~~~~~~~~~~~~~~~~~~~~~ Install build dependencies only @@ -139,7 +146,7 @@ Install build dependencies only **USAGE** :: - drom build-deps [OPTIONS] + main.exe build-deps [OPTIONS] Where options are: @@ -148,8 +155,6 @@ Where options are: * :code:`--local` Create a local switch instead of using a global switch -* :code:`--locked` (since version 0.2.1) Use .locked file if it exists - * :code:`--profile PROFILE` Build profile to use * :code:`--switch OPAM_SWITCH` Use global switch SWITCH instead of creating a local switch @@ -159,8 +164,8 @@ Where options are: * :code:`-y` or :code:`--yes` Reply yes to all questions -drom clean -~~~~~~~~~~~~ +main.exe clean +~~~~~~~~~~~~~~~~ Clean the project from build files @@ -168,7 +173,7 @@ Clean the project from build files **USAGE** :: - drom clean [OPTIONS] + main.exe clean [OPTIONS] Where options are: @@ -176,8 +181,8 @@ Where options are: * :code:`--distclean` Also remove _opam/ (local switch) and _drom/ -drom config -~~~~~~~~~~~~~ +main.exe config +~~~~~~~~~~~~~~~~~ Read/write configuration @@ -194,27 +199,35 @@ This command is useful to read/write drom configuration The following displays the list of project skeletons: :: + drom config --project-skeletons + **USAGE** :: - drom config [OPTIONS] + main.exe config [OPTIONS] Where options are: -* :code:`--drom-project-skeletons` List available project skeletons from drom +* :code:`--no-fetch-share` Prevent fetching updates from the share repo (in particular without network connection * :code:`--package-skeletons` List available package skeletons * :code:`--project-skeletons` List available project skeletons +* :code:`--reclone-share` Reclone share repository + +* :code:`--share-repo SHARE_REPO` Set the repository URL of the share database (use 'default' for default repo) + +* :code:`--share-version SHARE_VERSION` Set the version of share database (use 'latest' for latest version) -drom dep (since version 0.2.1) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +main.exe dep (since version 0.2.1) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Manage dependency of a package @@ -237,6 +250,7 @@ If no modification argument is provided, the dependency is printed in the termin **EXAMPLE** :: + drom dep --package drom_lib --add ez_cmdliner --ver ">0.1" drom dep --package drom_lib --remove ez_cmdliner @@ -244,6 +258,7 @@ If no modification argument is provided, the dependency is printed in the termin + **VERSION SPECIFICATION** @@ -264,7 +279,7 @@ The version specified in the **--ver VERSION** argument should follow the follow **USAGE** :: - drom dep DEPENDENCY [OPTIONS] + main.exe dep DEPENDENCY [OPTIONS] Where options are: @@ -273,20 +288,36 @@ Where options are: * :code:`--add` Add as new dependency +* :code:`--create BOOL` Change project creation status + * :code:`--diff` Print a diff of user-modified files that are being skipped * :code:`--doc BOOL` Whether dependency is only for doc +* :code:`--edition OCAMLVERSION` Set project default OCaml version + * :code:`-f` or :code:`--force` Force overwriting modified files (otherwise, they would be skipped) * :code:`--lib LIBNAME` Dependency should have this libname in dune +* :code:`--min-edition OCAMLVERSION` Set project minimal OCaml version + +* :code:`--no-fetch-share` Prevent fetching updates from the share repo (in particular without network connection + +* :code:`--opt BOOL` Whether dependency is optional or not + * :code:`--package PACKAGE` Attach dependency to this package name * :code:`--promote-skip` Promote user-modified files to skip field +* :code:`--reclone-share` Reclone share repository + * :code:`--remove` Remove this dependency +* :code:`--share-repo SHARE_REPO` Set the repository URL of the share database (use 'default' for default repo) + +* :code:`--share-version SHARE_VERSION` Set the version of share database (use 'latest' for latest version) + * :code:`--skip FILE` Add FILE to skip list * :code:`--test BOOL` Whether dependency is only for tests @@ -298,8 +329,8 @@ Where options are: * :code:`--ver VERSION` Dependency should have this version -drom dev-deps -~~~~~~~~~~~~~~~ +main.exe dev-deps +~~~~~~~~~~~~~~~~~~~ Install dev dependencies (odoc, ocamlformat, merlin, etc.) @@ -307,7 +338,7 @@ Install dev dependencies (odoc, ocamlformat, merlin, etc.) **USAGE** :: - drom dev-deps [OPTIONS] + main.exe dev-deps [OPTIONS] Where options are: @@ -316,8 +347,6 @@ Where options are: * :code:`--local` Create a local switch instead of using a global switch -* :code:`--locked` (since version 0.2.1) Use .locked file if it exists - * :code:`--profile PROFILE` Build profile to use * :code:`--switch OPAM_SWITCH` Use global switch SWITCH instead of creating a local switch @@ -327,8 +356,8 @@ Where options are: * :code:`-y` or :code:`--yes` Reply yes to all questions -drom doc -~~~~~~~~~~ +main.exe doc +~~~~~~~~~~~~~~ Generate all documentation (API and Sphinx) @@ -336,7 +365,7 @@ Generate all documentation (API and Sphinx) **USAGE** :: - drom doc [OPTIONS] + main.exe doc [OPTIONS] Where options are: @@ -345,8 +374,6 @@ Where options are: * :code:`--local` Create a local switch instead of using a global switch -* :code:`--locked` (since version 0.2.1) Use .locked file if it exists - * :code:`--profile PROFILE` Build profile to use * :code:`--switch OPAM_SWITCH` Use global switch SWITCH instead of creating a local switch @@ -358,8 +385,8 @@ Where options are: * :code:`-y` or :code:`--yes` Reply yes to all questions -drom fmt -~~~~~~~~~~ +main.exe fmt +~~~~~~~~~~~~~~ Format sources with ocamlformat @@ -367,7 +394,7 @@ Format sources with ocamlformat **USAGE** :: - drom fmt [OPTIONS] + main.exe fmt [OPTIONS] Where options are: @@ -378,8 +405,6 @@ Where options are: * :code:`--local` Create a local switch instead of using a global switch -* :code:`--locked` (since version 0.2.1) Use .locked file if it exists - * :code:`--profile PROFILE` Build profile to use * :code:`--switch OPAM_SWITCH` Use global switch SWITCH instead of creating a local switch @@ -389,8 +414,33 @@ Where options are: * :code:`-y` or :code:`--yes` Reply yes to all questions -drom install -~~~~~~~~~~~~~~ +main.exe headers +~~~~~~~~~~~~~~~~~~ + +Check all headers in project + + +**USAGE** +:: + + main.exe headers [OPTIONS] + +Where options are: + + +* :code:`--add-default HEADER_ID` Add this header as the default for these files + +* :code:`--from HEADER_ID` Replace this header + +* :code:`--replace SRC:DST` Replace header SRC by header DST + +* :code:`--replace-by HEADER_ID` Replace by this header + +* :code:`--skip HEADER_ID` skip this header when printing headers + + +main.exe install +~~~~~~~~~~~~~~~~~~ Build & install the project in the project opam switch @@ -398,17 +448,17 @@ Build & install the project in the project opam switch **USAGE** :: - drom install [OPTIONS] + main.exe install PACKAGES [OPTIONS] Where options are: +* :code:`PACKAGES` Specify the list of packages to install + * :code:`--edition VERSION` Use this OCaml edition * :code:`--local` Create a local switch instead of using a global switch -* :code:`--locked` (since version 0.2.1) Use .locked file if it exists - * :code:`--profile PROFILE` Build profile to use * :code:`--switch OPAM_SWITCH` Use global switch SWITCH instead of creating a local switch @@ -418,45 +468,39 @@ Where options are: * :code:`-y` or :code:`--yes` Reply yes to all questions -drom lock (since version 0.2.1) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +main.exe list (since version 0.4.0) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Generate a .locked file for the project +List available project or packages skeletons **DESCRIPTION** -This command will build the project and call **opam lock** to generate a file *${project}-deps.opam.locked* with the exact dependencies used during the build, and that file will be added to the git-managed files of the project to be committed. - -The generated .locked file can be used by other developers to build in the exact same environment by calling **drom build --locked** to build the current project. +List available project or packages skeletons **USAGE** :: - drom lock [OPTIONS] + main.exe list ARGUMENTS [OPTIONS] Where options are: -* :code:`--edition VERSION` Use this OCaml edition +* :code:`ARGUMENTS` Use 'projects' or 'packages' to display corresponding skeletons -* :code:`--local` Create a local switch instead of using a global switch +* :code:`--no-fetch-share` Prevent fetching updates from the share repo (in particular without network connection -* :code:`--locked` (since version 0.2.1) Use .locked file if it exists +* :code:`--reclone-share` Reclone share repository -* :code:`--profile PROFILE` Build profile to use - -* :code:`--switch OPAM_SWITCH` Use global switch SWITCH instead of creating a local switch - -* :code:`--upgrade` Upgrade project files from drom.toml +* :code:`--share-repo SHARE_REPO` Set the repository URL of the share database (use 'default' for default repo) -* :code:`-y` or :code:`--yes` Reply yes to all questions +* :code:`--share-version SHARE_VERSION` Set the version of share database (use 'latest' for latest version) -drom new -~~~~~~~~~~ +main.exe new +~~~~~~~~~~~~~~ Create a new project @@ -473,44 +517,58 @@ This command creates a new project, with name **PROJECT** in a directory **PROJE The following command creates a project containing library **my_lib** in **src/my_lib**: :: + drom new my_lib --skeleton library + The following command creates a project containing a library **hello_lib** in **src/hello_lib** and a program **hello** in **src/hello** calling the library: :: + drom new hello --skeleton program + **USAGE** :: - drom new PROJECT [OPTIONS] + main.exe new PROJECT [OPTIONS] Where options are: * :code:`PROJECT` Name of the project -* :code:`--binary` Compile to binary +* :code:`--create BOOL` Change project creation status * :code:`--diff` Print a diff of user-modified files that are being skipped * :code:`--dir DIRECTORY` Dir where package sources are stored (src by default) +* :code:`--edition OCAMLVERSION` Set project default OCaml version + * :code:`-f` or :code:`--force` Force overwriting modified files (otherwise, they would be skipped) * :code:`--inplace` Create project in the the current directory -* :code:`--javascript` Compile to javascript - * :code:`--library` Project contains only a library +* :code:`--min-edition OCAMLVERSION` Set project minimal OCaml version + +* :code:`--no-fetch-share` Prevent fetching updates from the share repo (in particular without network connection + * :code:`--program` Project contains only a program * :code:`--promote-skip` Promote user-modified files to skip field +* :code:`--reclone-share` Reclone share repository + +* :code:`--share-repo SHARE_REPO` Set the repository URL of the share database (use 'default' for default repo) + +* :code:`--share-version SHARE_VERSION` Set the version of share database (use 'latest' for latest version) + * :code:`--skeleton SKELETON` Create project using a predefined skeleton or one specified in ~/.config/drom/skeletons/ * :code:`--skip FILE` Add FILE to skip list @@ -520,8 +578,8 @@ Where options are: * :code:`--virtual` Package is virtual, i.e. no code -drom odoc -~~~~~~~~~~~ +main.exe odoc +~~~~~~~~~~~~~~~ Generate API documentation using odoc in the _drom/docs/doc directory @@ -529,7 +587,7 @@ Generate API documentation using odoc in the _drom/docs/doc directory **USAGE** :: - drom odoc [OPTIONS] + main.exe odoc [OPTIONS] Where options are: @@ -538,8 +596,6 @@ Where options are: * :code:`--local` Create a local switch instead of using a global switch -* :code:`--locked` (since version 0.2.1) Use .locked file if it exists - * :code:`--profile PROFILE` Build profile to use * :code:`--switch OPAM_SWITCH` Use global switch SWITCH instead of creating a local switch @@ -551,8 +607,8 @@ Where options are: * :code:`-y` or :code:`--yes` Reply yes to all questions -drom opam-plugin (since version 0.2.1) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +main.exe opam-plugin (since version 0.2.1) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Install drom as an opam plugin (called by 'opam drom') @@ -572,7 +628,7 @@ This command performs the following actions: **USAGE** :: - drom opam-plugin [OPTIONS] + main.exe opam-plugin [OPTIONS] Where options are: @@ -580,8 +636,8 @@ Where options are: * :code:`--remove` Remove drom as an opam plugin -drom package -~~~~~~~~~~~~~~ +main.exe package +~~~~~~~~~~~~~~~~~~ Manage a package within a project @@ -589,33 +645,41 @@ Manage a package within a project **USAGE** :: - drom package PACKAGE [OPTIONS] + main.exe package PACKAGE [OPTIONS] Where options are: * :code:`PACKAGE` Name of the package -* :code:`--binary` Compile to binary +* :code:`--create BOOL` Change project creation status * :code:`--diff` Print a diff of user-modified files that are being skipped * :code:`--dir DIRECTORY` Dir where package sources are stored (src by default) -* :code:`-f` or :code:`--force` Force overwriting modified files (otherwise, they would be skipped) +* :code:`--edit` Edit package.toml description with EDITOR -* :code:`--javascript` Compile to javascript +* :code:`--edition OCAMLVERSION` Set project default OCaml version + +* :code:`-f` or :code:`--force` Force overwriting modified files (otherwise, they would be skipped) * :code:`--library` Package is a library +* :code:`--min-edition OCAMLVERSION` Set project minimal OCaml version + * :code:`--new SKELETON` Add a new package to the project with skeleton NAME * :code:`--new-file FILENAME` (since version 0.2.1) Add new source file +* :code:`--no-fetch-share` Prevent fetching updates from the share repo (in particular without network connection + * :code:`--program` Package is a program * :code:`--promote-skip` Promote user-modified files to skip field +* :code:`--reclone-share` Reclone share repository + * :code:`--remove` (since version 0.2.1) Remove a package from the project * :code:`--rename NEW_NAME` Rename secondary package to a new name @@ -627,8 +691,8 @@ Where options are: * :code:`--virtual` Package is virtual, i.e. no code -drom project -~~~~~~~~~~~~~~ +main.exe project +~~~~~~~~~~~~~~~~~~ Update an existing project @@ -644,25 +708,37 @@ With argument **--upgrade**, it can also be used to reformat the toml files, fro **USAGE** :: - drom project [OPTIONS] + main.exe project [OPTIONS] Where options are: -* :code:`--binary` Compile to binary +* :code:`--create BOOL` Change project creation status * :code:`--diff` Print a diff of user-modified files that are being skipped -* :code:`-f` or :code:`--force` Force overwriting modified files (otherwise, they would be skipped) +* :code:`--edit` Edit project description -* :code:`--javascript` Compile to javascript +* :code:`--edition OCAMLVERSION` Set project default OCaml version + +* :code:`-f` or :code:`--force` Force overwriting modified files (otherwise, they would be skipped) * :code:`--library` Project contains only a library. Equivalent to **--skeleton library** +* :code:`--min-edition OCAMLVERSION` Set project minimal OCaml version + +* :code:`--no-fetch-share` Prevent fetching updates from the share repo (in particular without network connection + * :code:`--program` Project contains a program. Equivalent to **--skeleton program**. The generated project will be composed of a *library* package and a *driver* package calling the **Main.main** of the library. * :code:`--promote-skip` Promote user-modified files to skip field +* :code:`--reclone-share` Reclone share repository + +* :code:`--share-repo SHARE_REPO` Set the repository URL of the share database (use 'default' for default repo) + +* :code:`--share-version SHARE_VERSION` Set the version of share database (use 'latest' for latest version) + * :code:`--skeleton SKELETON` Create project using a predefined skeleton or one specified in ~/.config/drom/skeletons/ * :code:`--skip FILE` Add FILE to skip list @@ -674,8 +750,8 @@ Where options are: * :code:`--virtual` Package is virtual, i.e. no code. Equivalent to **--skeleton virtual**. -drom promote -~~~~~~~~~~~~~~ +main.exe promote +~~~~~~~~~~~~~~~~~~ Promote detected changes after running drom test or drom fmt @@ -683,7 +759,7 @@ Promote detected changes after running drom test or drom fmt **USAGE** :: - drom promote [OPTIONS] + main.exe promote [OPTIONS] Where options are: @@ -692,8 +768,6 @@ Where options are: * :code:`--local` Create a local switch instead of using a global switch -* :code:`--locked` (since version 0.2.1) Use .locked file if it exists - * :code:`--profile PROFILE` Build profile to use * :code:`--switch OPAM_SWITCH` Use global switch SWITCH instead of creating a local switch @@ -703,8 +777,8 @@ Where options are: * :code:`-y` or :code:`--yes` Reply yes to all questions -drom publish -~~~~~~~~~~~~~~ +main.exe publish +~~~~~~~~~~~~~~~~~~ Update opam files with checksums and copy them to a local opam-repository for publication @@ -715,15 +789,17 @@ Update opam files with checksums and copy them to a local opam-repository for pu Before running this command, you should edit the file **$HOME/.config/drom/config** and set the value of the *opam-repo* option, like: :: + [user] author = "John Doe " github-organization = "ocaml" license = "LGPL2" - copyright = "OCamlPro SAS & Origin Labs SAS" + copyright = "OCamlPro SAS" opam-repo = "/home/john/GIT/opam-repository" + Alternatively, you can run it with option **--opam-repo REPOSITORY**. In both case, **REPOSITORY** should be the absolute path to the location of a local git-managed opam repository. @@ -741,11 +817,14 @@ In both case, **REPOSITORY** should be the absolute path to the location of a lo Note that, prior to calling **drom publish**, you should update the opam-repository to the latest version of the **master** branch: :: + git checkout master git pull ocaml master + Once the opam files have been added, you should push them to your local fork of opam-repository and create a merge request: :: + cd ~/GIT/opam-repository git checkout -b z-$(date --iso)-new-package-version git add packages @@ -753,12 +832,13 @@ Once the opam files have been added, you should push them to your local fork of git push + To download the project source archive, **drom publish** will either use the *archive* URL of the drom.toml file, or the Github URL (if the *github-organization* is set in the project), assuming in this later case that the version starts with 'v' (like v1.0.0). Two substitutions are allowed in *archive*: *${version}* for the version, *${name}* for the package name. **USAGE** :: - drom publish [OPTIONS] + main.exe publish [OPTIONS] Where options are: @@ -770,8 +850,8 @@ Where options are: * :code:`--opam-repo DIRECTORY` Path to local git-managed opam-repository. The path should be absolute. Overwrites the value *opam-repo* from *$HOME/.config/drom/config* -drom run -~~~~~~~~~~ +main.exe run +~~~~~~~~~~~~~~ Execute the project @@ -794,7 +874,7 @@ This command performs the following actions: **USAGE** :: - drom run ARGUMENTS [OPTIONS] + main.exe run ARGUMENTS [OPTIONS] Where options are: @@ -805,8 +885,6 @@ Where options are: * :code:`--local` Create a local switch instead of using a global switch -* :code:`--locked` (since version 0.2.1) Use .locked file if it exists - * :code:`-p PACKAGE` Package to run * :code:`--profile PROFILE` Build profile to use @@ -818,8 +896,8 @@ Where options are: * :code:`-y` or :code:`--yes` Reply yes to all questions -drom sphinx -~~~~~~~~~~~~~ +main.exe sphinx +~~~~~~~~~~~~~~~~~ Generate documentation using sphinx @@ -845,7 +923,7 @@ This command performs the following actions: **USAGE** :: - drom sphinx [OPTIONS] + main.exe sphinx [OPTIONS] Where options are: @@ -854,8 +932,6 @@ Where options are: * :code:`--local` Create a local switch instead of using a global switch -* :code:`--locked` (since version 0.2.1) Use .locked file if it exists - * :code:`--profile PROFILE` Build profile to use * :code:`--switch OPAM_SWITCH` Use global switch SWITCH instead of creating a local switch @@ -867,8 +943,8 @@ Where options are: * :code:`-y` or :code:`--yes` Reply yes to all questions -drom test -~~~~~~~~~~~ +main.exe test +~~~~~~~~~~~~~~~ Run tests @@ -890,7 +966,7 @@ If the **--all** argument was provided, a file **_drom/dune-workspace.dev** is c **USAGE** :: - drom test [OPTIONS] + main.exe test [OPTIONS] Where options are: @@ -901,7 +977,57 @@ Where options are: * :code:`--local` Create a local switch instead of using a global switch -* :code:`--locked` (since version 0.2.1) Use .locked file if it exists +* :code:`--profile PROFILE` Build profile to use + +* :code:`--switch OPAM_SWITCH` Use global switch SWITCH instead of creating a local switch + +* :code:`--upgrade` Upgrade project files from drom.toml + +* :code:`-y` or :code:`--yes` Reply yes to all questions + + +main.exe toml +~~~~~~~~~~~~~~~ + +Read TOML files and print them back on stdout + + + +**DESCRIPTION** + + +Test the TOML parser/printer: + +**USAGE** +:: + + main.exe toml FILE [OPTIONS] + +Where options are: + + +* :code:`FILE` Parse FILE and write it back on stdout + + +main.exe top +~~~~~~~~~~~~~~ + +Run the ocaml toplevel + + +**USAGE** +:: + + main.exe top ARGUMENTS [OPTIONS] + +Where options are: + + +* :code:`ARGUMENTS` Provide arguments for the ocaml toplevel + +* :code:`--edition VERSION` Use this OCaml edition + +* :code:`--local` Create a local switch instead of using a global switch * :code:`--profile PROFILE` Build profile to use @@ -912,8 +1038,8 @@ Where options are: * :code:`-y` or :code:`--yes` Reply yes to all questions -drom tree -~~~~~~~~~~~ +main.exe tree +~~~~~~~~~~~~~~~ Display a tree of dependencies @@ -928,6 +1054,7 @@ Print the project as a tree of dependencies, i.e. dependencies are printed as br **EXAMPLE** :: + └──drom (/src/drom) └──drom_lib (/src/drom_lib) @@ -945,17 +1072,18 @@ Print the project as a tree of dependencies, i.e. dependencies are printed as br └── ocamlformat + **USAGE** :: - drom tree [OPTIONS] + main.exe tree [OPTIONS] Where options are: -drom uninstall -~~~~~~~~~~~~~~~~ +main.exe uninstall +~~~~~~~~~~~~~~~~~~~~ Uninstall the project from the project opam switch @@ -963,7 +1091,7 @@ Uninstall the project from the project opam switch **USAGE** :: - drom uninstall [OPTIONS] + main.exe uninstall [OPTIONS] Where options are: @@ -972,8 +1100,6 @@ Where options are: * :code:`--local` Create a local switch instead of using a global switch -* :code:`--locked` (since version 0.2.1) Use .locked file if it exists - * :code:`--profile PROFILE` Build profile to use * :code:`--switch OPAM_SWITCH` Use global switch SWITCH instead of creating a local switch @@ -983,8 +1109,8 @@ Where options are: * :code:`-y` or :code:`--yes` Reply yes to all questions -drom update -~~~~~~~~~~~~~ +main.exe update +~~~~~~~~~~~~~~~~~ Update packages in switch @@ -1010,7 +1136,7 @@ This command performs the following actions: **USAGE** :: - drom update [OPTIONS] + main.exe update [OPTIONS] Where options are: @@ -1019,8 +1145,6 @@ Where options are: * :code:`--local` Create a local switch instead of using a global switch -* :code:`--locked` (since version 0.2.1) Use .locked file if it exists - * :code:`--profile PROFILE` Build profile to use * :code:`--switch OPAM_SWITCH` Use global switch SWITCH instead of creating a local switch diff --git a/sphinx/conf.py b/sphinx/conf.py index 83986c77..deeee34e 100644 --- a/sphinx/conf.py +++ b/sphinx/conf.py @@ -220,4 +220,4 @@ # entry point for setup def setup(app): - app.add_stylesheet('css/fixes.css') + app.add_css_file('css/fixes.css') diff --git a/sphinx/reference.rst b/sphinx/reference.rst index 9fbdfbd6..72f6c4d3 100644 --- a/sphinx/reference.rst +++ b/sphinx/reference.rst @@ -340,6 +340,22 @@ if not specified: * :code:`synopsis`: the one-line description of the package * :code:`version`: the version of this package +For :code:`menhir` usage, you will find an optional :code:`[menhir]` talbe, +with the following fields: +* :code:`version`: the version of the menhir language configuration +* :code:`parser`: a table with the following fields: + * :code:`modules`: an array of string with all your menhir modules + * :code:`merge-into`: an optional string for the name of the merged module, + by default the last value in the :code:`modules` array if not provided + * :code:`tokens`: an optional to add the :code:`--external-tokens` flag + * :code:`flags`: an optional string array with menhir flags + * :code:`infer`: an optional boolean which adds the :code:`(infer )` + rule to the :code:`dune` file +* :code:`tokens`: an optional table that will add the `--only-tokens` flag + to the :code:`menhir` rule with the following fiels: + * :code:`modules`: a string array with all the modules to add to the rule + * :code:`flags`: an optional string array with all the flags to add to menhir + Finally, there is a table :code:`[fields]` within a package. Currently, the following fields are used by skeletons: diff --git a/sphinx/usecases.rst b/sphinx/usecases.rst index 099da9d3..7958ee6f 100644 --- a/sphinx/usecases.rst +++ b/sphinx/usecases.rst @@ -8,18 +8,52 @@ This sections describes how the handle common use cases with :code:`drom`. Using :code:`menhir` -------------------- -Whereas :code:`ocamlyacc` is the legacy parser generator for OCaml, +Whereas :code:`ocamlyacc` is the legacy parser generator for OCaml, :code:`menhir` is much more powerful and probably more prevalent nowadays. For trivial usage where there is a simple :code:`parser.mly` file in your package, setting:: - + generators = ["menhir"] -into the corresponding :code:`package.toml` will likely work. However, if +into the corresponding :code:`package.toml` will likely work. However, if you have multiple :code:`.mly` files, or -need to specify custom :code:`menhir` flags, you'll probably need to tune -the :code:`dune` generation. A good way to properly do that is to disable +need to specify custom :code:`menhir` flags, you'll probably need to use the +:code:`[menhir]` table in the corresponding :code:`package.toml`. For example:: + + [menhir] + version = "2.1" + parser = { + modules = ["tokens", "parser"], + merge-into = "parser", + tokens = "Tokens", + flags = [ "--table" ], + infer = true + } + tokens = { + modules = ["tokens"], + #flags = [] + } + + +This will generate the following rules in you :code:`dune` file:: + + (menhir + (modules tokens) + (flags --only-tokens)) + (menhir + (modules tokens parser) + (merge_into parser) + (flags --table --external-tokens Tokens) + (infer true)) + +and will add:: + + (using menhir 2.1) + +to the :code:`dune-project` file. + +You can also can tune the :code:`dune` generation. A good way to properly do that is to disable the default :code:`dune` generation for and add your own :code:`dune` stanzas for parsing generators. First, add :code:`(using menhir X.Y)` in the :code:`drom.toml`'s ':code:`dune-project-header` field. For example:: @@ -35,8 +69,8 @@ Then replace the :code:`generators = ["menhir"]` line by the following:: generators = [] -in :code:`package.toml` to disable the default :code:`dune` stanzas generation. -Finally, add the following :code:`dune` stanzas to your +in :code:`package.toml` to disable the default :code:`dune` stanzas generation. +Finally, add the following :code:`dune` stanzas to your :code:`dune-trailer` field:: [fields] @@ -56,4 +90,4 @@ Finally, add the following :code:`dune` stanzas to your Of course, this is just a basic tuning and you can modify the flags or targets as needed. The overall result will likely fit in most of :code:`menhir` usages in :code:`drom` projects waiting for a better -:code:`menhir` support. \ No newline at end of file +:code:`menhir` support. diff --git a/src/drom_lib/dune.ml b/src/drom_lib/dune.ml index e8695dea..3dc7c3e0 100644 --- a/src/drom_lib/dune.ml +++ b/src/drom_lib/dune.ml @@ -25,7 +25,58 @@ let package_dune_files package = let p_generators = match package.p_generators with | None -> StringSet.of_list [ "ocamllex"; "ocamlyacc" ] - | Some generators -> generators + | Some generators -> + begin match package.p_menhir with + | Some { parser; tokens = menhir_tokens; _ } + when StringSet.mem "menhir" generators -> + let { modules; tokens; merge_into; flags; infer } = parser in + Printf.bprintf b "(menhir\n (modules"; + List.iter (fun module_ -> Printf.bprintf b " %s" module_) modules; + Printf.bprintf b ")"; + begin match merge_into with + | Some merge_into -> + Printf.bprintf b "\n (merge_into %s)" merge_into + | None -> + if List.length modules > 1 then + let merge_into = List.rev modules |> List.hd in + Printf.bprintf b "\n (merge_into %s)" merge_into + end; + begin match flags with + | Some flags -> + Printf.bprintf b "\n (flags"; + List.iter (fun flag -> Printf.bprintf b " %s" flag) flags; + begin match tokens with + | Some tokens -> Printf.bprintf b "--external-token %s" tokens + | None -> () + end; + Printf.bprintf b ")"; + | None -> () + end; + begin match infer with + | Some infer -> Printf.bprintf b "\n (infer %B)" infer + | None -> () + end; + Printf.bprintf b ")\n"; + begin match menhir_tokens with + | Some { modules; flags; } -> + Printf.bprintf b "(menhir (modules"; + List.iter (fun module_ -> Printf.bprintf b " %s" module_) modules; + Printf.bprintf b ")"; + begin match flags with + | Some flags -> + Printf.bprintf b "\n (flags"; + List.iter (fun flag -> Printf.bprintf b " %s" flag) flags; + Printf.bprintf b " --only-tokens)"; + | None -> () + end; + Printf.bprintf b ")\n" + | None -> () + end + | Some _ -> + Printf.eprintf "'menhir' table defined without menhir generator" + | None -> () + end; + generators in ( match Sys.readdir package.dir with | exception _ -> () @@ -56,15 +107,18 @@ let package_dune_files package = Printf.bprintf b "\n (mode %s)" mode; Printf.bprintf b ")\n" end else if StringSet.mem "menhir" p_generators then begin - Printf.bprintf b "(menhir (modules %s)" - (Filename.chop_suffix file ".mly"); - List.iter - (fun ext -> - match StringMap.find ("menhir-" ^ ext) package.p_fields with - | exception Not_found -> () - | s -> Printf.bprintf b "\n (%s %s)" ext s ) - [ "flags"; "into"; "infer" ]; - Printf.bprintf b ")\n" + match package.p_menhir with + | None -> + Printf.bprintf b "(menhir (modules %s)" + (Filename.chop_suffix file ".mly"); + List.iter + (fun ext -> + match StringMap.find ("menhir-" ^ ext) package.p_fields with + | exception Not_found -> () + | s -> Printf.bprintf b "\n (%s %s)" ext s ) + [ "flags"; "into"; "infer" ]; + Printf.bprintf b ")\n" + | Some _ -> () end else Printf.eprintf "no generator for %s\n%!" file end ) @@ -148,7 +202,11 @@ let packages p = (* If menhir is used as a generator, prevents dune from modifying dune-project by adding this line ourselves. *) if StringSet.mem "menhir" p.generators then - Buffer.add_string b "(using menhir 2.0)\n"; + begin match p.menhir_version with + | Some version -> + Printf.bprintf b "(using menhir %s)\n" version + | None -> Buffer.add_string b "(using menhir 2.0)\n" + end; List.iter add_package p.packages; Buffer.contents b diff --git a/src/drom_lib/globals.ml b/src/drom_lib/globals.ml index af207824..7e89d298 100644 --- a/src/drom_lib/globals.ml +++ b/src/drom_lib/globals.ml @@ -153,6 +153,7 @@ let rec dummy_project = share_dirs = [ "share" ]; year = (Misc.date ()).Unix.tm_year; generators = StringSet.empty; + menhir_version = None; dune_version = current_dune_version ; project_create = false ; } @@ -175,6 +176,7 @@ and dummy_package = p_fields = StringMap.empty; p_skeleton = None; p_generators = None; + p_menhir = None; p_skip = None; p_optional = None; p_preprocess = None diff --git a/src/drom_lib/package.ml b/src/drom_lib/package.ml index 50acb8eb..898d7a59 100644 --- a/src/drom_lib/package.ml +++ b/src/drom_lib/package.ml @@ -193,6 +193,65 @@ let stringSet_encoding = let fields_encoding = EzToml.ENCODING.stringMap EzToml.string_encoding +let menhir_parser_encoding = + EzToml.encoding + ~to_toml:(fun { modules; tokens; merge_into; flags; infer } -> + let table = EzToml.empty + |> EzToml.put_string_list [ "modules" ] modules + |> EzToml.put_string_option [ "tokens" ] tokens + |> EzToml.put_string_option [ "merge-into" ] merge_into + |> EzToml.put_string_list_option [ "flags" ] flags + |> EzToml.put_bool_option [ "infer" ] infer + in + TTable table) + ~of_toml:(fun ~key v -> + match v with + | TTable table -> + let modules = EzToml.get_string_list_default table [ "modules" ] [ "parser" ] in + let tokens = EzToml.get_string_option table [ "tokens" ] in + let merge_into = EzToml.get_string_option table [ "merge-into" ] in + let flags = EzToml.get_string_list_option table [ "flags" ] in + let infer = EzToml.get_bool_option table [ "infer" ] in + { modules; tokens; merge_into; flags; infer; } + | _ -> + EzToml.expecting_type "table" key) + +let menhir_tokens_encoding = + EzToml.encoding + ~to_toml:(fun { modules; flags } -> + let table = EzToml.empty + |> EzToml.put_string_list [ "modules" ] modules + |> EzToml.put_string_list_option [ "flags" ] flags + in + TTable table) + ~of_toml:(fun ~key v -> + match v with + | TTable table -> + let modules = EzToml.get_string_list_default table [ "modules"] [ "tokens" ] in + let flags = EzToml.get_string_list_option table [ "flags" ] in + { modules; flags } + | _ -> + EzToml.expecting_type "table" key) + +let menhir_encoding = + EzToml.encoding + ~to_toml:(fun { version; parser; tokens } -> + let table = EzToml.empty + |> EzToml.put_string [ "version" ] version + |> EzToml.put_encoding menhir_parser_encoding [ "parser" ] parser + |> EzToml.put_encoding_option menhir_tokens_encoding [ "encoding" ] tokens + in + TTable table) + ~of_toml:(fun ~key v -> + match v with + | TTable table -> + let version = EzToml.get_string table [ "version" ] in + let parser = EzToml.get_encoding menhir_parser_encoding table [ "parser" ] in + let tokens = EzToml.get_encoding_option menhir_tokens_encoding table [ "tokens" ] in + { version; parser; tokens; } + | _ -> + EzToml.expecting_type "talbe" key) + let to_string pk = EzToml.CONST.( s_ @@ -226,6 +285,15 @@ let to_string pk = ] ~default:{|generators = [ "ocamllex", "menhir" ]|} (encoding_option stringSet_encoding pk.p_generators); + option "menhir" + ~comment: + [ "menhir options for the package"; + "Example:"; + {|version = "2.0"|}; + {|parser = { modules = ["parser"]; tokens = "Tokens" }|}; + {|tokens = { modules = ["tokens"]}|}; + ] + (encoding_option menhir_encoding pk.p_menhir); option "pack-modules" ~comment: [ "whether all modules should be packed/wrapped (default is true)" ] @@ -366,6 +434,9 @@ let of_toml ?default ?p_file table = EzToml.get_encoding_option stringSet_encoding table [ "generators" ] ?default:default.p_generators in + let p_menhir = + EzToml.get_encoding_option menhir_encoding table [ "menhir" ] + in let p_fields = EzToml.get_encoding_default fields_encoding table [ "fields" ] StringMap.empty @@ -400,6 +471,7 @@ let of_toml ?default ?p_file table = p_fields; p_skeleton; p_generators; + p_menhir; p_skip; p_optional } diff --git a/src/drom_lib/project.ml b/src/drom_lib/project.ml index e938780e..5db78266 100644 --- a/src/drom_lib/project.ml +++ b/src/drom_lib/project.ml @@ -531,6 +531,28 @@ let project_of_toml ?file ?default table = generators := StringSet.union !generators p_generators ) packages; let generators = !generators in + let menhir_version = + List.fold_left + (fun acc p -> + match p.p_menhir with + | None -> acc + | Some { version; _ } -> + match acc with + | None -> + begin try Scanf.sscanf version "%d.%d" (fun _ _ -> ()) + with Scanf.Scan_failure s -> + Error.raise "In package %s, invalid menhir version: %s (error: %s)" + p.name version s + end; + Some version + | Some acc_version -> + if version <> acc_version then + Error.raise "In package %s, menhir version is different from other packages \ + got %s when expecting %s" p.name version acc_version; + acc) + None + packages + in let year = EzToml.get_int_default table [ project_key; "year" ] d.year in (* Check dune specification consistency : @@ -637,6 +659,7 @@ let project_of_toml ?file ?default table = profile; fields; generators; + menhir_version; year; dune_version; project_create; diff --git a/src/drom_lib/types.ml b/src/drom_lib/types.ml index b0257a93..f63933c2 100644 --- a/src/drom_lib/types.ml +++ b/src/drom_lib/types.ml @@ -42,6 +42,28 @@ type dependency = dep_pin: string option; } +type menhir_parser = + { + modules: string list; + tokens: string option; + merge_into: string option; + flags: string list option; + infer: bool option; + } + +type menhir_tokens = + { + modules: string list; + flags: string list option; + } + +type menhir = + { + version: string; + parser: menhir_parser; + tokens: menhir_tokens option; + } + type package = { name : string; mutable dir : string; @@ -59,6 +81,7 @@ type package = mutable p_gen_version : string option; mutable p_fields : string StringMap.t; mutable p_generators : StringSet.t option; + mutable p_menhir : menhir option; mutable p_file : string option; mutable p_skip : string list option; mutable p_optional : bool option; @@ -71,6 +94,7 @@ and project = mutable packages : package list; mutable file : string option; (* name of the file *) mutable generators : StringSet.t; (* sub-packages *) + mutable menhir_version : string option; (* from sub-packages *) (* common fields *) mutable skeleton : string option; project_share_repo : string option ;