euler314 commited on
Commit
34f2fda
·
verified ·
1 Parent(s): c9b3fde

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +223 -214
app.py CHANGED
@@ -10,6 +10,7 @@ from PIL import Image
10
  import fitz # PyMuPDF
11
  import time
12
  import re
 
13
 
14
  # Set page configuration
15
  st.set_page_config(
@@ -191,6 +192,24 @@ def find_environments(latex_code):
191
 
192
  return environments
193
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
194
  # Default LaTeX template
195
  default_template = r"""\documentclass{article}
196
  \usepackage[utf8]{inputenc}
@@ -286,7 +305,7 @@ Your conclusion here.
286
  \end{document}
287
  """
288
 
289
- # Enhanced VSCode-like styling with inline syntax highlighting
290
  st.markdown("""
291
  <style>
292
  /* Base theming - VS Code inspired */
@@ -309,48 +328,6 @@ st.markdown("""
309
  background-color: #1177bb;
310
  }
311
 
312
- /* Custom editor with built-in syntax highlighting */
313
- #latex-editor-container {
314
- position: relative;
315
- width: 100%;
316
- height: 600px;
317
- font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
318
- font-size: 14px;
319
- line-height: 1.5;
320
- background-color: #1e1e1e;
321
- color: #d4d4d4;
322
- border-radius: 4px;
323
- border: 1px solid #252526;
324
- padding: 10px;
325
- }
326
-
327
- /* Default coloring for textarea */
328
- .stTextArea textarea {
329
- font-family: 'Consolas', 'Monaco', 'Courier New', monospace !important;
330
- font-size: 14px !important;
331
- line-height: 1.5 !important;
332
- background-color: #1e1e1e !important;
333
- color: #d4d4d4 !important;
334
- padding: 10px !important;
335
- border-radius: 4px !important;
336
- border: 1px solid #252526 !important;
337
- }
338
-
339
- /* Highlight LaTeX specific elements */
340
- .stTextArea textarea::selection {
341
- background-color: #264f78;
342
- }
343
-
344
- /* VS Code-like editor container */
345
- .editor-container {
346
- background-color: #1e1e1e;
347
- border-radius: 4px;
348
- border: 1px solid #2d2d2d;
349
- margin-bottom: 1rem;
350
- display: flex;
351
- flex-direction: column;
352
- }
353
-
354
  /* Editor tab bar */
