起:.gitignore
のちょっとした悩み
ことの発端
プロジェクトをInitial commit
した後におもむろにやる作業として、「gitignore.ioから良さげな.gitignore
を作る」というのがありますよね? 1 2
ありますよね?
時間経過で.gitignoreは変化する...こともある
最初のまま運用できれば問題ないのですが、
- あ、この環境用のignoreもつけたい
- ちょっと特殊なignoreが必要になりそう
ということが出てきたりします。
出てきたりします。
(1)のケースだと、もう一回gitignore.ioに行って再生成しないといけなかったりします。
(2)のケースだと、テンプレ生成した.gitignore
のどこかに記述しないといけなくなるのですが、
こうなってくると(1)の対応のたびに若干の手間を感じてしまったりします。多分
承:雑な思いつきと、MVPっぽいの
思いつき
そこで「.gitignore
編集時にいい感じに『言語名』と『言語のignore』をいい感じに連携しつつ簡素に書くエディタ」とか作れないかなと考えてみました。lazygitみたいなUIかっこいいじゃないですか
- キーワードを入れると、「そのキーワードを含む言語・環境の候補」が出る
- Tabで候補に移動して右とか押したら、、言語として反映
- 候補がない中でキーワードを選択して右を押したら、パターンとして反映
- 保存時に、勝手にAPIコールしてgitignore.io+パターンで構築
とかできると、派生でignoreしたいパターンなどをまとめて放り込めて便利かなーなんて。
とはいえ、こういう形式でのエディタを作成する能力は今の所ありません。
手間を掛けずにそれっぽいの(=MVP?)を作ってみる
超雑に、MVPっぽい超簡易実装を試してみました。
こちら => vigi = vi gitignore
vigi
コマンドを実行すると、
# ~~~~~~
こんな感じのファイルをvim
で開き、
.idea
# ~~~~~~
python
virtualenv
こんな感じで編集してvim
を終了すると、
.idea
# ~~~~~~
# https://www.gitignore.io/api/python,virtualenv の中身
みたいな状態の.gitignore
を作ってくれます。
ちなみに、この状態でvigi
コマンドを実行すると、gitignore.io部分はちゃんと言語のみの情報になります。編集がしやすい……かなと思います。
転:中身はこんな感じ
.gi
という名で仮ファイルを作って編集し、保存されたらそれを.gitignore
に変換するスタイル
import subprocess
from pathlib import Path
from subprocess import CalledProcessError, PIPE
def main():
gi_path = Path.cwd() / '.gi'
gitignore_path = Path.cwd() / '.gitignore'
try:
# Convert from ``.gitignore`` to ``.gi``
if gitignore_path.exists():
encode_gitignore(gitignore_path, gi_path)
else:
with gi_path.open('w') as fp:
fp.write(dedent(gi_template).strip())
# Spawn vim
vim_args = ['/usr/bin/vim', str(gi_path)]
vim_proc = subprocess.run(vim_args, check=True)
# Convert from ``.gi`` to ``.gitignore``
decode_gitignore(gi_path, gitignore_path)
except CalledProcessError:
pass
finally:
# Remove ``.gi``
gi_path.unlink()
vimを呼ぶ
subprocess.run
でvim
を呼出し、CalledProcessError
例外がなければOKというざっくりスタイル。楽で良いですね。
.gi
は残さない
try
〜finally
を使って、最終的に.gi
ファイルは捨てちゃってます。エラーなら.gitignore
の編集もしないので環境に配慮されていますね。
素材をもとに.gitignore
を作る
.gi
ファイルはこの時点でファイルシステム上に普通にあるので、普通にファイルとして開く感じです。
そして、言語側の情報をまとめてgitignore.ioにパス。
HTTPステータスが404の時に限り、通常と同じようにレスポンスを保存してますが、
これは「マスターに存在しない情報を含む」ケースが全て404になるっぽいためです。
唯一と言っていい、ちょっとした工夫点ですね。
def decode_gitignore(src, dest):
custom = []
online = []
with src.open() as fp:
# .giファイルを開いて、デリミタの前後を分けるなど
if online:
url = f'https://www.gitignore.io/api/{",".join(online)}'
req = Request(url, None, headers={'User-Agent': 'vigi'})
try:
resp = urlopen(req)
custom.append(resp.read().decode())
except HTTPError as err:
if err.code == 404:
custom.append(resp.read().decode())
raise err
with dest.open('w') as fp:
fp.write('\n'.join(custom))
結:使用感とか
一応、vigi
プロジェクト内にある.gitignore
はこのコマンドベースで作りました。
編集時点で表示される行数が格段に減るのはメリットではあるかなと思います。
そういう意味ではMVPとしての仕事はきちんと全うしてくれました。
ただ、言語マスターにどんなパターンが含まれているかが、.gitignore
への変換を終えないとわからないので、
仮にもうちょっと開発してみようと思ったら、きちんとパターン候補から言語マスターを引っ張り出すようにしないと、
本当に良いものなのかはわからないですね。何かの言語のトレーニングには向いてるかも?