Running a macro for multiple files in a local folder

Can anybody help with some clues about running a macro for multiple files in a local folder (e.g. D:/000/):

for example:

 ko.find.replaceAllInMacro(window, 0, 'XYZ', 'ABC', false, 0, 2, false, false);

Thanks a lot!

@nathanr

You’d have to use the Mozilla SDK to receive the list of files in a given directory, then perform your functions on them.

For Komodo 8 and below you can have a look at: https://developer.mozilla.org/en-US/Add-ons/Code_snippets/File_I_O#Enumerating_files_in_given_directory

If you’re using the Komodo 9 pre-release you’ll be able to use the new CommonJS SDK, which is much easier to use. In particular you’ll want to have a look at: https://developer.mozilla.org/en-US/Add-ons/SDK/Low-Level_APIs/io_file#list(path)

@surfactant - where you wanting to run a replace operation for the files in a particular directory (via a macro)?

where? it doesn’t matter. It would be best to simply execute a macro in the right pane of Komodo Edit. My problem is to run a series of regex replacement on a group of files. Would appreciate if you can come up with some quick solution. Thanks!

I tried codes below, but failed.


Components.utils.import("resource://gre/modules/FileUtils.jsm");

var file = FileUtils.getDir("Desk", ["FileBank"], true);

var entries = file.directoryEntries;

while(entries.hasMoreElements()) {

  var entry = entries.getNext();
  entry.QueryInterface(Components.interfaces.nsIFile);
 
  ko.open.URI("file:///" + entry.path);
  
  ko.views.currentView.setFocus();
  
  ko.find.replaceAllInMacro(window, 0, 'X[yY]Z', 'XYZ', false, 2, 1, false, false);
  
  ko.commands.doCommand('cmd_save');
  ko.commands.doCommand('cmd_bufferClose');
}

Could you kindly have a look?

Thank you so much!

Can you elaborate, what failed? I’d be happy to help you with any error messages you get but I personally don’t have time right now to fix the code outright for you.

@nathanr Thanks for your quick response first. Please look at sentences below in bold:


Components.utils.import("resource://gre/modules/FileUtils.jsm");

var file = FileUtils.getDir("Desk", ["FileBank"], true);

var entries = file.directoryEntries;

while(entries.hasMoreElements()) {

  var entry = entries.getNext();
  entry.QueryInterface(Components.interfaces.nsIFile);

  ko.open.URI("file:///" + entry.path);

Codes above (file enumeration) work well.

But codes below do not work. After execution, all files to be processed would be left open in the editor without any replacements happening. So the problem seems to be:

How to move focus to the newly opened file, make replacements in it, save/close it after all replacements and move on to open the next file for processing.


  ko.views.currentView.setFocus();

  ko.find.replaceAllInMacro(window, 0, 'X[yY]Z', 'XYZ', false, 2, 1, false, false);

  ko.commands.doCommand('cmd_save');
  ko.commands.doCommand('cmd_bufferClose');
}

It seems a bit wasteful to open these files in Komodo just to do a replace. You could instead use the Mozilla API’s here:

Reading files: https://developer.mozilla.org/en-US/Add-ons/Code_snippets/File_I_O#Reading_from_a_file
Writing files: https://developer.mozilla.org/en-US/Add-ons/Code_snippets/File_I_O#Writing_to_a_file

This all becomes a lot easier if/when you update ot Komodo 9 (currently in pre-release): https://developer.mozilla.org/en-US/Add-ons/SDK/Low-Level_APIs/io_file#Usage

Alternatively you could write your Macro in Python and just use standard Python API’s to read/write files.

@nathanr I need to do sophisticated regex replacements (not a replace) in Komodo Edit …

You can still do that? You can do regex replacements in base JS - https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/RegExp

Perhaps you could explain what you are trying to do exactly?

I need to process thousands of html files. Something like text mining.

In that case I’d highly recommend writing it in Python. You could simply invoke your Python script from Komodo.

Doing this using the actual Komodo API will make it extremely slow as it is not what the Komodo API is intended for.

I’m confused. Based on the code you posted above it looks like you’re trying to implement Komdo’s Find/Replace. If all you need to do is a find/replace on a directory using a regex then why not use “find/replace” in a directory using Komodos find/replace tool?

Edit > Replace in Files. Then enable “Regex”, set “Search in” to files, pick the directory to perform the task on, enable “Confirm” so it does what you think it will, then Replace All.

If that’s not your use case, @nathanr is right. It’s extremaly SLOW to open all those files in Komodo to perform whatever it is that you want to do with them.

Cheers,

  • Carey

Komodo’s find/replace tool can only do ONE (not multiple!) replacement one time on a directory/folder.

@nathanr I’m not a professional coding guy and simply want to use JS macro in Komodo for a quick solution, just as I use VBA in Microsoft Office.

Thanks anyway!

Trust me; Python is the quick solution. You’re free to build your tool however you want of course, if you really want to do so in Komodo I’d recommend you have a look at the links I included before.

OK. Let me try some python. Thanks!

The problem got solved with codes below


Components.utils.import("resource://gre/modules/FileUtils.jsm");
Components.utils.import("resource://gre/modules/NetUtil.jsm");

var osPath = Components.classes["@activestate.com/koOsPath;1"].getService(Components.interfaces.koIOsPath);

var os = Components.classes["@activestate.com/koOs;1"].getService(Components.interfaces.koIOs);

var file = FileUtils.getDir("Desk", ["000-CCC"], true);
var entries = file.directoryEntries;

while(entries.hasMoreElements()) {
   var entry = entries.getNext();
   entry.QueryInterface(Components.interfaces.nsIFile);   
   var myOutput = "D:\\000-DDD\\" + entry.leafName;
  //----------------------------------------   
  var content = "";
  var fstream = Components.classes["@mozilla.org/network/file-input-stream;1"].
                createInstance(Components.interfaces.nsIFileInputStream);
  var cstream = Components.classes["@mozilla.org/intl/converter-input-stream;1"].
                createInstance(Components.interfaces.nsIConverterInputStream);
  fstream.init(entry, -1, 0, 0);
  cstream.init(fstream, "UTF-8", 0, 0); // you can use another encoding here if you wish
  let (str = {}) {
    let read = 0;
    do { 
      read = cstream.readString(0xffffffff, str); // read as much as we can and put it in str.value
      content += str.value;
    } while (read != 0);
  }
  cstream.close(); // this closes fstream
  //----------------------------------------
  //----------------------------------------
  content = content.replace(/([A-Z][A-Z])([A-Z])/g, '$1-$2'); 
  //----------------------------------------
  //----------------------------------------
  os.writefile(myOutput, content);  
}

@nathanr Thanks for your advice!

The solution need to be attibuted to the page you gave:

I still have two more questions for your help:

1. How to create a file in a local folder

var file = new FileUtils.File("/home");

_When I change “/home” to e.g. “D:\000”, the code never works.

2. How to build a folder in a local drive

 var file = FileUtils.getDir("Desk", ["TEST"], true);

_I see a list of something like “Desk” “ProfD” on the I/O webpage, but how can I build a folder in “D:”?

3. How to force the output file to UTF-8 encoding?

@nathanr Thank you so much for your help!

Glad you got it sorted :slight_smile: For what its worth Python can do this much simpler and way faster, in case you ever need to do something similar and are feeling adventurous.

Sure. I would try to learn some Python recently. Thanks again!