2020年12月28日月曜日

PPx+howmでtodo管理

僕はPPx+howmでメモ環境を構築している(参考:MoE)。これに

  • 一行編集からタイトルを指定してhowmファイルを作成
  • 一行編集からhowmファイルのタイトルを変更

を追加して、todo管理もできるようにする。




 準備


以下をScriptフォルダに保存。それぞれ「タイトルを指定してhowmファイルを作成」「タイトルを変更」「タイトルを取得」するスクリプト。

settitle.js
//!*script

// howmファイルを作成する
// 第一引数:作成するフォルダ
// 第二引数:タイトル
// *script %0Script\makehowm.js,%1,homuhomu
// editor %*script(%0Script\makehowm.js,%1,%*now(date))

var fso = PPx.CreateObject("Scripting.FileSystemObject");
var dirname = PPx.Arguments.Item(0);
var filename = PPx.Extract("%*nowdatetime(Y-N-D-HMS)")+".howm";
var filepath = fso.BuildPath(dirname,filename);
var str="= ";

// 引数が複数あればそれをつなげる
for (var i = 1; i < PPx.Arguments.length; i++) {
  if (i==1){
    str += PPx.Arguments.Item(i);
  } else {
    str += ","+PPx.Arguments.Item(i);
  }
}

str += "\r\n\r\n\r\n["+PPx.Extract('%*now')+"]";

var file = fso.OpenTextFile(filepath, 2, true);
file.Write(str);
file.Close();
PPx.result = filename;

changetitle.js

//!*script
// 与えられたhowmファイルのタイトルを変更するスクリプト
// 第一引数:howmファイルパス
// 第二引数:変更するタイトル
// *script %0Script\changetitle.js,%R,homuhomu

var s="";
var str = "";
var filepath = PPx.Arguments.Item(0);
var fso = PPx.CreateObject("Scripting.FileSystemObject");
var f = fso.OpenTextFile(filepath, 1);

// 引数が複数あればそれをつなげる
for (var i = 1; i < PPx.Arguments.length; i++) {
  if (i==1){
    str=str + PPx.Arguments.Item(i);
  } else {
    str=str + ","+PPx.Arguments.Item(i);
  }
}

s = "= "+str+"\r\n";

f.ReadLine(); //空読みで一行目を飛ばす

while (!f.AtEndOfStream) {
s += f.ReadLine()+"\r\n"; //sに一行づつ読み込み
}
f.Close();

//PPx.Echo(s);

// 書き込み
var f2 = fso.OpenTextFile(filepath, 2);
f2.Write(s);
f2.Close();


gettitle.js

//!*script
// 与えられたhowmファイルの一行目の2文字~30字を切り取ったものを返すスクリプト
// 第一引数:howmファイルのパス
// %*script(%0Script\gettitle.js,%R)

var filepath = PPx.Arguments.Item(0);
var objFileSys = PPx.CreateObject("Scripting.FileSystemObject");
var objInFile = objFileSys.OpenTextFile(filepath, 1);
var str = objInFile.ReadLine().slice( 2,30 );
objInFile.Close();

PPx.result = str;


以下を編集して取り込み。パスは各自で読み替えてください。
KC_main	= {	; PPcメイン窓
\K	,*ifmatch "/D:\\Temp\\todo/",%1 %: *script %0Script\settitle.js,D:\\Temp\\todo,%"todo"%E %: *stop
	%K"@\K"
\E	,*ifmatch "/D:\\Temp\\todo/",%1 %: *script %0Script\changetitle.js,%R,%"todoの変更"%{%*script(%0Script\gettitle.js,%R)%}%: *stop
	%K"@\E"
}

_Command	= {	; ユーザコマンド・関数
todo	= *script %0Script\settitle.js,D:\Temp\todo,%*arg(1)
}


やり方


*todo メモの内容

でメモを作成。todoフォルダでShift+Kを押すと表示される一行編集に入力してもいい。


todoフォルダでhowmファイルにカーソルをあわせ、Shift+Eを押すとタイトルを変更できる。


追記 2021-01-28

*todo の引数がなければtodoフォルダを開く設定は以下のようになる。

_Command	= {	; ユーザコマンド・関数
todo	= *ifmatch !0,0%*arg(1) %: *script %0Script\settitle.js,C:\Users\tukasa\Dropbox\todo,%*arg(1) %: *stop
	*execute C,*jumppath "C:\Users\tukasa\Dropbox\todo" %: *focus C
}

2020年12月16日水曜日

キーバインドを含めてPPxをもっとあふっぽくする

キーバインド含めてもっとあふっぽくしてみた。



PPxをできるだけあふっぽくする」のときは色々スクリプトやModuleが必要だったりしたが、今回は基本不要。
AFXWKEY.TXTを見ながらやったからだいたい網羅してるはずだが、ややこしそうなのは実装してない。具体的には

・2列~9列表示(2~9):列指定はおそらくできない。表示形式はMC_celsで好きにカスタマイズできるのであえて指定する必要性もない気がする
・サムネイル表示トグル( shift+, ):*viewstyle サムネイル1(&T)でできるが、デフォの表示形式をどれにするか決めないと、通常表示とサムネイル表示のトグルが難しそうだなと思ってやってない
・保持画像(G):PPvのLOADEVENTでパスを取得、適当な変数に保存するとかすればいけるかなと思ったけどやってない
左右窓それぞれの履歴メニュー(H):履歴は*dirhistory(n)で取得できるがメニュー化するには多分スクリプトが必要普通にできました^^;
・画像表示場所切り替え(M):「反対窓→両窓→メッセージ窓含めて全体表示」と切り替わるが、メッセージ窓含める/含めないの区別は無理?「反対窓→両窓」切り替えだけなら、エイリアスを利用すればいけそうではある
・小物メニュー

など。

やり方


