PowerShell でページャ less / lv を使う

前書き

PowerShell ではページャとしてコマンドプロンプトと同じ more を使えるが、後戻りができないので不便だった。そこで次の方法を試したがうまくいかなかった。

  • GnuWin32 のバイナリを使う
    • 文字が表示されない
  • WSL (Windows Subsystem for Linux) の less や lv を使う
    • 引数にファイルを指定したときに WSL と Windows でパス区切りが違うためファイルを読めない

次の方法もあったが LCC (C Compiler) が必要だったため試さなかった。

使用方法

試した中で WSL の less / lv を使うのが一番良さそうだったので、パスを変換するためのスクリプトPHP で書いた。

使用方法は次の通り。

  • この lv.cmd をパスの通ったディレクトリ、 lv.php を適当なディレクトリに配置する
  • lv.cmd で指定している php および lv.php のパスを環境に合わせて修正する
  • less を使う場合は lv.phpconst PAGER = 'wsl lv'; の部分を、またファイル名を修正する
  • lv を使う場合は WSL に lv をインストールする

f:id:scientre:20200617103156p:plain
PowerShell で lv

xyzzy から標準のファイラのかわりに FreeCommander を起動する

以前にコードエディタを xyzzy から Visual Studio Codexyzzy のファイラから FreeCommander に乗り換えた。

それでもメモ書きに xyzzy を使うことがあり、癖で xyzzy のファイラを起動してしまうことがあるので C-c C-f のキーバインドで FreeCommander を起動できるようにした。

;; FreeCommander XE を起動する
(defun open-freecommander (&optional (dir nil))
  "FreeCommander で開く"
  (interactive)
  (let ((command "\"C:\\Program Files\\FreeCommander XE\\FreeCommander.exe\""))
	(if dir
		(call-process
		 (concat command " /C \"" dir "\" /T"))
	  (call-process
	   (concat command " /C"))
	  )))

;; 標準のファイラがわりに使う
(global-set-key '(#\C-c #\C-f) 'open-freecommander)

引数にディレクトリのパスを渡すと FreeCommander の新しいタブでそのディレクトリを開けるが、今のところ使っていない。

VSCode May 2020 (version 1.46) に Selection Anchor が導入されたので xyzzy 風のリージョン操作ができるようにした

VSCode が May 2020 (version 1.46) にアップデートされる前は拡張機能 Emacs Friendly Keymap を導入して Emacs 風のキーバインドを使っていたが、次の点が不満だった。

  • C-SPC でマークをセットしたあと、リージョンの終わりに検索でカーソルを移動できない
  • 別の拡張機能 Clipboard History に kill-ring の内容が反映されない

そこで今回搭載されたキーボードでの選択を補助するための次の機能を使ってこれを改善した。また、クリップボード履歴の拡張機能を Multiple Clipboards for VSCode に変更した。

  • Set Selection Anchor (Ctrl+K Ctrl+B)
  • Select From Anchor to Cursor (Ctrl+K Ctrl+K)
  • Cancel Selection Anchor (Escape)
  • Go to Selection Anchor

この動作をするためには拡張機能 multi-command が必要。これは一つのキーバインドで複数のコマンドを実行するためのものだ。

設定内容

  • C-Space (set-mark-command) 相当
    • カーソル位置にアンカーを設定する
  • M-w (copy-region-as-kill) 相当
    • アンカーからカーソル位置までを選択し、クリップボードにコピーする
    • コピー後は選択を解除する
    • アンカーを設定せずにこのコマンドを実行すると、カーソル位置の行をコピーする(editor.emptySelectionClipboard がオンの場合)
  • C-w (kill-region) 相当
    • アンカーからカーソル位置までを選択し、クリップボードにカットする
    • アンカーを設定せずにこのコマンドを実行すると、カーソル位置の行をカットする(editor.emptySelectionClipboard がオンの場合)
  • C-y (yank) 相当
  • C-c C-y
    • Clipboard History から貼り付け

