euler314 commited on
Commit
eb4383f
·
verified ·
1 Parent(s): df162fc

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +248 -80
app.py CHANGED
@@ -20,25 +20,30 @@ except ImportError:
20
 
21
  # Set page configuration
22
  st.set_page_config(
23
- page_title="Professional LaTeX Editor",
24
  page_icon="📝",
25
  layout="wide",
26
  initial_sidebar_state="collapsed"
27
  )
28
 
29
- # Check if pdflatex is available
30
- def is_pdflatex_installed():
31
- return shutil.which("pdflatex") is not None
 
 
 
 
 
32
 
33
- # Function to convert LaTeX to PDF
34
- def latex_to_pdf(latex_code):
35
- # Check if pdflatex is installed
36
- if not is_pdflatex_installed():
37
- st.error("pdflatex not found. Debug info:")
38
  st.code(f"PATH: {os.environ.get('PATH')}")
39
- result = subprocess.run(["which", "pdflatex"], capture_output=True, text=True)
40
- st.code(f"which pdflatex: {result.stdout} {result.stderr}")
41
- return None, "", "Error: pdflatex is not installed or not in PATH."
42
 
43
  with tempfile.TemporaryDirectory() as temp_dir:
44
  temp_path = Path(temp_dir)
@@ -46,16 +51,20 @@ def latex_to_pdf(latex_code):
46
  pdf_file = temp_path / "document.pdf"
47
 
48
  # Write LaTeX code to file
49
- with open(tex_file, "w") as f:
50
  f.write(latex_code)
51
 
52
  try:
53
- # Run pdflatex to compile the LaTeX file
54
- process = subprocess.run(
55
- ["pdflatex", "-interaction=nonstopmode", "-output-directory", temp_dir, str(tex_file)],
56
- capture_output=True,
57
- text=True
58
- )
 
 
 
 
59
 
60
  # Check if PDF was created
61
  if pdf_file.exists():
@@ -198,8 +207,116 @@ def find_environments(latex_code):
198
 
199
  return environments
200
 
201
- # Default LaTeX template
202
- default_template = r"""\documentclass{article}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
203
  \usepackage[utf8]{inputenc}
204
  \usepackage{amsmath}
205
  \usepackage{amssymb}
@@ -265,27 +382,9 @@ An integral example:
265
  \label{tab:simple}
266
  \end{table}
267
 
268
- \section{Figures}
269
- You can include figures using the following syntax:
270
-
271
- % \begin{figure}[h]
272
- % \centering
273
- % \includegraphics[width=0.7\textwidth]{example-image}
274
- % \caption{Example figure}
275
- % \label{fig:example}
276
- % \end{figure}
277
-
278
- \section{Citations}
279
- You can cite references using the \verb|\cite{}| command \cite{example}.
280
-
281
- \section{Cross-References}
282
- You can reference sections, figures, and tables using the \verb|\ref{}| command.
283
- For example, see Table~\ref{tab:simple}.
284
-
285
  \section{Conclusion}
286
  Your conclusion here.
287
 
288
- % Sample bibliography entry
289
  \begin{thebibliography}{9}
290
  \bibitem{example} Author, A. (2023). \textit{Title of the Work}. Publisher.
291
  \end{thebibliography}
@@ -293,7 +392,7 @@ Your conclusion here.
293
  \end{document}
294
  """
295
 
296
- # Enhanced VSCode-like styling
297
  st.markdown("""
298
  <style>
299
  /* Base theming - VS Code inspired */
@@ -389,7 +488,36 @@ st.markdown("""
389
  color: #cca700;
390
  }
391
 