以下を「編集して取込」してPPxを再起動するだけ。
ただ、Alt+Enterによる画像の「最大化/通常表示トグル」はPaper Plane xUI Window Moduleが必要。
ログ窓がほしいときはメニューバーの「view - レイアウト - ログ」で表示できる。
XC_celD	= _AUTO,_AUTO,1,7	; エントリ表示 文字,背景,カーソル,マーク
XC_dpmk	= 1	; エントリマスクを表示	0:しない 1:する
X_combo = 1 ; 複数 PPc を一体化 0:しない 1:する
X_mpane = 2,2 ; 一体化時の最大同時表示ペイン数,起動時のペイン数
X_inag = 0 ; 現在窓以外はグレー調に 0:しない 1:する
XC_page	= 1
XC_mvLR	= 4,1,0,B0100,0,B100	; [←][→]
CC_log	= _WHI,_BLA	; 共用ログ、アドレスバー(文字,背景)_AUTO可
XV_drag = 2,1,3,0 ; ドラッグ開始ボタン スクロール,選択,窓移動,ジェスチャ(右のみ)
  ; 0:使用しない 1:左 2:右 3:中/ホイール 4:左右同時 5:第4 6:第5
X_fles	= 1	; 画面のちらつき対策を 0:しない 1:する
XC_isea	= 0,1,1,0,0	; インクリメンタルサーチ動作 方法,位置,対象,ハイライト,ヒストリ保存
C_eInfo	= _AUTO,_DRED,_AUTO,_DBLA,_DBLU,_DCYA, _DBLA,_BRO,_GRE,_WHI,_AUTO,HA00000,_AUTO, _SBLU,_BRO,_CYA,_GRE,_RED,_MAG,_DRED, _AUTO 
X_bg	= { 
Bright	= 60
}

_others	= {	; その他設定
SyncViewID	= Y
}

_Command	= {	; ユーザコマンド・関数
afxview	= *ifmatch %NC,%NCBA#L %: *ppv -bootid:Y -parent:%N~ %*name(CD,"%R","%1") -k *execute C,*ppvoption sync on %: *stop
	*ppv -bootid:A -popup:%NC# %*name(CD,"%R","%1")
allview	= *ppv -bootid:A -popup:%NC# %*name(CD,"%R","%1")
halfview	= *ppv -bootid:Y -parent:%N~ %*name(CD,"%R","%1") -k *execute C,*ppvoption sync on
}

KC_main = { ; PPcメイン窓
TAB	,*ifmatch 0,0%NVY %: %K"@TAB" %: *stop
ENTER	,*ifmatch 0,0%NVY %: %K"@ENTER" %: *stop
	 %K"@\Y"
ESC	,*ifmatch 0,0%NVY %: %K"@PAUSE" %: *stop
	 *execute CA,*ppvoption sync off %: *focus CAEND = @F5
HOME = @\HOME
LEFT	,*ifmatch 0,0%NVY %: %K"@LEFT" %: *stop
	 %K"@UP"
RIGHT	,*ifmatch 0,0%NVY %: %K"@RIGHT" %: *stop
	 %K"@DOWN"
INS = @\INS
DEL = @\DEL
'-'	= @^D
NUM- ,*pairrate 50
A = @\HOME
D = @\D
E ,%"JMTE|Text edit"%Ob,editor %*name(CD,"%R","%1")
F = @\J
H = @^\LEFT
I ,*countsize
J = @0
L = @\L
N , %j%*tree(\\)
O	,*ifmatch "/^%*regexp("%FD","s/\\/\\\\/g")$/",%2 %: %J%*extract(~"%%R") %: *stop
	 %j%2
Q = @&F4
T , %j%*tree(%1)
W = @O
Z = CUSTOMIZE
':' = @F
'*' = @\F
'`' = @'+'
'\' = NULL
V_HDC , %J\
V_HE2 , %KC"^\F10
\END , %K~"@F5
\HOME = @\END
\A = @\END
\C , *ppcfile !copy,%M_pjump,A
\D = @D
\E ,*makefile %1\%"新規テキストの編集"%$E.txt %: %Ob editor %1\%"新規テキストの編集"%$E.txt
\F = @^W
\J = @L
\M ,*ppcfile !move,%M_pjump,A
\O	,*ifmatch "/^%*regexp("%FD","s/\\/\\\\/g")$/",%2 %: *execute ~,%%J%R %: *stop
	 *execute ~,%%j%1
\P , *pack "%2",indiv
\V = @I
\X = @H
^ENTER = @Z
^SPACE ,*range lastmark cursor
^END = @^F5
^LEFT ,*cursor 8,1,12,0,12,0
^UP = @PUP
^RIGHT ,*cursor 8,1,13,0,13,0
^DOWN = @PDOWN
^INS ,%z"#17:\"
^DEL ,%z"#10:\"
^V_HBA ,*cursor 16,1,5,1,5,0
^\END ,%K"@^F5"
^\LEFT = @^LEFT
^\UP = @DEL @UP @UP @INS @DOWN
^\RIGHT = @^RIGHT
^\DOWN = @DEL @INS @DOWN
^\V_HBA ,*cursor 16,-1,5,1,5,0
&ENTER , *ifmatch 0,0%NVY %: *stop
	 %K"@\Y" %: %Oi *ppv -bootid:A -popup:%NC# %*name(CD,"%R","%1") %: *maximize %NVA
&RIGHT ,*ifmatch %NC,%NCBA#L %: *pairrate +3 %: *stop
 *pairrate -3
&LEFT ,*ifmatch %NC,%NCBA#L %: *pairrate -3 %: *stop
 *pairrate +3
&Z ,*ppc -alone
&'\' ,%M_ClipPath
&\Z ,*ppc -runas -alone
^A = @&\A
^B = @&\B
^C = @&\C
^D = @&\D
^E = @&\E
^F = @&\F
^G = @&\G
^H = @&\H
^I = @&\I
^J = @&\J
^K = @&\K
^L = @&\L
^M = @&\M
^N = @&\N
^O = @&\O
^P = @&\P
^Q = @&\Q
^R = @&\R
^S = @&\S
^T = @&\T
^U = @&\U
^V = @&\V
^W = @&\W
^X = @&\X
^Y = @&\Y
^Z = @&\Z
^V_H31 = @&\1
^V_H32 = @&\2
^V_H33 = @&\3
^V_H34 = @&\4
^V_H35 = @&\5
^V_H36 = @&\6
^V_H37 = @&\7
^V_H38 = @&\8
^V_H39 = @&\9
}

KV_main = {
ENTER , %K"@Q" %: %KC"@DOWN"
ESC = @Q
2 , *viewoption -tab:2
4 , *viewoption -tab:4
8 , *viewoption -tab:8
\E , *viewoption -euc
\I , *viewoption -utf16be
\J , *viewoption -jis
\O , *viewoption -utf8
\S , *viewoption -sjis
\U , *viewoption -utf16
&Z , *ppc -alone
&\Z , *ppc -runas -alone
}

