Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improvements for extending & help template overwriting #1338

Closed
wants to merge 2 commits into from
Closed

Improvements for extending & help template overwriting #1338

wants to merge 2 commits into from

Conversation

cravler
Copy link
Contributor

@cravler cravler commented Aug 27, 2020

Example

const { Command } = require('./index');
const nunjucks = require('nunjucks');

nunjucks.configure({ autoescape: false });

class MyCommand extends Command {
  createCommand(name) {
    return new this.constructor(name);
  };

  helpInformation() {
    const help = this.helpData({ baseIndent: 2 });

    const res = nunjucks.renderString(`
>>> Usage:

  {{ usage }}
{% if description %}
{{ description }}
{% endif %}
{%- if args | length %}
>>> Arguments:

{{ args | join("\n") }}
{% endif -%}
{%- if options | length %}
>>> Options:

{{ options | join("\n") }}
{% endif -%}
{%- if commands | length %}
>>> Commands:

{{ commands | join("\n") }}
{% endif -%}
`, help);

    return res.replace(/^/gm, '  ').trimEnd() + '\n\n';
  };
}

const program = new MyCommand('example');

program.version('0.0.1');

program
  .command('test <cmd> [env] [val]')
  .description(Array(100).join('long description '), {
    cmd: 'cmd description',
    env: 'env description',
    val: Array(50).join('val description ')
  })
  .action(function(cmd, env, options){});

program.parse(process.argv);

@shadowspawn
Copy link
Collaborator

I see issues about people wanting to disable the built-in help, but not issues about what people are replacing it with, or requests to make more support routines public to let people build their own. We might get more interest if #1296 lands and it is easier to override the help.

The code uses arrays of strings internally to build up the help in an efficient and convenient way. I don't think that is a very natural form to return to the user for building custom help though. Some different ideas for what to expose could be:

  • the text blocks, say because I just want to rearrange the order or customise the headings (i.e. rather than return an array of strings, return a single string)
  • array of visible options including help option for custom processing
  • array of visible commands including help command for custom processing

The help code is a bit of a historical mess! I do like that you have tidied it up while making the changes.

index.js Outdated Show resolved Hide resolved
@cravler
Copy link
Contributor Author

cravler commented Aug 29, 2020

With my changes I can do something like this:
Example
but with #1296 I do not see this ability

@shadowspawn
Copy link
Collaborator

Nice example of fancy help! Thanks.

#1296 just provides hooks for before and after and overriding the built-in help, it does not provide any assistance doing the fancy help.

@cravler
Copy link
Contributor Author

cravler commented Aug 29, 2020

May be instead of:

function padDetails(value, description) {
  if (description) {
    return [pad(value, width), optionalWrap(description, descriptionWidth, width + separatorWidth)];
  }
  return [value];
};

you prefer:

const utils = {
  pad: val => pad(val, width),
  wrap: val => optionalWrap(val, descriptionWidth, width + separatorWidth)
};

const renderDetails = params.renderDetails || ((value, description, utils) => {
  const data = description ? [utils.pad(value), utils.wrap(description)] : [value];
  return data.join(separatorStr).replace(/^/gm, valueIndentStr);
});

function prepareDetails(value, description) {
  return renderDetails(value, description, utils);
};

@shadowspawn
Copy link
Collaborator

The code uses arrays of strings internally to build up the help in an efficient and convenient way. I don't think that is a very natural form to return to the user for building custom help though.

I see running the code and dumping helpData() that options and commands are not just an array of the strings, but an array of [entry, description]. That is closer to what I had in mind as building blocks.

@cravler
Copy link
Contributor Author

cravler commented Aug 29, 2020

pushed the changes, now helpData() response:

{
  usage: 'string',
  description: 'string',
  args: ['string'],
  options: ['string'],
  commands: ['string']
}

@shadowspawn
Copy link
Collaborator

I am wondering about what approach to take. This is just an idea.

There is already access to some of the content that is displayed in the help. There is .usage() and .description() and option.flags. Much of the help code is just joining the parts together with headings.

There are a few pieces of logic that are buried in code. e.g.

const help = this.options.map((option) => {
  const fullDesc = option.description +
    ((!option.negate && option.defaultValue !== undefined) ? ' (default: ' + JSON.stringify(option.defaultValue) + ')' : '');
  return padOptionDetails(option.flags, fullDesc);
});

I wonder how it would go separating the construction and the formatting, and making the constructed parts available directly? So the built-in formatting code would look like (say):

const help = this.options.map((option) => {
  return padOptionDetails(option.flags, option.fullDescription());
});

@shadowspawn
Copy link
Collaborator

Thanks @cravler
FYI I am working on a couple of other PR, and likely to be a while before I dig into this one.

@shadowspawn
Copy link
Collaborator

Experimenting in #1346 with refactoring and making help building blocks accessible.

@cravler
Copy link
Contributor Author

cravler commented Oct 5, 2020

Closing this in favour of #1365

@cravler cravler closed this Oct 5, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants