2019年9月28日土曜日

pecoでフォルダ階層移動

pecoのインストール


以下からWindows版のバイナリ(peco_windows_amd64.zip)をダウンロード

https://github.com/peco/peco/releases/

PPXフォルダにpeco.exeを置く

コマンド


(echo .. & dir /a:d /b)  | %0peco.exe | %0ppbw.exe -c *execute C,*jumppath %%*stdin

適当なフォルダでこれを実行。カーソル上下か、インクリメンタルサーチで絞り込むかしてから、Enter。



思ったこととか


・サブフォルダを選択したら、さらにそのサブディレクトリをpecoって階層移動

ができたら楽しそうだなと思って、ここ数日研究していた。bash環境だとやってる例はあるのだが(pecoでcdを快適にした|bashでもpeco - マクロ生物学徒の備忘録)、wshでやろうとすると割とややこしそうなので、放置しようかなと思っている。

ここで僕がしようとしてるのは、「思考の流れと一致する操作」を「思考と同じ速度で行う」こと。少しでもタイムラグがあれば、結局その手段は使わなくなる。ターミナルを開くまでの時間、挙動速度などを考えると、別の手段を取った方がいい気もする。

参考



2019年9月25日水曜日

連番付き変数で一時ブックマーク

一時ブックマークを実装する。以前はエイリアスを利用していたが、今回はユーザーデータを利用する。

  • setSeqUserData.js
  • getSeqUserData.js
  • SeqUserData2file.js
  • file2SeqUserData.js

は以下にあり。


設定


A_exec = { ; エイリアス
xyzzy = D:\bin\xyzzy\xyzzy.exe
}

KC_main = { ; PPcメイン窓
^S ,*setnextkey K_bookmark
}

K_bookmark = { ** comment **
S ,*script %0\Script\setSeqUserData.js,BM,%FCD
^S ,%J %*script(%0\Script\getSeqUserData.js,BM)
E ,*ppb -c *string o,name=%%*script(%%0\Script\SeqUserData2file.js,BM) %%: %%Obsq xyzzy %%so"name" %%: *script %%0\Script\file2SeqUserData.js,BM,%%so"name"
^E ,*ifmatch !CX,%n %: *alias ppcx_cmd = *execute %n,%%%%J%%FCD %%: %%K"@Q" %: *ppc -bootid:x -single %*script(%0\Script\SeqUserData2file.js,BM)
}

キーバインド


2ストロークキーを利用。
例えばC_s,sなら「Ctrl+Sのあと、Sを押す」の意味。

・C_s,s カーソル下のファイルを登録
・C_s,C_s 登録したパスに順番に移動
・C_s,e 登録したパスをエディタで編集
・C_s,C_e 登録したパスをPPCで表示

使い方


C_s,s カーソル下のファイルを登録



C_s,C_s 登録したパスに順番に移動



C_s,e 登録したパスをエディタで編集




C_s,C_e 登録したパスをPPCで表示。Shift+Enterでジャンプ



参考


つかさのほえほえ日記 - PPxで一時ブックマーク

2019年9月21日土曜日

サブ窓中心の運用③実行ファイルに投げる

1.メイン窓でファイルを選択してから、Shift+X
2.実行ファイルをサブ窓で選び、Shift+Enter



あらかじめ、実行ファイルのパスを並べたListFileを作成しておく。ここでは、PPXフォルダにbin.txtという名前で保存している。
KC_main    = {
\ENTER    ,*ifmatch CX,%n %: *execute ,%'ppcx_cmd' %: *stop
    %K"@\ENTER"
CLOSEEVENT ,*ifmatch CX,%n %: *alias ppcx_cmd = %%K"@\ENTER" %: *stop
\X ,*alias ppcx_cmd = %%Ob %%{%%FCD %%|%%} %%*extract(%n"%%%%#FCD") %%: %%K"@Q" %: *ppc -bootid:x -single %0bin.txt
}

サブ窓中心の運用②「戻る」履歴一覧

1.メイン窓でShift+Gを押して、「戻る」の履歴一覧をサブ窓で表示
2.サブ窓でShift+Enterを押し、メイン窓のパスを変更する