KV_crt = {
SPACE = @']'
E , %Ob editor %FCD %: %K"@Q"
H = @'['
L = @']'
F1 = @HOME
F2 = @END
F3 = @J
F4 = @F
F5 = @']'
\ENTER , %Ob editor %FCD %: %K"@Q"
\SPACE = @'['
\C = @C
\F = @B
\L = @'['
\N = @T
\T = @C
\F4 = @B
\F5 = @'['
^SPACE = @I
^PUP = @HOME
\PDOWN = @END
&UP , %KC"@UP@N"
&DOWN , %KC"@DOWN@N"
}

KV_page = {
SPACE = @']'
LEFT = @PUP
RIGHT = @PDOWN
E , %Ob editor %FCD %: %K"@Q"
H = @'['
L = @']'
F1 = @HOME
F2 = @END
F3 = @J
F4 = @F
F5 = @']'
\ENTER , %Ob editor %FCD %: %K"@Q"
\SPACE = @'['
\C = @C
\F = @B
\L = @'['
\N = @T
\T = @C
\F4 = @B
\F5 = @'['
^SPACE = @I
^PUP = @HOME
\PDOWN = @END
&UP , %KC"@UP@N"
&DOWN , %KC"@DOWN@N"
}

KV_img    = {
SPACE , %KC"@SPACE@N"
END , *zoom -1
HOME , *zoom 0
LEFT ,%KC"@UP@N"
UP ,%KC"@UP@N"
RIGHT ,%KC"@DOWN@N"
DOWN ,%KC"@DOWN@N"
G = @Q
L = @K
R = @L
'\' ,%M_WallPaper
\SPACE , %KC"@\SPACE@N"
\END , *zoom -1
^I , *cliptext %R
^W , *setcust X_bg:P_%*extract(C"%%n")=%FCD %: *customize X_bg:T_%*extract(C"%%n")=1
&ENTER , *togglewinsize
}

E_cr	= {	; [Enter]用判別
*	,*allview
TXT	,*allview
:UTEXT	,*allview
JPEG	,*afxview
:JPEG	,*afxview
BMP	,*afxview
:BMP	,*afxview
HOWM	,*allview
CFG	,*allview
INI	,*allview
PNG	,*afxview
:PNG	,*afxview
GIF	,*afxview
:GIF	,*afxview
}

-|M_ClipPath =

M_ClipPath    = {
ファイル名\t【カーソル上】    = *cliptext %R %: *linemessage Clip : %R
フルパスファイル名\t【カーソル上】    = *cliptext %FCD %: *linemessage Clip : %FCD
--    = 
フルパス名    = *cliptext %1 %: *linemessage Clip : %1
--    = 
ファイル名\t【マーク・スペース区切り】    = *cliptext %#FC %: *linemessage Clip : %#FC
フルパスファイル名\t【マーク・スペース区切り】    = *cliptext %#FCD %: *linemessage Clip : %#FCD
}

-|M_WallPaper =

M_WallPaper = { ** comment **
画像をクリップボードに転送 = %K"@^C"
情報をクリップボードに転送 = *cliptext %R 
ファイルに保存する = %K"@^S"
-- =
PPC[&A]の壁紙にする = *setcust X_bg:P_ca=%FCD %: *customize X_bg:T_ca=1
PPC[&B]の壁紙にする = *setcust X_bg:P_cb=%FCD %: *customize X_bg:T_cb=1
-- =
PPC[A]の壁紙をナシにする = *setcust X_bg:-|P_ca= %: *customize X_bg:-|T_ca=
PPC[B]の壁紙をナシにする = *setcust X_bg:-|P_cb= %: *customize X_bg:-|T_cb=
}

2020年12月11日金曜日

PPxをあふっぽくする改

少し時間に余裕ができると「PPxをあふとかだいなファイラーとかっぽくしてみるかー!」という気になる。以前はあふっぽい画像表示を*capturewindowや*fitwindowで実現してたが、最近(一年以上前だから最近ではない)-popupとか-parentとかが実装されたので、もっとあふっぽくできそうだ。

時間ができたらそのうち「キーバインドを含めてあふっぽくする」「できるだけあふっぽくする」とかもするつもり。


やり方

以下をクリップボードにコピーして、編集して取込をする。

X_combo = 1 ; 複数 PPc を一体化 0:しない 1:する
X_mpane = 2,2 ; 一体化時の最大同時表示ペイン数,起動時のペイン数
X_inag = 0 ; 現在窓以外はグレー調に 0:しない 1:する
XC_page	= 1
XC_mvLR	= 4,1,0,B0100,0,B100	; [←][→]

_others	= {	; その他設定
SyncViewID	= Y
}
_Command	= {	; ユーザコマンド・関数
afxview	= *ifmatch %NC,%NCBA#L %: *ppv -bootid:Y -parent:%N~ %*name(CD,"%R","%1") -k *execute C,*ppvoption sync on %: *stop
	*ppv -bootid:A -popup:%NC# %*name(CD,"%R","%1")
allview	= *ppv -bootid:A -popup:%NC# %*name(CD,"%R","%1")
halfview	= *ppv -bootid:Y -parent:%N~ %*name(CD,"%R","%1") -k *execute C,*ppvoption sync on
}
E_cr	= {	; [Enter]用判別
TXT	,*allview
:UTEXT	,*allview
JPEG	,*afxview
:JPEG	,*afxview
BMP	,*afxview
:BMP	,*afxview
HOWM	,*allview
CFG	,*allview
INI	,*allview
PNG	,*afxview
:PNG	,*afxview
GIF	,*afxview
:GIF	,*afxview
}

KC_main	= {	; PPcメイン窓
TAB	,*ifmatch 0,0%NVY %: %K"@TAB" %: *stop
RIGHT	,*ifmatch 0,0%NVY %: %K"@RIGHT" %: *stop
	 %K"@DOWN"
LEFT	,*ifmatch 0,0%NVY %: %K"@LEFT" %: *stop
	 %K"@UP"
ENTER	,*ifmatch 0,0%NVY %: %K"@ENTER" %: *stop
	 %K"@\Y"
}
KV_main	= {	; PPvメイン窓
ENTER , %K"@Q" %: %KC"@DOWN"
ESC = @Q
}

