2014年1月29日水曜日

PPxでステップイン・ステップアウトをしたい② 一行編集の利用


やりたいのは、今いるフォルダを軸にしたフォルダ移動。
具体的には

  • 親フォルダへの移動
  • 隣り合ったフォルダへの移動

などができればいい。これをスクリプトを用いて実現する。
ちなみにファイル名の補完については、デフォルトでも一行編集でTabキーやInsキーで可能。


やり方


以下の4つのファイルをScriptフォルダに保存。2chのPaper Plane xUI Part.4にあったスクリプトを参考にした。

GoParentDir.js
//!*script

fs = PPx.CreateObject("Scripting.FileSystemObject"); 
fn = PPx.Extract("%*edittext");

if( !fs.FolderExists(fn) ) PPx.Quit(1); 
//  パスから親の階層のパスを取得
currentDir = fs.GetFolder(fn);
if( currentDir.IsRootFolder ) PPx.Quit(1);

if( currentDir.ParentFolder.IsRootFolder ){
  PPx.Execute("*replace \"" + fs.GetParentFolderName( currentDir ) + "\"");
} else {
  PPx.Execute("*replace \"" + fs.GetParentFolderName( currentDir ) + "\\\"");
}

PPx.Execute("%K\"@^PDOWN\"");

GoSubDir.js
//!*script


fs = PPx.CreateObject("Scripting.FileSystemObject");
// 一行編集の内容を取得
fn = PPx.Extract("%*edittext");

// サブフォルダのリストを取得
if( !fs.FolderExists(fn) ) PPx.Quit(1); 
currentDir = fs.GetFolder(fn);
e = new Enumerator(currentDir.SubFolders); 
flds = new Array(); 
for( ; !e.atEnd(); e.moveNext()) {
  fuga = fs.GetFolder(fs.BuildPath(fn, e.item().Name));
  if (fuga.Attributes <= 17) flds.push(e.item().Name);
}
// 名前順でソート
flds.sort(function(a, b){return a.toLowerCase()>b.toLowerCase()?1:-1;}); 

// 一行編集の内容を最初のサブフォルダに置き換え
PPx.Execute("*replace \"" + fs.BuildPath(fn, flds[0]) + "\"");
PPx.Execute("%K\"@^PDOWN\"");

NextDir.js
//!*script


fs = PPx.CreateObject("Scripting.FileSystemObject");
// 一行編集の内容を取得
fn = PPx.Extract("%*edittext");
currentDir = fs.GetFolder(fn);

// 親フォルダがルートフォルダなら終了
if( currentDir.IsRootFolder ) PPx.Quit(1);

// 同階層のフォルダのリストを取得
e = new Enumerator(currentDir.ParentFolder.SubFolders); 
flds = new Array(); 
for( ; !e.atEnd(); e.moveNext()) {
  fuga = fs.GetFolder(fs.BuildPath(currentDir.ParentFolder.Path, e.item().Name));
  if (fuga.Attributes <= 17) flds.push(e.item().Name);
}
// 名前順でソート
flds.sort(function(a, b){return a.toLowerCase() > b.toLowerCase()?1:-1;}); 
for(i = 0; i < flds.length; i++) {
  if( flds[i] == currentDir.Name ) break;
}
// 次のフォルダを取得
nextDir = flds[Math.min(i+1, flds.length-1)];

// 一行編集の内容を置き換え
PPx.Execute("*replace \"" + fs.BuildPath(fs.GetParentFolderName( fn ), nextDir) + "\"");
PPx.Execute("%K\"@^PDOWN\"");

PrevDir.js
//!*script


fs = PPx.CreateObject("Scripting.FileSystemObject");
// 一行編集の内容を取得
fn = PPx.Extract("%*edittext");

// フォルダが存在しなければ終了
if( !fs.FolderExists(fn) ) PPx.Quit(1); 
currentDir = fs.GetFolder(fn);
// 親フォルダがルートフォルダなら終了
if( currentDir.IsRootFolder ) PPx.Quit(1);

// 同階層のフォルダのリストを取得
e = new Enumerator(currentDir.ParentFolder.SubFolders); 
flds = new Array(); 
for( ; !e.atEnd(); e.moveNext()) {
  fuga = fs.GetFolder(fs.BuildPath(currentDir.ParentFolder.Path, e.item().Name));
  if (fuga.Attributes <= 17) flds.push(e.item().Name);
}
// 名前順でソート
flds.sort(function(a, b){return a.toLowerCase() > b.toLowerCase()?1:-1;}); 
for(i = 0; i < flds.length; i++) {
  if( flds[i] == currentDir.Name ) break;
}
// 前のフォルダを取得
nextDir = flds[Math.max(i-1, 0)];

