Add the ability to scan through the child hierarchy of the current directory during find-as-you-type

The find-as-you-type folders mode describes where the search will be done, but we cannot scan through the child hierarchy of the current directory (or better, the whole drive).

Even better, filtering the view to not lose track of file hierarchy while you search, which is done brilliantly by broot.

This mode is meant to quickly go to certain folders, not to search folders.

You seem to be looking for a quick search. Try Everything (Local).

Well, not really a quick search since I already know where the directory is, but I just don’t want to browse through the entire hierarchy. And if I haven’t already visited the wanted directory before, the FAYT feature won’t work in that case.

I’m actually looking for a way to quickly jump to a directory just by typing a few matching letters. I gave the example of broot because I find it really intuitive, but a simpler approach would be what PSFzf offers: you hit Alt + C, and it gives you a prompt to enter some letters while it is already indexing the hierarchy in your CWD.

A similar example – similar, because it is indexing files instead of directory tree – is IntelliJ IDEA: when you hit Ctrl + N, it will open a window where the user can type some letters that matches the wanted class. You already know the class exists, you just don’t want to browse the directory tree each time you want to open a class.

I can provide a screen capture to illustrate the concept if I’m not clear enough.

Have you tried Everything (Local) with the modifier folder:?

If you prefer a separate window, you could launch Everything like this:

@nofilenamequoting
@async:"/programfiles\Everything\Everything.exe" -search """"{sourcepath}""" folder:"

FAYT has modes that search under the current folder. Search for “Quick Keys” in Preferences for the list.

Might I suggest for the least number of keystrokes - going straight to Everything:

Set up a filter in Everything that looks only for folder names, e.g., "!M: folder: groupcolors:" where !M: excludes an indexed partition

  1. Open Everything, e.g., with a keystroke that can be set from within Everything
  2. Choose your filter, if it is not already selected
  3. Type a few search characters from the folder name
  4. Double click the desired folder name to open it in Directory Opus

Thanks for your suggestion, but I would prefer to not rely on external tools if possible. Besides, my company doesn’t allow the installation of Everything for some reason.

Could you provide more information about that? The documentation doesn’t mention anything about jumping to a directory under the current directory.

And again, I insist on the fact I’m not searching for a directory; I already know where it is. What I want is a way to quickly jump to a known directory that matches some string, without browsing into a deep hierarchy of folders.

One of my use case would be the following:
A Maven package will be cached into your %USERPROFILE%\.m2\repository directory. For instance, the Apache Commons Lang v3.14.0 has the ID org.apache.commons:commons-lang3:3.14.0. So I do know that the directory that contains this dependency will be located in %USERPROFILE%\.m2\repository\org\apache\commons\commons-lang3\3.14.0. And when you have dozens of dependencies, DOpus doesn’t seem to help more than Windows Explorer: you have to browse the hierarchy deep down to the wanted directory.
The current directory being %USERPROFILE%\.m2, if the user just types lang3, the system would suggest %USERPROFILE%\.m2\repository\org\apache\commons\commons-lang3.
Or, if the user just types lang3 314, the system would suggest %USERPROFILE%\.m2\repository\org\apache\commons\commons-lang3\3.14.0.

record

I know the function, some other programs use that too, but sounds like you need scripting for that.

This would most likely work: A. You code a FAYT script, which automatically indexes all subfolders when triggered and searches for all the tokens you typed, like lang 314, and fills its autosuggest list.

B. Or you could send the query from your pseudo-FAYT script to to ES local search instead and have the suggestions shown in the lister instead; you would read the current lister path and build a regex '/^' + currentPath + '.*(' + tokens_separated_by_pipe_or_dotstar_depends_on_behavior_you_want + ')/'. This would be much much faster than reading all subfolders yourself and ensure you get only the results under current folder, not from whole disk. Once results are listed you just press Enter.

C. You could even combine these 2 too, i.e. populate the FAYT suggestion popup from ES, but that'd require probably much more work, because I know of no easy way at the moment to query ES from a script in a hidden fashion. But that would be an awesome feature, maybe a new "Everything " scripting object, which gives fine-grained control and querying functions, instead of DOpus automatically showing ES results or populating a collection.

Thanks for your suggestion. I will evaluate the effort needed to implement that. Maybe fzf can be interfaced with GUI tools.

Actually reading subdirectories with DOpus seems to be quite fast. Here's a template script with a user command "TestListAllSubfolders" (add it to a test button) to get you started, you have to put the FAYT & regex logic on top as mentioned above. Implement where it says "APPLY YOUR FILTERING HERE".


// @ts-check
/* eslint quotes: ['error', 'single'] */
/* eslint-disable no-inner-declarations */
/* global Enumerator DOpus Script */
///<reference path="./_DOpusDefinitions.d.ts" />

var DEBUG = true;
function $dbg(/**@type {any}*/str) { if (DEBUG) DOpus.output(str); }

function OnInit(/** @type {DOpusScriptInitData} */ initData) { // eslint-disable-line no-unused-vars
    initData.name = '_cySandbox';
    initData.desc = '_cySandbox';
    initData.default_enable = true;
    initData.group = 'cy';

    var cmd = initData.addCommand();
    cmd.name = 'TestListAllSubfolders';
    cmd.method = 'OnTestListAllSubfolders';
}

function OnTestListAllSubfolders(/** @type {DOpusScriptCommandData} */ scriptCmdData) { // eslint-disable-line no-unused-vars
    var allDirs = ReadSubdirsOfTab('' + scriptCmdData.func.sourceTab.path);
    $dbg('allDirs: ' + JSON.stringify(allDirs, null, 4));
    //
    // APPLY YOUR FILTERING HERE
    //
}

function ReadSubdirsOfTab(/** @type {String} */ currentPath) {
    function isValidDOItem(/** @type {DOpusItem} */ oItem) {
        return (typeof oItem === 'object' && typeof oItem.realpath !== 'undefined' && typeof oItem.modify !== 'undefined');
    }
    function isDir(/** @type {DOpusItem} */ oItem) {
        return (typeof oItem === 'object' && typeof oItem.realpath !== 'undefined' && oItem.is_dir === true);
    }
    var allDirs = [];
    $dbg('currentPath: ' + currentPath);

    var icnt = 0, imax = Math.pow(10, 7); // just as a precaution for while loop
    var fsUtil = DOpus.fsUtil();
    var fEnum = fsUtil.readDir(currentPath, 'r');
    if (fEnum.error) {
        DOpus.output('fsUtil.readDir - cannot read:\nError: ' + fEnum.error);
        return;
    }
    icnt = 0;
    while (!fEnum.complete && icnt++ < imax) {
        var subitem = fEnum.next();
        if (isDir(subitem) && isValidDOItem(subitem)) {
            // $dbg('subitem: ' + subitem.realpath);
            allDirs.push('' + subitem.realpath);
        }
    }
    return allDirs;
}