KV_page = {
LEFT ,%K"@PUP"
RIGHT ,%K"@PDOWN"
}

KV_img = {
UP ,%KC"@UP@N"
LEFT ,%KC"@UP@N"
DOWN ,%KC"@DOWN@N"
RIGHT ,%KC"@DOWN@N"
SPACE    ,%KC"@SPACE@N"
\SPACE    ,%KC"@\SPACE@N"
}

2020年9月8日火曜日

サブ窓の起動パスをフォルダごとに指定

僕は、移動やコピーや解凍をする際は、サブ窓で処理先を指定している(参考:コピー/移動/解凍先フォルダ選択を別窓で)。

サブ窓の起動パスを、フォルダごとにリストファイルで指定できるようにする。


準備

以下を編集して取り込み。ちなみに展開に使ってるwrap_7z.jsについては、一つ前の記事を参照のこと。

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 %*getfileto()
\C ,*ifmatch !CX,%n %: *alias ppcx_cmd = *file !copy ,%%*extract(%n"%%%%@*8FCDN"),%%1 %%: %%K"@Q" %: *ppc -r -bootid:x -single %*getfileto()
\U ,*ifmatch !CX,%n %: *alias ppcx_cmd = *script %0Script\wrap_7z.js,%%*extract(%n"%%%%a8FDC"),%%1 %%: %%K"@Q" %: *ppc -r -bootid:x -single %*getfileto()
}

_Command = {
getfileto = *ifmatch "o:e,a:d-","fileto.txt" %: *return "fileto.txt"
  %1
}

次に、起動パスを指定したいフォルダに、リストファイルのfileto.txtを用意する。例えばdownloadフォルダから、binフォルダやTempフォルダを処理先に選ぶことが多い場合は、downloadフォルダにfileto.txtをおいて、その中身を以下のようにする。

D:\bin
D:\Temp

カレントフォルダにfileto.txtがあればそれを、なければカレントフォルダパスを返すユーザーコマンドgetfiletoを使い、サブ窓のパスを変更するという仕組みになっている。

やり方

コピーの例で説明する。コピーしたいファイルにマークしてShift+C。するとサブ窓が開く。サブ窓の起動フォルダは、カレントフォルダにfileto.txtがあればそれを参照したものに、なければカレントディレクトリになる。

サブ窓で処理先のフォルダ内に移動し、Shift+Enterを押すと、先にマークしたファイルはそこにコピーされ、サブ窓は消える。


移動したい場合はShift+M、書庫を展開したい場合はShift+Uで同じようにする。

2020年9月7日月曜日

7-zip(7z.exe)で書庫の展開

以前作ったwrap_7zG.jsが機能しなくなってたのでスクリプトを見直してみた。

7-Zipを使い、複数の書庫ファイルを特定のフォルダに展開したい場合に使う。

例えばカレントフォルダに展開したい場合は、書庫ファイルをマークして以下のコマンドを実行する。

*script %0\Script\wrap_7z.js,%a8FCDN,%1

wrap_7z.js

//!*script
// 7-zipを実行して展開先フォルダにアーカイブファイルを展開する
// 第一引数: レスポンスファイル
// 第二引数: 展開先フォルダ

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

//  7z.exeのパス
var Exec = "C:\\Program Files\\7-Zip\\7z.exe";
var responseFile = PPx.Arguments.Item(0);
var extractFolder = PPx.Arguments.Item(1);

var archiveFiles = GetList(responseFile);
// 個々のファイルごとに7-Zipで展開
for (x in archiveFiles){
  if (archiveFiles[x] == ""){
    break;}
  PPx.Execute('\"'+Exec+'\" x -o\"'+extractFolder+'\\*\" '+archiveFiles[x]);
}

// レスポンスファイルからファイル名のリストを作成
function GetList(list)
{
  var f = CreateObject("ADODB.Stream");
  
  f.type = 2;
  f.charset = "UTF-8";
  f.open;
  f.LoadFromFile(list);
  text = f.readText(-1).split("\r\n");
  f.close;
  return text;
}


2020年5月19日火曜日

PPb+pecoで英和辞書

英和辞典を一行編集で引く方法を以前紹介したが、連続的に辞書を引く必要があるとき、一行編集をその度に表示しないといけないのが煩わしいなと思っていた。
なので別の方法を考案。

chcp 65001 %: type %0ejdic-hand-utf8.txt | %0peco.exe

これでPPbを辞書代わりにできる。


辞書ファイルは以下。

2020年5月5日火曜日

PPx+pecoで柔軟にフォルダ階層移動


pecoで柔軟に階層移動できるようにする。以前は一階層しか移動できなかったが、今回は複数階層の移動が可能。
Script Module以外にText Moduleが必要。Releases · peco/peco · GitHubからWindows版のバイナリ(peco_windows_amd64.zip)をダウンロードし、peco.exeをPPxフォルダに置いておく。



以下を編集して取込。

_Command = {
folder2peco = chcp 65001
 %Oi (echo ---thispath & echo .. & dir /a:d-s /b)  | %0peco.exe | %0ppbw.exe -c *alias selectedpath=%%*stdin(-utf8)
 *return %'selectedpath'
root2peco = chcp 65001
 %Oi (echo ---thispath & dir /a:d-s /b)  | %0peco.exe | %0ppbw.exe -c *alias selectedpath=%%*stdin(-utf8)
 *return %'selectedpath'
move2folder = *ifmatch 0,0%*substring("%1",3) %: *string o,hoge=%*root2peco()
 *ifmatch !0,0%*substring("%1",3) %: *string o,hoge=%*folder2peco()
 *ifmatch ---thispath,%so"hoge" %: *return
 *jumppath %*name(DC,%so"hoge") %: *execute,*%*arg(0)
}

PPcで

*move2folder %: *focus "PPB[" %: %k"ESC"

を実行する。

