Rustでランチャ開発その2: 欲しい機能
- #launcher-dev #rust
前回(第1回)の記事の続き
高速ランチャアプリを開発するにあたって実装したい機能や簡単な仕様などをまとめていく
基本方針を固める
手始めに、開発する上で これだけは絶対譲れない という部分をリストアップした
- 安定的に動作し、滅多にクラッシュしない1こと
- 動作が高速でキビキビしている(とユーザー2が感じられる)こと
- 文字列入力時のテキスト表示・更新速度
- 文字列検索に対するマッチ結果の表示・更新速度
- ホットキー押下時のGUI表示・非表示の反応速度
- など
- 多機能 にはせず、シンプル&クリーンなソフトウェアを目指す
- 文字列検索&ファイルに対するアクション実行、インデックス作成&更新、自動アップデートはそれぞれ別のバイナリにする予定
- 各機能を分割することで保守性と安定性の向上を図る
- CLIコマンドのエイリアスやカスタムコマンドが登録でき、 柔軟に拡張可能 であること
- 極力レジストリは使わない
まとめ
- 安定性・高速性・拡張性・非多機能3 を重視する
実現したい機能
私の載せたい機能、多すぎ……!?
※あくまで願望・イメージです
UI
GUIイメージ1
GUIイメージ2
GUIイメージ3
GUIイメージ4
GUIはシンプルな文字列入力欄(インプットボックス)のみで構成
- ボーダレスウィンドウのようにタイトルバーなどをデフォルトで非表示
- 極小サイズのシンプルな表示にする
検索・文字入力時はインプットボックスのすぐ近くにリストボックスを表示
- リスト内に文字列検索でマッチしたファイル・フォルダ一覧を表示
- リスト内の各項目左側にはアイコンを表示可能
- ユーザーはアイコンの表示と非表示も切り替えられる
入力時には補助となる小さなポップアップも入力欄の近くに表示(予定)
ウィンドウの移動とリサイズ
上辺をつかんでドラッグすることでウィンドウが移動できる
(fenrirの改善点) 上辺を常にD&Dする必要があるのはユーザーにとって多少ストレスになる
- 文字入力欄とそうでないエリアの見分け がつくようにし、下の方など上辺以外をつかんでもドラッグで移動できると良い
右下など縁(ふち)をつかんでドラッグするとウィンドウサイズの拡大および縮小が出来るようにもする
- 開発初期の段階でウィンドウリサイズ時のGUI再描画による実行速度低下を考慮
基本操作
- ホットキーで呼び出し、ランチャアプリ本体のGUIを表示
- GUI表示時点でカーソルが入力待機状態となる
- その後、ユーザーはテキスト入力欄に文字列を入力する
- ユーザーが入力した文字列に対し、場合に応じて様々な挙動を用意
- インデックスされたファイル・フォルダ一覧の中で文字列にマッチするものがあればリアルタイムでリスト表示
- 登録されたエイリアスに合致するものがあれば通常のリスト表示は中止し、そのエイリアスの内容(文字列)をポップアップで入力欄のすぐ近くに表示し続ける
文字列入力
- リスト内ではカーソルを
Up
・Down
キーあるいはPageUp
・PageDown
キーで移動し、カーソルで選択中のファイル・フォルダに対して各種操作を行う - フォルダにカーソルが当たった状態で
Right
キーを入力することでフォルダを展開し、Left
キーを押下することで親フォルダを展開する- 「展開」とは、フォルダ直下のファイル・フォルダ一覧を入力欄のすぐ近くにリスト表示することを指す
Ctrl+BackSpace
やCtrl+Delete
の入力では 行ごと削除ではなく単語ごと削除 を行う- オプションで切り替え可能にする
- カーソルUI自体は一般的な縦棒カーソル
|
とブロックカーソル■
とで選択可能にする
検索機能
- 検索対象となる全てのものを 「オブジェクト」 と呼ぶ
- オブジェクトの種類には ファイル・フォルダ・エイリアス などがある
- インクリメンタルサーチでリアルタイムに検索マッチしたオブジェクト候補をリスト表示
- 入力された文字列に対して下記の検索方式を用意する
- 先頭部分一致
- 中間部分一致
- スキップマッチング
- 上記検索方式を、通常検索時とフォルダ展開時とで分ける
- 「通常検索」とは、フォルダを展開していないデフォルト状態からの文字列入力時に、DBキャッシュ内部のファイル・フォルダや優先検索対象に指定したフォルダ群を対象に文字列検索するケースを指す
Tab補完・カーソル移動機能
- 入力中に
Tab
キーを押下することで過去の入力履歴を呼び出してその場で補完可能- 補完対象となるのは全オブジェクト
- ファイル
- フォルダ
- エイリアス
- エイリアス内引数
- etc
- 補完対象となるのは全オブジェクト
Tab
キーの押下により文字列の補完が行われるのと同時に次の引数があればその先頭位置までカーソル移動するShift + Tab
キーによって1つ前の引数までカーソルが戻る機能も搭載Tab
によるカーソル移動時は移動先の引数に対応した部分だけを選択状態にも出来る- もちろんこれはオプションでON/OFF設定可能
検索履歴機能
- ユーザーの入力履歴を保存し、入力欄からUpキーやDownキーで呼び出し可能
- 同じエイリアスの同じ位置の引数 で過去に入力された文字列を呼び出し補完する機能
- もちろんこの場合にも
Tab
補完が働く
- もちろんこの場合にも
- 単に履歴を呼び出すだけでなく 文字列推定 する機能も付けたい
- 恐らく実行速度に影響を与えるのでオプションでON/OFF可能にする
高度な検索機能
これらは採用するRustクレートにもよるので詳細は未定
- migemo検索
- ユーザーの方で辞書(
dict
)を導入してもらう予定
- ユーザーの方で辞書(
- 正規表現(RegEx)検索
- あくまで置換用ではなく検索用の実装
- ignorecase/noignorecase・smartcase検索
- Vimと同じ要領で大文字小文字を区別したり無視したり
- smartcaseが特に重要だが実装は骨が折れそう(速度的な意味で)
カスタムコマンド機能
fenrirの
cmd/
以下で定義できる カスタムコマンド のようなものを用意拡張子毎に複数コマンドを割り当て可能 にし、それぞれのコマンドに対する挙動(アクション)を個別に定義できるようにする
例えば
*.*
(全てのファイル)に対してCtrl+Enter
なら親フォルダがエクスプローラで開く*.txt
ファイルに対してShift+Enter
ならコンテクストメニューが表示され、その中から実行内容を選択・実行できる*.{txt,ini,c,cs,cpp,rs,py,js,ts}
に対してAlt+N
を押下するとNeovim上で編集、Alt+V
を押すとVSCode上で編集が出来る- などなど、ユーザーが自由に設定できる
Everything、あふw、PPx、NyanFiなどのCLIコマンドを登録すればランチャからすぐに各種アプリケーションへパスを渡すことも可能
下の画像はfenrirの
Shift+Enter
でコンテクストメニューを表示した場合の例.txt
ファイルに対して複数のエディタによる編集(とタイムスタンプのクリップボードコピー)を選択できる状態
エイリアス機能
- エイリアスも設定可能で、エイリアスの接頭辞(prefix)もユーザーが自由に設定可能
- エイリアスの接頭辞はVimの記法に従い、下記を想定
/
(検索用):
(コマンド・アプリ実行用)@
(マクロ・スクリプト実行用)- その他ユーザー指定の文字
- 例えば
/tw=""https://twitter.com/search?q=%A""
というエイリアスを登録している場合- ランチャ上で「/tw あいうえお」と入力するとプレースホルダー
%A
に「あいうえお」が渡され、Webブラウザ上で「あいうえお」という文字列によるTwitter検索結果画面が開く
- ランチャ上で「/tw あいうえお」と入力するとプレースホルダー
- GUIイメージ2にもあるように、エイリアス候補はインクリメンタルにリスト表示する
- その際、エイリアスのすぐ後ろに表示される文字列を下記から選択可能にする
- 登録済みコマンド文字列(
https://twitter.com/search?q=%A
など) - エイリアス別のユーザーコメント(
ツイッター検索用
など)
- 登録済みコマンド文字列(
- その際、エイリアスのすぐ後ろに表示される文字列を下記から選択可能にする
- エイリアス引数の入力時、 引数がハイライト 状態になる
- GUIイメージ3を参照
- 引数ハイライトは背景を塗りつぶして文字色を反転させたものにしたい
- パッと見でユーザーが視認できるようにする
- エイリアスの変数リストは無限個にはしない
- 常識的な範囲で設定
デリミタ自動入力機能
- デリミタはエイリアス引数同士を区分するためのもの
- デリミタは
(半角スペース)、
,
(カンマ)などユーザーが指定した文字を設定可能- エイリアス登録されたCLIコマンド文字列内にある同一文字との識別も出来るようにする
- また、
Tab
による補完とカーソル移動の際にはデリミタ(Delimiter)を自動で入力しながら次の引数リストまでジャンプするようにしたい
設定変更・カスタマイズ機能
- 各エイリアスの 引数の数は可変的 にする
- 例えばfenrirの
instant.ini
書式では ターミナルで実行できるワンライナーコマンドでさえあれば何でも実行 できる、という柔軟性を備えている
- 例えばfenrirの
- 設定ファイル用の記法は 「入れ子」かつ「モジュール」形式 にしたい
- モジュールとは任意の要素ごと他の部分への組み込みや再利用が可能な形式
- モジュール化によって「別のエイリアスの設定や引数を丸ごと再利用するエイリアス」などが作れる
- その分 エラーチェック機構 が必要
- JSONの場合はJSON Schemaがこれに該当すると思われる
- モジュールとは任意の要素ごと他の部分への組み込みや再利用が可能な形式
- 既存のfenrirの
.ini
ファイルを引き継げるような機能を用意instant.ini
をパースしてJSONやYAMLを吐き出すバイナリなど
JSONで管理する場合
- 動作やGUIの設定は JSON 形式外部ファイルの
settings.json
ファイルなどで設定することを想定- 文字色・背景色・フォント
- リストとして表示するファイル・フォルダの総数
- JSONC(コメント可能なJSON)パーサを利用するかは未定
YAMLで管理する場合
- YAMLによる設定ファイル
aliases.yml
のイメージ- ※あくまでイメージなので構文も適当です
env
は ローカルな環境変数としてモジュール化 して別エイリアスから再利用可能- 例えば同じパスに対して複数のマクロをランチャ上から同時実行あるいは逐次実行できるようにしたい(願望)
- このファイルにより2つのエイリアスが定義される
@rm2
というシェルスクリプトマクロ@twc %A
というURLアクセスマクロ
alias:
type: macro
executor: bash
prefix: "@"
body: rm2
commandline:
command: |
cd $path1
echo "hello" > ./hello.txt
cd $path2
echo "changed directory: '${path2}'"
rm -vf ./*
echo "finished"
params:
- param:
type: path
name: path1
env: "FILE_PATH_ONE"
- param:
type: path
name: path2
env: "FILE_PATH_TWO"
alias:
type: macro
executor: dos
prefix: "@"
body: twc
comment: "open Twitch user's channel"
commandline:
command: |
"https://twitch.tv/%A"
params:
- param:
type: string
name: A
その他機能
- トレイアイコン表示機能
- 入力ウィンドウ(GUI)表示と同時にIMEをOFFにする機能
- リスト内選択カーソルのループON/OFF機能
- 最下段からのDownキーの入力で最上段にカーソル移動
- 最上段からのUpキーの入力で最下段にカーソル移動
- 直近で展開したフォルダの検索時優先度を上げる機能
- Windowsプロセスのワーキングセットを縮小処理する機能
- これは……実装できるか分からんかも
- 設定済みエイリアスをショートカット(
.lnk
あるいは.url
)形式で出力する機能- マウス派ユーザーの為の機能
- ただこれは ランチャ本体じゃなくて付属するバイナリ に割り当てた方が良い
次回予告
次はこれらの機能・仕様を実現するため最適なRustクレートを探す旅に出ます
今回は特にツッコミどころが満載だと思われますが、ツッコミたい方はこちらのTwitterアカウント: @roodolv からツッコミを入れに来て頂けると幸いです