モブ沢工房

プログラミングとかLinux関連(特にOSSのグラフィックツール関連)とかレトロゲームとか3Dプリンタやら日曜大工等、色々。

エラーの箇所に飛ぶスクリプトを書きました

この記事はfc2から引っ越した記事です

pythonvimで非常に鬱陶しいのは、シンタックスエラーが起きた時の処理です。
python-lintをかけるという手法もありますか…まぁそれはともかく。

テストの前段階で何度も何度もエディタとターミナルを往復する…
これはストレスです。

以前作っていたoredb.pyではこれを、gvimからデバッガ実行→エラー捕捉→呼び出したgvimにファイル名を送り、さらにキーストロークを送りつけてエラー箇所を表示 ということをやっていましたが、pudbがあまりにも出来が良かったために放置となりました。日本語回りは若干弱いですけどね…

そこで考えました。
もっとごくシンプルに、エラー出力を奪って解析して、gvimでリモートオープンしてキーコマンドもリモートで送り、エラーの場所に飛ばすだけのプログラムを作ったらどうだろうか?と。

そんなわけで作りました。synerrjump.pyです。

最初、標準エラー出力から入力しようとしたという笑えることをしてしまいましたがw
そして次に、sys.std系でエラー出力を得られそうにないので、うーむ?と思って
シェルスクリプトを作ってそいつが 2&>1 (エラー出力も標準出力に出しちゃう指定) して 標準出力を読んでスクレイピングする」
という手法を思いつきました。
で、一旦完成までたどり着いて満足していたのですが、ハッと閃きが。

subprocessで呼んで、エラー出力を奪えばいいだけなのでは?

なんとまぁそのとおりですね。まったく遠回りで間抜けなことをしてしまいました。
そして作りなおしたのがこれです。


synerrjump.py

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

import sys
import re
import os
import subprocess

def execute_prog(args):
args.insert(0,'python')
p = subprocess.Popen(args,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
shell=False)
p.wait()
return p.stderr.readlines()



def decode_input(gvim_name,all_lines):

ro_info=re.compile('File\s\"(.+)\",\sline\s([0-9]+)')
matched=None
lastline=''

for line in all_lines:
mo=ro_info.search(line)
if mo:
matched=mo
lastline=line

if matched:
fpath=os.path.abspath(matched.group(1))
linenum=matched.group(2)
print('error is file %s,line %s' % (fpath,linenum))
cmds=['gvim','--remote',fpath]
cmds_keystroke=['gvim','--remote-send',"%sG" % linenum]

if gvim_name!=None:
svrname_cmd=['--servername',gvim_name]
cmds[1:1]=svrname_cmd
cmds_keystroke[1:1]=svrname_cmd

#print(cmds)
#print(cmds_keystroke)
subprocess.call(cmds)
subprocess.call(cmds_keystroke)
print lastline
else:
print('no error found')




if __name__ == '__main__':
import getopt
try:
opts,args=getopt.getopt(sys.argv[1:],"hn:",["help","vimname="])
except getopt.GetoptError,e:
print(str(e))

gvim_name=None

for cmd,arg in opts:

if cmd=='-h' or cmd=='--help':
print "help document"
elif cmd=='-n' or cmd=='--vimname':
gvim_name=arg
else:
pass

decode_input(gvim_name,execute_prog(args))



毎度お粗末なコードでございますが…動けばよかろうなのだァァァァッ!

なお、どんなエラーなのかは最後の行に表示されるので、それも表示しています。

これを使ったら作業が捗ること、捗ること。きっと似たようなものが既に存在しているに違いありません。

pythonvimで非常に鬱陶しいのは、シンタックスエラーが起きた時の処理です。
python-lintをかけるという手法もありますか…まぁそれはともかく。

テストの前段階で何度も何度もエディタとターミナルを往復する…
これはストレスです。

以前作っていたoredb.pyではこれを、gvimからデバッガ実行→エラー捕捉→呼び出したgvimにファイル名を送り、さらにキーストロークを送りつけてエラー箇所を表示 ということをやっていましたが、pudbがあまりにも出来が良かったために放置となりました。日本語回りは若干弱いですけどね…

そこで考えました。
もっとごくシンプルに、エラー出力を奪って解析して、gvimでリモートオープンしてキーコマンドもリモートで送り、エラーの場所に飛ばすだけのプログラムを作ったらどうだろうか?と。

そんなわけで作りました。synerrjump.pyです。

最初、標準エラー出力から入力しようとしたという笑えることをしてしまいましたがw
そして次に、sys.std系でエラー出力を得られそうにないので、うーむ?と思って
シェルスクリプトを作ってそいつが 2&>1 (エラー出力も標準出力に出しちゃう指定) して 標準出力を読んでスクレイピングする」
という手法を思いつきました。
で、一旦完成までたどり着いて満足していたのですが、ハッと閃きが。

subprocessで呼んで、エラー出力を奪えばいいだけなのでは?

なんとまぁそのとおりですね。まったく遠回りで間抜けなことをしてしまいました。
そして作りなおしたのがこれです。


synerrjump.py

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

import sys
import re
import os
import subprocess

def execute_prog(args):
args.insert(0,'python')
p = subprocess.Popen(args,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
shell=False)
p.wait()
return p.stderr.readlines()



def decode_input(gvim_name,all_lines):

ro_info=re.compile('File\s\"(.+)\",\sline\s([0-9]+)')
matched=None
lastline=''

for line in all_lines:
mo=ro_info.search(line)
if mo:
matched=mo
lastline=line

if matched:
fpath=os.path.abspath(matched.group(1))
linenum=matched.group(2)
print('error is file %s,line %s' % (fpath,linenum))
cmds=['gvim','--remote',fpath]
cmds_keystroke=['gvim','--remote-send',"%sG" % linenum]

if gvim_name!=None:
svrname_cmd=['--servername',gvim_name]
cmds[1:1]=svrname_cmd
cmds_keystroke[1:1]=svrname_cmd

#print(cmds)
#print(cmds_keystroke)
subprocess.call(cmds)
subprocess.call(cmds_keystroke)
print lastline
else:
print('no error found')




if __name__ == '__main__':
import getopt
try:
opts,args=getopt.getopt(sys.argv[1:],"hn:",["help","vimname="])
except getopt.GetoptError,e:
print(str(e))

gvim_name=None

for cmd,arg in opts:

if cmd=='-h' or cmd=='--help':
print "help document"
elif cmd=='-n' or cmd=='--vimname':
gvim_name=arg
else:
pass

decode_input(gvim_name,execute_prog(args))



毎度お粗末なコードでございますが…動けばよかろうなのだァァァァッ!

なお、どんなエラーなのかは最後の行に表示されるので、それも表示しています。

これを使ったら作業が捗ること、捗ること。きっと似たようなものが既に存在しているに違いありません。