ポイントとか


  • 試行錯誤してる間、二度くらいカスタマイザーが起動しなくなって再インスコすることになった(再現性はよくわからない)。試す方は注意を
  • move2folderが本体
  • folder2pecoとroot2pecoは、カレントフォルダのサブフォルダ一覧をpecoに投げ、結果を返すユーザコマンド。2つの違いは「..」を表示するか否か
  • chcp 65001 で文字コードをUTF-8に
  • ユーザコマンドは*test以外に%*test()の形でも使える
  • linuxだと標準出力は簡単に取り出せるようだが、Windowsだと難しい(多分)。そこで、「エイリアスに格納して、returnで返す」という手続きを踏んでいる。_User:nameではなくエイリアスを使ってるのは、_User:nameだと処理速度が落ちるから(おま環かも)
  • ユーザコマンド中の*%arg(0)で再帰呼び出しができる。以下はもっと単純な例


_Command = {
test = *ifmatch 0,0%"何も入力しないでくだしあ><"%E %: *return
 *execute,*%*arg(0)
}


2020年5月3日日曜日

ウィンドウの位置とサイズを引数で変更

xyzzyの位置がずれたとき、いちいちマウスでつまんだりドラッグしたりして直すのが面倒なので、コマンドで戻せるようにする。

;; ウィンドウの位置とサイズを引数で変更
;; 「X座標 Y座標 ウィンドウ幅 ウインドウの高さ」の4つの引数を取る
;; > xyzzy の音 - バッファ/ウィンドウ/フレーム
;; > http://hie.s64.xrea.com/xyzzy/note/buffer.html#xyzzy-resize
;; を参考にした

