Created
January 15, 2012 13:38
-
-
Save tiye/1615885 to your computer and use it in GitHub Desktop.
极简规则自动补全 Lisp 式括号
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
''' | |
想做对于 Lisp-like 的括号自动补全, 用 py 脚本处理 | |
先做了测试看(虽然我没学会 clj 没的测), 默认读取 file 输出 new_file | |
现在的定义的规则如下(其中空行被排除) | |
每行代码开头添加 '(' | |
每行代码结尾, 判断缩进个数比下一行多 n 个 | |
当 (n >= 0), 在当前行末尾添加 (n+1) 个 ')' | |
每行代码结尾, 如果 '(' 数 a, ')' 数 b, 下一行多 c 个缩进 | |
若 (a-b-c) 为正, 在该行末尾添加对应个 ')' | |
可以有多层的缩进, 对应手动添加一次括号 '(' | |
Jan 16 重新构造代码, 增加单行括号数统计和补全 | |
添加单行注释, 识别用下面这条正则, 不能处理行尾注释 | |
r'^\s$|^\s*;' | |
用下面的正则大致尝试匹配单行中的单个值, 否则多余的括号会报错 | |
r'\t+(\S)+\n' | |
$ cat file | |
curry0 | |
curry1 (curry2 | |
curry3 | |
curry4 | |
curry5 | |
curry00 | |
curry01 | |
curry02 | |
curry03 | |
$ cat fi | |
(curry0 | |
(curry1 (curry2 | |
curry3) | |
curry4) | |
curry5) | |
(curry00 | |
curry01 | |
curry02 | |
curry03) | |
$ cat fibo.0 | |
defun fibonacci (N | |
d | |
if (or (zerop N) (= N 1 | |
1 | |
+ (fibonacci (- N 1)) (fibonacci (- N 2 | |
$ cat fibo | |
(defun fibonacci (N) | |
d | |
(if (or (zerop N) (= N 1)) | |
1) | |
(+ (fibonacci (- N 1)) (fibonacci (- N 2))) | |
''' | |
#!/usr/bin/python3 | |
import sys | |
import re | |
def count_indents (line): | |
line = str (line) | |
count = 0 | |
for char in line: | |
if char == '\t': | |
count += 1 | |
line = line[1:] | |
else: | |
break | |
return count | |
def add_head (line, current_count, next_count): | |
if re.match (r'\t+(\S)+\n|^\t+\[.*\]$', line): | |
if current_count >= next_count: | |
return line | |
else: | |
line = line[:current_count] + '(' + line[current_count:] | |
return line | |
else: | |
line = line[:current_count] + '(' + line[current_count:] | |
return line | |
def add_back (line, current_count, next_count): | |
tabs = current_count - next_count | |
if tabs > 0: | |
line = line[:-1] + ')'*tabs + '\n' | |
return line | |
def complete_back (line, current_count, next_count): | |
tabs = next_count - current_count | |
pre_bracket = 0 | |
after_bracket = 0 | |
for char in line: | |
if char == '(': | |
pre_bracket += 1 | |
if char == ')': | |
after_bracket += 1 | |
num = pre_bracket - after_bracket - tabs | |
if num > 0: | |
line = line[:-1] + ')'*(num) + '\n' | |
return line | |
return line | |
file_name = sys.argv[1] | |
new_name = file_name[:-2] | |
texts = [] | |
indents = [] | |
comments = [] | |
comment_index = [] | |
index = 0 | |
input_text = open (file_name, 'r') | |
for i in input_text: | |
line = str (i) | |
if re.match(r'^\s$|^\s*;', line): | |
comments.append (line) | |
comment_index.append (index) | |
else: | |
texts.append (line) | |
index += 1 | |
indents.append (count_indents (line)) | |
length = len (texts) | |
texts.append ('') | |
indents.append (0) | |
input_text.close () | |
output_texts = '' | |
for i in range (length): | |
for j in range (len (comment_index)): | |
if comment_index[j] == i: | |
output_texts += comments[j] | |
texts[i] = add_head (texts[i], indents[i], indents[i+1]) | |
texts[i] = add_back (texts[i], indents[i], indents[i+1]) | |
texts[i] = complete_back (texts[i], indents[i], indents[i+1]) | |
output_texts += texts[i] | |
output_text = open (new_name, 'w') | |
output_text.write (output_texts) | |
output_text.close () | |
print ('Done:', new_name) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment