sakai-memoru
12/2/2019 - 12:39 PM

Sakura Macro Library::app_searchSnippets 指定フォルダのSnippetを検索して、選択したものをClipboardに

コーディング時に、Snippetを検索して、活用するためのマクロ

よく使うコードの破片(Snippet)を、ファイルとして保存しておき、そのファイル名で検索して、選ばれたものを、Clipboardに入れる。

Snippetの保存場所は、setting.jsで指定。対象フォルダ配下の-Depth 2まで検索対象。

// app_searchSnippets.jse  
// + sakura macro folder  
//    + app_searchSnippets.jse  
//    + app_searchSnippets  
//      + config  
//        + setting.js  
// 

(function(){

// const 
var CONS_PWSH_EXE = 'powershell -noprofile -Sta -command ';

var CONS_COMMON_LIBPATH = 'G:\\Users\\sakai\\AppData\\Roaming\\sakura';
var CONS_COMMON_LIBS = [
  "./app_searchSnippets/config/setting.js",
]

// load external libraries
var check_env = function(){
  // set env_name for targetting wsh, sakura, node
  var env_name = '';
  if (typeof(WScript) !== "undefined") env_name = 'wsh';
  if (typeof(Editor) !== "undefined") env_name = 'sakura';
  if (typeof(alert) !== "undefined") {env_name = 'browser';}
  else if (typeof(console) !== "undefined") env_name = 'node';
  return env_name;
}
var flag = check_env();
var CONFIG = {};

if(flag == "wsh"||flag == "sakura"){
  var objFS = new ActiveXObject("Scripting.FileSystemObject");
  var lib_path = CONS_COMMON_LIBPATH ? CONS_COMMON_LIBPATH: './';
  // require common module
  with({
    libs : CONS_COMMON_LIBS, 
    get_moduleCode : function(path){
      return objFS.OpenTextFile(path,1).ReadAll();
    }
  }) {
    var len = libs.length;
    for (var i = 0; i < len; i++){
      try {
        var module_path = objFS.BuildPath(lib_path,libs[i]);
        eval(get_moduleCode(module_path));
      } catch (e) {
        //console.log( e.description || e.message || "error" );
        null;
      }
    }
  };
  objFS = null;
}

// powershell statement
var herestrings_powershell = function(){
/*
function search-files(){
  [CmdletBinding()]
  param(
    [Parameter(Position=0,Mandatory=$true)]
    [string] $folder,
    [Parameter(Position=1)]
    [string] $likestr = '*.*'
  )
  Get-ChildItem $folder $likestr -File -Recurse -Depth 2 | foreach{$_.FullName} | set -Name ret
  # return
  $ret
}
search-files -folder "{{folder_name}}" -likestr "{{condition}}"
*/
}

// local function
function replace_all(string, target, replacement) {
  var result = "";
  var offset = 0;
  var target_length = target.length;
  if (target_length === 0) {
    for (var i = 0, c = string.length; i < c; i++) {
      result += string[i];
      result += replacement;
    }
    if (result.length)
      return result.substr(0, result.length - replacement.length);
    return result;
  }
  do {
    var i = string.indexOf(target, offset);
    if (i === -1) {
      result += string.substring(offset);
      return result;
    }
    result += string.substring(offset, i);
    result += replacement;
    offset = i + target_length;
  } while (true);
}

if(!Object.keys){
    Object.keys = function(obj){
        var keys = [];
        for(var i in obj){
            if(obj.hasOwnProperty(i)){
                keys.push(i);
            }
        }
        return keys;
    };
}

function merge_map(template, map_){
  var keys_ = Object.keys(map_);
  for(key_ in keys_){
    var value_ = map_[keys_[key_]];
    template = replace_all(template, '{{' + keys_[key_] + '}}', value_);
  };
  return template;
}

function get_template(herestrings, sep){
  sep = sep || '\r\n';
  var template = herestrings.toString().split(sep).slice(2,-2).join(sep);
  return template;
}

var chopTail = function(str, num){
  var len = str.length;
  return str.substr(0,len - num);
};

var doBatchAndGetStdOut = function(target_){
  // WScript.Echo(target_);
  var objShell = new ActiveXObject("WScript.Shell");
  var objExec = objShell.Exec(target_);
  objExec.StdIn.Close();
  var text = objExec.StdOut.ReadAll()
  objExec = null;
  objShell = null;
  if(text){
    text = chopTail(text,2);
  }
  return text;
}

var exec_fileSearch = function(folder_name, condition){
  var target_ = get_template(herestrings_powershell);
  var map_ = {
    'folder_name' : folder_name,
    'condition' : condition
  };
  var target_ = merge_map(target_, map_);
  var cmd_statement = CONS_PWSH_EXE + target_;
  //Editor.TraceOut(cmd_statement);
  var ret = doBatchAndGetStdOut(cmd_statement);
  return ret;
}

var get_filePathes = function(folder_name, condition){
  var result_ = exec_fileSearch(folder_name, condition);
  var ary_path = result_.split("\r\n");
  return ary_path
}

var get_filenames = function(ary_path){
  var objFS = new ActiveXObject('Scripting.FileSystemObject');
  var ret_ary = [];
  var len = ary_path.length;
  for (var i = 0; i < len ; i++){
    ret_ary.push(objFS.GetFileName(ary_path[i]));
  }
  objFS = null;
  return ret_ary;
}

var generate_menuAndGetOpe = function(ary){
  var menu_ = '';
  var len = ary.length;
  for (var i = 0; i < len; i++){
    menu_ = menu_ + ary[i] + ',';
  }
  menu_ = chopTail(menu_,1);
  var ope = Editor.CreateMenu(1, menu_);
  return ope;
}

var output_display = function(str){
  if(Editor.isTextSelected){
    //Editor.InsText(str);
    Editor.SetClipboard(0,str);
    Editor.TraceOut(str);
  } else {
    Editor.SetClipboard(0,str);
    Editor.TraceOut(str);
  }
}

var read_fileUtf8 = function(path){
  if (!path) {
    throw new Error('StreamReader: filename is not defined.');
  }
  var objSR = new ActiveXObject('ADODB.Stream');
  objSR.Type = 2; // 1 : binary , 2 : text
  objSR.Charset = 'UTF-8';
  try {
    objSR.Open();
  } catch (e) {
    throw new Error('StreamReader: failed to open file.');
  }
  objSR.LoadFromFile(path);
  var text = objSR.ReadText(-1)  // read all : -1, read line : -2
  objSR.Close();
  objSR = null;
  return text;
}

var read_file = function(path){
  var ret = '';
  if(CONFIG.ENCODE.toLowerCase() === 'utf-8'){
    ret = read_fileUtf8(path);
  } else {
    var objFS = new ActiveXObject("Scripting.FileSystemObject");
    var ret = objFS.OpenTextFile(path,1).ReadAll();
    objFS = null;
  }
  return ret;
}

var get_target = function(expandParam){
  // $F : opened file's full path
  // $f : opened file's name
  // $e : opened file's folder path
  // $b : opened file's extention
  // $C : 選択中の場合、選択テキストの1行目のテキスト(改行コード除く)
  //      選択中でない場合、カーソル位置の単語
  var ret = Editor.ExpandParameter(expandParam);
  return ret;
};

// 
// Search some snippet with file name and get the snippet
function doProcess(){
  // get target
  var current_ext = get_target('$b');
  var target_ = get_target('$C');
  // open folder diaglog
  var message_ = 'Select Folder';
  var initialDirectory = CONFIG.SNIPPETS_FOLDER;
  var folder_name = Editor.FolderDialog(message_,initialDirectory);
  // open inputbox
  var windowTitle = 'file search';
  var message2_ = 'Input a keyword for search.'
  var target_cond = Editor.InputBox(message2_, target_, 32);
  var condition = '*' + target_cond + '*.' + chopTail(current_ext,1) + '*';
  // execute file search
  var ary_path = get_filePathes(folder_name, condition);
  var ary = get_filenames(ary_path);
  // create menu
  var ope = generate_menuAndGetOpe(ary);
  // get text 
  var text = '';
  if(ope != 0){
    text = read_file(ary_path[ope-1]);
    // set text
    output_display(text);
  }
}

// -------------- entry point
if(typeof(Editor) !== 'undefined'){
  Editor.FileSave();
  doProcess();
  
} else {
  if(typeof(WScript) !== 'undefined'){
    WScript.Echo('[Warn] This script is for sakura macro. A env is maybe wsh.')
  } else {
    console.log('[Warn] This script is for sakura macro. A env is maybe node.')
  }
}

}())

// NOTICE:JSON記述が正しくないとevalでエラーとなり、CONFIGを読み込めない
var CONFIG = {
  "DEBUG_MODE": false,
  "APP_NAME": "app_searchSnippets.jse",
  "SNIPPETS_FOLDER": "G:\\Users\\sakai\\AppData\\Roaming\\sakura\\snippet",
  "ENCODE" : "utf-8"
}