355
  .tab-bar {
356
  display: flex;
@@ -693,171 +670,15 @@ st.markdown("""
693
  margin-right: 10px;
694
  }
695
 
696
- /* Inline syntax highlighting for LaTeX - applied via JavaScript */
697
- #syntax-styles {
698
- display: none;
 
 
699
  }
700
  </style>
701
-
702
- <div id="syntax-styles">
703
- <style>
704
- .latex-command { color: #569cd6; }
705
- .latex-environment { color: #4ec9b0; }
706
- .latex-bracket { color: #d4d4d4; }
707
- .latex-math { color: #c586c0; }
708
- .latex-comment { color: #6a9955; }
709
- .latex-package { color: #dcdcaa; }
710
- </style>
711
- </div>
712
-
713
- <script>
714
- // Add inline syntax highlighting support for the editor
715
- document.addEventListener('DOMContentLoaded', function() {
716
- // Function to apply syntax highlighting to the textarea
717
- function applySyntaxHighlighting() {
718
- const textarea = document.querySelector('textarea');
719
- if (!textarea) return;
720
-
721
- // Find text matches and colorize them
722
- const text = textarea.value;
723
-
724
- // Color LaTeX commands
725
- textarea.style.color = '#d4d4d4'; // Default text color
726
-
727
- // Apply specific colors for different LaTeX constructs
728
- // We can't do this directly in the textarea, but we indicate the presence of these elements
729
- if (text.match(/\\usepackage/g)) {
730
- const packageButtons = document.querySelectorAll('.toolbar-button[title="Add Package"]');
731
- packageButtons.forEach(button => button.style.color = '#dcdcaa');
732
- }
733
-
734
- if (text.match(/\\begin\{align\}/g)) {
735
- const alignButtons = document.querySelectorAll('.toolbar-button[title="Align"]');
736
- alignButtons.forEach(button => button.style.color = '#4ec9b0');
737
- }
738
-
739
- if (text.match(/\\\w+/g)) {
740
- // Commands are present
741
- }
742
-
743
- if (text.match(/\$/g)) {
744
- const mathButtons = document.querySelectorAll('.toolbar-button[title="Inline Math"]');
745
- mathButtons.forEach(button => button.style.color = '#c586c0');
746
- }
747
- }
748
-
749
- // Set up an interval to periodically check and update highlighting
750
- setInterval(applySyntaxHighlighting, 1000);
751
- });
752
- </script>
753
  """, unsafe_allow_html=True)
754
 
755
- # Function to create a functional VS Code-like toolbar
756
- def render_functional_toolbar():
757
- toolbar_html = """
758
- <div class="toolbar">
759
- <button class="toolbar-button" title="Bold" onclick="insertAtCursor('\\\\textbf{', '}')">
760
- <strong>B</strong>
761
- </button>
762
- <button class="toolbar-button" title="Italic" onclick="insertAtCursor('\\\\textit{', '}')">
763
- <em>I</em>
764
- </button>
765
- <button class="toolbar-button" title="Inline Math" onclick="insertAtCursor('$', '$')">
766
-
767
- </button>
768
- <div class="toolbar-separator"></div>
769
- <button class="toolbar-button" title="Section" onclick="insertAtCursor('\\\\section{', '}')">
770
- §
771
- </button>
772
- <button class="toolbar-button" title="Subsection" onclick="insertAtCursor('\\\\subsection{', '}')">
773
- §§
774
- </button>
775
- <div class="toolbar-separator"></div>
776
- <button class="toolbar-button" title="Itemize" onclick="insertAtCursor('\\\\begin{itemize}\\n \\\\item ', '\\n\\\\end{itemize}')">
777
-
778
- </button>
779
- <button class="toolbar-button" title="Enumerate" onclick="insertAtCursor('\\\\begin{enumerate}\\n \\\\item ', '\\n\\\\end{enumerate}')">
780
- 1.
781
- </button>
782
- <div class="toolbar-separator"></div>
783
- <button class="toolbar-button" title="Equation" onclick="insertAtCursor('\\\\begin{equation}\\n ', '\\n\\\\end{equation}')">
784
- =
785
- </button>
786
- <button class="toolbar-button" title="Align" onclick="insertAtCursor('\\\\begin{align}\\n ', '\\n\\\\end{align}')">
787
-
788
- </button>
789
- <button class="toolbar-button" title="Figure" onclick="insertAtCursor('\\\\begin{figure}[h]\\n \\\\centering\\n \\\\includegraphics[width=0.8\\\\textwidth]{', '}\\n \\\\caption{Caption}\\n \\\\label{fig:label}\\n\\\\end{figure}')">
790
- 🖼
791
- </button>
792
- <button class="toolbar-button" title="Table" onclick="insertAtCursor('\\\\begin{table}[h]\\n \\\\centering\\n \\\\begin{tabular}{ccc}\\n ', ' & B & C \\\\\\\\\\n 1 & 2 & 3 \\\\\\\\\\n \\\\end{tabular}\\n \\\\caption{Caption}\\n \\\\label{tab:label}\\n\\\\end{table}')">
793
-
794
- </button>
795
- <div class="toolbar-separator"></div>
796
- <button class="toolbar-button" title="Fraction" onclick="insertAtCursor('\\\\frac{', '}{denominator}')">
797
-
798
- </button>
799
- <button class="toolbar-button" title="Square Root" onclick="insertAtCursor('\\\\sqrt{', '}')">
800
-
801
- </button>
802
- <button class="toolbar-button" title="Add Package" onclick="insertAtCursor('\\\\usepackage{', '}')">
803
- 📦
804
- </button>
805
- </div>
806
-
807
- <script>
808
- function insertAtCursor(before, after) {
809
- // Find the textarea element
810
- var textarea = document.querySelector('textarea');
811
- if (!textarea) return;
812
-
813
- // Get current cursor position
814
- var startPos = textarea.selectionStart;
815
- var endPos = textarea.selectionEnd;
816
-
817
- // Get text before and after selection
818
- var textBefore = textarea.value.substring(0, startPos);
819
- var textSelected = textarea.value.substring(startPos, endPos);
820
- var textAfter = textarea.value.substring(endPos);
821
-
822
- // Insert the text
823
- var newText;
824
- if (textSelected) {
825
- // If text is selected, wrap it with before and after
826
- newText = textBefore + before + textSelected + after + textAfter;
827
- } else {
828
- // If no text is selected, just insert before and after
829
- newText = textBefore + before + after + textAfter;
830
- // Put cursor between before and after
831
- var newCursorPos = startPos + before.length;
832
- }
833
-
834
- // Update textarea value
835
- textarea.value = newText;
836
-
837
- // Set selection range to position cursor appropriately
838
- if (textSelected) {
839
- // If text was selected, select the wrapped text
840
- textarea.setSelectionRange(startPos, endPos + before.length + after.length);
841
- } else {
842
- // Otherwise position cursor between before and after
843
- textarea.setSelectionRange(newCursorPos, newCursorPos);
844
- }
845
-
846
- // Focus on textarea
847
- textarea.focus();
848
-
849
- // Trigger an input event to update Streamlit
850
- var event = new Event('input', { bubbles: true });
851
- textarea.dispatchEvent(event);
852
-
853
- // Trigger change event to update Streamlit session state
854
- var changeEvent = new Event('change', { bubbles: true });
855
- textarea.dispatchEvent(changeEvent);
856
- }
857
- </script>
858
- """
859
- st.markdown(toolbar_html, unsafe_allow_html=True)
860
-
861
  # VS Code-style editor tabs
862
  def render_editor_tabs(active_tab="document.tex"):
863
  tab_html = f"""
@@ -880,6 +701,26 @@ def render_status_bar():
880
  """
881
  st.markdown(status_html, unsafe_allow_html=True)
882
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
883
  # Render a document outline based on section hierarchy
884
  def render_document_outline(structure):
885
  if not structure:
@@ -1052,7 +893,7 @@ def render_environments_panel(environments):
1052
 
1053
  st.markdown('</div>', unsafe_allow_html=True)
1054
 
1055
- # Display a simple F5 keyboard shortcut reminder
1056
  def render_f5_shortcut():
1057
  st.markdown(
1058
  '<div class="shortcut-item">'
@@ -1062,6 +903,120 @@ def render_f5_shortcut():
1062
  unsafe_allow_html=True
1063
  )
1064
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1065
  # Main application
1066
  def main():
1067
  # Initialize session state
@@ -1094,20 +1049,74 @@ def main():
1094
  # Tab bar
1095
  render_editor_tabs()
1096
 
1097
- # Toolbar with functional buttons
1098
- render_functional_toolbar()
 
 
 
 
1099
 
1100
- # Editor with VS Code styling and syntax highlighting
1101
- st.markdown('<div id="syntax-highlighting-editor">', unsafe_allow_html=True)
1102
- latex_code = st.text_area(
1103
- "",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1104
  value=st.session_state.latex_code,
1105
  height=500,
1106
- key="latex_editor",
1107
- label_visibility="collapsed"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1108
  )
 
1109
  st.markdown('</div>', unsafe_allow_html=True)
1110
- st.session_state.latex_code = latex_code
 
 
1111
 
1112
  # Status bar
1113
  render_status_bar()
 
10
  import fitz # PyMuPDF
11
  import time
12
  import re
13
+ from streamlit_monaco import st_monaco
14
 
15
  # Set page configuration
16
  st.set_page_config(
 
192
 
193
  return environments
194
 
195
+ # Define LaTeX code snippets for toolbar actions
196
+ latex_snippets = {
197
+ "bold": "\\textbf{$0}",
198
+ "italic": "\\textit{$0}",
199
+ "math_inline": "$\n$0\n$",
200
+ "section": "\\section{$0}",
201
+ "subsection": "\\subsection{$0}",
202
+ "itemize": "\\begin{itemize}\n\t\\item $0\n\\end{itemize}",
203
+ "enumerate": "\\begin{enumerate}\n\t\\item $0\n\\end{enumerate}",
204
+ "equation": "\\begin{equation}\n\t$0\n\\end{equation}",
205
+ "align": "\\begin{align}\n\t$0\n\\end{align}",
206
+ "figure": "\\begin{figure}[h]\n\t\\centering\n\t\\includegraphics[width=0.8\\textwidth]{$0}\n\t\\caption{Caption}\n\t\\label{fig:label}\n\\end{figure}",
207
+ "table": "\\begin{table}[h]\n\t\\centering\n\t\\begin{tabular}{ccc}\n\t\t$0 & B & C \\\\\n\t\t1 & 2 & 3 \\\\\n\t\\end{tabular}\n\t\\caption{Caption}\n\t\\label{tab:label}\n\\end{table}",
208
+ "fraction": "\\frac{$0}{denominator}",
209
+ "sqrt": "\\sqrt{$0}",
210
+ "package": "\\usepackage{$0}"
211
+ }
212
+
213
  # Default LaTeX template
214
  default_template = r"""\documentclass{article}
215
  \usepackage[utf8]{inputenc}
 
305
  \end{document}
306
  """
307
 
308
+ # Enhanced VSCode-like styling
309
  st.markdown("""
310
  <style>
311
  /* Base theming - VS Code inspired */
 
328
  background-color: #1177bb;
329
  }
330
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
331
  /* Editor tab bar */
332
  .tab-bar {
333
  display: flex;
 
670
  margin-right: 10px;
671
  }
672
 
673
+ /* Monaco editor container */
674
+ .monaco-editor-container {
675
+ border: 1px solid #2d2d2d;
676
+ border-radius: 4px;
677
+ overflow: hidden;
678
  }
679
  </style>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
680
  """, unsafe_allow_html=True)
681
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
682
  # VS Code-style editor tabs
683
  def render_editor_tabs(active_tab="document.tex"):
684
  tab_html = f"""
 
701
  """
702
  st.markdown(status_html, unsafe_allow_html=True)
703
 
704
+ # VS Code-style toolbar buttons
705
+ def render_toolbar_buttons():
706
+ col1, col2, col3, col4, col5 = st.columns([1, 1, 1, 1, 5])
707
+
708
+ with col1:
709
+ st.button("Bold", key="btn_bold", help="Insert bold text")
710
+ st.button("Italic", key="btn_italic", help="Insert italic text")
711
+
712
+ with col2:
713
+ st.button("Section", key="btn_section", help="Insert section heading")
714
+ st.button("Subsection", key="btn_subsection", help="Insert subsection heading")
715
+
716
+ with col3:
717
+ st.button("Itemize", key="btn_itemize", help="Insert bulleted list")
718
+ st.button("Enumerate", key="btn_enumerate", help="Insert numbered list")
719
+
720
+ with col4:
721
+ st.button("Equation", key="btn_equation", help="Insert equation environment")
722
+ st.button("Table", key="btn_table", help="Insert table environment")
723
+
724
  # Render a document outline based on section hierarchy
725
  def render_document_outline(structure):
726
  if not structure:
 
893
 
894
  st.markdown('</div>', unsafe_allow_html=True)
895
 
896
+ # Display a simple F5 shortcut reminder
897
  def render_f5_shortcut():
898
  st.markdown(
899
  '<div class="shortcut-item">'
 
903
  unsafe_allow_html=True
904
  )
905
 
906
+ # Define LaTeX language for Monaco editor
907
+ def get_latex_language_definition():
908
+ return {
909
+ "defaultToken": "",
910
+ "tokenPostfix": ".tex",
911
+ "ignoreCase": True,
912
+
913
+ "brackets": [
914
+ { "token": "delimiter.curly", "open": "{", "close": "}" },
915
+ { "token": "delimiter.square", "open": "[", "close": "]" },
916
+ { "token": "delimiter.parenthesis", "open": "(", "close": ")" }
917
+ ],
918
+
919
+ "keywords": [
920
+ "documentclass", "usepackage", "begin", "end", "section", "subsection",
921
+ "subsubsection", "chapter", "paragraph", "subparagraph", "part", "appendix",
922
+ "maketitle", "tableofcontents", "figure", "table", "equation", "align",
923
+ "itemize", "enumerate", "description", "center", "verbatim", "minipage",
924
+ "textbf", "textit", "texttt", "textrm", "textsc", "textsf", "emph", "cite",
925
+ "ref", "label", "caption", "includegraphics", "input", "include", "hline",
926
+ "vspace", "hspace", "newpage", "clearpage", "pagebreak", "newcommand",
927
+ "renewcommand", "providecommand", "newenvironment", "renewenvironment",
928
+ "provideenvironment", "newtheorem", "footnote", "item", "multicolumn"
929
+ ],
930
+
931
+ "operators": [
932
+ "&", "_", "^", "~", "'", "\"", "`"
933
+ ],
934
+
935
+ "tokenizer": {
936
+ "root": [
937
+ [/\\([a-zA-Z]+)/, {
938
+ cases: {
939
+ "@keywords": { token: "keyword.$1" },
940
+ "@default": "keyword"
941
+ }
942
+ }],
943
+ [/\{/, "delimiter.curly"],
944
+ [/\}/, "delimiter.curly"],
945
+ [/\[/, "delimiter.square"],
946
+ [/\]/, "delimiter.square"],
947
+ [/\(/, "delimiter.parenthesis"],
948
+ [/\)/, "delimiter.parenthesis"],
949
+ [/\$\$/, { token: "delimiter.dollar", next: "@math_block" }],
950
+ [/\$/, { token: "delimiter.dollar", next: "@math_inline" }],
951
+ [/%.*$/, "comment"],
952
+ [/[^\\{}\[\]$%&_\^~'"` ]+/, ""]
953
+ ],
954
+
955
+ "math_block": [
956
+ [/\$\$/, { token: "delimiter.dollar", next: "@pop" }],
957
+ [/[^\\$]+/, "predefined.mathematical"],
958
+ [/\\[a-zA-Z]+/, "predefined.mathematical"],
959
+ [/[\\$]/, "predefined.mathematical"]
960
+ ],
961
+
962
+ "math_inline": [
963
+ [/\$/, { token: "delimiter.dollar", next: "@pop" }],
964
+ [/[^\\$]+/, "predefined.mathematical"],
965
+ [/\\[a-zA-Z]+/, "predefined.mathematical"],
966
+ [/[\\$]/, "predefined.mathematical"]
967
+ ]
968
+ }
969
+ }
970
+
971
+ # Define LaTeX autocompletion suggestions for Monaco editor
972
+ def get_latex_completions():
973
+ return [
974
+ # Document structure
975
+ {"label": "\\documentclass", "kind": 14, "insertText": "\\documentclass{${1:article}}", "documentation": "Defines the document class"},
976
+ {"label": "\\usepackage", "kind": 14, "insertText": "\\usepackage{${1:package}}", "documentation": "Imports a package"},
977
+ {"label": "\\begin", "kind": 14, "insertText": "\\begin{${1:environment}}\n\t$0\n\\end{$1}", "documentation": "Creates an environment"},
978
+ {"label": "\\end", "kind": 14, "insertText": "\\end{${1:environment}}", "documentation": "Ends an environment"},
979
+
980
+ # Sections
981
+ {"label": "\\section", "kind": 14, "insertText": "\\section{${1:title}}", "documentation": "Creates a section"},
982
+ {"label": "\\subsection", "kind": 14, "insertText": "\\subsection{${1:title}}", "documentation": "Creates a subsection"},
983
+ {"label": "\\subsubsection", "kind": 14, "insertText": "\\subsubsection{${1:title}}", "documentation": "Creates a subsubsection"},
984
+
985
+ # Formatting
986
+ {"label": "\\textbf", "kind": 14, "insertText": "\\textbf{${1:text}}", "documentation": "Makes text bold"},
987
+ {"label": "\\textit", "kind": 14, "insertText": "\\textit{${1:text}}", "documentation": "Makes text italic"},
988
+ {"label": "\\underline", "kind": 14, "insertText": "\\underline{${1:text}}", "documentation": "Underlines text"},
989
+ {"label": "\\emph", "kind": 14, "insertText": "\\emph{${1:text}}", "documentation": "Emphasizes text"},
990
+
991
+ # Math
992
+ {"label": "\\begin{equation}", "kind": 14, "insertText": "\\begin{equation}\n\t${1}\n\\end{equation}", "documentation": "Creates an equation environment"},
993
+ {"label": "\\begin{align}", "kind": 14, "insertText": "\\begin{align}\n\t${1}\n\\end{align}", "documentation": "Creates an align environment"},
994
+ {"label": "\\frac", "kind": 14, "insertText": "\\frac{${1:numerator}}{${2:denominator}}", "documentation": "Creates a fraction"},
995
+ {"label": "\\sqrt", "kind": 14, "insertText": "\\sqrt{${1:expression}}", "documentation": "Creates a square root"},
996
+ {"label": "\\sum", "kind": 14, "insertText": "\\sum_{${1:lower}}^{${2:upper}}", "documentation": "Creates a summation"},
997
+ {"label": "\\int", "kind": 14, "insertText": "\\int_{${1:lower}}^{${2:upper}}", "documentation": "Creates an integral"},
998
+
999
+ # Lists
1000
+ {"label": "\\begin{itemize}", "kind": 14, "insertText": "\\begin{itemize}\n\t\\item ${1}\n\\end{itemize}", "documentation": "Creates a bulleted list"},
1001
+ {"label": "\\begin{enumerate}", "kind": 14, "insertText": "\\begin{enumerate}\n\t\\item ${1}\n\\end{enumerate}", "documentation": "Creates a numbered list"},
1002
+ {"label": "\\item", "kind": 14, "insertText": "\\item ${1}", "documentation": "Creates a list item"},
1003
+
1004
+ # Tables
1005
+ {"label": "\\begin{table}", "kind": 14, "insertText": "\\begin{table}[${1:h}]\n\t\\centering\n\t\\begin{tabular}{${2:ccc}}\n\t\t${3}\n\t\\end{tabular}\n\t\\caption{${4:caption}}\n\t\\label{tab:${5:label}}\n\\end{table}", "documentation": "Creates a table environment"},
1006
+
1007
+ # Figures
1008
+ {"label": "\\begin{figure}", "kind": 14, "insertText": "\\begin{figure}[${1:h}]\n\t\\centering\n\t\\includegraphics[width=${2:0.8}\\textwidth]{${3:filename}}\n\t\\caption{${4:caption}}\n\t\\label{fig:${5:label}}\n\\end{figure}", "documentation": "Creates a figure environment"},
1009
+
1010
+ # Common environments
1011
+ {"label": "\\begin{center}", "kind": 14, "insertText": "\\begin{center}\n\t${1}\n\\end{center}", "documentation": "Creates centered text"},
1012
+ {"label": "\\begin{verbatim}", "kind": 14, "insertText": "\\begin{verbatim}\n${1}\n\\end{verbatim}", "documentation": "Creates verbatim text"},
1013
+
1014
+ # References
1015
+ {"label": "\\label", "kind": 14, "insertText": "\\label{${1:label}}", "documentation": "Creates a label for cross-referencing"},
1016
+ {"label": "\\ref", "kind": 14, "insertText": "\\ref{${1:label}}", "documentation": "References a label"},
1017
+ {"label": "\\cite", "kind": 14, "insertText": "\\cite{${1:key}}", "documentation": "Cites a reference"}
1018
+ ]
1019
+
1020
  # Main application
1021
  def main():
1022
  # Initialize session state
 
1049
  # Tab bar
1050
  render_editor_tabs()
1051
 
1052
+ # Toolbar buttons
1053
+ render_toolbar_buttons()
1054
+
1055
+ # Check for toolbar button clicks
1056
+ button_clicked = False
1057
+ snippet_to_insert = ""
1058
 
1059
+ if st.session_state.get("btn_bold", False):
1060
+ snippet_to_insert = latex_snippets["bold"]
1061
+ button_clicked = True
1062
+ elif st.session_state.get("btn_italic", False):
1063
+ snippet_to_insert = latex_snippets["italic"]
1064
+ button_clicked = True
1065
+ elif st.session_state.get("btn_section", False):
1066
+ snippet_to_insert = latex_snippets["section"]
1067
+ button_clicked = True
1068
+ elif st.session_state.get("btn_subsection", False):
1069
+ snippet_to_insert = latex_snippets["subsection"]
1070
+ button_clicked = True
1071
+ elif st.session_state.get("btn_itemize", False):
1072
+ snippet_to_insert = latex_snippets["itemize"]
1073
+ button_clicked = True
1074
+ elif st.session_state.get("btn_enumerate", False):
1075
+ snippet_to_insert = latex_snippets["enumerate"]
1076
+ button_clicked = True
1077
+ elif st.session_state.get("btn_equation", False):
1078
+ snippet_to_insert = latex_snippets["equation"]
1079
+ button_clicked = True
1080
+ elif st.session_state.get("btn_table", False):
1081
+ snippet_to_insert = latex_snippets["table"]
1082
+ button_clicked = True
1083
+
1084
+ # Monaco Editor with LaTeX configuration
1085
+ st.markdown('<div class="monaco-editor-container">', unsafe_allow_html=True)
1086
+
1087
+ # Define LaTeX language configuration for Monaco
1088
+ latex_language = get_latex_language_definition()
1089
+ latex_completions = get_latex_completions()
1090
+
1091
+ # Create Monaco editor component
1092
+ latex_code = st_monaco(
1093
  value=st.session_state.latex_code,
1094
  height=500,
1095
+ language="latex",
1096
+ theme="vs-dark",
1097
+ options={
1098
+ "scrollBeyondLastLine": False,
1099
+ "minimap": {"enabled": True},
1100
+ "lineNumbers": "on",
1101
+ "tabSize": 2,
1102
+ "insertSpaces": True,
1103
+ "fontSize": 14,
1104
+ "wordWrap": "on",
1105
+ "automaticLayout": True,
1106
+ "suggestOnTriggerCharacters": True,
1107
+ "quickSuggestions": True,
1108
+ "snippetSuggestions": "inline",
1109
+ "folding": True,
1110
+ "bracketPairColorization.enabled": True,
1111
+ "renderWhitespace": "boundary"
1112
+ },
1113
+ key="monaco_editor"
1114
  )
1115
+
1116
  st.markdown('</div>', unsafe_allow_html=True)
1117
+
1118
+ if latex_code is not None:
1119
+ st.session_state.latex_code = latex_code
1120
 
1121
  # Status bar
1122
  render_status_bar()