Microのプラグイン開発の例、開いているファイルのパスをクリップボードに保存する

Microのプラグイン開発の例として、現在開いているファイルのパスをクリップボードに保存するという処理を書いてみます。


Microでのプラグイン開発はinit.luaに処理を記述するか?配布できる形にするか?の2つの形式がありますが、内容を簡略化する為にinit.luaに記述する方式を取ります。

Microのinit.luaを試す

Microのプラグイン開発、文字列を出力する


環境

Micro:2.0.11


今回追加したい機能はコマンドモードで

> cp path

を実行した時は、現在開いているファイルのパスをクリップボードに保存し、

> cp dir

を実行した時は、現在開いているファイルが配置されているディレクトリをクリップボードに保存します。


クリップボードに関しては、コマンドライン上でのクリップボードの利用方法をご覧ください。

※今回の内容を読み進める前に、上記のリンク先の記事を参考にして、wl-copyosc52のコマンドを使用できるようにしておきましょう。




先に今回作成したコードを載せておきます。


~/.config/micro/init.lua

local micro = import("micro")
local config = import("micro/config")
local shell = import("micro/shell")

function init()
	config.MakeCommand("cp", cp, config.NoComplete)
end

-- コマンド実行時に引数を取得する
function extractCpMode(args)
	local mode = "";
	for i = 1, #args do
		mode = args[i]
	end
	return mode
end

-- 使用しているディスプレイサーバを取得する (wayland|x11|tty)
function getDisplayServerType()
	local srv, err = shell.RunCommand("sh -c 'echo $XDG_SESSION_TYPE'")
	
	if err == nil and srv:len() > 0 then
		local strings = import("strings")
		srv = strings.TrimRight(srv, "\n")
		if srv:len() > 0 then
			return srv
		end
	end
	
	return "tty"
end

function cp(bp, args)
	local mode = extractCpMode(args)
	local path = bp.Buf.AbsPath

	if mode == "dir" then
		local fp = import("filepath")
		path = fp.Dir(path)
	end

	local srv = getDisplayServerType()
	if srv == "wayland" then
		cmd = "sh -c 'echo -n \""..path.."\" | wl-copy'"
	elseif srv == "tty" then
		cmd = "sh -c 'echo -n \""..path.."\" | osc52'"
	else
		cmd = "sh -c 'echo -n \""..path.."\" | xclip -selection clipboard'"
	end

	local output, err = shell.RunInteractiveShell(cmd, false, false)
	if err == nil then
		micro.InfoBar():Message("copied filepath.")
	else
		micro.InfoBar():Error(err)
	end
end

コードの解説になります。

extractCpMode関数に関しては省略します。


function getDisplayServerType()
	local srv, err = shell.RunCommand("sh -c 'echo $XDG_SESSION_TYPE'")
	
	if err == nil and srv:len() > 0 then
		local strings = import("strings")
		srv = strings.TrimRight(srv, "\n")
		if srv:len() > 0 then
			return srv
		end
	end
	
	return "tty"
end

ですが、シェルモードで

sh -c 'echo $XDG_SESSION_TYPE

を実行し、その値を返します。

何も値が返ってこなかった場合は tty を返すようにしています。

Microでシェルモードを使ってみる


この関数で注意すべき内容は、シェルモードを

RunCommand(input string) (string, error)

を介してコマンドを実行しているのですが、実行結果には必ず改行コードが付いてしまいますので、Go言語の strings パッケージにあるTrimRightメソッドで改行コードを削除しています。

micro/runtime/help/plugins.md at master · zyedidia/micro


Luaのコード内でGo言語のパッケージを使用できるようにしているのは、GopherLuaとgopher-luarによって実現しています。

yuin/gopher-lua: GopherLua: VM and compiler for Lua in Go

layeh/gopher-luar: simplifies data passing to and from gopher-lua


使い方は

local strings = import("strings")
srv = strings.TrimRight(srv, "\n")

import関数でGo言語のパッケージを読み込み、Go言語の仕様と同様にドット区切りでメソッドを呼び出します。

strings package - strings#TrimRight - Go Packages


使用可能なメソッドはmicro/internal/lua/lua.go at master · zyedidia/microをご確認ください。




続いて見るべきコードは cp 関数内にあります

local path = bp.Buf.AbsPath

になります。


BufのAbsPathはbuffer package - github.com/zyedidia/micro/v2/internal/buffer#SharedBuffer - Go Packagesを参考にしました。


cp 関数内の下記の処理にも触れておきます。

local srv = getDisplayServerType()
if srv == "wayland" then
	cmd = "sh -c 'echo -n \""..path.."\" | wl-copy'"
elseif srv == "tty" then
	cmd = "sh -c 'echo -n \""..path.."\" | osc52'"
else
	cmd = "sh -c 'echo -n \""..path.."\" | xclip -selection clipboard'"
end

local output, err = shell.RunInteractiveShell(cmd, false, false)

になります。


ディスプレイサーバに合わせて、クリップボードに文字列を保存するコマンドを生成してシェルモードで実行なのですが、今回は

RunInteractiveShell(input string, wait bool, getOutput bool) (string, error)

を利用しています。


何故、ディスプレイサーバの確認時と異なるメソッドを使用する必要があるのか?

これは、RunInteractiveShellの引数にあります wait と getOutput を使用したいからになります。

micro/runtime/help/plugins.md at master · zyedidia/micro


Microのシェルモードで wl-copy を実行すると、実行結果がない状態でエンターキーの入力待ちになります。

※ シェルモードで echo を実行すると待機にはなりますが、実行結果がある為、RunCommandでも問題ないようです。


入力待ち状態を回避するために、wait と getOutput のパラメータを false にしておく必要があります。


追記

tmuxを起動した状態で、Microを開いた時、

> cp path

をしても意図通りに動作しないことがあります。


tmuxの設定を変更する - ターミナルの内容を参考にして、tmux上でクリップボードを使用できるようにしておきましょう。


~/.tmux.conf

set -g set-clipboard on
同じカテゴリーの記事
マインクラフト用ビジュアルエディタを開発しています。
詳しくはinunosinsi/mcws_blockly - githubをご覧ください。