modify something
This commit is contained in:
parent
cb2cd421d3
commit
c04efe041d
12 changed files with 308 additions and 76 deletions
|
@ -3,6 +3,7 @@ A Scheme-like typesetting LISP interpreter and editor that using SILE typesettin
|
|||
|
||||
|
||||
## Dependencies
|
||||
* Python3
|
||||
* PyQt5>=5.15
|
||||
* QScintilla>=2.12
|
||||
* SILE>=0.10
|
||||
|
@ -20,10 +21,10 @@ see `src/example.pdf`
|
|||
|
||||
To make a wheel package, run the following command in the root folder:
|
||||
|
||||
`python setup.py bdist_wheel`
|
||||
`python3 setup.py bdist_wheel`
|
||||
|
||||
and then:
|
||||
|
||||
`cd dist; ls`
|
||||
|
||||
`Clochur-x.y.z-py3-none-any.whl` will in it.
|
||||
`Clochur-x.y.z-py3-none-any.whl` will be in it.
|
||||
|
|
|
@ -2,6 +2,28 @@
|
|||
[script "packages/font-fallback"]
|
||||
[script "packages/grid"]
|
||||
|
||||
[define section-var 1]
|
||||
[define sub-section-var 1]
|
||||
[define section-title ""]
|
||||
|
||||
% custom macro
|
||||
[def-syntax section
|
||||
[[_ x][begin
|
||||
[set! section-title [str-append [str-append [str section-var] [str ". " ]] [str x]]]
|
||||
[font [[size "20pt"][weight "800"]] section-title]
|
||||
[set! section-var [+ section-var 1]]
|
||||
[set! sub-section-var 1]
|
||||
]]]
|
||||
|
||||
% custom macro
|
||||
|
||||
|
||||
[def-syntax subsection
|
||||
[[_ x][begin
|
||||
[set! section-title [str-append [str-append [str sub-section-var] [str ". " ]] [str x]]]
|
||||
[font [[size "16pt"][weight "600"]] section-title]
|
||||
[set! sub-section-var [+ sub-section-var 1]]
|
||||
]]]
|
||||
|
||||
|
||||
[docu-para [[class "book"][papersize "b5"]]]
|
||||
|
@ -12,9 +34,11 @@
|
|||
|
||||
[font-size "20pt" "Welcome to use"] [font [[family "sligeach_orig"][size "20pt"]] "Clóċur"][font-size "20pt" ", a toy editor, toy intepreter and a toy typesetting-engine frontend."]
|
||||
|
||||
[call section "What is Clochur?"]
|
||||
[section "What is Clochur?"]
|
||||
|
||||
Clochur, or printed as [str "\""][font-family "sligeach_orig" "Clóċur" ][str "\""] in Irish language (Clóċur as Roman type, which means [q]typesetting[q]), is a toy-lisp typesetting language with a intepreter written in Python, and with a simple Editor written in PyQt and Qscintilla.
|
||||
|
||||
|
||||
Clochur, or printed as "\""[font-family "sligeach_orig" "Clóċur"]"\"" in Irish language ([italic "\"CLOW-kur\""] Clóċur as Roman type, which means [q]typesetting[q]), is a toy-lisp typesetting language with a intepreter written in Python 3, and with a simple Editor written in PyQt5 and QScintilla.
|
||||
|
||||
It generate a XML that is readable for SILE, which is a typesetting engine written in Lua,
|
||||
and it generate PDF with SILE.
|
||||
|
@ -28,4 +52,23 @@ The functions that it has (although may be buggy or needed to be tested) is:
|
|||
- count basic arithmetic expression.
|
||||
|
||||
[str "- lambda function"], function definition.
|
||||
]
|
||||
|
||||
[section "Simple manual"]
|
||||
|
||||
[subsection "Macro"]
|
||||
|
||||
Using 'def-syntax', you can add your macro to sile. the example is a "custom-section" macro:
|
||||
|
||||
[font-family "Noto Sans Mono CJK TC"
|
||||
% custom macro
|
||||
"[def-syntax \"section\"
|
||||
|
||||
[[_ x][begin] ]
|
||||
|
||||
[set! section-title [str-append [str-append [str [str \"section-var\"]] [str \". \" ]] [str x]]]
|
||||
|
||||
[font [[size \"20pt\"][weight \"800\"]] [str \"section-title\"]]
|
||||
|
||||
[set! [str \"section-var\"] [+ [str \"section-var\"] 1]]
|
||||
|
||||
]]]"
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
import re
|
||||
from PyQt5.Qsci import QsciLexerCustom, QsciScintilla
|
||||
from PyQt5.QtGui import *
|
||||
from Editor.Parser import Parser
|
||||
from Clochur.Parser import Parser
|
||||
|
||||
|
||||
|
||||
|
@ -34,8 +34,16 @@ class ClochurLexer(QsciLexerCustom):
|
|||
self.QUOTES = ['"']
|
||||
self.PARENTHESIS = ["[", "]"]
|
||||
|
||||
self.PRIMARY = ['define', 'def-syntax' , 'True', 'False', 'lambda', '-', '+',
|
||||
'*', '/', '>' ,'=','<','>=','<=', 'if', 'docu', 'font', 'font-family']
|
||||
self.parent = parent
|
||||
|
||||
|
||||
macro_list = ['docu', 'font', 'font-family','font-size','underline','bold','italic']
|
||||
boolean_list = ['True', 'False']
|
||||
operator_list = [ '-', '+', '*', '/', '>' ,'=','<','>=','<=']
|
||||
# SILE and SILE-STRING-ADD! is internal, so they're not added.
|
||||
function_list = ['if', 'docu', 'docu-para', 'script', 'call','xml-to-string', 'begin',
|
||||
'str','str-append','set!','print', 'define', 'def-syntax', 'lambda', 'eval']
|
||||
self.PRIMARY = macro_list + boolean_list + operator_list + function_list
|
||||
|
||||
self.split_pattern = re.compile(r'(\s+|\\%|%|\\\[|\\\]|[[]|[]])')
|
||||
|
||||
|
@ -106,7 +114,7 @@ class ClochurLexer(QsciLexerCustom):
|
|||
|
||||
|
||||
self.startStyling(start, 0x1f)
|
||||
rainbow_state = 0
|
||||
rainbow_state = 0 # 0~6 = Rainbowmode ; 0~6 + 10 (i.e. 10~16) = Rainbowmode with string
|
||||
|
||||
index = SCI(QsciScintilla.SCI_LINEFROMPOSITION, start)
|
||||
|
||||
|
@ -128,7 +136,7 @@ class ClochurLexer(QsciLexerCustom):
|
|||
#print(line_utf8_splitted_len_pair)
|
||||
|
||||
is_comment = False
|
||||
is_string = False
|
||||
next_is_defined_var = False
|
||||
|
||||
i = 0
|
||||
if index > 0:
|
||||
|
@ -140,12 +148,37 @@ class ClochurLexer(QsciLexerCustom):
|
|||
|
||||
for item in line_utf8_splitted_len_pair:
|
||||
|
||||
## add to complete list
|
||||
#if item["str"] in [ "define", "def-syntax"]:
|
||||
# next_is_defined_var = True
|
||||
#elif next_is_defined_var == True and not (item["str"] in ["[","]"]):
|
||||
# print(next_is_defined_var,item["str"])
|
||||
# self.parent.append_autocompletion_item(item["str"])
|
||||
# next_is_defined_var = False
|
||||
#else:
|
||||
# pass
|
||||
|
||||
'''comment'''
|
||||
if item["str"] == "%":
|
||||
is_comment = True
|
||||
if is_comment == True:
|
||||
new_state = self.Comment # end of comment
|
||||
|
||||
# string
|
||||
elif re.match(tmp_parser.string_pattern ,item["str"]):
|
||||
new_state = self.String
|
||||
elif re.match(r"[\"]([^\"\\]|[\\][\"nt]|[\\][\\])+?", item["str"]):
|
||||
rainbow_state += 10
|
||||
new_state = self.String
|
||||
elif (re.match(r"([^\"\\]|[\\][\"nt]|[\\][\\])+?[\"]" ,item["str"]) or re.match(r'["]' ,item["str"])):
|
||||
new_state = self.String
|
||||
rainbow_state -= 10
|
||||
|
||||
elif item["str"] == "]" and rainbow_state >= 10:
|
||||
new_state = self.String
|
||||
elif rainbow_state >= 10:
|
||||
new_state = self.String
|
||||
|
||||
elif item["str"] in self.PRIMARY: # keywords
|
||||
new_state = self.Keyword
|
||||
|
||||
|
@ -155,25 +188,24 @@ class ClochurLexer(QsciLexerCustom):
|
|||
elif re.match(tmp_parser.float_pattern, item["str"]):
|
||||
new_state = self.Number
|
||||
|
||||
# string
|
||||
elif re.match(tmp_parser.string_pattern ,item["str"]):
|
||||
new_state = self.String
|
||||
elif re.match(r"[\"]([^\"\\]|[\\][\"\n\t]|[\\])*?", item["str"]):
|
||||
is_string = True
|
||||
new_state = self.String
|
||||
elif re.match(r"([^\"\\]|[\\][\"\n\t]|[\\])*?[\"]" ,item["str"]):
|
||||
new_state = self.String
|
||||
is_string = False
|
||||
elif is_string == True:
|
||||
new_state = self.String
|
||||
|
||||
#parenthesis: rainbow mode
|
||||
elif item["str"] == "[":
|
||||
new_state = getattr(self, "Rainbow" + str(rainbow_state))
|
||||
rainbow_state = (rainbow_state + 1) % 7
|
||||
if rainbow_state >= 10:
|
||||
new_state = self.String
|
||||
elif rainbow_state < 7:
|
||||
print("rainbow_state" + str(type(rainbow_state)) + str(rainbow_state))
|
||||
new_state = getattr(self, "Rainbow" + str(rainbow_state))
|
||||
rainbow_state = (rainbow_state + 1) % 7
|
||||
else:
|
||||
pass
|
||||
elif item["str"] == "]":
|
||||
rainbow_state = (rainbow_state - 1) % 7
|
||||
new_state = getattr(self, "Rainbow" + str(rainbow_state))
|
||||
if rainbow_state >= 10:
|
||||
new_state = self.String
|
||||
elif rainbow_state < 7:
|
||||
rainbow_state = (rainbow_state - 1) % 7
|
||||
new_state = getattr(self, "Rainbow" + str(rainbow_state))
|
||||
else:
|
||||
pass
|
||||
else:
|
||||
pass
|
||||
|
|
@ -2,9 +2,9 @@
|
|||
#-*-coding:utf-8-*-
|
||||
|
||||
from PyQt5.QtGui import *
|
||||
from PyQt5.Qsci import QsciScintilla
|
||||
from PyQt5.Qsci import QsciScintilla, QsciAPIs
|
||||
|
||||
from Editor.ClochurLexer import ClochurLexer
|
||||
from Clochur.ClochurLexer import ClochurLexer
|
||||
|
||||
class CustomQsciEditor(QsciScintilla):
|
||||
def __init__(self, parent=None):
|
||||
|
@ -15,8 +15,7 @@ class CustomQsciEditor(QsciScintilla):
|
|||
|
||||
self.tab_width = 4
|
||||
|
||||
lexer = ClochurLexer(self)
|
||||
self.setLexer(lexer)
|
||||
|
||||
|
||||
# Margin 0 for line numbers
|
||||
font = QFont()
|
||||
|
@ -51,6 +50,39 @@ class CustomQsciEditor(QsciScintilla):
|
|||
self.setTabWidth(4)
|
||||
self.setBackspaceUnindents(True)
|
||||
|
||||
# set auto complete
|
||||
|
||||
#set lexer
|
||||
self.lexer = ClochurLexer(self)
|
||||
self.auto_complete_api = QsciAPIs(self.lexer) # autocomplete function
|
||||
self.setLexer(self.lexer)
|
||||
|
||||
self.setAutoCompletionCaseSensitivity(True)
|
||||
|
||||
self.setAutoCompletionReplaceWord(False)
|
||||
|
||||
# Use the predefined APIs as the source.
|
||||
self.setAutoCompletionSource(QsciScintilla.AcsAll)
|
||||
|
||||
|
||||
|
||||
# after 1 character, show completetion
|
||||
self.setAutoCompletionThreshold(1)
|
||||
|
||||
# add autocompletion items
|
||||
autocompletions = self.lexer.PRIMARY
|
||||
|
||||
|
||||
for ac in autocompletions:
|
||||
self.auto_complete_api.add(ac)
|
||||
|
||||
# "prepare" the QsciAPIs-object:
|
||||
self.auto_complete_api.prepare()
|
||||
|
||||
def append_autocompletion_item(self, item):
|
||||
self.auto_complete_api.add(item)
|
||||
self.auto_complete_api.prepare()
|
||||
|
||||
def set_word_wrap(self):
|
||||
self.setWrapMode(QsciScintilla.WrapMode.WrapWord)
|
||||
def set_no_word_wrap(self):
|
|
@ -2,7 +2,8 @@
|
|||
|
||||
import re
|
||||
import xml.etree.ElementTree as ET
|
||||
from Editor.Parser import Parser
|
||||
import itertools
|
||||
from Clochur.Parser import Parser
|
||||
|
||||
'''
|
||||
macro expansion for example:
|
||||
|
@ -21,6 +22,11 @@ class Interpreter:
|
|||
self.macro_list = dict()
|
||||
self.silexml = ET.Element('sile')
|
||||
|
||||
#self.editor = None
|
||||
|
||||
#if "editor" in kwargs.keys():
|
||||
# self.editor = kwargs["editor"]
|
||||
|
||||
self.preprocessing_commands = '''[def-syntax docu
|
||||
[[_ x] [SILE[docu-aux x]]]
|
||||
[[_ x y...] [SILE[docu-aux x y...]]]]
|
||||
|
@ -103,9 +109,11 @@ class Interpreter:
|
|||
string = str(string)
|
||||
if re.match(string_pattern, string):
|
||||
# reverse the escape characters
|
||||
print(string)
|
||||
string = re.sub(r'\\"(.+)',r'"\1',string)
|
||||
print(string)
|
||||
while True:
|
||||
string_before = string
|
||||
string = re.sub(r'\\"(.+)',r'"\1',string)
|
||||
if string_before == string:
|
||||
break
|
||||
return string[1:-1]
|
||||
else:
|
||||
return string
|
||||
|
@ -153,10 +161,26 @@ class Interpreter:
|
|||
|
||||
else:
|
||||
return sexp["token"]
|
||||
|
||||
elif isinstance(sexp, Lambda):
|
||||
return sexp
|
||||
|
||||
# lambda apply
|
||||
elif isinstance(sexp[0], Lambda):
|
||||
return self.apply(sexp)
|
||||
|
||||
# count sexp[0] first.
|
||||
elif isinstance(sexp[0], list):
|
||||
new_sexp_0 = self.interprete_aux(sexp[0])
|
||||
new_sexp = [new_sexp_0] + sexp[1:]
|
||||
return self.interprete_aux(new_sexp)
|
||||
|
||||
|
||||
elif sexp[0]["token"] in ["+", "-", "*", "/", "<", "=", ">", "<=", ">="]:
|
||||
if len(sexp) != 3:
|
||||
parser = Parser()
|
||||
raise Exception("Ln %d, Col %d: the argument length %d of %s is not correct." %
|
||||
(sexp[0]["line"], sexp[0]["col"], len(sexp), a.generate_printable_sexp(sexp)))
|
||||
(sexp[0]["line"], sexp[0]["col"], len(sexp), parser.generate_printable_sexp(sexp)))
|
||||
else:
|
||||
if sexp[0]["token"] == "+":
|
||||
return self.interprete_aux(sexp[1]) + self.interprete_aux(sexp[2])
|
||||
|
@ -203,7 +227,8 @@ class Interpreter:
|
|||
pass
|
||||
|
||||
if not is_found:
|
||||
raise Exception("The syntax pattern for %s is not found." % a.generate_printable_sexp(sexp))
|
||||
parser = Parser()
|
||||
raise Exception("The syntax pattern for %s is not found." % parser.generate_printable_sexp(sexp))
|
||||
else:
|
||||
new_sexp = self.macro_expand(syntax_after, unification)
|
||||
|
||||
|
@ -217,7 +242,13 @@ class Interpreter:
|
|||
raise Exception("Ln %d, Col %d: the type of %s should be symbol, not %s" %
|
||||
(sexp[1]["line"], sexp[1]["col"], sexp[1], sexp[1]["type"]))
|
||||
else:
|
||||
self.env[-1][sexp[1]["token"]] = self.interprete_aux(sexp[2])
|
||||
defined_var = sexp[1]["token"]
|
||||
self.env[-1][defined_var] = self.interprete_aux(sexp[2])
|
||||
|
||||
#if self.editor != None:
|
||||
# self.editor.append_autocompletion_item(defined_var)
|
||||
return ""
|
||||
|
||||
elif sexp[0]["token"] == "if":
|
||||
if len(sexp) != 4:
|
||||
raise Exception("Ln %d, Col %d: the number of argument of if should be 3." %
|
||||
|
@ -233,7 +264,12 @@ class Interpreter:
|
|||
raise Exception("Ln %d, Col %d: the argument number of str should be 1" %
|
||||
(sexp[0]["line"], sexp[0]["col"]))
|
||||
else:
|
||||
if isinstance(sexp[1], dict) and (not (sexp[1]["token"] in self.macro_list.keys())):
|
||||
vars_frame = [frame.keys() for frame in self.env]
|
||||
vars_list = list(itertools.chain.from_iterable(vars_frame))
|
||||
macro_vars = self.macro_list.keys()
|
||||
if isinstance(sexp[1], dict) and \
|
||||
(not (sexp[1]["token"] in macro_vars)) and \
|
||||
(not (sexp[1]["token"] in vars_list)) :
|
||||
return str(self.destring(sexp[1]["token"]))
|
||||
else:
|
||||
return str(self.destring(self.interprete_aux(sexp[1])))
|
||||
|
@ -253,6 +289,14 @@ class Interpreter:
|
|||
result = self.interprete_aux(sexp[1])
|
||||
print(result)
|
||||
return ""
|
||||
elif sexp[0]["token"] == 'eval':
|
||||
if len(sexp) != 2:
|
||||
raise Exception("Ln %d, Col %d: the argument number of eval should be 1" %
|
||||
(sexp[0]["line"], sexp[0]["col"]))
|
||||
else:
|
||||
result = self.interprete_aux(sexp[1])
|
||||
return result
|
||||
|
||||
elif sexp[0]["token"] == "set!":
|
||||
if sexp[1]["type"] != "sym":
|
||||
raise Exception("Ln %d, Col %d: the type of %s should be symbol, not %s" %
|
||||
|
@ -269,6 +313,8 @@ class Interpreter:
|
|||
raise Exception("Ln %d, Col %d: the variable %s is not found!" %
|
||||
(sexp[1]["line"], sexp[1]["col"], sexp[1]["token"]))
|
||||
|
||||
return ""
|
||||
|
||||
|
||||
elif sexp[0]["token"] == "def-syntax":
|
||||
if len(sexp) < 3:
|
||||
|
@ -289,6 +335,10 @@ class Interpreter:
|
|||
|
||||
self.macro_list[syntax_name] = result_list
|
||||
|
||||
# add to auto completion list
|
||||
#if self.editor != None:
|
||||
# self.editor.append_autocompletion_item(defined_var)
|
||||
|
||||
return ""
|
||||
|
||||
elif sexp[0]["token"] == "begin":
|
||||
|
@ -351,6 +401,58 @@ class Interpreter:
|
|||
else:
|
||||
raise Exception("Line %d, Col. %d, the form of call is mal-formed." % (sexp[0]["line"], sexp[0]["col"]))
|
||||
|
||||
# make a List class object
|
||||
elif sexp[0]["token"] == "ls":
|
||||
result = []
|
||||
|
||||
if len(sexp) == 1:
|
||||
return result
|
||||
else:
|
||||
result = [self.interprete_aux(x) for x in sexp[1:]]
|
||||
|
||||
return List(result)
|
||||
|
||||
# (car List)
|
||||
elif sexp[0]["token"] == "car":
|
||||
if len(sexp) != 2:
|
||||
raise Exception("Line %d, Col. %d, the argument length should be 1" % (sexp[0]["line"], sexp[0]["col"]))
|
||||
elif not isinstance(sexp[1], List):
|
||||
raise Exception("Line %d, Col. %d, the argument is not a list." % (sexp[1]["line"], sexp[1]["col"]))
|
||||
else:
|
||||
ls = sexp[1].ls
|
||||
return ls[0]
|
||||
|
||||
# (cdr List)
|
||||
elif sexp[0]["token"] == "cdr":
|
||||
if len(sexp) != 2:
|
||||
raise Exception("Line %d, Col. %d, the argument length should be 1" % (sexp[0]["line"], sexp[0]["col"]))
|
||||
elif not isinstance(sexp[1], List):
|
||||
raise Exception("Line %d, Col. %d, the argument is not a list." % (sexp[1]["line"], sexp[1]["col"]))
|
||||
else:
|
||||
ls = sexp[1].ls
|
||||
return ls[1:]
|
||||
|
||||
# (cons any List)
|
||||
elif sexp[0]["token"] == "cons":
|
||||
if len(sexp) != 3:
|
||||
raise Exception("Line %d, Col. %d, the argument length should be 2" % (sexp[0]["line"], sexp[0]["col"]))
|
||||
elif not isinstance(sexp[2], List):
|
||||
raise Exception("Line %d, Col. %d, the 2nd argument of cons is not a list." % (sexp[2]["line"], sexp[2]["col"]))
|
||||
else:
|
||||
car = sexp[1]
|
||||
cdr = sexp[2].ls
|
||||
result_ls = List([sexp[1]]+cdr)
|
||||
return result_ls
|
||||
|
||||
|
||||
elif sexp[0]["token"] == "ls-ref":
|
||||
if len(sexp) != 3:
|
||||
raise Exception("Line %d, Col. %d, the argument length should be 1" % (sexp[0]["line"], sexp[0]["col"]))
|
||||
elif not isinstance(sexp[1], List):
|
||||
raise Exception("Line %d, Col. %d, the 2nd argument of cons is not a list." % (sexp[2]["line"], sexp[2]["col"]))
|
||||
|
||||
|
||||
|
||||
# if it's a sub-xml-element, show the string form of it, or return the input unchanged.
|
||||
# It's recommended to use it only print it in terminal with 'print'
|
||||
elif sexp[0]["token"] == "xml-to-string":
|
||||
|
@ -384,29 +486,34 @@ class Interpreter:
|
|||
return ET.tostring(self.silexml, encoding="unicode")
|
||||
|
||||
else:
|
||||
sexp_new = [self.interprete_aux(x) for x in sexp]
|
||||
ret = self.apply(sexp)
|
||||
return ret
|
||||
|
||||
if isinstance(sexp_new[0], Lambda):
|
||||
vars = sexp_new[0].vars
|
||||
env = sexp_new[0].env
|
||||
body = sexp_new[0].body
|
||||
vars_input = sexp_new[1:]
|
||||
def apply(self, sexp):
|
||||
|
||||
if len(vars) != len(vars_input):
|
||||
raise Exception("Ln %d, Col %d: argument length is not matched." %
|
||||
(self.get_first_item(sexp[0])["line"], self.get_first_item(sexp[0])["col"]))
|
||||
sexp_new = [self.interprete_aux(x) for x in sexp]
|
||||
|
||||
new_env_block = dict()
|
||||
for i in range(len(vars)):
|
||||
new_env_block[vars[i]] = vars_input[i]
|
||||
if isinstance(sexp_new[0], Lambda):
|
||||
vars = sexp_new[0].vars
|
||||
env = sexp_new[0].env
|
||||
body = sexp_new[0].body
|
||||
vars_input = sexp_new[1:]
|
||||
|
||||
new_env = [new_env_block] + env
|
||||
if len(vars) != len(vars_input):
|
||||
raise Exception("Ln %d, Col %d: argument length is not matched." %
|
||||
(self.get_first_item(sexp[0])["line"], self.get_first_item(sexp[0])["col"]))
|
||||
|
||||
old_env = self.env
|
||||
self.env = new_env
|
||||
ret = self.interprete_aux(body)
|
||||
self.env = old_env
|
||||
return ret
|
||||
new_env_block = dict()
|
||||
for i in range(len(vars)):
|
||||
new_env_block[vars[i]] = vars_input[i]
|
||||
|
||||
new_env = [new_env_block] + env
|
||||
|
||||
old_env = self.env
|
||||
self.env = new_env
|
||||
ret = self.interprete_aux(body)
|
||||
self.env = old_env
|
||||
return ret
|
||||
|
||||
|
||||
def remove_dict_form(self, sexp):
|
||||
|
@ -426,7 +533,7 @@ class Interpreter:
|
|||
if isinstance(before_stx[i], list):
|
||||
unification = self.unify(sexp[i], before_stx[i], unification)
|
||||
elif before_stx[i]["token"] in unification.keys():
|
||||
raise Exception("the variable %s is double defined." % before-stx[i])
|
||||
raise Exception("the variable %s is double defined." % before_stx[i])
|
||||
elif re.match(r".+[.]{3}$", before_stx[i]["token"]):
|
||||
if i == len(before_stx) - 1:
|
||||
unification[before_stx[i]["token"]] = {"content": sexp[i:], "dotted":True}
|
||||
|
@ -467,8 +574,14 @@ class SubXMLElement:
|
|||
def __init__(self, element):
|
||||
self.element = element
|
||||
|
||||
def __str__(init):
|
||||
def __str__(self):
|
||||
return ""
|
||||
|
||||
# closure
|
||||
class List:
|
||||
def __init__(self, ls):
|
||||
self.ls = ls
|
||||
|
||||
# closure
|
||||
class Lambda:
|
||||
def __init__(self, vars, body, env):
|
|
@ -6,7 +6,7 @@ class Parser():
|
|||
bool_pattern = r"(?P<bool>True|False)"
|
||||
int_pattern =r"(?P<int>[+-]?\d+)"
|
||||
symbol_pattern = r"(?P<sym>[_a-zA-Z][-!:._0-9a-zA-Z]*)"
|
||||
string_pattern = r"(?P<str>[\"]([^\"\\]|[\\][\\\"\n\t]|[\\])*?[\"])"
|
||||
string_pattern = r"(?P<str>[\"]([^\"\\]|[\\][\\\"nt]|[\\])*?[\"])"
|
||||
parenthesis_pattern = r"(?P<paren>[[]|[]])"
|
||||
percent_pattern = r"(?P<percent>[%])"
|
||||
space_pattern = r"(?P<space>[ \t]+)"
|
|
@ -14,13 +14,17 @@ from PyQt5 import QtWebEngineWidgets
|
|||
from PyQt5.QtWidgets import *
|
||||
from PyQt5.Qsci import QsciScintilla
|
||||
|
||||
from Editor import qrc_resources
|
||||
src_dirname = os.path.dirname(os.path.abspath(os.path.dirname(__file__)))
|
||||
sys.path.append(src_dirname)
|
||||
|
||||
from Editor import __about__
|
||||
from Editor import FindReplace
|
||||
from Editor.Interpreter import Interpreter, Lambda
|
||||
from Editorimport CustomQsciEditor
|
||||
from Editor.Parser import Parser
|
||||
|
||||
from Clochur import qrc_resources
|
||||
|
||||
from Clochur import __about__
|
||||
from Clochur import FindReplace
|
||||
from Clochur.Interpreter import Interpreter, Lambda
|
||||
from Clochur import CustomQsciEditor
|
||||
from Clochur.Parser import Parser
|
||||
|
||||
|
||||
sile_command = 'sile'
|
||||
|
@ -175,7 +179,6 @@ class Window(QMainWindow):
|
|||
format_menu = menuBar.addMenu("&Format")
|
||||
format_menu.addAction(self.bold_action)
|
||||
format_menu.addAction(self.italic_action)
|
||||
format_menu.addAction(self.strike_action)
|
||||
format_menu.addAction(self.underline_action)
|
||||
|
||||
help_menu = menuBar.addMenu("&Help")
|
||||
|
@ -195,7 +198,11 @@ class Window(QMainWindow):
|
|||
self.opened_file_dirname = os.path.dirname(file_path[0])
|
||||
self.file = open(file_path[0], 'r', encoding='utf-8')
|
||||
self.editor.setText(self.file.read())
|
||||
self.setWindowTitle("Clochur - %s" % self.filename)
|
||||
self.editor.setModified(False)
|
||||
self.file.close()
|
||||
else:
|
||||
pass
|
||||
|
||||
|
||||
|
||||
|
@ -207,7 +214,7 @@ class Window(QMainWindow):
|
|||
|
||||
else:
|
||||
self.file = open(os.path.join(self.opened_file_dirname,self.filename), 'w', encoding='utf-8')
|
||||
file_content = editor.text()
|
||||
file_content = self.editor.text()
|
||||
self.file.write(file_content)
|
||||
self.file.close()
|
||||
|
||||
|
@ -218,6 +225,7 @@ class Window(QMainWindow):
|
|||
with open(os.path.join(self.tmp_folder, self.tmp_file), 'r') as f:
|
||||
data = json.load(f)
|
||||
data["untitled"].remove(self.untitled_id)
|
||||
self.untitled_id = None
|
||||
|
||||
with open(os.path.join(self.tmp_folder, self.tmp_file), 'w') as f:
|
||||
json.dump(data, f, indent=4)
|
||||
|
@ -286,13 +294,17 @@ class Window(QMainWindow):
|
|||
if self.editor.isModified():
|
||||
reply = QMessageBox.question(self,'','Do You want to save this file? The text has been modified', QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel, QMessageBox.No)
|
||||
if reply == QMessageBox.Yes:
|
||||
file_path = QFileDialog.getSaveFileName(self, 'Save file as...', self.opened_file_dirname, "CLC typesetting format (*.clc)")
|
||||
if file_path[0] != '':
|
||||
self.file = open(file_path[0], 'w', encoding='utf-8')
|
||||
file_content = editor.text()
|
||||
self.file.write(file_content)
|
||||
self.file.close()
|
||||
self.removing_untitled_id()
|
||||
if self.filename != None:
|
||||
self.save_call()
|
||||
else:
|
||||
|
||||
file_path = QFileDialog.getSaveFileName(self, 'Save file as...', self.opened_file_dirname, "CLC typesetting format (*.clc)")
|
||||
if file_path[0] != '':
|
||||
self.file = open(file_path[0], 'w', encoding='utf-8')
|
||||
file_content = self.editor.text()
|
||||
self.file.write(file_content)
|
||||
self.file.close()
|
||||
self.removing_untitled_id()
|
||||
|
||||
elif reply == QMessageBox.No:
|
||||
self.removing_untitled_id()
|
||||
|
@ -378,7 +390,6 @@ class Window(QMainWindow):
|
|||
|
||||
formatToolBar.addAction(self.bold_action)
|
||||
formatToolBar.addAction(self.italic_action)
|
||||
formatToolBar.addAction(self.strike_action)
|
||||
formatToolBar.addAction(self.underline_action)
|
||||
|
||||
'''create font adder'''
|
BIN
src/example.pdf
BIN
src/example.pdf
Binary file not shown.
Loading…
Reference in a new issue