(require "wip/winapi")
(unless (fboundp 'SetWindowPos)
  (c:*define-dll-entry winapi:BOOL SetWindowPos
    (winapi:HWND winapi:HWND winapi:INT winapi:INT winapi:INT winapi:INT winapi:UINT)
    "user32"))
;サイズを変更
(defun xyzzy-resize ()
  (interactive)
  (if si:*command-line-args* (setq x (pop si:*command-line-args*))(setq x "1280"))
  (if si:*command-line-args* (setq y (pop si:*command-line-args*))(setq y "43"))
  (if si:*command-line-args* (setq w (pop si:*command-line-args*))(setq w "608"))
  (if si:*command-line-args* (setq h (pop si:*command-line-args*))(setq h "1023"))
  ;位置/サイズを指定
  (SetWindowPos (get-window-handle) 0
  (parse-integer x)  ;X座標
  (parse-integer y) ;Y座標
  (parse-integer w) ;ウィンドウ幅
  (parse-integer h) ;ウィンドウ高さ
  0))


xyzzy -e (xyzzy-resize) 1280 43 608 1023

のように「X座標 Y座標 幅 高さ」の数値を与えて外部から変更する。

参考


2020年4月25日土曜日

DialogHandler+PPc



画像とかをtwitterにうpするとき、PPcから選べるようにする。DialogHandlerを利用。以前はPPvから起動できるようにしてたが、使い勝手が悪く使わなくなっていた。

以下を編集して取込。

KC_main = { ; PPcメイン窓
\ENTER ,*ifmatch CX,%n %: *execute ,%'ppcx_cmd' %: *stop
 %K"@\ENTER"
}
_Command = { ; ユーザコマンド・関数
changedialog = *ifmatch !CX,%n %: *alias ppcx_cmd = %%Ob D:\bin\DialogHandler\DialogHandler.x86-64.exe %%#FCD %%: %%K"@Q" %: *ppc -r -bootid:x -single
}

一行編集から*changedialogを実行すると、PPC[X]が起動する。目的のファイルにカーソルを合わせてShift+Enterで、ダイアログが切り替わる。
ちなみにエイリアスをかませたりとややこしいことをしてるのは、PPC[X]を別の用途でも使いたいから

2020年4月24日金曜日

複数の窓の位置と大きさを一度に変更

窓を複数枚運用していると、大きさや位置をそれぞれ手動で調整するのが面倒になる。
そこで、一度に変更するスクリプトを作った。
PPx Window Moduleが必要。またScript Moduleは最新のものを。

SetDimensions.js

//!*script

// 要Window Module
// 引数として
// C_A 5 5 600 600 ,C_B 5 605 600 600 ,V_A 605 5 600 600
// のように「窓ID 左端の座標 上端の座標 幅 高さ」を,で区切って取得
// それを再現する

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

var ary;
var win_id;
for(i = 0; i < PPx.Arguments.Length; i++) {
  ary = PPx.Arguments.Item(i).split(/\s+/);
  win_id = ary[0].slice(-1);
  if (ary[0].slice(0,1)=="C"){
    PPx.Execute("%Oi *ppc -r -bootid:"+win_id);
    PPx.Execute("*windowposition %NC"+win_id+","+ary[1]+","+ary[2]);
    PPx.Execute("*windowsize %NC"+win_id+","+ary[3]+","+ary[4]);
  } else {
    PPx.Execute("%Oi *ppv -bootid:"+win_id);
    PPx.Execute("*windowposition %NV"+win_id+","+ary[1]+","+ary[2]);
    PPx.Execute("*windowsize %NV"+win_id+","+ary[3]+","+ary[4]);
  }
}

使い方


*script %0Script\SetDimensions.js,C_A 5 5 600 600 ,C_B 5 605 600 600 ,V_A 605 5 600 600

と、引数に「窓ID 左端の座標 上端の座標 幅 高さ」を与えると、それぞれのIDのPPCあるいはPPVを起動。窓の位置や大きさを変更する。

*script %0Script\SetDimensions.js, %*getcust(S_dimensions:normal)

のように、与える情報をユーザ変数に登録して使うとかするとスマート。
ちなみに以下は、現在開いている窓の情報をこの形式で取得するためのスクリプト。僕は

echo %*script(%0Script\GetDimensions.js)

で情報を吐き出させて使っている。

GetDimensions.js

//!*script

// 要Window Module
// 実行すると
// C_A 5 5 600 600 ,C_B 5 605 600 600 ,V_A 605 5 600 600
// のように「窓ID 左端の座標 上端の座標 幅 高さ」を,で区切った
// 返り値を返す

var ppclist = PPx.Extract('%*ppxlist(-C)').split( "," );
ppclist.pop();
var ppvlist = PPx.Extract('%*ppxlist(-V)').split( "," );
ppvlist.pop();
var winlist = ppclist.concat(ppvlist);
var str = "";
var l,t,w,h;
for(i = 0; i < winlist.length; i++) {
  l = PPx.Extract("%*windowrect(%N"+winlist[i]+",l)");
  t = PPx.Extract("%*windowrect(%N"+winlist[i]+",t)");
  w = PPx.Extract("%*windowrect(%N"+winlist[i]+",w)");
  h = PPx.Extract("%*windowrect(%N"+winlist[i]+",h)");
  str = str + winlist[i]+" "+l+" "+t+" "+w+" "+h+" ,";
}

PPx.Result = str;


2020年4月18日土曜日

LaTeX(upLaTeX)+jlreqで縦書き・二段組の冊子を作る

必要があって十年ぶりくらいにLaTeXについて調べ直し、縦書きの冊子を作った。ていうかTeXって縦書きできたんだね!
忘れる前にそのまとめ。環境はWindows10。

TeXLiveのインストール


TeXLiveをインストール。以前主流だったTeXインストーラ 3よりも簡単にできるようだ。
Acquiring TeX Live as an ISO imageからISOファイルを落としてインストールする。僕のLIVAZ2では数時間かかった。

TeXStudioのインストール


総合環境のTeXStudioをインストールする。xyzzyでやる方法とかもあるが(kyotex-mode - xyzzy lisp - 米澤進吾 ホームページ)、一時的にLaTeXを使えればいいのならこっちのほうが手っ取り早い。

設定


「オプション」→「TeXstudioの設定」→「コマンド」から、LaTeXのコマンドを変更。latex.exeをuplatex.exeにする。


「オプション」→「TeXstudioの設定」→「ビルド」から、「ビルド&表示」を「DVI->PDFチェーン」に、「既定のコンパイラ」を「LaTeX」にする。これで、F5を押せばupLaTeXでDVIファイルをビルド→さらにそれをPDFにして表示、という一連の動作をするようになる。



TeXとLaTeXの関係性がいまいちわかってなかったのだが、TeXは言語あるいは処理系を、LaTeXはマクロ体系を指しているらしい。そして、TeX以外の処理系やLaTeX以外のマクロ体系が存在する。処理系には、和文組版(縦書き含む)が可能なpTeX、さらにそれをUNICODE化したupTeX等。マクロ体系にはそれに対応したpLaTeX、upLaTeX等がある。これらはTeXLiveで既にインストールされていて、設定するだけで使うことができる。

参考:
TeXstudioのインストールと初期設定 ― tm23forest.com 
TeX と LaTeX の違い ― ラング・ラグ

文書の構成


大まかには


  1. ドキュメントクラスを指定
  2. 設定をプリアンプルに
  3. \begin{document}\end{document}の間に本文を書く


という構成になっている。

ドキュメントクラスを指定


\documentclass[uplatex,
tate,twoside,openany, % 縦書き、見開きレイアウト
twocolumn, % 二段組
paper=b5,  % 用紙サイズ (a0〜a10 / b0〜b10 / {横mm,縦mm})
fontsize=14Q,jafontsize=14Q, % フォントサイズ
line_length=30zw,   % 一行の文字数 (zw=全角1文字の幅)
number_of_lines=24, % 行数
gutter=20.8mm,        % ノド側の余白
column_gap=10mm,    % 段と段の空白
head_space=20mm,    % 天の余白 (天/地どちらか一方を指定)
%foot_space=15mm,    % 地の余白
baselineskip=1.7zw, % 行送り
headfoot_verticalposition=1.5zw, % ノンブルと本文の間の空白
book, % 書籍のためのスタイル
hanging_punctuation] % ぶら下げ
{jlreq}

LaTeXでは作る文書の種類を最初に指定するようだ。文書の種類とは「本、論文、報告書」といった規模、あるいは縦書きか否かといったもの。ここでは最近熱いらしいjlreqを使う。

設定をプリアンプルに


% ノンブルを小口/下に (小口/上なら以下2行を消す)
\ModifyPageStyle{plain}{nombre_position=bottom-center}
\ModifyPageStyle{plain}{even_running_head=ヘッダーをここに}
\ModifyPageStyle{plain}{running_head_position=top-left}
\ModifyPageStyle{plain}{running_head_font=\footnotesize }
\pagestyle{plain}

\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{amsmath}
\usepackage{amsfonts}
\usepackage{amssymb}
\usepackage[dvipdfmx]{graphicx}

% 倍角ダッシュをつなげる
\def\――{―\kern-.5zw―\kern-.5zw―}

%写真のキャプションに「図」を入れない
\renewcommand{\figurename}{}

\jlreqsetup{
 caption_label_format={図\tatechuyoko{#1}},
}

\ModifyHeading{chapter}{pagebreak=nariyuki}

% 先頭ページ番号

\setcounter{page}{0}

ついで設定を書く。本文の前にあるこの部分をプリアンプルと呼ぶようだ。


本文を書く


\begin{document}
\end{document}


の間に本文を書く。


サンプル


いらすとやからcooking_frypan_teflon.pngを拾い、TeXファイルと同じ場所に置いておきましょう。

\documentclass[uplatex,
tate,twoside,openany, % 縦書き、見開きレイアウト
twocolumn, % 二段組
paper=b5,  % 用紙サイズ (a0〜a10 / b0〜b10 / {横mm,縦mm})
fontsize=14Q,jafontsize=14Q, % フォントサイズ
line_length=30zw,   % 一行の文字数 (zw=全角1文字の幅)
number_of_lines=24, % 行数
gutter=20.8mm,        % ノド側の余白
column_gap=10mm,    % 段と段の空白
head_space=20mm,    % 天の余白 (天/地どちらか一方を指定)
%foot_space=15mm,    % 地の余白
baselineskip=1.7zw, % 行送り
headfoot_verticalposition=1.5zw, % ノンブルと本文の間の空白
book, % 書籍のためのスタイル
hanging_punctuation] % ぶら下げ
{jlreq}

% ノンブルを小口/下に (小口/上なら以下2行を消す)
\ModifyPageStyle{plain}{nombre_position=bottom-center}
\ModifyPageStyle{plain}{even_running_head=ヘッダーをここに}
\ModifyPageStyle{plain}{running_head_position=top-left}
\ModifyPageStyle{plain}{running_head_font=\footnotesize }
\pagestyle{plain}

\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{amsmath}
\usepackage{amsfonts}
\usepackage{amssymb}
\usepackage[dvipdfmx]{graphicx}

% 倍角ダッシュをつなげる
\def\――{―\kern-.5zw―\kern-.5zw―}

%写真のキャプションに「図」を入れない
\renewcommand{\figurename}{}

\jlreqsetup{
 caption_label_format={図\tatechuyoko{#1}},
}

\ModifyHeading{chapter}{pagebreak=nariyuki}

% 先頭ページ番号

\setcounter{page}{2}


\begin{document}
 \chapter*{第一章}
 \section*{第一節}
 数字は2020年のように横を向いてしまうので、二〇二〇年とするか、
 あるいは\tatechuyoko{20}年のように縦中横を使うといい。
 
 図\tatechuyoko{\ref{zu1}}はいらすとやから拾ってきた。
 
 \
 
 \begin{quote}
  滲み出す混濁の紋章
  
  不遜なる狂気の器
  
  湧き上がり・否定し・痺れ・瞬き
  
  眠りを妨げる
  
  爬行する鉄の王女
  
  絶えず自壊する泥の人形
  
  結合せよ 反発せよ
  
  地に満ち 己の無力を知れ
  
  破道の九十 「黒棺」
 \end{quote}
 

 \begin{figure}[btp]
  \centering
  \includegraphics[angle=90,keepaspectratio,scale=0.2]{cooking_frypan_teflon.png}
  \caption{料理をしてるひと}
  \label{zu1}
 \end{figure}

\end{document}

これを貼り付け、F5を押すか赤く囲った部分をクリックすると、PDFが作成される。






参考




2020年2月10日月曜日

PPxをアウトラインプロセッサに

僕は今まで、PPxとhowmを組み合わせてメモ環境を作っていた(参考:MoE)。
ここにさらに

1.エントリ順序の任意設定
2.レベルの実装

を追加して、PPxをアウトラインプロセッサとして使えるようにする。



実装は以下のようになる。

1.エントリ上で特定のキーを押すことで、エントリ位置の入れ替えやレベルの変更を可能に
2.コメントファイル作成時、エントリ順で記載する。行頭の空白も保存
3.コメントファイルの記載順序で拡張コメントソート

準備


以下の2つのファイルをScriptフォルダに保存。

MakeOutlineComment.js

//!*script
// カレントディレクトリに一行目とファイルパスを対応させたコメントファイル(00_INDEX.txt)を作成
// アウトラインプロセッサ用。行頭の空白を維持し、エントリの順番通りに書き出す

var strLine = "\r\n";
var fs = PPx.CreateObject("Scripting.FileSystemObject");

for (var i = 0; i < PPx.EntryAllCount; i++) {
  // エントリがディレクトリの時の処理
  if (PPx.Entry(i).Attributes & 16) {
    if (PPx.Entry(i).Name == "."){
      strLine += PPx.Entry(i).Name + "\t*\r\n";
    } else if (PPx.Entry(i).Name == "..") {
      strLine += PPx.Entry(i).Name + "\t**\r\n";
    } else if (PPx.Entry(i).Comment=="") {
      strLine += PPx.Entry(i).Name + "\t" + PPx.Entry(i).Name + "\r\n";
    } else {
      strLine += PPx.Entry(i).Name + "\t" + PPx.Entry(i).Comment + "\r\n";
    }
  // エントリがhowmのときの処理
  } else if (PPx.Entry(i).Name.match(/.howm$/i)) {
    // ファイルの一行目を取得
    var f = fs.OpenTextFile(PPx.Entry(i).Name, 1);
    var title = f.ReadLine().slice( 2 );
    // コメントの最初に空白があればそれを反映
    if (PPx.Entry(i).Comment.match(/^ +/)) {
      var heading = PPx.Entry(i).Comment.match(/^ +/);
      strLine += PPx.Entry(i).Name + "\t" + heading + title + "\r\n";
    } else {
      strLine += PPx.Entry(i).Name + "\t" + title + "\r\n";
    }
    f.Close();
  }
}
if (strLine == "\r\n"){
  PPx.Quit();
} else {
  strLine += '00_INDEX.txt\t *** COMMENT FILE ***';
}

// 00_INDEX.txtに書き込み
var f2 = fs.OpenTextFile("00_INDEX.txt", 2, true, -1); // unicodeで書き込み
f2.Write(strLine);
f2.Close();

OutlineSort.js

//!*script
// 拡張コメントソート用。拡張コメント1を利用。
// 00_INDEX.txtの記載順に連番を付ける。

var fs = PPx.CreateObject("Scripting.FileSystemObject");
if (!fs.FileExists("00_INDEX.txt")) {
  PPx.Quit();
}

// ゼロ埋め
function zeroPadding(num,length){
    return ('0000000000' + num).slice(-length);
}

var array = {};

var stream         = new ActiveXObject("ADODB.Stream");
    stream.type    = 2;
stream.charset = "Unicode";
stream.open();
stream.loadFromFile("00_INDEX.txt");

var i = 1;
var firstLine = '';
while(!stream.EOS){
  firstLine = stream.readText('-2').split("\t")[0];
  array[firstLine]=i;
  i +=1;
}
stream.close();

for (var i = 0; i < PPx.EntryAllCount; i++) {
  if (PPx.Entry(i).Name.match(/.howm$/i)) {
    var num = zeroPadding(parseInt(array[PPx.Entry(i).Name]),4);
    PPx.Entry(i).SetComment(1,num);
  }
}


以下を編集して取込。

KC_main = { ; PPcメイン窓
^\LEFT ,*comment "%*regexp("%*comment","s/^\s?(.*)/$1/")"
^\RIGHT ,*comment " %*comment"
^\DOWN = @DEL @INS @DOWN
^\UP = @UP @DEL @INS
F7 ,*script %0Script\MakeOutlineComment.js
COMMENTEVENT1 ,*script %0Script\OutlineSort.js
}
MC_sort = {
拡張ソート&1 = 24,-1,-1,B11111,1
}
XC_cwrt = 0


対象フォルダでSを押してソートメニューを出し、拡張ソート1を選択する。


やりかた


1.エントリ位置やレベル調整をカーソルキーで行う:

Ctrl+Shift+カーソル上下:エントリ位置変更
Ctrl+Shift+カーソル左右:エントリレベル変更



2.F7を押して現在のエントリ状態を保存する:

COMMENTIVENT1に設定しているMakeOutlineComment.jsが実行され、現在のエントリ状態をコメントファイルに保存する。
それ以降は、フォルダを再読み込み時にOutlineSort.jsが実行され、保存時と同じ並びでソートされる。

2020年2月7日金曜日

一行編集でブックマーク

僕は、一行ごとにコマンドを記入したl_cmd.txtを%*imputで読み込ませて、一行編集をランチャとして用いている(参考:つかさのほえほえ日記: 一行編集でランチャ改)。
今回は、任意のパスをl_cmd.txtに直接書き込み、一行編集からジャンプできるようにする。
コマンドプロンプトのコマンドだとエスケープが超面倒そうなので、busyboxを使用。

_Command = { ; ユーザコマンド・関数
setbookmark = *string o,hoge= *execute C,*jumppath %"パスを入力してください"%{%*extract(C"%%FCD")%} %%m%"コメントを入力してください"%{%*extract(C"%%FC")%} %:
 %Ob %0busybox64.exe echo %so"hoge" >> %0l_cmd.txt
}


l_cmd.txtに以下の行を追加。

*setbookmark

やりかた


1.PPcで、ブックマークしたいフォルダにカーソルをあわせた後、一行編集から*setbookmarkを実行。パスとコメントを入力する。これで、l_cmd.txtに登録される


2.ブックマークを開きたいときは、一行編集から絞り込んでジャンプ



ブックマークを消したい場合はl_cmd.txtを直接開いて編集する。ちなみに

editor %0l_cmd.txt

みたいなコマンドをl_cmd.txtに書き込んでおき、一行編集から実行できるようにしておくと便利。

2020年2月2日日曜日

拡張コメントでゼロ埋めソート

音楽ファイルや画像ファイルの連番が

1-ゆらゆら.flac
2-新しい友達 II.flac
3-トムソンガゼルになりたかった.flac
4-新しい友達.flac
5-大観覧車.flac
6-君と仲良くなるためのメロディ.flac
7-灯台.flac
8-あの日に帰りたい.flac
9-へんないきもの.flac
10-ホラーすぎる彼女です.flac
11-マジカル走れ走れYO!.flac
12-ロードムービー.flac

となっている場合、名前順ソートだと

1-ゆらゆら.flac
10-ホラーすぎる彼女です.flac
11-マジカル走れ走れYO!.flac
12-ロードムービー.flac
2-新しい友達 II.flac
3-トムソンガゼルになりたかった.flac
4-新しい友達.flac
5-大観覧車.flac
6-君と仲良くなるためのメロディ.flac
7-灯台.flac
8-あの日に帰りたい.flac
9-へんないきもの.flac

と順序が崩れてしまう。拡張コメントを利用して、順序どおりにソートするようにする。
以下を編集して取込。

_Command = {
zeropadding = *ifmatch "option:e,attribute:d+" %: *return 9999
  *ifmatch "!/^\d/",%FC %: *return 9999
  *string o,hoge=%*regexp(%FBC,"s/^(\d+).*/0000$1/") %: *return %*regexp(%so"hoge","s/^0*(\d{4})/$1/")
}
KC_main = {
COMMENTEVENT1 , *comment 1,all extract,%%*zeropadding
}

zero-paddingは、冒頭の数値をゼロ埋めして返すコマンド。例えば「1-ゆらゆら.flac」を与えると「0001」が返ってくる。数値がなければ一律に「9999」を返す。
次に、ソートを実行したいフォルダで、以下を実行。

*sortentry -thispath 24,1,0,B11111,1

すると、COMMENTEVENT1が呼び出され、各項目にzeropaddingによる拡張コメントが追加された後に、拡張コメントを用いたソートがなされる。

追記 2020-02-07


拡張コメントを利用しなくても、デフォルトでできるみたいだ。

ソートメニューから「詳細」を選択し、数値順を選ぶ。




2020年1月28日火曜日

vivaldiをツリー型タブに

グッバイkinza、ハローvivaldi


覚えらんない人の記事でkikiというブラウザを知って以来、タブはずっとツリー型を使っている。
kikiから、FireFox系統+ツリー型タブを経て、最近まではずっとkinzaをデフォルト機能でツリー型タブにして使っていたが、画像表示、動画表示でよく失敗するという不満があった。twitterで画像を開くのに一々時間がかかるし、動画再生になると半分以上の確率で失敗する。
最近、vivaldiでツリー型タブを使えることがわかったので、そちらへ乗り換えることにする。今回はその記録。

tree tabsのインストール


まず、vivaldi用のtree tabsをダウンロードする。僕のときは「Tree Tabs 1.9.2 Vivaldi.zip」だった。これを適当な場所に展開する。

展開した中にあるglobal.jsを編集し、2行目を

let browserId = 'V';

に変える。Vivaldi 2.10+だと必要らしい(Tree Tabs | Vivaldi Forum)。

メニューからツール→拡張機能を選択し、拡張機能のページを開く。そこで、デベロッパーモードをONに。「パッケージ化されていない拡張機能を読み込む」から、先に展開したフォルダを選択する。



これで、拡張機能のページに、Tree Tabsが追加される。詳細をクリックし、「拡張機能のオプション」を選択する。




Vivaldiの欄にあるURLをコピーする。この時、Vivaldiのバージョンが2.10+だと、global.jsを編集しないとこの欄が表示されなくなるようだ。


他にも色々設定項目があるので、必要なら設定しよう。僕は、マウスホイールでタブを変更するように設定している。



次に、VivaldiのWebパネルに追加する。Webパネルの「+」ボタンを押すと入力欄が表示される(下の画像の赤矢印)ので、そこに先のURLをペーストする。すると、Webパネルに新しくTree Tabsが追加される(下の画像のオレンジ矢印)。これを選択するとツリー型タブが表示される。



その他インストールした拡張


vivaldiはChrome拡張をそのまま利用できるらしいので、今まで使っていて必要なものをインストールした。

  • Keepa - Amazon Price Tracker
  • Google Chromeのスーパードラッグ
  • Checker Plus for Gmail
  • GoodTwitter
  • uBlock Origin
  • Simple URL Copy
  • Page Monitor
  • Picture-in-Picture Extension
  • Libron

参考