settings.json

    "multiCommand.commands": [
        {
            "command": "emacs.copy-region",
            "sequence": [
                "editor.action.selectFromAnchorToCursor",
                "multiclip.copy",
                "cancelSelection"
            ]
        },
        {
            "command": "emacs.kill-region",
            "sequence": [
                "editor.action.selectFromAnchorToCursor",
                "multiclip.cut"
            ]
        },
        {
            "command": "emacs.paste",
            "sequence": ["editor.action.clipboardPasteAction"]
        },
        {
            "command": "emacs.expand-selection",
            "sequence": [
                "editor.action.cancelSelectionAnchor",
                "editor.action.smartSelect.expand"
            ]
        }
    ],

keybindings.json

	{
		"key": "ctrl+space",
		"command": "editor.action.setSelectionAnchor",
		"when": "editorTextFocus"
	},
	{
		"key": "alt+w",
		"command": "emacs.copy-region",
		"when": "editorTextFocus"
	},
	{
		"key": "ctrl+w",
		"command": "emacs.kill-region",
		"when": "editorTextFocus"
	},
	{
		"key": "ctrl+y",
		"command": "emacs.paste",
		"when": "editorTextFocus && !editorReadonly"
	},
	{
		"key": "ctrl+c ctrl+y",
		"command": "multiclip.list",
		"when": "editorTextFocus && !editorReadonly"
	},

Glyphs で背景レイヤーに描いた骨格から線幅を持ったパスを自動生成する

フォント作成ソフト Glyphs でグリフに対する操作を自動化してみた。

一番分かりやすいドキュメントは Glyphs SDK の ObjectWrapper/GlyphsApp/__init__.py だった。

#MenuTitle: Make Offset
# -*- coding: utf-8 -*-
__doc__="""
Make paths offset from background layer
"""

import copy

# Get the filter
offsetCurveFilter = NSClassFromString("GlyphsFilterOffsetCurve")

for glyph in Glyphs.font.glyphs:
	layer = glyph.layers[0]
	""":type : GSLayer"""

	paths = glyph.layers[0].paths
	""":type : LayerPathsProxy"""

	# Remove current paths
	for path in paths:
		paths.remove(path)
	
	# Copy paths from background
	bgPaths = glyph.layers[0].background.paths
	""":type : LayerPathsProxy"""
	for bgPath in bgPaths:
		paths.append(copy.copy(bgPath))
	
	# Apply filter
	offsetCurveFilter.offsetLayer_offsetX_offsetY_makeStroke_autoStroke_position_error_shadow_(layer, 15, 15, True, 0, 0.5, None, None)
  • Glyphs.font は現在開いているフォント
  • 今はレイヤーが1枚なので glyph.layers[0] で参照できているが、レイヤーが複数になったときその順序がどうなるかまだ試していない
  • Python ではリストの項目をすべて削除するのに del paths[:] のようにできるが、LayerPathsProxy は del paths[:] が使えないので paths.remove(path) で一つ一つ消す
  • オブジェクトの deep copy には copy モジュールを使う

Karabiner-Elements でキーボードのカスタマイズ

先日から導入しているファイルマネージャ ForkLift の操作性向上のため、 macOS のキーボードを徹底的にカスタマイズできる Karabiner-Elements を導入した。

やりたいこと

  • ForkLift のカーソル移動に Emacs キーバインドを使う
  • ファイル操作を xyzzy のファイラとほぼ同じにしたい
    • ただし修飾キーとして shift の代わりに control を使用する
    • C-m が Emacs キーバインドの return にあたるので C-m だけ除外する

実現方法

  1. Complex modifications → Rules → Add Rules を選ぶ
  2. Import more rules from Internet を選ぶ
  3. Emacs で検索し、「Emacs key bindings (rev 12) by @tekezo」を追加
  4. Emacs key bindings [control+keys] (rev 10)」「Emacs key bindings [option+keys] (rev 5)」を有効にする
  5. ~/.config/karabiner/karabiner.json を開き、C-m のキーバインドの部分を次のように変更する
{
  "conditions": [
      {
          "bundle_identifiers": [
              "^com\\.binarynights\\.ForkLift-3$"
          ],
          "type": "frontmost_application_unless"
      }
  ],
  "from": {
      "key_code": "m",
      "modifiers": {
          "mandatory": [
              "control"
          ],
          "optional": [
              "caps_lock",
              "shift",
              "option"
          ]
      }
  },
  "to": [
      {
          "key_code": "return_or_enter"
      }
  ],
  "type": "basic"
},