フォルダツリーをポップアップ表示

2024年12月31日 (火) 07:31時点におけるMSY-07 (トーク | 投稿記録)による版 (ソースコードの整形)

今開いているファイルのフォルダの内容をポップアップで表示して、選択するとそのファイルを開きます。

手石さんのポップアップメニューでファイル選択の下位互換です。手石さんのものはページ切り替えなどのボタンがあり、これよりも使いやすいと思います。

インストール

  1. 下のスクリプトをコピーして、MeryのMy Macroフォルダなどに保存
  2. マクロを[カスタマイズ]→[新規作成]で登録し、Alt+Pなどお好みで設定する

カスタマイズ

変数を変えることで、挙動がいくらかカスタマイズできます。

名前 初期設定 効果
CONFIG.folder_pattern /^[^\.]/ この正規表現にマッチするフォルダ名を一覧に含めます。

初期設定では . で始まるフォルダを除外します。

CONFIG.file_pattern /^[^\.]/ この正規表現にマッチするファイル名を一覧に含めます。

初期設定では . で始まるフォルダを除外します。

CONFIG.file_ignore_pattern /\.(?:png|jpg|gif|db|exe|dll|obj|tmp)$/i この正規表現にマッチするファイル名は一覧から除きます。

初期設定では画像ファイルなど適当に思いついたものを除外してあります。

CONFIG.ignore_case true trueにすると一覧のソートで大文字小文字を無視します。
CONFIG.sort_by_extension true trueにすると一覧で拡張子ごとにまとめます。
CONFIG.sort_by_modified_time false trueにするとファイルの最終変更時間で降順にソートします。

これをtrueにすると上2つの設定は無視されます。

変更履歴

  • r2 (2013-09-21)
    • ディレクトリをまたぐと開けなかったバグの修正
  • r1 (2013-09-10)
    • 初版

ソースコード

// 同じフォルダにあるファイルを開く.js r2
// もしくは 簡易フォルダツリー

CONFIG = {}

/** 設定 **/

// 一覧に含めるフォルダ名の正規表現
CONFIG.folder_pattern = /^[^\.]/

// 一覧に含めるファイル名の正規表現
CONFIG.file_pattern = /^[^\.]/

// 別例: 現在のファイルと同じ拡張子だけ表示
// CONFIG.file_pattern = document.Name.indexOf('.') == -1 ? /./ : RegExp(document.Name.substr(document.Name.indexOf('.')), "i")

// 一覧から除外するファイル名の正規表現
CONFIG.file_ignore_pattern = /\.(?:png|jpg|gif|db|exe|dll|obj|tmp)$/i

// 大文字小文字を無視するならtrue、そうでなければfalse
CONFIG.ignore_case = true

// 拡張子ごとにまとめるならtrue、そうでなければfalse
CONFIG.sort_by_extension = true

// 時間でソートするならtrue、そうでなければfalse
CONFIG.sort_by_modified_time = false

/** 以下本体 **/

var FS = new ActiveXObject("Scripting.FileSystemObject")

function main() {
	var dir = document.Path
	var choosed = choose(ls(dir))

	while (choosed && /\/$/.test(choosed)) {
		dir = FS.BuildPath(dir, choosed)
		choosed = choose(ls(dir))
	}

	if (choosed) {
		var path = FS.BuildPath(dir, choosed).replace(/\//g, '\\')
		editor.OpenFile(path, 0, meOpenAllowNewWindow)
	}
}

function ls(path) {
	var folder = FS.GetFolder(path)

	var folders = []
	each_item(folder.SubFolders, function(e) {
		if (CONFIG.folder_pattern.test(e.Name)) {
			folders.push(e.Name + "/")
		}
	})
	folders.sort()

	folders.unshift('../')

	var files = []
	each_item(folder.Files, function(e) {
		if (CONFIG.file_pattern.test(e.Name) && !CONFIG.file_ignore_pattern.test(e.Name)) {
			files.push(e.Name)
		}
	})

	if (CONFIG.sort_by_time) {
		files.sort(function(a, b) {
			a = FS.GetFile(a).DateLastModified
			b = FS.GetFile(b).DateLastModified
			return a < b ? 1 : a > b ? -1 : 0
		})
	} else if (CONFIG.ignore_case) {
		files.sort(function(a, b) {
			a = a.toLocaleLowerCase()
			b = b.toLocaleLowerCase()
			return !a ? -1 : !b ? 1 : a < b ? -1 : a > b ? 1 : 0
		})
	} else {
		files.sort()
	}

	if (CONFIG.sort_by_extension) {
		// JScriptは安定ソートなのでこれでも大丈夫なはず
		files.sort(function(a, b) {
			var sa = get_extension(a)
			var sb = get_extension(b)
			return !sa ? 1 : !sb ? -1 : sa < sb ? -1 : sa > sb ? 1 : 0
		})
	}

	return folders.concat(files)
}

function get_extension(str) {
	var i = str.lastIndexOf('.')
	return i >= 0 && str.substr(i + 1)
}

function each_item(collection, callback) {
	var result

	for (var e = new Enumerator(collection); !e.atEnd(); e.moveNext()) {
		result = callback(e.item())
		if (result) {
			return result
		}
	}
}

function choose(words) {
	var menu = makeMenu()
	var i = menu.Track(0)

	return i && words[i - 1]

	function makeMenu() {
		var menu = window.CreatePopupMenu()

		if (!words || words.length == 0) {
			return menu
		}

		var n = -1

		function addHotkey(word) {
			if (n > 34) {
				return word
			}
			n++
			return "&" + n.toString(36) + ". " + word
		}

		for (var i = 0; i < words.length; i++) {
			menu.Add(addHotkey(words[i]), i + 1)
		}

		return menu
	}
}

main()
スポンサーリンク