Git Product home page Git Product logo

configure_me's People

Contributors

akloboucnik avatar kixunil avatar romanz avatar tcharding avatar zaijo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

configure_me's Issues

Document default values

Document default values in help and man pages. This will need doc_default to work with man pages.

  • doc_default
  • help
  • man

debconf support

It'd be neat if template files and scripts could be generated from the configuration.

When file list is implemented in build script, then it could auto-generate the config file too. That'd help a lot.

Split data validation from parsing

By splitting data validation and putting it into a separate library, it'd be possible to share the validation code between codegen and generated code. It might be also useful for other projects.

Consider moving to xtask

xtask pattern could improve compilation times for libraries. However it's not entirely suited for this kind of optimization. So instead we can put codegen into cfg_me and if it's installed just run it, if it's not run xtask which will do the same thing.

And make sure cfg_me is versioned similarly to cargo +version ... (but maybe scan the project file for version instead?) so that we can make sure codegen matches.

Subcommands

Support subcommands like e.g. commit is a subcommand of git.

Example input:

[general]
# global options

# This is a global param - given to program in the form of cmd --foo subcmd
# We could later support cmd subcmd --foo
[[param]]
name = "foo"
type = "String"
# ...

# same as above an be done with switch

# We use subcmd instead of subcommand to keep it reasonably short because it will be repeated
[subcmd.subcmdname.general]
# Only support these two for now, other things available above are mostly non-sensical here
summary = "This command does something"
doc = "Long explanation of what this command is all about..."
# LATER we could also support include = "file-relative-to-current"
# included files should probably only support params and switches

# works exactly the same as in top-level
[[subcmd.subcmdname.param]]
name = "bar"
type = "String"

# switch is supported here as well
# nested subcommand is also supported

The generated code will look something like this:

enum Subcommand {
    Subcmdname(subcmdname::Config),
}

// recursively generates almost the same thing as top-level
mod subcmdname {
    struct Config {
        // no _program_name here, it's pointless
        bar: String,
    }

    // also has raw module like the top-level
    mod raw {
    }
}

Specification parsing code will get subcmd: HashMap<Ident, Subcommand> field.

struct Subcommand {
    global: SubcommandGlobal,
    param: Vec<Param>,
    switch: Vec<Switch>,
}

Difficult stuff:

  • How to parse and process config files for subcommands? Suggestion: don't support in initial impl
  • How to process env vars for config files? Suggestion: don't support in initial impl
  • Should subcommand be inside Config, or outside? The advantage of being outside is it can get global config without self-reference but maybe that's not useful as immutable references will most likely be used?
  • Should we support more straightforward design as clap does? If there are multiple nested subcommands and mid-commmands don't have any options, then avoiding the struct would lead to easier-to-write code, although harder-to-refactor. Maybe instead have Subcmdname { config: subcmdname::Config, subcmd: subcmdname::Subcommand }, then matching code can just ignore empty struct. This obviously implies "outside" for the question about.

Screwed up merging

Merging of conf files is illogical, error-prone, confusing and possibly buggy. Tests need to be written and merge_in modified to override &mut self.

Add list of config files to config spec and document them

Currently man page doesn't include FILES section, so config files aren't documented.

  • Add config_files option to General
  • Make sure FILES section is in man crate
  • Add FILES section to man page
  • Implement Config::including_default_config_files() to make use of the information provided in config spec

Man page generation

  • Wait for merging of description section
  • Wait for release of man with description section
  • Implement description
  • Verify that the resulting man page conforms to standards
  • Add option to override binary name
  • Add ability to write to custom destination as well as default one

Change sequence to map

Consider changing sequence to map in specification Toml input. That means:

[[param]]
name = "foo"
type = "String"

would become:

[param.foo]
type = "String"

Alternative that makes Toml input map more directly to Rust code, catching duplicates much more early:

[field.foo]
cli = "param" # other possibilities: switch, disabled
type = "String"

So far I think I prefer the less verbose option, duplicate detection can be written differently.

@dr-orlovsky @romanz would appreciate your thoughts.

Toml sections?

Sorry if I missed something, but looking in the docs I have not found possibility to use multiple configuration sections, like

[networking]
ip = "192.168.0.1"
port = 8000

[cli]
enable = true

Custom merge function

It should be possible to provide custom merge function for cases when value of a field comes from two sources.

Consider support out_file setting

set out_dir like pb builder's style:Builder::out_dir.


fn path_in_out_dir<P: AsRef<Path>>(file_name: P) -> Result<PathBuf, Error> {
    //TODO  pass the out_dir config
    let mut out: PathBuf = std::env::var_os("OUT_DIR").ok_or(ErrorData::MissingOutDir)?.into();
    out.push(file_name);

    Ok(out)
}

Re-evaluate proc macro approach

Pros:

  • Easy to use
  • User can immediately see the struct
  • Syntax checking of type names etc by rustc
  • Possible to add other derives

Cons:

  • possibly harder to debug (can be resolved by some attribute?)
  • possibly weird man page generation (have filename in the source code?)
  • hygiene?

Native support for collecting multiple arguments into a collection

It's currently possible to collect multiple arguments by using custom merge_fn, but that would require a newtype wrapper around the collection that implements ParseArg by inserting it into the collection. It might be nicer to avoid forcing everyone into implementing it by either:

  • Providing a generic version of it
  • Adding an option to specification and modifying codegen
  • Possibly adding a shortcut option, but internally using that wrapper type.

Bump Toml version

Since a new version of Toml came out, it creates duplicates in crates that use the new version.

Nicer help output

Currently help wraps at 80 chars, which is a hard-coded value. It'd be nicer to detect the size of the terminal run-time and use that.

Env vars

Support env vars. Abusing parse_arg for parsing should be fine.

  • env var prefix
  • search env vars - params
  • search env vars - switches
  • document them
  • turn off individual env vars
  • turn off all env vars by default if prefix wasn't specified in order to avoid accidents

Multiple switches

It should be possible to define verbosity by specifying --verbose argument multiple times.

Case for LNP Node and other LNP/BP microservices

Just would like to check that I am using this lib efficiently with cases we have in different LNP/BP nodes (LNP Node, BP Node, RGB Node).

Each node is represented by

  • a set of microservices, each of which can be loaded either in form of separate process (daemon) or as a thread withing a single process, depending on the configuration and environment (mobile app or server + docker).
  • a main service (it can also be just a thread withing mobile app) which launches and manages the rest.

The main service should be configured with either:

  • config file + command-line args matching config file + env variables (in case it is a process), or
  • with rust structure passed to it's entry point (in case it is started as a thread).

The rest of services are never intended to be launched by human from command-line (they are started as threads or processes by the main service, or automatically by something like Kubernetes), but they also should be configured with

  • some service-specific command line options/env vars, which should not map to the configuration file (their value is unique per service instance) +
  • read parts of the shared config from the main service - or get it's configuration structure for multi-threaded case.

What I plan is:

  • to have a single configure_me-based configuration for the main service, generating command-line args for it + support for env variables and man pages
  • to re-use that config file by the rest of services, but using direct TOML reads, not configure_me-based routines
  • to add other per-service command-line configuration options (which do not map to the config file and do not need man page) using Clap

Clippy: used binding `_program_path` which is prefixed with an underscore.

Code generated by configure_me triggers a clippy warning:

used binding `_program_path` which is prefixed with an underscore. A leading underscore signals that a binding will not be used.

(pedantic)

I think the underscore was to prevent clashes with user-defined fields. Maybe there's a workaround?

Clippy: enum with no variants (clippy:empty-enum) in generated code

Clippy with -- -W clippy::pedantic produces $subj error on generated code if no env_prefix is configured

Clippy output:

    Checking configure_me_user v0.1.0 (<path>/configure_me_user)
warning: enum with no variants
  --> <path>/configure_me_user/target/debug/build/configure_me_user-72c791d01889789c/out/configure_me_config.rs:46:1
   |
46 | pub enum EnvParseError {}
   | ^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: `-W clippy::empty-enum` implied by `-W clippy::pedantic`
help: consider using the uninhabited type `!` or a wrapper around it
  --> <path>/configure_me_user/target/debug/build/configure_me_user-72c791d01889789c/out/configure_me_config.rs:46:1
   |
46 | pub enum EnvParseError {}
   | ^^^^^^^^^^^^^^^^^^^^^^^^^
   = help: for further information visit https://rust-lang-nursery.github.io/rust-clippy/master/index.html#empty_enum

Support conditional compilation

It'd be nice to be able to condition switches/params on features being enabled or based on platform etc.

Suggested design:

  • When enabled, everything works like now.
  • When disabled, the parameters are still parsed but generate a nice error.
  • Help page does not mention the parameter but it could mention that the app was built with specific features.

generate trigger files

After implementing #4 there could be an additional option to implement trigger file and scripts.

Support for multiple binaries mis-documented

I am trying to use configure_me for a crate with two executables each with their own config files.
This section in the documentation seems wrong:

# config for binary foo
[package.metadata.configure_me.bin]
foo = "foo_config_spec.toml"

# config for binary bar
[package.metadata.configure_me.bin]
bar = "bar_config_spec.toml"

I believe it should be

# config for binary foo
[package.metadata.configure_me.bin]
foo = "foo_config_spec.toml"
bar = "bar_config_spec.toml"

I can open a PR for this later.

Convert into parameter

It might be nice to be able to convert parameter type to a different type. This would be useful for scenarios when newtype is used to implement ParseArg.

Skipping default config files

It'd be great to add an option to enable skipping default config files. It'd resolve romanz/electrs#217 as well as provide some robustness for other interesting cases. Programs that don't have such options are sometimes painful to work with (pkg-config comes to mind).

Proposed solution: make it possible to add skip_default_configs to a boolean flag. After processing arguments, this is checked and configs are not loaded if it's set to true.

Pros:

  • Looks very easy to implement
  • Implicitly prevents people from making two different options of the same name (because of the field name in the struct).
  • Makes it possible to access this value - e.g. for logging purposes
  • No need to write a separate documentation generating code

Cons:

  • One might accidentally make more than one such option - this would work, but it'd be weird - maybe issue a warning?
  • It leaks the value, cementing the implementation detail immediately, removing the ability to change it in the future
  • It forces everyone to document this option, while it might be entirely fine to provide doc string automatically. Maybe we could set it as the default, but I'm not sure if it'd be easy enough.

Alternatives:

  • Silently ignore bunch of other errors (e.g. EPERM) - lot of hair pulling in cases where the user forgot didn't want this behavior.
  • Print warning if a file is skipped because of any other reason - annoying warning clutter for projects that'd need this feature
  • Make this option always present in configure_me - would remove configuration handling, but be inflexible. There's a precedent with --help, but that is extremely widespread - basically every program understands -h and --help. This isn't true for skipping default config.

Standard config files

Add standard_config_files bool option to General. After enabling, it should pull from /etc/name and ~/.config/name

This will be implemented after #4.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.