LoginSignup
33
12

More than 5 years have passed since last update.

「立体インデント」を自動化する

Last updated at Posted at 2018-07-27

2018/07/28

ソースと結果を直しました。


@set0gut1 さんの寄り目を利用した「目diff」および「立体インデント」の考案からインスパイアされた記事です。
Python3 で立体インデント化したソースコードを出力できるようにしました。

ソース

いろいろツッコミどころのあるコードですが、大目に見てやってください…
ソースコードはここにもあげています。

make3Dindent.py
#!/usr/bin/env python3
import sys
import os

start = '{' # ネストの起点
end = '}' # ネストの終点
width = 20 # 改行幅

def make3Dindent(stream, reverse=False):
  depth = 0 # いまの浮かび具合(右側のテキストに適用)
  depthList = [0] # 行ごとの浮かび具合の管理
  leftLines = []
  rightLines = []
  for line in stream: 
    charcount = 0
    left = ''
    right = ''
    for c in line:
      charcount += 1
      if(c == start):
        # 浮かび具合を上げる
        depth += 1
        left += c
        right += ' ' + c
      elif(c == end):
        # 浮かび具合を下げる
        depth -= 1
        left += c + ' '
        right += c
      elif c == "\n": # 改行処理
        pad = (width - charcount) * ' '
        leftLines.append(left + pad)
        rightLines.append(right + pad)
        depthList.append(depth)
        left = ''
        right = ''
        charcount = 0
        continue
      else:
        left += c
        right += c

      if charcount >= width:
        leftLines.append(left)
        rightLines.append(right)
        depthList.append(depth)
        left = ''
        right = ''
        charcount = 0

  if c != "\n" and charcount > 0:
    pad = (width - charcount) * ' '
    leftLines.append(left + pad)
    rightLines.append(right + pad)
    depthList.append(depth)

  depthList.pop()

  maxDepth = max(depthList)
  maxLength = max([len(line) for line in leftLines])

  retRight = []
  retLeft = []

  baseWidth = maxDepth + maxLength
  for (l, r, d) in zip(leftLines, rightLines, depthList):
    retLeft.append((' ' * (maxDepth - d)) + l + (' ' * (baseWidth - (len(l) + (maxDepth - d)))))
    retRight.append((' ' * d) + r + (' ' * (baseWidth - (len(r) + d))))

  # 焦点補助のドット
  pad = ' ' * int(baseWidth / 2)
  dotLine = pad + '●' + pad
  retLeft.append(dotLine)
  retRight.append(dotLine)

  if reverse:
    # 沈む
    return (retRight, retLeft)
  else:
    # 浮かぶ
    return (retLeft, retRight)

# 出力用
def printLeftRight(left, right):
  for (l, r) in zip(left, right):
    print (l + ' ' + r)


if __name__ == '__main__':
  if len(sys.argv) == 1:
    (left, right) = make3Dindent(sys.stdin)
    printLeftRight(left, right)
  else:
    input_file = sys.argv[1]
    if not os.path.isfile(input_file):
      print(input_file + ': not found')
      sys.exit(1)

    f = open(input_file)
    (left, right) = make3Dindent(f)
    f.close()
    printLeftRight(left, right)

実行

$ ./make3Dindent.py input.js

# 標準入力からも可能
$ ./make3Dindent.py < input.js

結果

   for(var i=1;i<=100;i   for(var i=1;i<=100;i     
   ++){if(i%3===0){if(i   ++) {if(i%3===0) {if(i   
 %5===0){console.log(       %5===0) {console.log(  
"FizzBuzz")} else{con        "FizzBuzz")}else {con 
sole.log("Fizz")} } el       sole.log("Fizz")}}el  
  se if(i%5===0){conso     se if(i%5===0) {conso   
 le.log("Buzz")} else{      le.log("Buzz")}else {  
 console.log(i)} }          console.log(i)}}       
                                                 

問題

改行位置をwidthで指定しているので、単語の途中でも改行されてしまう。

所感

動作確認で目がいたい…
printLeftRight ってなんだよ

33
12
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
33
12