// 一行編集の内容を置き換え
PPx.Execute("*replace \"" + fs.BuildPath(fs.GetParentFolderName( fn ), nextDir) + "\"");
PPx.Execute("%K\"@^PDOWN\"");


以下を編集して取込。
KC_main = { ; PPcメイン窓
G ,%j%ee%"パスを変更"%{%1%|%}
}

K_edit = { ; 一行編集
^LEFT ,*script %0\Script\GoParentDir.js
^RIGHT ,*script %0\Script\GoSubDir.js
^UP ,*script %0\Script\PrevDir.js
^DOWN ,*script %0\Script\NextDir.js
}


これで、一行編集上で

  • Ctrl+←で親フォルダ
  • Ctrl+→でサブフォルダ
  • Ctrl+↑ or Ctrl+↓で隣り合ったフォルダ

のパスに切り替えることができる。

たとえば隣り合ったフォルダに行きたい時には、

  1. Gで一行編集(今いるフォルダパスが入力されているはず)を表示
  2. Ctrl+↑あるいはCtrl+↓でジャンプしたいサブフォルダのパスにして
  3. Enterで移動


上の階層のフォルダに行きたい時は

  1. Gで一行編集(今いるフォルダパスが入力されているはず)を表示
  2. Ctrl+←でそのフォルダがあるフォルダに行き
  3. フォルダ名の一部を入力、TabやInsで補完してEnter
といった感じ

思ったこととか


改善点とかもっと適切なやり方は他にあると思っている。
この手の問題意識はずっと前から持ってて、そもそもほえほえ日記を作ったきっかけが、あふ+fenrirでステップイン・ステップアウトする方法を思いついて、どこかに書いてみたかったからだったりする。(あふとfenrirの連携 - つかさのほえほえ日記
問題として対象化したことだし、 これからぼちぼちいければいいかな、と。

2014年1月24日金曜日

PPxでステップイン・ステップアウトをしたい①


フォルダジャンプの2パターン


ファイラで今いるフォルダから別のフォルダへ移動したい場合には、二つのパターンがある。

  • 全然別のフォルダにジャンプ
  • 近いフォルダにジャンプ

「全然別のフォルダにジャンプ」は、fenrirだとかEverythingだとかを利用して行う。覚えているそのフォルダのパス名の一部を入力し、フォルダを絞り込んでそこに移動。

「近いフォルダにジャンプ」は、どこかのフォルダで何かの作業をしていて、関連するフォルダを参照したいときに必要になる。
例えばPPxフォルダをいじっていて、xyzzyフォルダなど関係するファイルも弄りたいという場合。
あるいは、画像フォルダで柊つかさフォルダにいて、隣の柊かがみフォルダをのぞいてみたい場合。などなど。

このような場合は、「そのフォルダの近く」ということが移動のキーになる。今いて意識を集中しているフォルダを基点にして、そこから階層的に上だとか下だとか、あるいは隣り合っているだとかを手がかりにフォルダ移動しようとする。「全然別のフォルダにジャンプ」の時のように、意識を今やっている作業から離して、移動したいフォルダのファイル名の一部を思い出し、それを入力してそれで移動しよう、というようにはならない。頭に浮かんでいる、フォルダをたどるために使うキーが全然別なのだ。

前者については、fenrir、あるいはEverythingを使うというように方法が確立している。だが、後者については今までしっくり来る方法というのがなかった。これをどうにかして確立したい、というのが今回の問題意識。

既存の方法


この用途に合致した既存の方法として有名なものに、あふ+CraftLaunchによるステップイン・ステップアウトがある。

あふ+CraftLaunch



CraftLaunchを応援したいし、生きているし。の【あふとの連携】を参考にして設定する。

あふから登録したキーでCraftLaunchを呼び出すと


こんな感じで、今いるフォルダパスが入力された状態でCraftLaunchが起動する。Ctrl+方向キーでパスをたどり、そのフォルダに移動することができる。


PPx+fenrir



fenrirを使っても似たようなことは可能。その場合は、コマンドラインオプションの/dirを使う。

たとえば次のようにしてfenrirを呼び出せば、PPxの中心に、カレントフォルダパスが入力された状態で起動する。
KC_main = {
G ,%Ob D:\bin\fenrir\fenrir.exe /dir="%1"%: *fitwindow %NC,%*findwindowclass("fenrirMainWindow"),20
}

他のやり方を探りたい


どちらも試すには試したがずっと使い続けるということがなく、この問題についてはずっと棚に上げた状態が続いていた。
だが最近、これをPPxの一行編集を利用してできないかと思いついた。それについては次回。

2014年1月20日月曜日

Emacsでhowmファイルを任意のフォルダに作成(改)-キーバインドと色付け


Emacsでhowmファイルを任意のフォルダに作成を少し変更。
僕は、howmファイルを見やすくするために、見出しと小見出しの二つをつけている。**が見出しで***が小見出し。



  • Ctrl+:を押せば行頭に**を挿入
  • Ctrl+]を押せば行頭に*を挿入

