Skip to main content
Inventsable
Legend
July 30, 2018
Answered

Trying to use Folder.getFiles() as the basis for a tree menu, but I've confused myself

  • July 30, 2018
  • 1 reply
  • 7710 views

Hi guys. I want to make a file tree menu GUI for my script, and I found window.cep.fs.readDir strange in that it returns undefined for directories, so I decided to do this through JSX:

recurseChildren(rootFolder)

function recurseChildren(path) {

  var subFolders = getChildren(path, 'Folders');

  var subFiles = getChildren(path, 'Files');

  var children = [];

  if (subFolders) {

    for (var i = 0; i < subFolders.length; i++) {

      children.push(subFolders)

      children.push(recurseChildren(subFolders));

    }

  }

  if (subFiles) {

    for (var i = 0; i < subFiles.length; i++) {

      children.push(subFiles);

    }

  }

  if (!children.length) {

    return false;

  } else {

    return children;

  }

}

function getChildren(path, type){

  var thisFolder = Folder(path);

  var children = thisFolder.getFiles();

  var subs = [];

  if (!children.length) {

    return false;

  } else {

    for (var i = 0; i < children.length; i++) {

      switch (type) {

        case 'Folders':

          if ((/\/(\w|\-|\d)*$/g.test(children)) && !(/LICENSE/.test(children)))

            subs.push(children);

          break;

        case 'Files':

          if ((/\/(\w|\d|\-)*\.(\w)*$/g.test(children)) || (/LICENSE/.test(children)))

            subs.push(children);

          break;

        default:

          subs.push(children);

          break;

      }

    }

    return subs;

  }

}

So I have access to all the files in all the folders of a single root directory, including ones that are excluded from getFiles() typically (like '.git', 'LICENSE', '.debug' and more), and my plan was to use this as a basis for constructing a tree view menu itself, but now I'm confused as to the best way to organize the data. I tried appending each new directory as a property of an object with each filename as another property within that, but found that traversing a 'nesting level' within an object without knowing it's name or what nesting level it is (to know what the parent would be) was really obfuscatory and pretty hard to do. Initially I thought I should use arrays within arrays, but then I tied myself up in a lot of corners trying to go that route too, because I need to know the name of the subfolder, the subfolder's parent, and the subfolder's contents.

How would you best organize this, or rewrite the above to give a better result? I feel like dropping the file reading and returning only directories, then using window.cep.readFile on all the directories contents back in vanilla JS would be far easier than anything I'm doing here, am I wrong? Are there better ways to do this?

This topic has been closed for replies.
Correct answer Silly-V

Hey, I don't have any spare minutes at the moment to create a test of what I feel I'd use for such a purpose, but perhaps what you could use in your toolset is:

    var f = Folder("~/Desktop");

    var allFiles = f.getFiles();

    var thisFile;

    for(var i = 0; i < allFiles.length; i++){

        thisFile = allFiles;

        $.writeln(decodeURI(thisFile.name) + " | Is Folder: " + (thisFile instanceof Folder) + ", Is File: " + (thisFile instanceof File)); 

    }

1 reply

Silly-V
Silly-VCorrect answer
Legend
July 30, 2018

Hey, I don't have any spare minutes at the moment to create a test of what I feel I'd use for such a purpose, but perhaps what you could use in your toolset is:

    var f = Folder("~/Desktop");

    var allFiles = f.getFiles();

    var thisFile;

    for(var i = 0; i < allFiles.length; i++){

        thisFile = allFiles;

        $.writeln(decodeURI(thisFile.name) + " | Is Folder: " + (thisFile instanceof Folder) + ", Is File: " + (thisFile instanceof File)); 

    }

Inventsable
Legend
July 31, 2018

Thanks! Using instanceof is giving perfect results, refactored all my code and ended up with an object result:

JSX:

function readFullDirectory(path){

  var mirror = {}

  var f = Folder(path);

  var allFiles = f.getFiles();

  var thisFile;

  for (var i = 0; i < allFiles.length; i++) {

    thisFile = allFiles;

    if (thisFile instanceof Folder) {

      mirror[thisFile.name] = readFullDirectory(thisFile);

    } else {

      mirror[thisFile.name] = thisFile;

    }

  }

  return JSON.stringify(mirror);

}

JS:

csInterface.evalScript(`readFullDirectory('${sysPath}')`, function(mirror){

  var root = parseAll(mirror);

  console.log(result);

});

function parseAll(str){

  var result = JSON.parse(str);

  for (let [key, value] of Object.entries(result)) {

    if (typeof value !== 'object') {

      result[key] = parseAll(value);

    }

  }

  return result;

}

Before recursively JSON parsing my console looked like a warzone, but I did get it to correctly display a hierarchy of folders/files this way:

This solves my problem and replaces a shameful amount of past code, lol. I'm still not sure if this is a dumb way to structure a hierarchy for folders and files, but I can iterate through and dynamically generate the tree menu from it, assign the file path as the value or even the corresponding HTML element, so it might work. It's a bit wonky in the sense that I have file extensions within property names, so I can only access via root.client['index.html'] but not directly as root.client.index.html, I'm sure this is very offensive to somebody out there.

Is it bad form to prod? If not, how would you detect any external changes to this folder outside the scope of this script -- any new, deleted, or renamed file, etc.? I figure that I could run the above scan with SetTimer every 500ms or so and discriminate the new result from the previous result, if no change return nothing and assign new to old, but if change then rebuild this tree object and trigger a redraw of the UI, but I keep having to window.reload() my scripts when using SetTimer this way and it seems to bring a few other glitches. Any ideas? How would you do it if you needed to?

Silly-V
Legend
July 31, 2018

This is all great stuff - but I have not yet done anything like it! Looking forward to all your progress.