├── calc.opam ├── test ├── TestCalc.re ├── TestFramework.re ├── TestCalculator.re └── dune ├── dune ├── dune-project ├── library ├── Calculator.re └── dune ├── .gitignore ├── executable ├── dune └── CalcApp.re ├── readme.md └── package.json /calc.opam: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/TestCalc.re: -------------------------------------------------------------------------------- 1 | TestFramework.cli(); 2 | -------------------------------------------------------------------------------- /dune: -------------------------------------------------------------------------------- 1 | (dirs (:standard \ node_modules \ _esy)) -------------------------------------------------------------------------------- /dune-project: -------------------------------------------------------------------------------- 1 | (lang dune 1.6) 2 | (name calc) -------------------------------------------------------------------------------- /library/Calculator.re: -------------------------------------------------------------------------------- 1 | let add = (a, b) => a + b; 2 | let subtract = (a, b) => a - b; 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | npm-debug.log 2 | .merlin 3 | yarn-error.log 4 | node_modules 5 | node_modules/ 6 | _build 7 | _release 8 | _esy/ 9 | calc.install 10 | .DS_Store 11 | *.install 12 | -------------------------------------------------------------------------------- /test/TestFramework.re: -------------------------------------------------------------------------------- 1 | include Rely.Make({ 2 | let config = 3 | Rely.TestFrameworkConfig.initialize({ 4 | snapshotDir: "path/to/test/lib/__snapshots__", 5 | projectDir: "path/to/your/project", 6 | }); 7 | }); 8 | -------------------------------------------------------------------------------- /test/TestCalculator.re: -------------------------------------------------------------------------------- 1 | open TestFramework; 2 | 3 | describe("Calculator.add", ({test}) => 4 | Calc.( 5 | test("add(1 , 3) should equal 4", ({expect}) => 6 | expect.int(Calculator.add(1, 3)).toBe(4) 7 | ) 8 | ) 9 | ); 10 | -------------------------------------------------------------------------------- /library/dune: -------------------------------------------------------------------------------- 1 | 2 | ; !!!! This dune file is generated from the package.json file by pesy. If you modify it by hand 3 | ; !!!! your changes will be undone! Instead, edit the package.json and then rerun 'esy pesy' at the project root. 4 | ; !!!! If you want to stop using pesy and manage this file by hand, change pacakge.json's 'esy.build' command to: refmterr dune build -p calc 5 | (library 6 | ; The namespace that other packages/libraries will access this library through 7 | (name Calc) 8 | ; Other libraries list this name in their package.json 'require' field to use this library. 9 | (public_name calc.lib) 10 | ) -------------------------------------------------------------------------------- /executable/dune: -------------------------------------------------------------------------------- 1 | 2 | ; !!!! This dune file is generated from the package.json file by pesy. If you modify it by hand 3 | ; !!!! your changes will be undone! Instead, edit the package.json and then rerun 'esy pesy' at the project root. 4 | ; !!!! If you want to stop using pesy and manage this file by hand, change pacakge.json's 'esy.build' command to: refmterr dune build -p calc 5 | (executable 6 | ; The entrypoint module 7 | (name CalcApp) ; From package.json main field 8 | ; The name of the executable (runnable via esy x CalcApp.exe) 9 | (public_name CalcApp.exe) ; From package.json name field 10 | (libraries cmdliner pastel.lib calc.lib ) ; From package.json require field (array of strings) 11 | ) -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # calc 2 | 3 | This is companion code for the blogpost [rolflekang.com/creating-a-cli-with-reason-native](https://rolflekang.com/creating-a-cli-with-reason-native). 4 | 5 | ## Developing: 6 | 7 | ```shell 8 | npm install -g esy 9 | git clone git@github.com:relekang/reason-calculator.git 10 | esy install 11 | esy build 12 | ``` 13 | 14 | ## Running Binary: 15 | 16 | After building the project, you can run the main binary that is produced. 17 | 18 | ```shell 19 | esy x CalcApp.exe 20 | ``` 21 | 22 | ## Running Tests: 23 | 24 | ```shell 25 | # Runs the "test" command in `package.json`. 26 | esy test 27 | ``` 28 | 29 | ## Creating release binary for current env 30 | 31 | ```shell 32 | esy test 33 | ``` 34 | 35 | -------------------------------------------------------------------------------- /test/dune: -------------------------------------------------------------------------------- 1 | 2 | ; !!!! This dune file is generated from the package.json file by pesy. If you modify it by hand 3 | ; !!!! your changes will be undone! Instead, edit the package.json and then rerun 'esy pesy' at the project root. 4 | ; !!!! If you want to stop using pesy and manage this file by hand, change pacakge.json's 'esy.build' command to: refmterr dune build -p calc 5 | (executable 6 | ; The entrypoint module 7 | (name TestCalc) ; From package.json main field 8 | ; The name of the executable (runnable via esy x TestCalc.exe) 9 | (public_name TestCalc.exe) ; From package.json name field 10 | (libraries calc.lib rely.lib ) ; From package.json require field (array of strings) 11 | (ocamlopt_flags ( -linkall -g )) ; From package.json ocamloptFlags field 12 | ) -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "calc", 3 | "version": "0.0.0", 4 | "description": "My Project", 5 | "esy": { 6 | "build": "pesy", 7 | "release": { "releasedBinaries": [ "CalcApp.exe" ] } 8 | }, 9 | "buildDirs": { 10 | "test": { 11 | "require": [ "calc.lib", "rely.lib" ], 12 | "ocamloptFlags": ["-linkall", "-g"], 13 | "main": "TestCalc", 14 | "name": "TestCalc.exe" 15 | }, 16 | "library": { "name": "calc.lib", "namespace": "Calc" }, 17 | "executable": { 18 | "require": [ "cmdliner", "pastel.lib", "calc.lib" ], 19 | "main": "CalcApp", 20 | "name": "CalcApp.exe" 21 | } 22 | }, 23 | "scripts": { 24 | "pesy": "bash -c 'env PESY_MODE=update pesy'", 25 | "test": "esy x TestCalc.exe" 26 | }, 27 | "dependencies": { 28 | "@esy-ocaml/reason": "*", 29 | "@opam/cmdliner": "1.0.3", 30 | "@opam/dune": ">=1.6.0", 31 | "@reason-native/pastel": "^0.1.0", 32 | "@reason-native/rely": "^1.1.0", 33 | "ocaml": "^4.4.0", 34 | "pesy": "*", 35 | "refmterr": "*" 36 | }, 37 | "devDependencies": { "@opam/merlin": "*", "isexe": "^2.0.0" } 38 | } 39 | -------------------------------------------------------------------------------- /executable/CalcApp.re: -------------------------------------------------------------------------------- 1 | open Cmdliner; 2 | open Calc; 3 | 4 | let version = "0.0.0"; 5 | 6 | let print_result = result => 7 | Pastel.( 8 | 9 | "Result: " 10 | {string_of_int(result)} 11 | 12 | ) 13 | |> print_endline; 14 | 15 | let add = { 16 | let x = 17 | Arg.( 18 | value & pos(0, int, 0) & info([], ~docv="number", ~docs="First number") 19 | ); 20 | let y = 21 | Arg.( 22 | value & pos(1, int, 0) & info([], ~docv="number", ~doc="Second number") 23 | ); 24 | ( 25 | Term.(const((x, y) => print_result(Calculator.add(x, y))) $ x $ y), 26 | Term.info("add"), 27 | ); 28 | }; 29 | 30 | let subtract = { 31 | let x = 32 | Arg.( 33 | value & pos(0, int, 0) & info([], ~docv="number", ~doc="First number") 34 | ); 35 | let y = 36 | Arg.( 37 | value & pos(1, int, 0) & info([], ~docv="number", ~doc="Second number") 38 | ); 39 | ( 40 | Term.(const((x, y) => Calculator.subtract(x, y) |> print_result) $ x $ y), 41 | Term.info("subtract"), 42 | ); 43 | }; 44 | 45 | let default = ( 46 | Term.(ret(const(_ => `Help((`Pager, None))) $ const())), 47 | Term.info("calc", ~version), 48 | ); 49 | 50 | let _ = Term.eval_choice(default, [add, subtract]) |> Term.exit; 51 | --------------------------------------------------------------------------------