Skip to content

Instantly share code, notes, and snippets.

@Getaji
Last active February 15, 2021 11:54
Show Gist options
  • Select an option

  • Save Getaji/af0048f956f29beea52fa96857c6caa1 to your computer and use it in GitHub Desktop.

Select an option

Save Getaji/af0048f956f29beea52fa96857c6caa1 to your computer and use it in GitHub Desktop.
テキストエディタMeryで開いているファイルに関する操作メニューを表示するマクロ

Meryファイル操作マクロ

Mery 2.6.13で動作確認しています。
FileControl.jsがメインのマクロファイルで、UsefulMenu.jsは動作に必要なライブラリです。

機能

  • ファイル名、フルパス、ディレクトリ名をコピー
  • ディレクトリのファイルを表示

予定

  • いろいろ機能追加予定

[開発者向け]UsefulMenu.jsについて

標準のPopupMenuが使いづらいので作ったラッパーライブラリです。
メニューアイテムを項目の種類を問わず統一された形式のオブジェクトで管理し、コールバック関数を直接渡して項目選択時にライブラリ側で呼び出してくれるようになっています。
ご自分でMeryのマクロを作成される際に流用していただくことも出来ます。自分用のライブラリなのでこれは必要だろうみたいな機能がなかったり、思わぬバグがあったりもします。それでも便利だと思うので、適当に弄って使っていただいてOKです。

#title = "ファイル操作"
#include "UsefulMenu.js"
const mery = editor.FullName;
const FS = new ActiveXObject("Scripting.FileSystemObject");
function foreachAXOList(list, fn) {
for (const fc = new Enumerator(list); !fc.atEnd(); fc.moveNext()) {
fn(fc.item());
}
}
function getFiles(path) {
const list = [];
const folder = FS.GetFolder(path);
const parent = folder.ParentFolder.Path;
list.push({
type: 'directory',
fullname: parent,
shortname: '..'
});
foreachAXOList(folder.SubFolders, function(folder) {
folder += '/';
list.push({
type: 'directory',
fullname: folder,
shortname: String(folder).substr(path.length)
});
});
list.push({
menutype: 'separator',
});
foreachAXOList(folder.Files, function(file) {
list.push({
type: 'file',
fullname: file,
shortname: String(file).substr(path.length)
});
});
return list;
}
function createFilesMenuObj(path) {
return getFiles(path).map(function(file) {
return {
label: file.shortname,
type: file.menutype,
callback: file.callback || function() {
actionFileOpen(file);
}
};
})
}
const menu = new Menu();
function actionFileOpen(file) {
switch (file.type) {
case 'file':
Editor.NewFile();
Editor.OpenFile(file.fullname);
break;
case 'directory':
new Menu().addItemAll(createFilesMenuObj(file.fullname)).show();
break;
case 'root':
break;
}
}
menu.addItem({
type: 'text',
label: 'ファイル名をコピー',
callback: function() {
ClipboardData.SetData(Document.Name);
}
});
menu.addItem({
type: 'text',
label: 'ファイルのフルパスをコピー',
callback: function() {
Document.CopyFullName();
}
});
menu.addItem({
type: 'text',
label: 'ディレクトリ名をコピー',
callback: function() {
Document.CopyPath();
}
});
menu.addItem({
type: 'popup',
label: 'ファイル一覧',
children: createFilesMenuObj(Document.Path)
});
menu.show();
const Menu = function(items) {
this.items = [];
this.callbacks = [];
this.menuobj = CreatePopupMenu();
this.idi = 1;
};
Menu.prototype.addLabelItem = function(item, targetmenu) {
this.items.push(item);
targetmenu.add(item.label, this.idi++);
};
Menu.prototype.addItem = function(item, targetmenu) {
if (!targetmenu) {
targetmenu = this.menuobj;
}
switch (item.type) {
case 'popup':
const popup = CreatePopupMenu();
targetmenu.addPopup(item.label, popup);
const self = this;
item.children.forEach((function(child) {
self.addItem(child, popup);
}));
break;
case undefined:
case null:
case 'text':
this.items.push(item);
targetmenu.add(item.label, this.idi++);
break;
case 'separator':
targetmenu.add('', 0, meMenuSeparator);
break;
}
};
Menu.prototype.onCallback = function(i) {
const item = this.items[i-1];
item.callback(item);
};
Menu.prototype.show = function(pos) {
if (pos === undefined) {
pos = mePosMouse;
}
const selected = this.menuobj.Track(pos);
if (selected > 0) {
return this.onCallback(selected);
}
};
Menu.prototype.addItemAll = function(items) {
const self = this;
items.forEach(function(item) {
self.addItem(item);
});
return this;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment