【问题标题】:How to suggest files with tab completion using readline?如何使用 readline 建议带有制表符完成的文件?
【发布时间】:2013-04-10 17:18:24
【问题描述】:

在 Bash shell 中,我可以使用 tab-completion 来使用建议的文件和目录名称。如何使用 nodejs 和 readline 实现这一点?

例子:

  • /<Tab> 应该建议 /root//bin/ 等。
  • /et<Tab> 应该完成到 /etc/
  • fo<Tab> 应该完成到 foobar 假设这样的文件存在于当前目录中。

我正在考虑使用 globbing(模式 search_term.replace(/[?*]/g, "\\$&") + "*"),但是否有我忽略的库?

这是我目前使用 glob 的方法,在使用 //<Tab> 时它会被破坏,因为它返回规范化的名称并且可能还有其他一些奇怪之处:

function command_completion(line) {
    var hits;
    // likely broken, one does not simply escape a glob char
    var pat = line.replace(/[?*]/g, "\\$&") + "*";
    // depends: glob >= 3.0
    var glob = require("glob").sync;
    hits = glob(pat, {
        silent: true,
        nobrace: true,
        noglobstar: true,
        noext: true,
        nocomment: true,
        nonegate: true
    });

    return [hits, line];
}

var readline = require("readline");
rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout,
    completer: command_completion
});
rl.prompt();

【问题讨论】:

    标签: node.js readline tab-completion


    【解决方案1】:

    也许你可以看看 readdir:https://www.npmjs.com/package/readdir

    只需读取用户正在创建选项卡的目录,然后将用户输入与目录中每个文件的开头进行比较,如果文件名匹配,则将其显示给用户。比如:

    var readDir = require('readdir');
    
    function strncmp(str1, str2, lgth) {
      var s1 = (str1 + '')
        .substr(0, lgth);
      var s2 = (str2 + '')
        .substr(0, lgth);
    
      return ((s1 == s2) ? 0 : ((s1 > s2) ? 1 : -1));
    }
    
    var userInput = // get user input;
    var path = // get the path;
    readDir.read(path, [*], function(err, files) {
        for (var i = 0; i < files.length; i++)
            if (strncmp(files[i], userInput, userInput.length) == 0)
                console.log(files[i]);
    });
    

    【讨论】:

      【解决方案2】:

      这是一个有一些怪癖的可行解决方案:

      • 不支持相对路径
      • 尝试按两次 Tab 键显示建议时,会在建议列表中显示完整路径。
      • 它更喜欢“/”而不是“\”,但在 Windows 上允许使用“\”分隔符
      • 它只支持目录和文件。 (没有设备、管道、套接字、软链接)

      代码:

      const { promises: fsPromises } = require("fs"); 
      const { parse, sep } = require("path");
      
      function fileSystemCompleter(line, callback) {
        let { dir, base } = parse(line);
        fsPromises.readdir(dir, { withFileTypes: true })
          .then((dirEntries) => {
            // for an exact match that is a directory, read the contents of the directory
            if (dirEntries.find((entry) => entry.name === base && entry.isDirectory())) {
              dir = dir === "/" || dir === sep ? `${dir}${base}` : `${dir}/${base}`;
              return fsPromises.readdir(dir, { withFileTypes: true })
            }
            return dirEntries.filter((entry) => entry.name.startsWith(base));
          })
          .then((matchingEntries) => {
            if (dir === sep || dir === "/") {
              dir = "";
            }
            const hits = matchingEntries
              .filter((entry) => entry.isFile() || entry.isDirectory())
              .map((entry) => `${dir}/${entry.name}${entry.isDirectory() && !entry.name.endsWith("/") ? "/" : ""}`);
            callback(null, [hits, line]);
          })
          .catch(() => (callback(null, [[], line])));
      }
      

      【讨论】:

        猜你喜欢
        • 2014-11-26
        • 2021-08-04
        • 2017-01-01
        • 1970-01-01
        • 2011-06-11
        • 1970-01-01
        • 2014-06-03
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多