iiyama ProLite E2473HDSが信号なしになってしまった場合の入力切替
iiyama ProLite E2473HDSの入力切替でちょっと躓いたのでメモ。
http://www.iiyama.co.jp/products/lcd/24/PLE2473HDS/
ProLite E2473HDSに2台のPCをVGAとDVIでつないでいるとする(
HDMIを使っている場合や3台以上の場合でも同様)。
このとき、入力としてVGAを選択した状態で、VGAにつないでいるPCの電源を落とした場合、ProLite E2473HDSは入力を自動的にDVIに切り替えてくれないためDVIからの入力があるのにもかかわらず信号なし状態になってしまう。
このような場合に、DVIに入力を切り替えるには[2]ボタンを押す(電源のランプがオレンジになっていても問題ない)。
また、入力切り替えでAutoを選択していれば、画面を出力しているPCの電源が落ちた際、自動的に別の入力に切り替えてくれる。よって、特定の入力を選択し画面を切り替えた後、入力切替でAutoを選択し直しておくと画面が真っ黒になって戸惑わずに済む。
pygmentizeで自作のlexerやstyleを使う
pygmentizeで使えるlexerやsytleに気に入るものがなかったり、変更を加えたい場合には自分でlexerやstyleを作ることができる。
今回は、Pygmentsにプラグインとして自作のlexer、styleを追加する。
setuptoolsが必要なのでインストールされていない場合には、インストールしておく。
http://pypi.python.org/pypi/setuptools
次に自作のlexerやstyle用のパッケージを作る。
今回はpygments_pluginという名前にすることにした。
ディレクトリをつくって、__init__.pyを配置。
mkdir pygments_plugin mkdir pygments_plugin/lexers mkdir pygmets_plugin/styles touch pygments_plugin/__init__.py touch pygments_plugin/lexers/__init__.py touch pygments_plugin/styles/__init__.py
bash用のlexerが実装されているpygments/lexers/other.pyをpygments_plugin/lexersに、pygments/styles/から好みのstyleをpygments/stylesにコピー。
cp /path/to/pytments/lexers/others.py pygments_plugin/lexers cp /path/to/pytments/styles/default.py pygments_plugin/styles
pygments_plugin/lexers/other.pyの中に以下のようなBash用のlexerがあるので、オリジナルとかぶっているnameやaliasesを変更する。例えば、name='My Shell'やaliases = ['mysh']など。
aliasesに設定した文字列で、pygmentizeからlexerを選択することができる。
class BashLexer(RegexLexer): """ Lexer for (ba|k|)sh shell scripts. *New in Pygments 0.6.* """ name = 'Bash' # これを変更 name = 'My Shell' aliases = ['bash', 'sh', 'ksh'] # これを変更 aliases = ['mysh'] filenames = ['*.sh', '*.ksh', '*.bash', '*.ebuild', '*.eclass'] mimetypes = ['application/x-sh', 'application/x-shellscript'] tokens = { 'root': [ include('basic'), (r'\$\(\(', Keyword, 'math'), (r'\$\(', Keyword, 'paren'), (r'\${#?', Keyword, 'curly'), (r'`', String.Backtick, 'backticks'), include('data'), ], 'basic': [ (r'\b(if|fi|else|while|do|done|for|then|return|function|case|' r'select|continue|until|esac|elif)\s*\b', Keyword), (r'\b(alias|bg|bind|break|builtin|caller|cd|command|compgen|' r'complete|declare|dirs|disown|echo|enable|eval|exec|exit|' r'export|false|fc|fg|getopts|hash|help|history|jobs|kill|let|' r'local|logout|popd|printf|pushd|pwd|read|readonly|set|shift|' r'shopt|source|suspend|test|time|times|trap|true|type|typeset|' r'ulimit|umask|unalias|unset|wait)\s*\b(?!\.)', Name.Builtin), (r'#.*\n', Comment), (r'\\[\w\W]', String.Escape), (r'(\b\w+)(\s*)(=)', bygroups(Name.Variable, Text, Operator)), (r'[\[\]{}()=]', Operator), (r'<<-?\s*(\'?)\\?(\w+)[\w\W]+?\2', String), (r'&&|\|\|', Operator), ], 'data': [ (r'(?s)\$?"(\\\\|\\[0-7]+|\\.|[^"\\])*"', String.Double), (r"(?s)\$?'(\\\\|\\[0-7]+|\\.|[^'\\])*'", String.Single), (r';', Text), (r'\s+', Text), (r'[^=\s\n\[\]{}()$"\'`\\<]+', Text), (r'\d+(?= |\Z)', Number), (r'\$#?(\w+|.)', Name.Variable), (r'<', Text), ], 'curly': [ (r'}', Keyword, '#pop'), (r':-', Keyword), (r'[a-zA-Z0-9_]+', Name.Variable), (r'[^}:"\'`$]+', Punctuation), (r':', Punctuation), include('root'), ], 'paren': [ (r'\)', Keyword, '#pop'), include('root'), ], 'math': [ (r'\)\)', Keyword, '#pop'), (r'[-+*/%^|&]|\*\*|\|\|', Operator), (r'\d+', Number), include('root'), ], 'backticks': [ (r'`', String.Backtick, '#pop'), include('root'), ], } def analyse_text(text): return shebang_matches(text, r'(ba|z|)sh')
次に以下のような内容のpygments_plugin/setup.pyを作成する。myshlexerやmystyleは好きな名前に変更してもよい。pygmentizeでstyleを選択するときは、ここでのmystyleに相当する文字列が使用される。
stylesからdefault.py以外を取ってきたときには、mystyle=の行のdefaultを取ってきたファイル名から.pyを除いたもの、DefaultStyleをとってきたファイル中で定義されているクラス名に変更する必要がある。
from setuptools import setup setup( name = "pygments_plugin", version = "0.1", package_dir = {"pygments_plugin": "", "pygments_plugin.lexers": "lexers", "pygments_plugin.styles": "styles"}, packages = ["pygments_plugin", "pygments_plugin.lexers", "pygments_plugin.styles"], entry_points = """ [pygments.lexers] myshlexer = pygments_plugin.lexers.other:BashLexer [pygments.styles] mystyle = pygments_plugin.styles.default:DefaultStyle """ )
ここまでで、以下のようなディレクトリ構成になっている。
% tree . ├── __init__.py ├── lexers │   ├── __init__.py │   └── other.py ├── setup.py └── styles ├── default.py └── __init__.py 2 directories, 6 files
pygments_pluginディレクトリで以下のコマンドを実行して、pygments_pluginをインストール。
python setup.py install
pygmentizeから追加されていることを確認。上記の例ではstyleにmystyle、lexerにmyshが追加されているはず。
pygmentize -L style pygmentize -L lexer
あとは、pygments_plugin/lexers/other.pyやpygments_plugin/sytles/default.pyを好きに変更する。
sytleに関しては基本的にカラーコードや修飾を変更するだけ。lexerに関してはtokens['basic']の中の正規表現に色を付けたいパターンを追加するのが簡単だと思う。詳細についてはPygmentsのドキュメントやソースコードを参照。
変更を加えたら再び下記のコマンドを実行すると、変更が反映される。
python setup.py install
実際に使用する際には、以下のようにする。formatterを指定しないとstyleを変えても意味がないので注意。
pygmentize -l mysh -f 256 -O syle=mystyle
コマンドが長いので、適当にaliasを作っておくと楽かもしれない。
pygmentizeでmakeやsconsの出力のシンタックスハイライト
makeやsconsを実行が失敗してしまったら、どのコマンドで失敗したのか調べなくてはならない。しかし、makeやsconsによって実行されるコマンドは引数が多かったり、絶対パスが使われたりしていて非常に読みにくい場合も多い。
そこで、これをシンタックスハイライトすることで少しでも読みやすくして、原因を見つけやすくする方法を考える。
今回はpygmentizeというコマンドを使って、シンタックスハイライトを行う。
pygmentizeコマンドはPygmentsをインストールすれば使えるようになるので、easy_installやpipでPygmentsをインストールすれば良い。
pip install pygments
pygmentizeは引数にファイルをとることもできるが、今回はmakeやsconsの出力をパイプで渡し、-lで入力がsh形式であることを教えてやる。
これで、echoやcdといったコマンドや文字列がハイライトされる。
make -n | pygmentize -l sh
日本語が含まれている場合にはencodingを指定する必要がある。
make -n | pygmentize -l sh -O encoding=utf-8
色を変更したい場合には、styleを変更する。formatterを256色ターミナル用に変更しないとstyleは反映されないので注意。
make -n | pygmentize -l sh -O -f256 style=vim
出力が長い場合にはlessを使ったり、行番号を追加すれば見やすくなる。
make -n | pygmentize -l sh | less -R make -n | pygmentize -l sh | cat -n | less -R
同じようなことはGNU Source-highlightを使って以下のようにもできるが、インストールが面倒そうだったし、ハイライトの結果もそんなに変わらないのでpygmentizeを使うことにした。
make -n | source-highlight -s sh -f esc | cat -n | less -R
追記:あるいは以下のようにvimなどをつかうのもありかもしれない。
make -n | vim +"set filetype=sh" -
不満点の一つはハイライトされる項目がかなり限られているため、せっかくハイライトしても見た目がほとんど変わらない場合が多いこと。例えば、この記事のようにオプションがハイライトされたりはしない。lexerとかを自分で書けば、エディタなどでの見た目に近づけられるだろうか
追記:本当は認識されている単語や記号でも、styleによっては色がついていないように見えることがある(例えば、&&や||とか)。上記の様にstyleを変えれば見えるようになることもある。
プロンプトで履歴を使って補完する
昨日作っていた関数を使うときに変数が長くなったり、何度も調べるときいちいち入力しなおすのが面倒なので履歴を使って補完できるようにした。
awful.promptにやりたいことと大体同じことをしてくれる関数があるので、それを使えればいいのだがlocalがついていて外からアクセスできなさそうだったのと、書き換えるのが面倒だったので単にrc.luaにコピーすることにした。
-- 履歴を格納するテーブル data = {} data.history = {} -- 履歴をロードする関数 awful/prompt.luaからのコピー function history_check_load(id, max) if id and id ~= "" and not data.history[id] then data.history[id] = { max = 50, table = {} } if max then data.history[id].max = max end local f = io.open(id, "r") -- Read history file if f then for line in f:lines() do table.insert(data.history[id].table, line) if #data.history[id].table >= data.history[id].max then break end end f:close() end end end -- data.historyに新しく入力されたデータを追加する関数 awful/prompt.luaからのコピー -- history_saveは元の関数がやってくれるのでコメントアウト function history_add(id, command) if data.history[id] then if command ~= "" and command ~= data.history[id].table[#data.history[id].table] then table.insert(data.history[id].table, command) -- Do not exceed our max_cmd if #data.history[id].table > data.history[id].max then table.remove(data.history[id].table, 1) end --history_save(id) end end end -- completion_callbackを返す関数 function completion_callback_using_history (id) history_check_load(id) f = function (text, cur_pos, ncomp) return awful.completion.generic(text, cur_pos, ncomp, data.history[id].table) end return f end
あとは、前回作った関数を以下のように書き換える。
以下に対応する引数あるいは行を追加した。
- 履歴ファイルの指定
- 履歴ファイルからの補間関数の作成
- 実行に履歴を保存
awful.key({ modkey, "Shift" }, "x", function () awful.prompt.run({ prompt = "variable name: " }, mypromptbox[mouse.screen].widget, function (var) history_add(awful.util.getdir("cache") .. "/history_variable_check", var) awful.util.eval("dbg('" .. var .. "'," .. var .. ")") end, completion_callback_using_history(awful.util.getdir("cache") .. "/history_variable_check"), awful.util.getdir("cache") .. "/history_variable_check") end),
これで何度も同じ文字列を入力することはなくなり、だいぶ便利になった。補完にはシェルを利用した関数も用意されているので、うまく利用すればパスの入力の手間を省いたりすることもできそう。
今回はコードをコピーして書いて、二度手間のような動作になってしまったが、実際にはawful.promptを少し書き換えたほうが(localを外せば)もっと簡単できれいにできると
思う。
キーバインドが増えてきて忘れそうなので、awful.keyやawful.promptを書き換えて、
キーバインドのリストを表示できるようにしたい。
Naughtyを使ったrc.luaのデバッグ
~/.config/awesome/rc.luaを書き換えた後に期待通り動かないときに、原因を探るのにはNaughtyを使って変数の値を調べるのが便利。
http://awesome.naquadah.org/wiki/Naughty
rc.luaに以下のような関数を定義する
function dbg(msg, var) local text = "<b>" .. msg .. "</b><br/>" text = text .. "type: " .. type(var) .. "<br/>" if var ~= nil then if type(var) == "string" or type(var) == "number" or type(var) == "nil" then text = text .. "value: " .. var elseif type(var) == "table" then text = text .. "value:<br/> " for k, v in pairs(var) do text = text .. " " .. tostring(k) .. " | " .. tostring(v) .. "<br/>" end else text = text .. "value: " .. tostring(var) .. "<br/>" end end naughty.notify({ text = text, timeout = 0}) end
この関数を適当なキーバインドからよび出せるようにしておくと、値が知りたい関数の名前を入力するだけなので楽。
awful.key({ modkey, "Shift" }, "x", function () awful.prompt.run({ prompt = "variable name: " }, mypromptbox[mouse.screen].widget, function (var) awful.util.eval("dbg('" .. var .. "'," .. var .. ")") end) end),
typeがtableでない時に属性を取得できれば、もっと便利になるのだがやり方がわからなかった。例えば、変数の型がtagの時にnameを表示してくれたりすると、コードを調べたりリファレンスを調べる手間が省けるのでありがたい。
あと変数名が長くなってくると毎回入力するのが面倒なので履歴を使えるようにしたい。
タイトルバーにつけているタグを表示してみる (awesome)
タイル型WMのawesomeを使っていて、複数のタグを同時に表示していると各クライアントにどのタグをつけているのかわからなくなってしまうことがあったので、各クライントのタイトルバーにつけているタグを表示するようにしてみた。
まず、awful.titlebar.addでタイトルバーをつけるときに、タグ名を書いたウィジェットを追加する。
titlebar_taglist = widget({ type = "textbox"}) titlebar_taglist.text = "tag:" for i, v in ipairs(c:tags()) do titlebar_taglist.text = titlebar_taglist.text .. " " .. v.name end awful.titlebar.add(c, { modkey = modkey, widget=titlebar_taglist })
あとは、クライアントのタグを付け替えたときに、表示が変わるように設定する。
タグリストからマウスでタグを付け替えることはないので、そちらには対応しなかった。
for i = 1, keynumber do awful.key({ modkey, "Shift" }, "#" .. i + 9, function () if client.focus and tags[client.focus.screen][i] then client.focus.titlebar.widgets[2].text = "tag: " .. tags[client.focus.screen][i].name awful.client.movetotag(tags[client.focus.screen][i]) end end), awful.key({ modkey, "Control", "Shift" }, "#" .. i + 9, function () if client.focus and tags[client.focus.screen][i] then local old_tags = {} local old_tags_count = 0 for _, v in ipairs(client.focus:tags()) do old_tags[v] = true old_tags_count = old_tags_count + 1 end if old_tags[tags[client.focus.screen][i]] then if old_tags_count > 1 then old_tags[tags[client.focus.screen][i]] = nil end else old_tags[tags[client.focus.screen][i]] = true end local client_tags = {} local index = 1 for i, v in ipairs(tags[client.focus.screen]) do if old_tags[v] then client_tags[index] = v index = index + 1 end end local c = client.focus c.titlebar.widgets[2].text = "tag:" for i, v in ipairs(client_tags) do c.titlebar.widgets[2].text = c.titlebar.widgets[2].text .. " " .. v.name end awful.client.toggletag(tags[client.focus.screen][i]) end end)) end
Luaの配列の扱いにけっこう苦戦したけど、慣れたらいろいろ設定できて面白そう。
ReadCubeで文献管理
新しい文献管理ツールReadCubeというのを見つけたので使ってみた。
PDFのインポートはPDFのあるディレクトリを選ぶだけで簡単。
検索、スナップショット、ハイライト、ノートといったアノテーション機能やリストを使ったファイル管理機能がある。ただし、ReadCubeでつけたアノテーションをFoxit Readerなど他のリーダーで見ることはできないようだ。
論文の管理に特化した機能として、PDFからのタイトルや著者の認識、論文のレコメンデーション、PubMed, Google Scholarの検索機能などがある。とくに、関連論文、リファレンス、引用情報をPubMedやGoogle Scholarなどを使って検索してくれる機能は便利だと感じた。検索結果を選択するとブラウザが開き比較的簡単にPDFを入手することができるので、関連論文のPDFを集めるのが捗りそうだ。
公開されているWeb Readerが便利だったので、自分のPDFをWebでも見られるようになったら嬉しい。