dthree / vorpal

Node's framework for interactive CLIs
http://vorpal.js.org
MIT License
5.63k stars 278 forks source link

Support question - autocompletion of filepaths #266

Closed ORESoftware closed 6 years ago

ORESoftware commented 7 years ago

I am trying to implement tab-autocompletion for filenames...here is what I have:

  vorpal.command('run [file]')
  .description('run a single test script')
  .autocomplete({
    data: function (input: string, cb: Function) {
      const basename = path.basename(input); 
      const dir = path.dirname(path.resolve(projectRoot + `/${input}`));
      fs.readdir(dir, function (err, items) {
        if (err) {
          return cb(null);   // do not support error-first callbacks
        }
        const matches = items.filter(function (item) {
          return String(item).match(basename);
        });

        if (matches.length === 1) {
          return cb(matches[0]);  // we only auto-complete when there is only one matching item
        }

        cb(null);

      });

    }
  })

it's hard to describe the problem I am seeing - and I am not even sure what to expect - if it's designed to work like a typical terminal. If you think I am close with the above code and can get me closer to something that will work that will help. It would also be really nice if Vorpal provided an example of filesystem autocompletion in the docs (I didn't see one). If I get this working, I can provide my solution, if you want to put that in the docs.

As an aside, since you are working on Vorpal2, my 2 cents is that it would be nice to support error-first callbacks, as far as I can tell, Vorpal is expecting the first argument to be the data, but it would be super nice if it stuck to the error-first convention, in Vorpal v2.

ORESoftware commented 7 years ago

actually my code was close. It looks like Vorpal handles this well. This is what worked for me:

  vorpal.command('run [file]')
  .description('run a single test script')
  .autocomplete({
    data: function (input: string, cb: Function) {
      const basename = path.basename(input); 
      const dir = path.dirname(path.resolve(projectRoot + `/${input}`));
      fs.readdir(dir, function (err, items) {
        if (err) {
          return cb(null);   // do not support error-first callbacks
        }
        const matches = items.filter(function (item) {
          return String(item).match(basename);
        });

        cb(matches);

      });

    }
  })

although I would have expected an error-first callback, like so:

  cb(null, matches);