「戻る」の履歴は、それぞれのPPCごとに記録され、%*dirhistoryで取得できるもの。ちなみに全PPC共通のヒストリは%hnで取得できる。

KC_main    = {
\ENTER    ,*ifmatch CX,%n %: *execute ,%'ppcx_cmd' %: *stop
    %K"@\ENTER"
CLOSEEVENT ,*ifmatch CX,%n %: *alias ppcx_cmd = %%K"@\ENTER" %: *stop
\G ,*ifmatch !CX,%n %: *alias ppcx_cmd = *execute %n,%%%%j%%FCD %%: %%K"@Q" %: *ppc -r -bootid:x -single %*script(%0\Script\dirhistory2file.js9)
}

dirhistory2file.js9

//!*script

// %*dirhistory(n)をListfile形式でファイルに保存。そのファイルパスを返す
// %j %*script(%0\Script\dirhistory2file.js9,fuga.txt)
// *ppc -bootid:z -single %*script(%0\Script\dirhistory2file.js9)
// という具合に使う

// 第一引数 : 保存先のファイルパス(省略可能。その場合はテンポラリファイルに保存)

// テンポラリファイル名の作成
function getTempFile() {
  var fso = new ActiveXObject("Scripting.FileSystemObject");
  var tDir = fso.GetSpecialFolder(2);
  var tFile = fso.GetTempName();
  return tDir + "\\" + tFile;
}

var arr1 = new Array();

var stream         = new ActiveXObject("ADODB.Stream");
    stream.type    = 2;
    stream.charset = 'UNICODE';

stream.open();
stream.WriteText( ";ListFile", 1);  // 第2引数が 0:改行なし, 1:改行あり
for (var i = 0; i < 10; i++) {
  if (PPx.Extract("%*dirhistory\("+i+"\)") != ""){
    arr1.push(PPx.Extract("%*dirhistory\("+i+"\)")); // 配列に登録
  } else {
    break;
  }
}

// 配列から重複を除く
var arr2 = arr1.filter(function (x, i, self) {
  return self.indexOf(x) === i;
});

arr2.forEach(function( value ) {
  stream.WriteText(value , 1);  // 第2引数が 0:改行なし, 1:改行あり
});


// 第ニ引数(保存先のファイルパス)があればそこに、なければテンポラリファイルに保存
var filepath;
if (PPx.Arguments.Length < 1){
  filepath = getTempFile();
} else {
  filepath = PPx.Arguments.Item(0);
}
stream.saveToFile(filepath, 2);    //1:新規作成 2:新規作成 or 上書き
stream.close();

PPx.Result = filepath;


2019年9月20日金曜日

サブ窓中心の運用①基本的な仕組み


やりたいこと


今回行いたいのは、以下の動作。

1.メイン窓から操作元のファイルを指定し、サブ窓を開く
2.サブ窓で操作先のファイルを選択し、Shift+Enter
3.操作が実行され、サブ窓が閉じる



例えばファイルをコピーしたい場合、思考の流れとしては、

1.コピーしたいファイルを窓Aで選択
2.コピー先のフォルダを窓Bで選択
3.実行

となる。「窓A→窓B」で操作は終わるはずなのだ。しかし、通常の操作では

1.コピーしたいファイルを窓Aで選択
2.コピー先のフォルダを窓Bで選択
3.窓Aへ戻り、コピー操作を実行

となる。「窓A→窓B→窓A」と窓間移動が一度増えるのである。それを解消するのが今回の目的(ちなみにこれは、サブ窓を使う以外にも、「反対窓でマークしたファイルを操作」「fenrirを使う」「一行編集を使う」といった解決方法が存在する)。

準備


ポイントは、サブ窓のキーバインドの一時的な変更。

KC_main    = {
\ENTER    ,*ifmatch CX,%n %: *execute ,%'ppcx_cmd' %: *stop
    %K"@\ENTER"
CLOSEEVENT ,*ifmatch CX,%n %: *alias ppcx_cmd = %%K"@\ENTER" %: *stop
}


こうすると、エイリアスppcx_cmdに実行したい内容を登録すれば、サブ窓に使うPPC[X]のShift+ENTERの挙動を変更することが可能になる。