392
- /* Outline view */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
393
  .outline-view {
394
  background-color: #252526;
395
  border: 1px solid #2d2d2d;
@@ -414,7 +542,6 @@ st.markdown("""
414
  margin-left: 5px;
415
  }
416
 
417
- /* Download button styling */
418
  .download-button {
419
  display: inline-block;
420
  padding: 8px 16px;
@@ -432,7 +559,6 @@ st.markdown("""
432
  background-color: #4eb772;
433
  }
434
 
435
- /* PDF preview area */
436
  .preview-container {
437
  background-color: #252526;
438
  border: 1px solid #2d2d2d;
@@ -441,7 +567,6 @@ st.markdown("""
441
  margin-top: 10px;
442
  }
443
 
444
- /* Control panel */
445
  .control-panel {
446
  background-color: #252526;
447
  border: 1px solid #2d2d2d;
@@ -455,7 +580,6 @@ st.markdown("""
455
  gap: 5px;
456
  }
457
 
458
- /* Messages */
459
  .stInfo {
460
  background-color: #063b49;
461
  color: #bbbbbb;
@@ -474,11 +598,9 @@ st.markdown("""
474
  border: 1px solid #1e5a3a;
475
  }
476
 
477
- /* Hide Streamlit footer and menu */
478
  footer, header {display: none !important;}
479
  #MainMenu {visibility: hidden;}
480
 
481
- /* Custom tabs */
482
  .stTabs [data-baseweb="tab-list"] {
483
  background-color: #2d2d2d;
484
  gap: 0px !important;
@@ -499,7 +621,6 @@ st.markdown("""
499
  color: white;
500
  }
501
 
502
- /* Problems panel */
503
  .problems-panel {
504
  background-color: #252526;
505
  border: 1px solid #2d2d2d;
@@ -537,7 +658,6 @@ st.markdown("""
537
  margin-top: 2px;
538
  }
539
 
540
- /* Document info panel */
541
  .document-info {
542
  background-color: #252526;
543
  border: 1px solid #2d2d2d;
@@ -564,7 +684,6 @@ st.markdown("""
564
  text-align: right;
565
  }
566
 
567
- /* Packages panel */
568
  .packages-panel {
569
  background-color: #252526;
570
  border: 1px solid #2d2d2d;
@@ -593,7 +712,6 @@ st.markdown("""
593
  font-family: monospace;
594
  }
595
 
596
- /* Environment analyzer */
597
  .environments-panel {
598
  background-color: #252526;
599
  border: 1px solid #2d2d2d;
@@ -620,7 +738,6 @@ st.markdown("""
620
  font-weight: bold;
621
  }
622
 
623
- /* Simple keyboard shortcut */
624
  .shortcut-item {
625
  background-color: #252526;
626
  border: 1px solid #2d2d2d;
@@ -641,7 +758,6 @@ st.markdown("""
641
  margin-right: 10px;
642
  }
643
 
644
- /* Monaco editor container */
645
  .monaco-editor-container {
646
  border: 1px solid #2d2d2d;
647
  border-radius: 4px;
@@ -649,7 +765,6 @@ st.markdown("""
649
  margin-bottom: 10px;
650
  }
651
 
652
- /* Make sure Monaco editor has correct background */
653
  .monaco-editor, .monaco-editor-background, .monaco-editor .margin {
654
  background-color: #1e1e1e !important;
655
  }
@@ -667,17 +782,30 @@ def render_editor_tabs(active_tab="document.tex"):
667
  """
668
  st.markdown(tab_html, unsafe_allow_html=True)
669
 
670
- # VS Code-style status bar
671
- def render_status_bar():
672
- status_html = """
673
  <div class="status-bar">
674
- <span>LaTeX</span>
675
  <span>Line: 1, Col: 1</span>
676
  <span>UTF-8</span>
677
  </div>
678
  """
679
  st.markdown(status_html, unsafe_allow_html=True)
680
 
 
 
 
 
 
 
 
 
 
 
 
 
 
681
  # Render a document outline based on section hierarchy
682
  def render_document_outline(structure):
683
  if not structure:
@@ -742,7 +870,7 @@ def render_problems(errors, warnings):
742
  st.markdown('</div>', unsafe_allow_html=True)
743
 
744
  # Render document information panel
745
- def render_document_info(latex_code):
746
  # Ensure latex_code is a string
747
  if not isinstance(latex_code, str):
748
  try:
@@ -776,14 +904,19 @@ def render_document_info(latex_code):
776
  ref_count = len(re.findall(r'\\ref\{', latex_code))
777
  cite_count = len(re.findall(r'\\cite\{', latex_code))
778
 
 
 
 
779
  # Render the info panel
780
  st.markdown('<div class="document-info">', unsafe_allow_html=True)
781
 
782
  info_rows = [
 
783
  ("Document Class", doc_class),
784
  ("Word Count", word_count),
785
  ("Character Count", char_count),
786
  ("Line Count", line_count),
 
787
  ("Equations", equation_count),
788
  ("Align Environments", align_count),
789
  ("Figures", figure_count),
@@ -864,7 +997,7 @@ def render_f5_shortcut():
864
  def main():
865
  # Initialize session state
866
  if 'latex_code' not in st.session_state:
867
- st.session_state.latex_code = default_template
868
  if 'show_preview' not in st.session_state:
869
  st.session_state.show_preview = False
870
  if 'last_compiled' not in st.session_state:
@@ -873,10 +1006,16 @@ def main():
873
  st.session_state.errors = []
874
  if 'warnings' not in st.session_state:
875
  st.session_state.warnings = []
 
 
 
 
 
 
876
 
877
- # Check installation status
878
- if not is_pdflatex_installed():
879
- st.warning("⚠️ LaTeX is not installed. The compilation feature will not work.")
880
 
881
  # Create main layout
882
  col1, col2 = st.columns([3, 2])
@@ -898,7 +1037,7 @@ def main():
898
  if MONACO_AVAILABLE:
899
  try:
900
  # Try to use Monaco editor with minimal parameters
901
- latex_code = st_monaco(st.session_state.latex_code, height=500)
902
  if latex_code is not None:
903
  st.session_state.latex_code = latex_code
904
  except Exception as e:
@@ -913,18 +1052,22 @@ def main():
913
 
914
  st.markdown('</div>', unsafe_allow_html=True)
915
 
916
- # Status bar
917
- render_status_bar()
918
 
919
  st.markdown('</div>', unsafe_allow_html=True)
920
 
 
 
 
921
  # F5 shortcut reminder
922
  render_f5_shortcut()
923
 
924
  # Control buttons with VS Code styling
925
  st.markdown('<div class="button-group">', unsafe_allow_html=True)
926
  compile_btn = st.button("Compile", help="Compile LaTeX to PDF (F5)")
927
- load_template_btn = st.button("Load Template", help="Load default template")
 
928
  clear_btn = st.button("Clear", help="Clear editor content")
929
  st.markdown('</div>', unsafe_allow_html=True)
930
 
@@ -933,8 +1076,12 @@ def main():
933
  st.session_state.compile_clicked = True
934
  st.session_state.last_compiled = time.time()
935
 
936
- if load_template_btn:
937
- st.session_state.latex_code = default_template
 
 
 
 
938
  st.rerun()
939
 
940
  if clear_btn:
@@ -948,8 +1095,17 @@ def main():
948
  col_a, col_b = st.columns(2)
949
 
950
  with col_a:
 
 
 
 
 
 
 
 
 
 
951
  st.checkbox("Auto-compile on save", value=False, key="auto_compile")
952
- st.checkbox("Use pdflatex", value=True, key="use_pdflatex")
953
  st.checkbox("Enable BibTeX", value=False, key="use_bibtex")
954
  st.checkbox("Show line numbers", value=True, key="show_line_numbers")
955
 
@@ -957,13 +1113,25 @@ def main():
957
  st.selectbox("Document Class",
958
  ["article", "report", "book", "letter", "beamer"],
959
  index=0, key="doc_class")
960
- st.selectbox("PDF Engine",
961
- ["pdflatex", "xelatex", "lualatex"],
962
- index=0, key="pdf_engine")
963
  st.selectbox("Editor Theme",
964
  ["Dark", "Light", "High Contrast"],
965
  index=0, key="editor_theme")
966
 
 
 
 
 
 
 
 
 
 
 
 
 
967
  st.markdown('</div>', unsafe_allow_html=True)
968
 
969
  with col2:
@@ -974,7 +1142,7 @@ def main():
974
  # PDF compilation and output
975
  if 'compile_clicked' in st.session_state and st.session_state.compile_clicked:
976
  with st.spinner("Compiling..."):
977
- pdf_data, stdout, stderr = latex_to_pdf(st.session_state.latex_code)
978
 
979
  # Parse errors and warnings
980
  errors, warnings = parse_latex_errors(stdout + stderr)
@@ -983,7 +1151,7 @@ def main():
983
 
984
  if pdf_data:
985
  st.session_state.pdf_data = pdf_data
986
- st.success("Compilation successful")
987
 
988
  # Toggle button for preview
989
  if st.button("Toggle Preview", help="Show or hide the PDF preview"):
@@ -995,7 +1163,7 @@ def main():
995
  # Display compilation info
996
  if st.session_state.last_compiled:
997
  time_str = time.strftime("%H:%M:%S", time.localtime(st.session_state.last_compiled))
998
- st.info(f"Last compiled: {time_str}")
999
 
1000
  # Optional preview
1001
  if st.session_state.show_preview:
@@ -1015,7 +1183,7 @@ def main():
1015
 
1016
  st.session_state.compile_clicked = False
1017
  else:
1018
- st.error("Compilation failed")
1019
  st.markdown('<div class="terminal">', unsafe_allow_html=True)
1020
 
1021
  # Highlight errors in output
@@ -1042,7 +1210,7 @@ def main():
1042
  # Display compilation info
1043
  if st.session_state.last_compiled:
1044
  time_str = time.strftime("%H:%M:%S", time.localtime(st.session_state.last_compiled))
1045
- st.info(f"Last compiled: {time_str}")
1046
 
1047
  # Optional preview
1048
  if st.session_state.show_preview:
@@ -1066,13 +1234,13 @@ def main():
1066
  if structure:
1067
  render_document_outline(structure)
1068
  else:
1069
- st.info("No document structure detected. Add sections using the toolbar.")
1070
 
1071
  with output_tabs[2]:
1072
  # Document analysis features
1073
 
1074
  # Document info
1075
- render_document_info(st.session_state.latex_code)
1076
 
1077
  # Package analysis
1078
  packages = analyze_packages(st.session_state.latex_code)
 
20
 
21
  # Set page configuration
22
  st.set_page_config(
23
+ page_title="Professional LaTeX Editor with Chinese Support",
24
  page_icon="📝",
25
  layout="wide",
26
  initial_sidebar_state="collapsed"
27
  )
28
 
29
+ # Check if LaTeX engines are available
30
+ def check_latex_engines():
31
+ engines = {
32
+ 'pdflatex': shutil.which("pdflatex") is not None,
33
+ 'xelatex': shutil.which("xelatex") is not None,
34
+ 'lualatex': shutil.which("lualatex") is not None
35
+ }
36
+ return engines
37
 
38
+ # Function to convert LaTeX to PDF with engine selection
39
+ def latex_to_pdf(latex_code, engine='xelatex'):
40
+ # Check if the specified engine is installed
41
+ if not shutil.which(engine):
42
+ st.error(f"{engine} not found. Debug info:")
43
  st.code(f"PATH: {os.environ.get('PATH')}")
44
+ result = subprocess.run(["which", engine], capture_output=True, text=True)
45
+ st.code(f"which {engine}: {result.stdout} {result.stderr}")
46
+ return None, "", f"Error: {engine} is not installed or not in PATH."
47
 
48
  with tempfile.TemporaryDirectory() as temp_dir:
49
  temp_path = Path(temp_dir)
 
51
  pdf_file = temp_path / "document.pdf"
52
 
53
  # Write LaTeX code to file
54
+ with open(tex_file, "w", encoding='utf-8') as f:
55
  f.write(latex_code)
56
 
57
  try:
58
+ # Different compilation arguments for different engines
59
+ if engine == 'xelatex':
60
+ cmd = ["xelatex", "-interaction=nonstopmode", "-output-directory", temp_dir, str(tex_file)]
61
+ elif engine == 'lualatex':
62
+ cmd = ["lualatex", "-interaction=nonstopmode", "-output-directory", temp_dir, str(tex_file)]
63
+ else: # pdflatex
64
+ cmd = ["pdflatex", "-interaction=nonstopmode", "-output-directory", temp_dir, str(tex_file)]
65
+
66
+ # Run LaTeX engine to compile the file
67
+ process = subprocess.run(cmd, capture_output=True, text=True)
68
 
69
  # Check if PDF was created
70
  if pdf_file.exists():
 
207
 
208
  return environments
209
 
210
+ # Default LaTeX template with Chinese support
211
+ default_template_chinese = r"""\documentclass{article}
212
+ \usepackage{xeCJK}
213
+ \usepackage{amsmath}
214
+ \usepackage{amssymb}
215
+ \usepackage{graphicx}
216
+ \usepackage{hyperref}
217
+ \usepackage{xcolor}
218
+ \usepackage{geometry}
219
+
220
+ % Set Chinese fonts (using Noto fonts available in the container)
221
+ \setCJKmainfont{Noto Serif CJK SC}
222
+ \setCJKsansfont{Noto Sans CJK SC}
223
+ \setCJKmonofont{Noto Sans Mono CJK SC}
224
+
225
+ % Page geometry
226
+ \geometry{a4paper, margin=1in}
227
+
228
+ \title{中文LaTeX文档示例}
229
+ \author{作者姓名}
230
+ \date{\today}
231
+
232
+ \begin{document}
233
+
234
+ \maketitle
235
+
236
+ \section{简介}
237
+ 这是一个支持中文的LaTeX文档示例。您可以在这里编写中文内容。
238
+
239
+ This document also supports English text seamlessly mixed with Chinese characters.
240
+
241
+ \section{数学表达式}
242
+ \subsection{方程式}
243
+ 著名的爱因斯坦质能方程:
244
+ \begin{equation}
245
+ E = mc^2
246
+ \end{equation}
247
+
248
+ 二次方程求解公式:
249
+ \begin{equation}
250
+ x = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a}
251
+ \end{equation}
252
+
253
+ \subsection{微积分}
254
+ 积分示例:
255
+ \begin{equation}
256
+ \int_{0}^{\pi} \sin(x) \, dx = 2
257
+ \end{equation}
258
+
259
+ \section{列表和项目}
260
+ \subsection{无序列表}
261
+ \begin{itemize}
262
+ \item 第一项包含\textbf{粗体文字}
263
+ \item 第二项包含\textit{斜体文字}
264
+ \item 第三项包含\textcolor{blue}{彩色文字}
265
+ \end{itemize}
266
+
267
+ \subsection{有序列表}
268
+ \begin{enumerate}
269
+ \item 第一步
270
+ \item 第二步
271
+ \item 第三步
272
+ \end{enumerate}
273
+
274
+ \section{表格}
275
+ \begin{table}[h]
276
+ \centering
277
+ \begin{tabular}{|c|c|c|}
278
+ \hline
279
+ 姓名 & 年龄 & 城市 \\
280
+ \hline
281
+ 张三 & 25 & 北京 \\
282
+ \hline
283
+ 李四 & 30 & 上海 \\
284
+ \hline
285
+ \end{tabular}
286
+ \caption{简单表格示例}
287
+ \label{tab:simple}
288
+ \end{table}
289
+
290
+ \section{图形}
291
+ 您可以使用以下语法包含图形:
292
+
293
+ % \begin{figure}[h]
294
+ % \centering
295
+ % \includegraphics[width=0.7\textwidth]{example-image}
296
+ % \caption{示例图形}
297
+ % \label{fig:example}
298
+ % \end{figure}
299
+
300
+ \section{引用文献}
301
+ 您可以使用 \verb|\cite{}| 命令引用参考文献 \cite{example}。
302
+
303
+ \section{交叉引用}
304
+ 您可以使用 \verb|\ref{}| 命令引用章节、图形和表格。
305
+ 例如,参见表格~\ref{tab:simple}。
306
+
307
+ \section{结论}
308
+ 这里是您的结论。
309
+
310
+ % 示例参考文献条目
311
+ \begin{thebibliography}{9}
312
+ \bibitem{example} 作者姓名 (2023). \textit{书籍标题}. 出版社.
313
+ \end{thebibliography}
314
+
315
+ \end{document}
316
+ """
317
+
318
+ # Default LaTeX template (English)
319
+ default_template_english = r"""\documentclass{article}
320
  \usepackage[utf8]{inputenc}
321
  \usepackage{amsmath}
322
  \usepackage{amssymb}
 
382
  \label{tab:simple}
383
  \end{table}
384
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
385
  \section{Conclusion}
386
  Your conclusion here.
387
 
 
388
  \begin{thebibliography}{9}
389
  \bibitem{example} Author, A. (2023). \textit{Title of the Work}. Publisher.
390
  \end{thebibliography}
 
392
  \end{document}
393
  """
394
 
395
+ # Enhanced VSCode-like styling (keeping the original styling)
396
  st.markdown("""
397
  <style>
398
  /* Base theming - VS Code inspired */
 
488
  color: #cca700;
489
  }
490
 
491
+ /* Engine status indicators */
492
+ .engine-status {
493
+ display: flex;
494
+ gap: 10px;
495
+ margin: 10px 0;
496
+ padding: 10px;
497
+ background-color: #252526;
498
+ border-radius: 4px;
499
+ }
500
+
501
+ .engine-item {
502
+ display: flex;
503
+ align-items: center;
504
+ gap: 5px;
505
+ padding: 5px 10px;
506
+ border-radius: 3px;
507
+ font-size: 12px;
508
+ }
509
+
510
+ .engine-available {
511
+ background-color: #1e3a1e;
512
+ color: #4caf50;
513
+ }
514
+
515
+ .engine-unavailable {
516
+ background-color: #3a1e1e;
517
+ color: #f44336;
518
+ }
519
+
520
+ /* All other existing styles remain the same */
521
  .outline-view {
522
  background-color: #252526;
523
  border: 1px solid #2d2d2d;
 
542
  margin-left: 5px;
543
  }
544
 
 
545
  .download-button {
546
  display: inline-block;
547
  padding: 8px 16px;
 
559
  background-color: #4eb772;
560
  }
561
 
 
562
  .preview-container {
563
  background-color: #252526;
564
  border: 1px solid #2d2d2d;
 
567
  margin-top: 10px;
568
  }
569
 
 
570
  .control-panel {
571
  background-color: #252526;
572
  border: 1px solid #2d2d2d;
 
580
  gap: 5px;
581
  }
582
 
 
583
  .stInfo {
584
  background-color: #063b49;
585
  color: #bbbbbb;
 
598
  border: 1px solid #1e5a3a;
599
  }
600
 
 
601
  footer, header {display: none !important;}
602
  #MainMenu {visibility: hidden;}
603
 
 
604
  .stTabs [data-baseweb="tab-list"] {
605
  background-color: #2d2d2d;
606
  gap: 0px !important;
 
621
  color: white;
622
  }
623
 
 
624
  .problems-panel {
625
  background-color: #252526;
626
  border: 1px solid #2d2d2d;
 
658
  margin-top: 2px;
659
  }
660
 
 
661
  .document-info {
662
  background-color: #252526;
663
  border: 1px solid #2d2d2d;
 
684
  text-align: right;
685
  }
686
 
 
687
  .packages-panel {
688
  background-color: #252526;
689
  border: 1px solid #2d2d2d;
 
712
  font-family: monospace;
713
  }
714
 
 
715
  .environments-panel {
716
  background-color: #252526;
717
  border: 1px solid #2d2d2d;
 
738
  font-weight: bold;
739
  }
740
 
 
741
  .shortcut-item {
742
  background-color: #252526;
743
  border: 1px solid #2d2d2d;
 
758
  margin-right: 10px;
759
  }
760
 
 
761
  .monaco-editor-container {
762
  border: 1px solid #2d2d2d;
763
  border-radius: 4px;
 
765
  margin-bottom: 10px;
766
  }
767
 
 
768
  .monaco-editor, .monaco-editor-background, .monaco-editor .margin {
769
  background-color: #1e1e1e !important;
770
  }
 
782
  """
783
  st.markdown(tab_html, unsafe_allow_html=True)
784
 
785
+ # VS Code-style status bar with engine info
786
+ def render_status_bar(engine="XeLaTeX"):
787
+ status_html = f"""
788
  <div class="status-bar">
789
+ <span>{engine}</span>
790
  <span>Line: 1, Col: 1</span>
791
  <span>UTF-8</span>
792
  </div>
793
  """
794
  st.markdown(status_html, unsafe_allow_html=True)
795
 
796
+ # Render engine status
797
+ def render_engine_status():
798
+ engines = check_latex_engines()
799
+
800
+ engine_html = '<div class="engine-status">'
801
+ for engine_name, available in engines.items():
802
+ status_class = "engine-available" if available else "engine-unavailable"
803
+ status_icon = "✅" if available else "❌"
804
+ engine_html += f'<div class="engine-item {status_class}">{status_icon} {engine_name}</div>'
805
+ engine_html += '</div>'
806
+
807
+ st.markdown(engine_html, unsafe_allow_html=True)
808
+
809
  # Render a document outline based on section hierarchy
810
  def render_document_outline(structure):
811
  if not structure:
 
870
  st.markdown('</div>', unsafe_allow_html=True)
871
 
872
  # Render document information panel
873
+ def render_document_info(latex_code, engine):
874
  # Ensure latex_code is a string
875
  if not isinstance(latex_code, str):
876
  try:
 
904
  ref_count = len(re.findall(r'\\ref\{', latex_code))
905
  cite_count = len(re.findall(r'\\cite\{', latex_code))
906
 
907
+ # Check for Chinese characters
908
+ chinese_chars = len(re.findall(r'[\u4e00-\u9fff]', latex_code))
909
+
910
  # Render the info panel
911
  st.markdown('<div class="document-info">', unsafe_allow_html=True)
912
 
913
  info_rows = [
914
+ ("LaTeX Engine", engine),
915
  ("Document Class", doc_class),
916
  ("Word Count", word_count),
917
  ("Character Count", char_count),
918
  ("Line Count", line_count),
919
+ ("Chinese Characters", chinese_chars),
920
  ("Equations", equation_count),
921
  ("Align Environments", align_count),
922
  ("Figures", figure_count),
 
997
  def main():
998
  # Initialize session state
999
  if 'latex_code' not in st.session_state:
1000
+ st.session_state.latex_code = default_template_chinese
1001
  if 'show_preview' not in st.session_state:
1002
  st.session_state.show_preview = False
1003
  if 'last_compiled' not in st.session_state:
 
1006
  st.session_state.errors = []
1007
  if 'warnings' not in st.session_state:
1008
  st.session_state.warnings = []
1009
+ if 'selected_engine' not in st.session_state:
1010
+ st.session_state.selected_engine = 'xelatex'
1011
+
1012
+ # Check available engines
1013
+ engines = check_latex_engines()
1014
+ available_engines = [engine for engine, available in engines.items() if available]
1015
 
1016
+ if not available_engines:
1017
+ st.error("⚠️ No LaTeX engines are installed. The compilation feature will not work.")
1018
+ return
1019
 
1020
  # Create main layout
1021
  col1, col2 = st.columns([3, 2])
 
1037
  if MONACO_AVAILABLE:
1038
  try:
1039
  # Try to use Monaco editor with minimal parameters
1040
+ latex_code = st_monaco(st.session_state.latex_code, height=500, language="latex")
1041
  if latex_code is not None:
1042
  st.session_state.latex_code = latex_code
1043
  except Exception as e:
 
1052
 
1053
  st.markdown('</div>', unsafe_allow_html=True)
1054
 
1055
+ # Status bar with engine info
1056
+ render_status_bar(st.session_state.selected_engine.upper())
1057
 
1058
  st.markdown('</div>', unsafe_allow_html=True)
1059
 
1060
+ # Engine status display
1061
+ render_engine_status()
1062
+
1063
  # F5 shortcut reminder
1064
  render_f5_shortcut()
1065
 
1066
  # Control buttons with VS Code styling
1067
  st.markdown('<div class="button-group">', unsafe_allow_html=True)
1068
  compile_btn = st.button("Compile", help="Compile LaTeX to PDF (F5)")
1069
+ load_chinese_btn = st.button("Load Chinese Template", help="Load Chinese template")
1070
+ load_english_btn = st.button("Load English Template", help="Load English template")
1071
  clear_btn = st.button("Clear", help="Clear editor content")
1072
  st.markdown('</div>', unsafe_allow_html=True)
1073
 
 
1076
  st.session_state.compile_clicked = True
1077
  st.session_state.last_compiled = time.time()
1078
 
1079
+ if load_chinese_btn:
1080
+ st.session_state.latex_code = default_template_chinese
1081
+ st.rerun()
1082
+
1083
+ if load_english_btn:
1084
+ st.session_state.latex_code = default_template_english
1085
  st.rerun()
1086
 
1087
  if clear_btn:
 
1095
  col_a, col_b = st.columns(2)
1096
 
1097
  with col_a:
1098
+ # Engine selection
1099
+ if available_engines:
1100
+ selected_engine = st.selectbox(
1101
+ "LaTeX Engine",
1102
+ available_engines,
1103
+ index=available_engines.index(st.session_state.selected_engine) if st.session_state.selected_engine in available_engines else 0,
1104
+ key="engine_select"
1105
+ )
1106
+ st.session_state.selected_engine = selected_engine
1107
+
1108
  st.checkbox("Auto-compile on save", value=False, key="auto_compile")
 
1109
  st.checkbox("Enable BibTeX", value=False, key="use_bibtex")
1110
  st.checkbox("Show line numbers", value=True, key="show_line_numbers")
1111
 
 
1113
  st.selectbox("Document Class",
1114
  ["article", "report", "book", "letter", "beamer"],
1115
  index=0, key="doc_class")
1116
+ st.selectbox("Font Selection",
1117
+ ["Noto CJK (Chinese)", "WQY (Chinese)", "Latin Modern (English)", "Times (English)"],
1118
+ index=0, key="font_selection")
1119
  st.selectbox("Editor Theme",
1120
  ["Dark", "Light", "High Contrast"],
1121
  index=0, key="editor_theme")
1122
 
1123
+ # Engine information
1124
+ st.markdown("### Engine Information")
1125
+ engine_info = {
1126
+ 'pdflatex': 'Traditional LaTeX engine, good for English documents',
1127
+ 'xelatex': 'Modern engine with Unicode support, excellent for Chinese and mixed languages',
1128
+ 'lualatex': 'Advanced engine with Lua scripting support, good for complex typography'
1129
+ }
1130
+
1131
+ for engine, description in engine_info.items():
1132
+ status = "✅ Available" if engines.get(engine, False) else "❌ Not Available"
1133
+ st.write(f"**{engine.upper()}**: {description} - {status}")
1134
+
1135
  st.markdown('</div>', unsafe_allow_html=True)
1136
 
1137
  with col2:
 
1142
  # PDF compilation and output
1143
  if 'compile_clicked' in st.session_state and st.session_state.compile_clicked:
1144
  with st.spinner("Compiling..."):
1145
+ pdf_data, stdout, stderr = latex_to_pdf(st.session_state.latex_code, st.session_state.selected_engine)
1146
 
1147
  # Parse errors and warnings
1148
  errors, warnings = parse_latex_errors(stdout + stderr)
 
1151
 
1152
  if pdf_data:
1153
  st.session_state.pdf_data = pdf_data
1154
+ st.success(f"Compilation successful using {st.session_state.selected_engine.upper()}")
1155
 
1156
  # Toggle button for preview
1157
  if st.button("Toggle Preview", help="Show or hide the PDF preview"):
 
1163
  # Display compilation info
1164
  if st.session_state.last_compiled:
1165
  time_str = time.strftime("%H:%M:%S", time.localtime(st.session_state.last_compiled))
1166
+ st.info(f"Last compiled: {time_str} with {st.session_state.selected_engine.upper()}")
1167
 
1168
  # Optional preview
1169
  if st.session_state.show_preview:
 
1183
 
1184
  st.session_state.compile_clicked = False
1185
  else:
1186
+ st.error(f"Compilation failed with {st.session_state.selected_engine.upper()}")
1187
  st.markdown('<div class="terminal">', unsafe_allow_html=True)
1188
 
1189
  # Highlight errors in output
 
1210
  # Display compilation info
1211
  if st.session_state.last_compiled:
1212
  time_str = time.strftime("%H:%M:%S", time.localtime(st.session_state.last_compiled))
1213
+ st.info(f"Last compiled: {time_str} with {st.session_state.selected_engine.upper()}")
1214
 
1215
  # Optional preview
1216
  if st.session_state.show_preview:
 
1234
  if structure:
1235
  render_document_outline(structure)
1236
  else:
1237
+ st.info("No document structure detected. Add sections using \\section{}, \\subsection{}, etc.")
1238
 
1239
  with output_tabs[2]:
1240
  # Document analysis features
1241
 
1242
  # Document info
1243
+ render_document_info(st.session_state.latex_code, st.session_state.selected_engine.upper())
1244
 
1245
  # Package analysis
1246
  packages = analyze_packages(st.session_state.latex_code)