し、また見出し行は色を変えて目立つようにxyzzyではしていた。

これをemacsでも実装してみる。前回のコードに

  • キーバインド
  • 色づけ

を付け足してます。

howm-create2dir.el

;;; howmファイルを作成
(defun make-howm-create2dir-file (&optional howm-dir)
  (interactive)
  (let* ((filename (format-time-string "%Y-%m-%d-%H%M%S.howm"))
  (filepath
   (if howm-dir
       (concat (file-name-as-directory howm-dir) (format-time-string "%Y-%m-%d-%H%M%S.howm"))
     (format-time-string "%Y-%m-%d-%H%M%S.howm"))))
    (find-file filepath)
    (if (eq (point-max) (point-min))
 (progn
   (insert (format-time-string "= \n\n[%Y-%m-%d %H:%M]\n"))
   (goto-char (+ (point-min) 2))))
    ))

;;; 本体
(defun howm-create2dir (arg)
  (if (file-directory-p arg)
      (progn
 (make-howm-create2dir-file arg)
 (howm-create2dir-mode))))

;;; メジャーモード
(define-derived-mode howm-create2dir-mode nil "howm2dir"
       "homu mode"
       (define-key howm-create2dir-mode-map "\C-c,c" 'make-howm-create2dir-file)
       (define-key howm-create2dir-mode-map (kbd "C-:") 'hateda-heading)
       (define-key howm-create2dir-mode-map (kbd "C-]") 'hateda-heading2)
       (font-lock-add-keywords
        nil
        '(("^\\*\\*\\*.*\n" . my-face-b-1)
   ("^\\*\\*.*\n" . my-face-b-2))))

;;; フェイス
(defface my-face-b-1 '((t (:foreground "white" :background "SteelBlue"))) nil)
(defface my-face-b-2 '((t (:foreground "white" :background "blue"))) nil)
(defvar my-face-b-1 'my-face-b-1)
(defvar my-face-b-2 'my-face-b-2)

;;; 行頭に見出しをつける
(defun hateda-heading ()
  (interactive "*")
  (save-excursion
    (beginning-of-line)
    (insert "**")))

(defun hateda-heading2 ()
  (interactive "*")
  (save-excursion
    (beginning-of-line)
    (insert "*")))

(provide 'howm-create2dir)
(provide 'howm-create2dir-mode)

色の付け方は
  • deffaceで色を設定
  • font-lock-add-keywordsで割り当て

という順序らしい。

2014年1月19日日曜日

Emacsでhowmファイルを任意のフォルダに作成

xyzzyで使ってたhowm-create2dir.lをEmacsに移植してみる。



howm-create2dir.は、引数に取ったディレクトリにhowm形式のファイルを作成する拡張Lisp。PPxと組み合わせての使用を想定している。

Emacsの設定


以下をsite-lispフォルダに保存する。

howm-create2dir.el

(defun make-howm-create2dir-file (&optional howm-dir)
  (interactive)
  (let* ((filename (format-time-string "%Y-%m-%d-%H%M%S.howm"))
  (filepath
   (if howm-dir
       (concat (file-name-as-directory howm-dir) (format-time-string "%Y-%m-%d-%H%M%S.howm"))
     (format-time-string "%Y-%m-%d-%H%M%S.howm"))))
    (find-file filepath)
    (if (eq (point-max) (point-min))
 (progn
   (insert (format-time-string "= \n\n[%Y-%m-%d %H:%M]\n"))
   (goto-char (+ (point-min) 2))))
    ))

(defun howm-create2dir (arg)
  (if (file-directory-p arg)
      (progn
 (make-howm-create2dir-file arg)
 (howm-create2dir-mode))))

(define-derived-mode howm-create2dir-mode nil "howm2dir"
       "homu mode"
       (define-key howm-create2dir-mode-map "\C-c,c" 'make-howm-create2dir-file))

(provide 'howm-create2dir)
(provide 'howm-create2dir-mode)

以下を.emacsにコピペ。

;; howm-create2dir読み込み
(require 'howm-create2dir)

;; howmファイルをhowm2dirモードで開く
(setq auto-mode-alist
      (cons (cons "\\.howm$" 'howm-create2dir-mode) auto-mode-alist))

PPxから呼び出す


ここからはPPx側の設定。
%Ob E:\emacs\bin\runemacs.exe -execute ("howm-create2dir \"%*regexp("%1","s/\\/\\\\/g")\"")

みたいなのを適当なキーかメニューに登録して実行すれば、カレントディレクトリにhowmファイルを作成する。
%*regexpの箇所でやってるのは、%1で取得したパスの修正。たとえばD:\howm\hogeならD:\\howm\\hogeとなるようにしている。 僕は、このコマンドをファイル作成メニューの一つとして登録している。

-|M_makefile =

M_makefile = { ** comment **
&howm = %Ob E:\emacs\bin\runemacs.exe -execute ("howm-create2dir \"%*regexp("%1","s/\\/\\\\/g")\"")
&TXT = *set name=%1\%"テキストファイル"%{%|.txt%} %: *makefile "%'name'" %: editor "%'name'" %: *jumppath "%'name'" /entry
&CFG = *set name=%1\%"CFGFile"%{%|.cfg%} %: *makefile "%'name'" %: editor "%'name'" %: *jumppath "%'name'" /entry
&PlainFile = *set name=%1\%"PlainFile"%E %: *makefile "%'name'" %: editor "%'name'" %: *jumppath "%'name'" /entry
&VBS = *set name=%1\%"VBScript"%{%|.vbs%} %: *makefile "%'name'" %: editor "%'name'" %: *jumppath "%'name'" /entry
&JS = *set name=%1\%"JScript"%{%|.js%} %: *makefile "%'name'" %: editor "%'name'" %: *jumppath "%'name'" /entry
}

KC_main = { ; PPcメイン窓
\K ,%M_makefile,H
}

2014年1月14日火曜日

Emacsのポータブル化

xyzzyをポータブル化する方法を模索してて、いっそのこと似たようなEmacsをポータブル化して使ってる拡張lispも移植したらいんじゃねとひらめいチャッチャ!
というわけで、今回はEmacsをポータブル化する方法。

インストール


emacs for gnupackをここからダウンロード。USBメモリに解凍する。



やり方


site-lispフォルダにsite-start.elを作成し、以下をコピペ。これでemacsフォルダがホームディレクトリになる。

(setenv "HOME" (substring data-directory 0 -4))

次に、emacsフォルダに.emacsを作成し、そこに設定を書いていく。以下は僕の例。

.emacs

;;起動時の画面を消す
(setq inhibit-startup-message t)

;;アイコンを消す
(tool-bar-mode -1)

; 行番号表示
(require 'linum)
(global-linum-mode)

;; メッセージを消す
(setq initial-scratch-message "")

;; beep音を消す
(setq visible-bell t)
(setq ring-bell-function 'ignore)

;;; *.~ とかのバックアップファイルを作らない
(setq make-backup-files nil)

;;; .#* とかのバックアップファイルを作らない
(setq auto-save-default nil)

ちなみに


emacsでは
  1. 最初に共通設定ファイルであるsite-start.elを読み込み
  2. 次に各ユーザーごとの設定ファイルを読み込み
  3. 最後にdefault.elを読み込む

という仕組みになってるらしい。

そして、「2.各ユーザーごとの設定ファイルの読み込み」だが、

  1. ~/.emacs.elc
  2. ~/.emacs.el
  3. ~/.emacs
  4. ~/.emacs.d/init.elc
  5. ~/.emacs.d/init.el

と順番に探していき、最初に見つかるファイルを読み込むようだ。「~」はホームディレクトリの意。

参考


EmacsをUSBで使えるようにするまでのやり方 - プログラムとかののblog

追記 2014/01/15


(defvar usb-drive-letter (substring data-directory 0 3))
(defvar usb-home-dir (concat usb-drive-letter "emacs/"))

(setenv "HOME" usb-home-dir)


(setenv "HOME" (substring data-directory 0 -4))

に変えた。変える前のやつを使う場合は、emacsをルートディレクトリに展開し、フォルダ名をemacs-24.2-20121208とかからemacsにリネームする必要がある。