ファイル移動、コピー、解凍


KC_main    = {
\ENTER    ,*ifmatch CX,%n %: *execute ,%'ppcx_cmd' %: *stop
    %K"@\ENTER"
CLOSEEVENT ,*ifmatch CX,%n %: *alias ppcx_cmd = %%K"@\ENTER" %: *stop
\M ,*ifmatch !CX,%n %: *alias ppcx_cmd = *file !move ,%%*extract(%n"%%%%@*8FCDN"),%%1 %%: %%K"@Q" %: *ppc -r -bootid:x -single %1
\C ,*ifmatch !CX,%n %: *alias ppcx_cmd = *file !copy ,%%*extract(%n"%%%%@*8FCDN"),%%1 %%: %%K"@Q" %: *ppc -r -bootid:x -single %1
\U ,*ifmatch !CX,%n %: *alias ppcx_cmd = *script %0Script\wrap_7zG.js,%%*extract(%n"%%%%a8FDC"),%%1 %%: %%K"@Q" %: *ppc -r -bootid:x -single %1
}

やってることは以前の記事と同じ。ただ少し書き方を変えている
処理元のファイルにカーソルをあわせるか、マークするかしたあと、

移動:Shift+M
コピー:Shift+C
解凍:Shift+U

でサブ窓PPC[X]が開く。あとは処理先のディレクトリで、Shift+Enterを押せばいい。

参考


PPx 逆引き辞典 - PC-98ファイラーHFやPyxisのような感覚でコピー/移動/解凍
キャズムを超えろ! - Pyxisという偉大なファイラ / OSSの魅力
つかさのほえほえ日記 - コピー/移動/解凍先フォルダ選択を別窓で
つかさのほえほえ日記 - 反対窓でマークしたファイルを現在窓に移動/コピー
つかさのほえほえ日記跡地 - PPxとfenrirの連携

追記


2019/09/20 サブ窓をZからXに変更

2019年9月19日木曜日

連番付き変数のファイル入出力


連番付き変数をファイルに書き出し


%*script(%0\Script\SeqUserData2file.js,hoge)

とすると、連番付き変数(この例なら_User:hoge1 _User:hoge2 _User:hoge3 …)を一時ファイルに一行ずつ書き込み、そのパスを返す。また、

*script %0\Script\SeqUserData2file.js,hoge,%0fuga.txt

として、指定したファイル(この場合はfuga.txt)に書き込むこともできる。
連番付き変数の中身がファイルパスなら、

*ppc %*script(%0\Script\SeqUserData2file.js,hoge)

とすれば、お気に入りのように使うことができる。

 SeqUserData2file.js

//!*script
// 連番付き変数をファイルに保存。そのファイルのパスを返す

// テンポラリファイルに保存してそのパスを利用したい場合は
// %*script(%0\Script\SeqUserData2file.js,hoge) のように。特定のファイルに保存したい場合は
// *script %0\Script\SeqUserData2file.js,hoge,fuga.txt とする

// 第一引数 : ユーザデータ(_User:hoge1 _User:hoge2 _User:hoge3...のhoge)
// 第ニ引数 :保存先のファイルパス(省略可能。その場合はテンポラリファイルに保存)

// 引数がなければ終了
if (PPx.Arguments.Length < 1){
  PPx.SetPopLineMessage("引数が正しくありません。");
  PPx.Quit();
}

// テンポラリファイル名の作成
function getTempFile() {
  var fso = new ActiveXObject("Scripting.FileSystemObject");
  var tDir = fso.GetSpecialFolder(2);
  var tFile = fso.GetTempName();
  return tDir + "\\" + tFile;
}

var cmd = PPx.Arguments.Item(0);

var stream         = new ActiveXObject("ADODB.Stream");
    stream.type    = 2;
    stream.charset = 'UNICODE';

stream.open();
stream.WriteText(';ListFile',1);

// 登録済みパス一覧を表示
for (var i = 0; true; i++) {
  var str = PPx.Extract("%*getcust\(_User:"+cmd+i+"\)");
  if (str){
    stream.WriteText(str,1);
  } else {
    break;
  }
}

// 第ニ引数(保存先のファイルパス)があればそこに、なければテンポラリファイルに保存
var filepath;
if (PPx.Arguments.Length < 2){
  filepath = getTempFile();
} else {
  filepath = PPx.Arguments.Item(1);
}
stream.saveToFile(filepath,2);
stream.close();
PPx.Result = filepath;

連番付き変数をファイルから読み込み


 *script %0\Script\file2SeqUserData.js,hoge,%0fuga.txt

とすると、fuga.txtの内容を一行ずつ読み込み、連番付き変数(この例なら_User:hoge1 _User:hoge2 _User:hoge3 …)にセットする。

file2SeqUserData.js

//!*script
// テキストファイルの内容を連番付き変数にセットする
// 第一引数:ユーザーデータユーザデータ(_User:hoge1 _User:hoge2 _User:hoge3...のhoge)
// 第二引数:テキストファイルのパス
// *script %0\Script\file2SeqUserData.js,hoge,%0fuga.txt のようにして使う

// 引数がなければ終了
if (PPx.Arguments.Length < 2){
  PPx.SetPopLineMessage("引数が正しくありません。");
  PPx.Quit(-1);
}

var s = new ActiveXObject('ADODB.Stream');
var cmd = PPx.Arguments.Item(0);
var fn = PPx.Arguments.Item(1);

// エイリアスをリセット
for (var i = 0; i < 20; i++) {
  PPx.Execute("*setcust _User:-|"+cmd+i+" = ");
}

// ファイルを読み取り
s.type = 2;
s.charset = 'UNICODE';
s.open();
s.loadFromFile(fn);

var i = 0;

// エイリアスを順次セット
while(!s.EOS){
  line = s.readText(-2);
  if (line != "" && line != ";ListFile") {
    PPx.Execute("*setcust _User:"+cmd+i+" = "+line);
    i++;
  }
}
s.close();


2019年9月16日月曜日

連番付き変数の登録・取得(_User:name)

_Userを使うと、一時的に文字列を記憶するための変数を利用できる。

_User *setcust _User:name=param , %*getcust(_User:name)
・PPxの設定項目として用意されています。
・PPx内で共通です。(PPc/PPv/PPtray等の何処からでも参照・変更できます。)
・プロセスが終了しても内容は失われません。
PPx間で内容を受け渡ししたいときや、長期に渡り設定を記憶する必要があるときに適しています。

_User:hoge0 _User:hoge1 _User:hoge2 _User:hoge3...というような、連番付き変数に登録する仕組みと、呼び出す仕組みとを作ってみる。

登録


*script %0\Script\setSeqUserData.js,hoge,%FCD

とすれば、_User:hoge0 _User:hoge1 _User:hoge2...にカレントファイルのパスを登録する。

setSeqUserData.js

//!*script
// 第一引数 : ユーザデータ(hoge1 hoge2 hoge3...のhoge)
// 第二引数 : 登録したいデータ(%FCDなど)
// *script %0\Script\setSeqUserData.js,hoge,%FCD のようにして使う。
// この例だと、_User:hoge0 _User:hoge1 _User:hoge2...に順番にカレントファイルを登録する

// 引数がなければ終了
if (PPx.Arguments.Length < 2){
  PPx.SetPopLineMessage("引数が正しくありません。");
  PPx.Quit();
}

var cmd = PPx.Arguments.Item(0);
var macro = PPx.Arguments.Item(1);

// 既に登録されていたら登録しない
for (var i = 0; i < 5; i++) {
  if (PPx.Extract("%*getcust\(_User:"+cmd+i+"\)") == PPx.Extract(macro)){
    PPx.SetPopLineMessage("既に登録されてます");
    PPx.Quit();
  }
}

// _User:に登録
for (var i = 0; i < 5; i++) {
  if (!PPx.Extract("%*getcust\(_User:"+cmd+i+"\)")){
    PPx.Execute("*setcust _User:"+cmd+i+" = "+macro);
    PPx.SetPopLineMessage(cmd+i+"に登録しました");
    break;
  }
}

呼び出し


%*script(%0\Script\getSeqUserData.js,hoge)


とすれば、_User:hoge0 _User:hoge1 _User:hoge2...の中身を順次取得する。

