You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
451 lines
9.3 KiB
451 lines
9.3 KiB
let version = Fnm.Fnm__Package.version; |
|
|
|
let runCmd = lwt => { |
|
lwt |
|
|> Lwt_main.run |
|
|> ( |
|
fun |
|
| Error(err_code) => exit(err_code) |
|
| Ok () => () |
|
); |
|
}; |
|
|
|
module Commands = { |
|
let exec = (version, useFileVersion, cmd) => |
|
Exec.run(~cmd=Array.of_list(cmd), ~version, ~useFileVersion) |> runCmd; |
|
let use = (version, quiet) => Use.run(~version, ~quiet) |> runCmd; |
|
let current = () => Current.run() |> runCmd; |
|
let alias = (version, name) => Alias.run(~name, ~version) |> runCmd; |
|
let default = version => Alias.run(~name="default", ~version) |> runCmd; |
|
let listRemote = version => ListRemote.run(~version) |> runCmd; |
|
let listLocal = () => ListLocal.run() |> runCmd; |
|
let install = version => Install.run(~version) |> runCmd; |
|
let uninstall = version => Uninstall.run(~version) |> runCmd; |
|
let env = |
|
( |
|
isFishShell, |
|
isMultishell, |
|
nodeDistMirror, |
|
fnmDir, |
|
shell, |
|
useOnCd, |
|
logLevel, |
|
) => |
|
Env.run( |
|
~forceShell=Fnm.System.Shell.(isFishShell ? Some(Fish) : shell), |
|
~multishell=isMultishell, |
|
~nodeDistMirror, |
|
~fnmDir, |
|
~useOnCd, |
|
~logLevel, |
|
) |
|
|> runCmd; |
|
}; |
|
|
|
open Cmdliner; |
|
|
|
let help_secs = [ |
|
`S(Manpage.s_common_options), |
|
`S(Manpage.s_environment), |
|
`P("These options are common to all commands."), |
|
`S("MORE HELP"), |
|
`P("Use `$(mname) $(i,COMMAND) --help' for help on a single command."), |
|
`Noblank, |
|
`S(Manpage.s_bugs), |
|
`P("File bug reports at https://github.com/Schniz/fnm"), |
|
]; |
|
|
|
let envs = |
|
Fnm.Config.getDocs() |
|
|> List.map(envVar => |
|
Fnm.Config.( |
|
Term.env_info( |
|
~doc= |
|
Printf.sprintf( |
|
"%s\ndefaults to \"%s\"", |
|
envVar.doc, |
|
envVar.default, |
|
), |
|
envVar.name, |
|
) |
|
) |
|
); |
|
|
|
let install = { |
|
let doc = "Install another node version"; |
|
let man = help_secs; |
|
let sdocs = Manpage.s_common_options; |
|
|
|
let selectedVersion = { |
|
let doc = "Install another version specified in $(docv)."; |
|
Arg.( |
|
value & pos(0, some(string), None) & info([], ~docv="VERSION", ~doc) |
|
); |
|
}; |
|
|
|
( |
|
Term.(const(Commands.install) $ selectedVersion), |
|
Term.info( |
|
"install", |
|
~envs, |
|
~version, |
|
~doc, |
|
~exits=Term.default_exits, |
|
~man, |
|
~sdocs, |
|
), |
|
); |
|
}; |
|
|
|
let uninstall = { |
|
let doc = "Uninstall a node version"; |
|
let sdocs = Manpage.s_common_options; |
|
let man = help_secs; |
|
|
|
let selectedVersion = { |
|
let doc = "Uninstall the node version specified in $(docv)."; |
|
Arg.( |
|
required |
|
& pos(0, some(string), None) |
|
& info([], ~docv="VERSION", ~doc) |
|
); |
|
}; |
|
|
|
( |
|
Term.(const(Commands.uninstall) $ selectedVersion), |
|
Term.info( |
|
"uninstall", |
|
~envs, |
|
~version, |
|
~doc, |
|
~exits=Term.default_exits, |
|
~man, |
|
~sdocs, |
|
), |
|
); |
|
}; |
|
|
|
let listLocal = { |
|
let doc = "List all the installed versions"; |
|
let sdocs = Manpage.s_common_options; |
|
let man = help_secs; |
|
|
|
( |
|
Term.(app(const(Commands.listLocal), const())), |
|
Term.info( |
|
"ls", |
|
~envs, |
|
~version, |
|
~doc, |
|
~exits=Term.default_exits, |
|
~man, |
|
~sdocs, |
|
), |
|
); |
|
}; |
|
|
|
let listRemote = { |
|
let doc = "List all the versions upstream"; |
|
let sdocs = Manpage.s_common_options; |
|
let man = help_secs; |
|
|
|
let selectedVersion = { |
|
let doc = "Filter by specific $(docv)."; |
|
Arg.( |
|
value & pos(0, some(string), None) & info([], ~docv="VERSION", ~doc) |
|
); |
|
}; |
|
|
|
( |
|
Term.(const(Commands.listRemote) $ selectedVersion), |
|
Term.info( |
|
"ls-remote", |
|
~version, |
|
~envs, |
|
~doc, |
|
~exits=Term.default_exits, |
|
~man, |
|
~sdocs, |
|
), |
|
); |
|
}; |
|
|
|
let use = { |
|
let doc = "Switch to another installed node version"; |
|
let man = help_secs; |
|
let sdocs = Manpage.s_common_options; |
|
|
|
let quiet = { |
|
let doc = "Don't print stuff"; |
|
Arg.(value & flag & info(["quiet"], ~doc)); |
|
}; |
|
|
|
let selectedVersion = { |
|
let doc = "Switch to version $(docv).\nLeave empty to look for value from an `.nvmrc` or `.node-version` file"; |
|
Arg.( |
|
value & pos(0, some(string), None) & info([], ~docv="VERSION", ~doc) |
|
); |
|
}; |
|
|
|
( |
|
Term.(const(Commands.use) $ selectedVersion $ quiet), |
|
Term.info( |
|
"use", |
|
~envs, |
|
~version, |
|
~doc, |
|
~exits=Term.default_exits, |
|
~man, |
|
~sdocs, |
|
), |
|
); |
|
}; |
|
|
|
let current = { |
|
let doc = "Display currently activated version"; |
|
let sdocs = Manpage.s_common_options; |
|
let man = help_secs; |
|
|
|
( |
|
Term.(app(const(Commands.current), const())), |
|
Term.info( |
|
"current", |
|
~envs, |
|
~version, |
|
~doc, |
|
~exits=Term.default_exits, |
|
~man, |
|
~sdocs, |
|
), |
|
); |
|
}; |
|
|
|
let alias = { |
|
let doc = "Alias a version"; |
|
let sdocs = Manpage.s_common_options; |
|
let man = help_secs; |
|
|
|
let selectedVersion = { |
|
let doc = "The version to be aliased"; |
|
Arg.( |
|
required |
|
& pos(0, some(string), None) |
|
& info([], ~docv="VERSION", ~doc) |
|
); |
|
}; |
|
|
|
let aliasName = { |
|
let doc = "The alias name"; |
|
Arg.( |
|
required & pos(1, some(string), None) & info([], ~docv="NAME", ~doc) |
|
); |
|
}; |
|
|
|
( |
|
Term.(const(Commands.alias) $ selectedVersion $ aliasName), |
|
Term.info( |
|
"alias", |
|
~envs, |
|
~version, |
|
~doc, |
|
~exits=Term.default_exits, |
|
~man, |
|
~sdocs, |
|
), |
|
); |
|
}; |
|
|
|
let exec = { |
|
let doc = "Execute a binary with the current Node.js in the PATH"; |
|
let man = help_secs; |
|
let sdocs = Manpage.s_common_options; |
|
|
|
let usingVersion = { |
|
let doc = "Use a specific $(docv)"; |
|
Arg.(value & opt(some(string), None) & info(["using"], ~doc)); |
|
}; |
|
|
|
let usingFileVersion = { |
|
let doc = "Use a version from a version file"; |
|
Arg.(value & flag & info(["using-file"], ~doc)); |
|
}; |
|
|
|
let command = { |
|
let doc = "The $(docv) to execute"; |
|
Arg.(non_empty & pos_all(string, []) & info([], ~docv="COMMAND", ~doc)); |
|
}; |
|
|
|
( |
|
Term.(const(Commands.exec) $ usingVersion $ usingFileVersion $ command), |
|
Term.info( |
|
"exec", |
|
~envs, |
|
~version, |
|
~doc, |
|
~exits=Term.default_exits, |
|
~man, |
|
~sdocs, |
|
), |
|
); |
|
}; |
|
|
|
let default = { |
|
let doc = "Alias a version as default"; |
|
let man = help_secs; |
|
let sdocs = Manpage.s_common_options; |
|
|
|
let selectedVersion = { |
|
let doc = "The version to be aliased as default"; |
|
Arg.( |
|
required |
|
& pos(0, some(string), None) |
|
& info([], ~docv="VERSION", ~doc) |
|
); |
|
}; |
|
|
|
( |
|
Term.(const(Commands.default) $ selectedVersion), |
|
Term.info( |
|
"default", |
|
~envs, |
|
~version, |
|
~doc, |
|
~exits=Term.default_exits, |
|
~man, |
|
~sdocs, |
|
), |
|
); |
|
}; |
|
|
|
let env = { |
|
let doc = "Show env configurations"; |
|
let sdocs = Manpage.s_common_options; |
|
let man = help_secs; |
|
|
|
let isFishShell = { |
|
let doc = "Output an env configuration for fish shell."; |
|
Arg.(value & flag & info(["fish"], ~doc)); |
|
}; |
|
|
|
let shell = { |
|
open Fnm.System.Shell; |
|
let doc = "Specifies a specific shell type. If omitted, it will be inferred based on the process tree. $(docv)"; |
|
let shellChoices = |
|
Arg.enum([("fish", Fish), ("bash", Bash), ("zsh", Zsh)]); |
|
Arg.(value & opt(some(shellChoices), None) & info(["shell"], ~doc)); |
|
}; |
|
|
|
let nodeDistMirror = { |
|
let doc = "https://nodejs.org/dist mirror"; |
|
Arg.( |
|
value |
|
& opt(string, "https://nodejs.org/dist") |
|
& info(["node-dist-mirror"], ~doc) |
|
); |
|
}; |
|
|
|
let fnmDir = { |
|
let doc = "The directory to store internal fnm data"; |
|
Arg.( |
|
value |
|
& opt(string, Fnm.Config.FNM_DIR.get()) |
|
& info(["fnm-dir"], ~doc) |
|
); |
|
}; |
|
|
|
let isMultishell = { |
|
let doc = "Allow different node versions for each shell"; |
|
Arg.(value & flag & info(["multi"], ~doc)); |
|
}; |
|
|
|
let useOnCd = { |
|
let doc = "Hook into the shell `cd` and automatically use the specified version for the project"; |
|
Arg.(value & flag & info(["use-on-cd"], ~doc)); |
|
}; |
|
|
|
let logLevel = { |
|
let doc = "The log level of fnm commands, can be 'quiet', 'error' or 'all'"; |
|
Arg.( |
|
value |
|
& opt( |
|
enum([ |
|
("quiet", Fnm.LogLevel.Quiet), |
|
("error", Fnm.LogLevel.Error), |
|
("info", Fnm.LogLevel.Info), |
|
("all", Fnm.LogLevel.Debug), |
|
("debug", Fnm.LogLevel.Debug), |
|
]), |
|
Fnm.Config.FNM_LOGLEVEL.get(), |
|
) |
|
& info(["log-level"], ~doc) |
|
); |
|
}; |
|
|
|
( |
|
Term.( |
|
const(Commands.env) |
|
$ isFishShell |
|
$ isMultishell |
|
$ nodeDistMirror |
|
$ fnmDir |
|
$ shell |
|
$ useOnCd |
|
$ logLevel |
|
), |
|
Term.info( |
|
"env", |
|
~envs, |
|
~version, |
|
~doc, |
|
~exits=Term.default_exits, |
|
~man, |
|
~sdocs, |
|
), |
|
); |
|
}; |
|
|
|
let defaultCmd = { |
|
let doc = "Manage Node.js installations"; |
|
let sdocs = Manpage.s_common_options; |
|
let man = help_secs; |
|
( |
|
Term.(ret(const(_ => `Help((`Pager, None))) $ const())), |
|
Term.info( |
|
"fnm", |
|
~envs, |
|
~version, |
|
~doc, |
|
~exits=Term.default_exits, |
|
~man, |
|
~sdocs, |
|
), |
|
); |
|
}; |
|
|
|
let argv = |
|
Sys.argv |
|
|> Array.map(arg => |
|
switch (arg) { |
|
| "-v" => "--version" |
|
| x => x |
|
} |
|
); |
|
|
|
let _ = |
|
Term.eval_choice( |
|
defaultCmd, |
|
[ |
|
install, |
|
uninstall, |
|
current, |
|
use, |
|
alias, |
|
default, |
|
listLocal, |
|
listRemote, |
|
env, |
|
exec, |
|
], |
|
~argv, |
|
) |
|
|> Term.exit;
|
|
|