modify something

This commit is contained in:
Tan, Kian-ting 2021-06-20 23:12:03 +08:00
parent cb2cd421d3
commit c04efe041d
12 changed files with 308 additions and 76 deletions

View file

@ -3,6 +3,7 @@ A Scheme-like typesetting LISP interpreter and editor that using SILE typesettin
## Dependencies ## Dependencies
* Python3
* PyQt5>=5.15 * PyQt5>=5.15
* QScintilla>=2.12 * QScintilla>=2.12
* SILE>=0.10 * SILE>=0.10
@ -20,10 +21,10 @@ see `src/example.pdf`
To make a wheel package, run the following command in the root folder: 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: and then:
`cd dist; ls` `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.

View file

@ -2,6 +2,28 @@
[script "packages/font-fallback"] [script "packages/font-fallback"]
[script "packages/grid"] [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"]]] [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."] [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, It generate a XML that is readable for SILE, which is a typesetting engine written in Lua,
and it generate PDF with SILE. 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. - count basic arithmetic expression.
[str "- lambda function"], function definition. [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]]
]]]"

View file

@ -4,7 +4,7 @@
import re import re
from PyQt5.Qsci import QsciLexerCustom, QsciScintilla from PyQt5.Qsci import QsciLexerCustom, QsciScintilla
from PyQt5.QtGui import * from PyQt5.QtGui import *
from Editor.Parser import Parser from Clochur.Parser import Parser
@ -34,8 +34,16 @@ class ClochurLexer(QsciLexerCustom):
self.QUOTES = ['"'] self.QUOTES = ['"']
self.PARENTHESIS = ["[", "]"] self.PARENTHESIS = ["[", "]"]
self.PRIMARY = ['define', 'def-syntax' , 'True', 'False', 'lambda', '-', '+', self.parent = parent
'*', '/', '>' ,'=','<','>=','<=', 'if', 'docu', 'font', 'font-family']
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+|\\%|%|\\\[|\\\]|[[]|[]])') self.split_pattern = re.compile(r'(\s+|\\%|%|\\\[|\\\]|[[]|[]])')
@ -106,7 +114,7 @@ class ClochurLexer(QsciLexerCustom):
self.startStyling(start, 0x1f) 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) index = SCI(QsciScintilla.SCI_LINEFROMPOSITION, start)
@ -128,7 +136,7 @@ class ClochurLexer(QsciLexerCustom):
#print(line_utf8_splitted_len_pair) #print(line_utf8_splitted_len_pair)
is_comment = False is_comment = False
is_string = False next_is_defined_var = False
i = 0 i = 0
if index > 0: if index > 0:
@ -140,12 +148,37 @@ class ClochurLexer(QsciLexerCustom):
for item in line_utf8_splitted_len_pair: 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''' '''comment'''
if item["str"] == "%": if item["str"] == "%":
is_comment = True is_comment = True
if is_comment == True: if is_comment == True:
new_state = self.Comment # end of comment 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 elif item["str"] in self.PRIMARY: # keywords
new_state = self.Keyword new_state = self.Keyword
@ -155,25 +188,24 @@ class ClochurLexer(QsciLexerCustom):
elif re.match(tmp_parser.float_pattern, item["str"]): elif re.match(tmp_parser.float_pattern, item["str"]):
new_state = self.Number 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 #parenthesis: rainbow mode
elif item["str"] == "[": elif item["str"] == "[":
new_state = getattr(self, "Rainbow" + str(rainbow_state)) if rainbow_state >= 10:
rainbow_state = (rainbow_state + 1) % 7 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"] == "]": elif item["str"] == "]":
rainbow_state = (rainbow_state - 1) % 7 if rainbow_state >= 10:
new_state = getattr(self, "Rainbow" + str(rainbow_state)) 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: else:
pass pass

View file

@ -2,9 +2,9 @@
#-*-coding:utf-8-*- #-*-coding:utf-8-*-
from PyQt5.QtGui import * 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): class CustomQsciEditor(QsciScintilla):
def __init__(self, parent=None): def __init__(self, parent=None):
@ -15,8 +15,7 @@ class CustomQsciEditor(QsciScintilla):
self.tab_width = 4 self.tab_width = 4
lexer = ClochurLexer(self)
self.setLexer(lexer)
# Margin 0 for line numbers # Margin 0 for line numbers
font = QFont() font = QFont()
@ -51,6 +50,39 @@ class CustomQsciEditor(QsciScintilla):
self.setTabWidth(4) self.setTabWidth(4)
self.setBackspaceUnindents(True) 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): def set_word_wrap(self):
self.setWrapMode(QsciScintilla.WrapMode.WrapWord) self.setWrapMode(QsciScintilla.WrapMode.WrapWord)
def set_no_word_wrap(self): def set_no_word_wrap(self):

View file

@ -2,7 +2,8 @@
import re import re
import xml.etree.ElementTree as ET import xml.etree.ElementTree as ET
from Editor.Parser import Parser import itertools
from Clochur.Parser import Parser
''' '''
macro expansion for example: macro expansion for example:
@ -21,6 +22,11 @@ class Interpreter:
self.macro_list = dict() self.macro_list = dict()
self.silexml = ET.Element('sile') self.silexml = ET.Element('sile')
#self.editor = None
#if "editor" in kwargs.keys():
# self.editor = kwargs["editor"]
self.preprocessing_commands = '''[def-syntax docu self.preprocessing_commands = '''[def-syntax docu
[[_ x] [SILE[docu-aux x]]] [[_ x] [SILE[docu-aux x]]]
[[_ x y...] [SILE[docu-aux x y...]]]] [[_ x y...] [SILE[docu-aux x y...]]]]
@ -103,9 +109,11 @@ class Interpreter:
string = str(string) string = str(string)
if re.match(string_pattern, string): if re.match(string_pattern, string):
# reverse the escape characters # reverse the escape characters
print(string) while True:
string = re.sub(r'\\"(.+)',r'"\1',string) string_before = string
print(string) string = re.sub(r'\\"(.+)',r'"\1',string)
if string_before == string:
break
return string[1:-1] return string[1:-1]
else: else:
return string return string
@ -153,10 +161,26 @@ class Interpreter:
else: else:
return sexp["token"] 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 ["+", "-", "*", "/", "<", "=", ">", "<=", ">="]: elif sexp[0]["token"] in ["+", "-", "*", "/", "<", "=", ">", "<=", ">="]:
if len(sexp) != 3: if len(sexp) != 3:
parser = Parser()
raise Exception("Ln %d, Col %d: the argument length %d of %s is not correct." % 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: else:
if sexp[0]["token"] == "+": if sexp[0]["token"] == "+":
return self.interprete_aux(sexp[1]) + self.interprete_aux(sexp[2]) return self.interprete_aux(sexp[1]) + self.interprete_aux(sexp[2])
@ -203,7 +227,8 @@ class Interpreter:
pass pass
if not is_found: 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: else:
new_sexp = self.macro_expand(syntax_after, unification) 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" % 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"])) (sexp[1]["line"], sexp[1]["col"], sexp[1], sexp[1]["type"]))
else: 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": elif sexp[0]["token"] == "if":
if len(sexp) != 4: if len(sexp) != 4:
raise Exception("Ln %d, Col %d: the number of argument of if should be 3." % 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" % raise Exception("Ln %d, Col %d: the argument number of str should be 1" %
(sexp[0]["line"], sexp[0]["col"])) (sexp[0]["line"], sexp[0]["col"]))
else: 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"])) return str(self.destring(sexp[1]["token"]))
else: else:
return str(self.destring(self.interprete_aux(sexp[1]))) return str(self.destring(self.interprete_aux(sexp[1])))
@ -253,6 +289,14 @@ class Interpreter:
result = self.interprete_aux(sexp[1]) result = self.interprete_aux(sexp[1])
print(result) print(result)
return "" 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!": elif sexp[0]["token"] == "set!":
if sexp[1]["type"] != "sym": if sexp[1]["type"] != "sym":
raise Exception("Ln %d, Col %d: the type of %s should be symbol, not %s" % 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!" % raise Exception("Ln %d, Col %d: the variable %s is not found!" %
(sexp[1]["line"], sexp[1]["col"], sexp[1]["token"])) (sexp[1]["line"], sexp[1]["col"], sexp[1]["token"]))
return ""
elif sexp[0]["token"] == "def-syntax": elif sexp[0]["token"] == "def-syntax":
if len(sexp) < 3: if len(sexp) < 3:
@ -289,6 +335,10 @@ class Interpreter:
self.macro_list[syntax_name] = result_list self.macro_list[syntax_name] = result_list
# add to auto completion list
#if self.editor != None:
# self.editor.append_autocompletion_item(defined_var)
return "" return ""
elif sexp[0]["token"] == "begin": elif sexp[0]["token"] == "begin":
@ -351,6 +401,58 @@ class Interpreter:
else: else:
raise Exception("Line %d, Col. %d, the form of call is mal-formed." % (sexp[0]["line"], sexp[0]["col"])) 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. # 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' # It's recommended to use it only print it in terminal with 'print'
elif sexp[0]["token"] == "xml-to-string": elif sexp[0]["token"] == "xml-to-string":
@ -384,29 +486,34 @@ class Interpreter:
return ET.tostring(self.silexml, encoding="unicode") return ET.tostring(self.silexml, encoding="unicode")
else: else:
sexp_new = [self.interprete_aux(x) for x in sexp] ret = self.apply(sexp)
return ret
if isinstance(sexp_new[0], Lambda): def apply(self, sexp):
vars = sexp_new[0].vars
env = sexp_new[0].env
body = sexp_new[0].body
vars_input = sexp_new[1:]
if len(vars) != len(vars_input): sexp_new = [self.interprete_aux(x) for x in sexp]
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"]))
new_env_block = dict() if isinstance(sexp_new[0], Lambda):
for i in range(len(vars)): vars = sexp_new[0].vars
new_env_block[vars[i]] = vars_input[i] 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 new_env_block = dict()
self.env = new_env for i in range(len(vars)):
ret = self.interprete_aux(body) new_env_block[vars[i]] = vars_input[i]
self.env = old_env
return ret 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): def remove_dict_form(self, sexp):
@ -426,7 +533,7 @@ class Interpreter:
if isinstance(before_stx[i], list): if isinstance(before_stx[i], list):
unification = self.unify(sexp[i], before_stx[i], unification) unification = self.unify(sexp[i], before_stx[i], unification)
elif before_stx[i]["token"] in unification.keys(): 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"]): elif re.match(r".+[.]{3}$", before_stx[i]["token"]):
if i == len(before_stx) - 1: if i == len(before_stx) - 1:
unification[before_stx[i]["token"]] = {"content": sexp[i:], "dotted":True} unification[before_stx[i]["token"]] = {"content": sexp[i:], "dotted":True}
@ -467,8 +574,14 @@ class SubXMLElement:
def __init__(self, element): def __init__(self, element):
self.element = element self.element = element
def __str__(init): def __str__(self):
return "" return ""
# closure
class List:
def __init__(self, ls):
self.ls = ls
# closure # closure
class Lambda: class Lambda:
def __init__(self, vars, body, env): def __init__(self, vars, body, env):

View file

@ -6,7 +6,7 @@ class Parser():
bool_pattern = r"(?P<bool>True|False)" bool_pattern = r"(?P<bool>True|False)"
int_pattern =r"(?P<int>[+-]?\d+)" int_pattern =r"(?P<int>[+-]?\d+)"
symbol_pattern = r"(?P<sym>[_a-zA-Z][-!:._0-9a-zA-Z]*)" 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>[[]|[]])" parenthesis_pattern = r"(?P<paren>[[]|[]])"
percent_pattern = r"(?P<percent>[%])" percent_pattern = r"(?P<percent>[%])"
space_pattern = r"(?P<space>[ \t]+)" space_pattern = r"(?P<space>[ \t]+)"

View file

@ -14,13 +14,17 @@ from PyQt5 import QtWebEngineWidgets
from PyQt5.QtWidgets import * from PyQt5.QtWidgets import *
from PyQt5.Qsci import QsciScintilla 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 Clochur import qrc_resources
from Editor.Interpreter import Interpreter, Lambda
from Editorimport CustomQsciEditor from Clochur import __about__
from Editor.Parser import Parser from Clochur import FindReplace
from Clochur.Interpreter import Interpreter, Lambda
from Clochur import CustomQsciEditor
from Clochur.Parser import Parser
sile_command = 'sile' sile_command = 'sile'
@ -175,7 +179,6 @@ class Window(QMainWindow):
format_menu = menuBar.addMenu("&Format") format_menu = menuBar.addMenu("&Format")
format_menu.addAction(self.bold_action) format_menu.addAction(self.bold_action)
format_menu.addAction(self.italic_action) format_menu.addAction(self.italic_action)
format_menu.addAction(self.strike_action)
format_menu.addAction(self.underline_action) format_menu.addAction(self.underline_action)
help_menu = menuBar.addMenu("&Help") help_menu = menuBar.addMenu("&Help")
@ -195,7 +198,11 @@ class Window(QMainWindow):
self.opened_file_dirname = os.path.dirname(file_path[0]) self.opened_file_dirname = os.path.dirname(file_path[0])
self.file = open(file_path[0], 'r', encoding='utf-8') self.file = open(file_path[0], 'r', encoding='utf-8')
self.editor.setText(self.file.read()) self.editor.setText(self.file.read())
self.setWindowTitle("Clochur - %s" % self.filename)
self.editor.setModified(False)
self.file.close() self.file.close()
else:
pass
@ -207,7 +214,7 @@ class Window(QMainWindow):
else: else:
self.file = open(os.path.join(self.opened_file_dirname,self.filename), 'w', encoding='utf-8') 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.write(file_content)
self.file.close() self.file.close()
@ -218,6 +225,7 @@ class Window(QMainWindow):
with open(os.path.join(self.tmp_folder, self.tmp_file), 'r') as f: with open(os.path.join(self.tmp_folder, self.tmp_file), 'r') as f:
data = json.load(f) data = json.load(f)
data["untitled"].remove(self.untitled_id) data["untitled"].remove(self.untitled_id)
self.untitled_id = None
with open(os.path.join(self.tmp_folder, self.tmp_file), 'w') as f: with open(os.path.join(self.tmp_folder, self.tmp_file), 'w') as f:
json.dump(data, f, indent=4) json.dump(data, f, indent=4)
@ -286,13 +294,17 @@ class Window(QMainWindow):
if self.editor.isModified(): 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) 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: if reply == QMessageBox.Yes:
file_path = QFileDialog.getSaveFileName(self, 'Save file as...', self.opened_file_dirname, "CLC typesetting format (*.clc)") if self.filename != None:
if file_path[0] != '': self.save_call()
self.file = open(file_path[0], 'w', encoding='utf-8') else:
file_content = editor.text()
self.file.write(file_content) file_path = QFileDialog.getSaveFileName(self, 'Save file as...', self.opened_file_dirname, "CLC typesetting format (*.clc)")
self.file.close() if file_path[0] != '':
self.removing_untitled_id() 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: elif reply == QMessageBox.No:
self.removing_untitled_id() self.removing_untitled_id()
@ -378,7 +390,6 @@ class Window(QMainWindow):
formatToolBar.addAction(self.bold_action) formatToolBar.addAction(self.bold_action)
formatToolBar.addAction(self.italic_action) formatToolBar.addAction(self.italic_action)
formatToolBar.addAction(self.strike_action)
formatToolBar.addAction(self.underline_action) formatToolBar.addAction(self.underline_action)
'''create font adder''' '''create font adder'''

Binary file not shown.