getSeqUserData.js

//!*script
// 第一引数: ユーザーデータ(hoge0 hoge1 hoge2...のhoge)
// 実行すると、hoge0 hoge1 hoge2 hoge3...の値を返す
// %*script(%0\Script\getSeqUserData.js,hoge)のようにして使う

// 引数がなければ終了
if (PPx.Arguments.Length < 1){
  PPx.SetPopLineMessage("引数が正しくありません。");
  PPx.Quit(-1);
}

var cmd = PPx.Arguments.Item(0);

// cmd0があるかどうかをチェック
if (!PPx.Extract("%*getcust\(_User:"+cmd+0+"\)")){
  PPx.SetPopLineMessage("コマンドが空です");
  PPx.Quit(-1);
}

// cmd_idに1を足す。なければ0を入力
if (!PPx.Extract("%*getcust\(_User:"+cmd+"_id\)")){
  PPx.Execute("*setcust _User:"+cmd+"_id = 0");
}else {
  var i = parseInt(PPx.Extract("%*getcust\(_User:"+cmd+"_id\)")) + 1;
  PPx.Execute("*setcust _User:"+cmd+"_id = "+ i);
}
var i2 = PPx.Extract("%*getcust\(_User:"+cmd+"_id\)");

// commandを実行
if (PPx.Extract("%*getcust\(_User:"+cmd+i2+"\)")){
  PPx.Result = PPx.Extract("%*getcust\(_User:"+cmd+i2+"\)");
}else{
  PPx.Execute("*setcust _User:"+cmd+"_id = 0");
  PPx.Result = PPx.Extract("%*getcust\(_User:"+cmd+0+"\)");
}


参考:ブックマークのローテート - ppxmemo

2019年9月15日日曜日

PPeでメモを取る

僕は普段、howm形式でメモをとっている(参考:MoE
このような、あとで保存しておきたい用のメモとは別に、覚え書き的なメモ(例えば今日これからする予定だとか、気になった本だとか、あとで検索したい言葉だとか)を取りたいと思った。
この用途にxyzzyだと大げさなので、PPeを使ってみる。
PPCからCtrl+Hで起動。PPxフォルダにmemo.txtを作成する。キーバインドは最低限僕が必要なものだけ。

KC_main = { ; PPcメイン窓
^H ,*ppe %0memo.txt -new -k *setcaption -memo-
}

-|K_xyzzy =

K_ppe = { ; PPe(K_ppeに該当しない場合はK_edit参照)
^X ,*setnextkey K_xyzzy ; 2ストロークキー。Key Moduleが必要
^E = @END ; 行末へ
}

K_xyzzy = { ** comment **
S ,%k"^S"
^C ,*ifmatch !-memo-,%W %: %k"^S &F4" %: *stop ; 内容が変更されていたら保存して終了
 %k"&F4"
}

2019年9月12日木曜日

一行編集でWebブックマークを開く



各行によく行くサイトのurlを書いたテキストファイルをPPxフォルダに用意する。
正規表現でurlを抽出し、実行する。

web.txt

http://hoehoetukasa.blogspot.com ほえほえ日記
https://twitter.com/ twitter
https://egg.5ch.net/test/read.cgi/software/1476708638 スレ
http://xopstukasa.blogspot.com/

以下を実行。

*start %*regexp("%*input("" -title:"Webブックマーク" -mode:e -k %%:
 *completelist /set /list /file:"%0web.txt")","s@(https?://[\w/:%#\$&\?\(\)~\.=\+\-]+)(.*)@$1@")

2019年9月7日土曜日

ImageMagickで複数画像ファイルを一つのPDFに

ImageMagickを使い、マークした複数の画像を一つのPDFにする。
レスポンスファイルを使う。

*string o,tempdir=%*name(D,"%aFDC")  %:
 *string o,filename=%*name(C,'%so"response")  %:
 *cd %so"tempdir" %:
 %Ob %'imagemagic' @%so"filename" %"拡張子を入力してください"%{%FD\%|hoge%|.pdf%}

普通に

%Ob %'imagemagic' %@FDC hoge.pdf


とすると失敗したので色々模索してみた。もっと簡単な書き方があるかもしれない。