🔙 Back to Top

Tue Mar 17 16:42:34 JST 2015

vim で編集しながら途中経過を監視したい

これらはvimで編集しながらも逐一、途中経過をコンパイル (または変換) して、 その結果を眺めたい

markdown

pandoc を用いて、htmlまたはpdfに変換したい
htmlに変換して見るだけでも脳内でpdfに対応付けさせることは容易

gnuplot

png画像を出力させたい

dot言語

png画像を出力させたい
Linuxならば、graphviz パッケージをいれると vimdot が付いてくるので、
これを使うのが手っ取り早い

作った

# watch.coffee
fs        = require 'fs'
path      = require 'path'
socket_io = require 'socket.io'
http      = require 'http'
express   = require 'express'

# make server
app    = express()
server = http.Server app
io     = socket_io server

app.get '/', (req, res) ->
  res.writeHead 200, 'Content-Type': 'text/html'
  res.end '''
<title>preview</title>
<script src="/socket.io/socket.io.js"></script>
<body><div id='win'></div>
<script>
var socket = io.connect("http://127.0.0.1"); 
socket.on('change', function (data) {
    win.innerHTML = data;
    });
</script>
'''

app.get /local\/.*/, (req, res) ->
  filename =
    req.url
      .replace /^\/local\//, ''
      .replace /\?.*$/, ''
  res.sendFile path.resolve filename

server.listen 80, (->)
io.listen server

# read configure
conf = require "./#{process.argv[2]}.coffee"

# socket
gsocket = false

emit = ->
  unless gsocket
    return
  console.log 'emit', gsocket.id
  conf.compile (err, data) ->
    throw err if err
    console.log data
    gsocket.emit 'change', data

io.sockets.on 'connection', (socket) ->
  gsocket = socket
  do emit

# watch the file
fs.exists conf.srcfile, (bl) ->
  unless bl
    console.log "#{conf.srcfile} not exists"
    process.exit 0
  fs.watchFile conf.srcfile, {interval:300}, (event) ->
    console.log event
    do emit

別途、監視対象のファイルと、それをどう処理するかを書いた設定ファイルを用意する
ファイル名は兎も角、処理は関数で書くしかないので
実用上、CoffeeScriptかJavaScriptで書くしかない
従って、設定ファイルは実際はモジュールである

markdown.coffee

fs = require 'fs'
{exec} = require 'child_process'

srcfile = './test.md'

compile = (cont) ->
  exec "pandoc -s -t html5 -i #{srcfile} -o test.html", (err) ->
    console.warn err if err
    fs.readFile './test.html', 'utf8', (err, data) ->
      throw err if err
      cont false, data

module.exports =
  srcfile: srcfile
  compile: compile

gnuplot.coffee

{exec} = require 'child_process'

srcfile = 'test.plt'
compile = (cont) ->
  exec "gnuplot #{srcfile}", (err) ->
    console.warn err if err
    cont err, "<img src=local/test.png?#{Math.random()}>"

module.exports =
  srcfile: srcfile
  compile: compile

dot.coffee

{exec} = require 'child_process'

srcfile = './test.dot'

compile = (cont) ->
  exec 'dot -Tpng test.dot > test.png', (err) ->
    console.warn err if err
    cont err, "<img src=local/test.png?#{Math.random()}>"

module.exports =
  srcfile: srcfile
  compile: compile

python.coffee

fs = require 'fs'
{exec} = require 'child_process'

srcfile = './test.py'

compile = (cont) ->
  exec "python #{srcfile} > out", (err) ->
    console.warn err if err
    fs.readFile './out', 'utf8', (err, data) ->
      throw err if err
      cont false, data.replace /\n/g, '<br>'

module.exports =
  srcfile: srcfile
  compile: compile

usage

watch.coffeeconf.coffee と、監視対象ファイルが全部同じディレクトリにあることにしてる
また、開始時に 監視対象ファイルは既に存在してることにしてる

sudo coffee watch.coffee conf

例えば、python.coffee なら

touch test.py
sudo coffee watch.coffee python

とこうして、 別な窓で test.py を編集する
ファイル変更がチェック出来るのは保存時だから、 ファイルを上書きした瞬間に python test.py > out が走る

コンパイルの結果は、 ブラウザで http://127.0.0.1/ を開くことで確認する

fs.watchfs.watchFile とがあって、 二つとも目的は同じである
手元のMacでは fs.watch は明らかに信用できない挙動であった
詳しくはドキュメント

こんだけならわざわざ、こんなsocket.ioまで使って面倒なことしないでも
リロードしまくるっていうhtml書けばいいのでゎ