euler314 commited on
Commit
fcb5c90
·
verified ·
1 Parent(s): c40dca1

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +457 -41
app.py CHANGED
@@ -13,7 +13,7 @@ import re
13
 
14
  # Set page configuration
15
  st.set_page_config(
16
- page_title="Advanced LaTeX Editor",
17
  page_icon="📝",
18
  layout="wide",
19
  initial_sidebar_state="collapsed"
@@ -109,7 +109,7 @@ def parse_latex_errors(output):
109
 
110
  return errors, warnings
111
 
112
- # Function to extract document structure - fixed to handle non-string input
113
  def extract_document_structure(latex_code):
114
  structure = []
115
 
@@ -149,6 +149,48 @@ def extract_document_structure(latex_code):
149
 
150
  return structure
151
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
152
  # Default LaTeX template
153
  default_template = r"""\documentclass{article}
154
  \usepackage[utf8]{inputenc}
@@ -158,7 +200,7 @@ default_template = r"""\documentclass{article}
158
  \usepackage{hyperref}
159
  \usepackage{xcolor}
160
 
161
- \title{Advanced \LaTeX{} Document}
162
  \author{Your Name}
163
  \date{\today}
164
 
@@ -244,7 +286,7 @@ Your conclusion here.
244
  \end{document}
245
  """
246
 
247
- # Enhanced VSCode-like advanced styling
248
  st.markdown("""
249
  <style>
250
  /* Base theming - VS Code inspired */
@@ -267,8 +309,8 @@ st.markdown("""
267
  background-color: #1177bb;
268
  }
269
 
270
- /* VS Code-like editor */
271
- .stTextArea textarea {
272
  font-family: 'Consolas', 'Monaco', 'Courier New', monospace !important;
273
  font-size: 14px !important;
274
  line-height: 1.5 !important;
@@ -279,6 +321,45 @@ st.markdown("""
279
  border: 1px solid #252526 !important;
280
  }
281
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
282
  /* VS Code-like editor container */
283
  .editor-container {
284
  background-color: #1e1e1e;
@@ -553,61 +634,236 @@ st.markdown("""
553
  .info-value {
554
  text-align: right;
555
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
556
  </style>
557
  """, unsafe_allow_html=True)
558
 
559
- # VS Code-style editor tabs
560
- def render_editor_tabs(active_tab="document.tex"):
561
- tab_html = f"""
562
- <div class="tab-bar">
563
- <div class="tab active">
564
- <span class="tab-icon">📄</span> {active_tab}
565
- </div>
566
- </div>
567
- """
568
- st.markdown(tab_html, unsafe_allow_html=True)
569
-
570
- # Build a VS Code-like toolbar
571
- def render_toolbar():
572
  toolbar_html = """
573
  <div class="toolbar">
574
- <button class="toolbar-button" title="Bold">
575
  <strong>B</strong>
576
  </button>
577
- <button class="toolbar-button" title="Italic">
578
  <em>I</em>
579
  </button>
580
- <button class="toolbar-button" title="Math">
581
 
582
  </button>
583
  <div class="toolbar-separator"></div>
584
- <button class="toolbar-button" title="Section">
585
  §
586
  </button>
587
- <button class="toolbar-button" title="Subsection">
588
  §§
589
  </button>
590
  <div class="toolbar-separator"></div>
591
- <button class="toolbar-button" title="Itemize">
592
 
593
  </button>
594
- <button class="toolbar-button" title="Enumerate">
595
  1.
596
  </button>
597
  <div class="toolbar-separator"></div>
598
- <button class="toolbar-button" title="Equation">
599
  =
600
  </button>
601
- <button class="toolbar-button" title="Figure">
 
 
 
602
  🖼
603
  </button>
604
- <button class="toolbar-button" title="Table">
605
 
606
  </button>
 
 
 
 
 
 
 
 
 
 
607
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
608
  """
609
  st.markdown(toolbar_html, unsafe_allow_html=True)
610
 
 
 
 
 
 
 
 
 
 
 
 
611
  # VS Code-style status bar
612
  def render_status_bar():
613
  status_html = """
@@ -619,6 +875,42 @@ def render_status_bar():
619
  """
620
  st.markdown(status_html, unsafe_allow_html=True)
621
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
622
  # Render a document outline based on section hierarchy
623
  def render_document_outline(structure):
624
  if not structure:
@@ -702,6 +994,7 @@ def render_document_info(latex_code):
702
 
703
  # Count equations
704
  equation_count = len(re.findall(r'\\begin\{equation', latex_code))
 
705
 
706
  # Count figures
707
  figure_count = len(re.findall(r'\\begin\{figure', latex_code))
@@ -709,6 +1002,13 @@ def render_document_info(latex_code):
709
  # Count tables
710
  table_count = len(re.findall(r'\\begin\{table', latex_code))
711
 
 
 
 
 
 
 
 
712
  # Render the info panel
713
  st.markdown('<div class="document-info">', unsafe_allow_html=True)
714
 
@@ -718,8 +1018,12 @@ def render_document_info(latex_code):
718
  ("Character Count", char_count),
719
  ("Line Count", line_count),
720
  ("Equations", equation_count),
 
721
  ("Figures", figure_count),
722
- ("Tables", table_count)
 
 
 
723
  ]
724
 
725
  for label, value in info_rows:
@@ -733,6 +1037,81 @@ def render_document_info(latex_code):
733
 
734
  st.markdown('</div>', unsafe_allow_html=True)
735
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
736
  # Main application
737
  def main():
738
  # Initialize session state
@@ -746,6 +1125,8 @@ def main():
746
  st.session_state.errors = []
747
  if 'warnings' not in st.session_state:
748
  st.session_state.warnings = []
 
 
749
 
750
  # Check installation status
751
  if not is_pdflatex_installed():
@@ -756,7 +1137,7 @@ def main():
756
 
757
  with col1:
758
  # Create tabs for main editing area with VS Code style
759
- editor_tabs = st.tabs(["Editor", "Settings"])
760
 
761
  with editor_tabs[0]:
762
  # VS Code-like editor interface
@@ -765,10 +1146,11 @@ def main():
765
  # Tab bar
766
  render_editor_tabs()
767
 
768
- # Toolbar
769
- render_toolbar()
770
 
771
- # Simple text area with VS Code styling
 
772
  latex_code = st.text_area(
773
  "",
774
  value=st.session_state.latex_code,
@@ -776,6 +1158,7 @@ def main():
776
  key="latex_editor",
777
  label_visibility="collapsed"
778
  )
 
779
  st.session_state.latex_code = latex_code
780
 
781
  # Status bar
@@ -804,6 +1187,14 @@ def main():
804
  st.rerun()
805
 
806
  with editor_tabs[1]:
 
 
 
 
 
 
 
 
807
  st.markdown("<h3>LaTeX Settings</h3>", unsafe_allow_html=True)
808
 
809
  st.markdown('<div class="control-panel">', unsafe_allow_html=True)
@@ -813,6 +1204,7 @@ def main():
813
  st.checkbox("Auto-compile on save", value=False, key="auto_compile")
814
  st.checkbox("Use pdflatex", value=True, key="use_pdflatex")
815
  st.checkbox("Enable BibTeX", value=False, key="use_bibtex")
 
816
 
817
  with col_b:
818
  st.selectbox("Document Class",
@@ -821,12 +1213,18 @@ def main():
821
  st.selectbox("PDF Engine",
822
  ["pdflatex", "xelatex", "lualatex"],
823
  index=0, key="pdf_engine")
 
 
 
824
 
825
  st.markdown('</div>', unsafe_allow_html=True)
 
 
 
826
 
827
  with col2:
828
  # Output tabs with VS Code style
829
- output_tabs = st.tabs(["Output", "Outline", "Problems", "Info"])
830
 
831
  with output_tabs[0]:
832
  # PDF compilation and output
@@ -920,18 +1318,36 @@ def main():
920
  structure = extract_document_structure(st.session_state.latex_code)
921
  else:
922
  structure = []
923
- render_document_outline(structure)
 
 
 
 
924
 
925
  with output_tabs[2]:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
926
  # Problems panel (errors & warnings)
927
  if st.session_state.errors or st.session_state.warnings:
928
  render_problems(st.session_state.errors, st.session_state.warnings)
929
  else:
930
- st.info("No problems detected")
931
-
932
- with output_tabs[3]:
933
- # Document information panel
934
- render_document_info(st.session_state.latex_code)
935
 
936
  if __name__ == "__main__":
937
  main()
 
13
 
14
  # Set page configuration
15
  st.set_page_config(
16
+ page_title="Professional LaTeX Editor",
17
  page_icon="📝",
18
  layout="wide",
19
  initial_sidebar_state="collapsed"
 
109
 
110
  return errors, warnings
111
 
112
+ # Function to extract document structure
113
  def extract_document_structure(latex_code):
114
  structure = []
115
 
 
149
 
150
  return structure
151
 
152
+ # Function to analyze LaTeX packages
153
+ def analyze_packages(latex_code):
154
+ if not isinstance(latex_code, str):
155
+ try:
156
+ latex_code = str(latex_code)
157
+ except:
158
+ return []
159
+
160
+ # Find all package imports
161
+ package_pattern = r'\\usepackage(?:\[.*?\])?\{([^}]+)\}'
162
+ matches = re.finditer(package_pattern, latex_code)
163
+
164
+ packages = []
165
+ for match in matches:
166
+ package_name = match.group(1)
167
+ packages.append(package_name)
168
+
169
+ return packages
170
+
171
+ # Function to find all environments in the document
172
+ def find_environments(latex_code):
173
+ if not isinstance(latex_code, str):
174
+ try:
175
+ latex_code = str(latex_code)
176
+ except:
177
+ return []
178
+
179
+ # Find all environments (begin-end pairs)
180
+ env_pattern = r'\\begin\{([^}]+)\}(.*?)\\end\{\1\}'
181
+ matches = re.finditer(env_pattern, latex_code, re.DOTALL)
182
+
183
+ environments = []
184
+ for match in matches:
185
+ env_name = match.group(1)
186
+ environments.append({
187
+ 'name': env_name,
188
+ 'position': match.start(),
189
+ 'content': match.group(2)
190
+ })
191
+
192
+ return environments
193
+
194
  # Default LaTeX template
195
  default_template = r"""\documentclass{article}
196
  \usepackage[utf8]{inputenc}
 
200
  \usepackage{hyperref}
201
  \usepackage{xcolor}
202
 
203
+ \title{Professional \LaTeX{} Document}
204
  \author{Your Name}
205
  \date{\today}
206
 
 
286
  \end{document}
287
  """
288
 
289
+ # Enhanced VSCode-like advanced styling with syntax highlighting
290
  st.markdown("""
291
  <style>
292
  /* Base theming - VS Code inspired */
 
309
  background-color: #1177bb;
310
  }
311
 
312
+ /* VS Code-like editor - with additional syntax highlighting */
313
+ .editor-area textarea {
314
  font-family: 'Consolas', 'Monaco', 'Courier New', monospace !important;
315
  font-size: 14px !important;
316
  line-height: 1.5 !important;
 
321
  border: 1px solid #252526 !important;
322
  }
323
 
324
+ /* Add a special class for syntax highlighting in the preview */
325
+ .syntax-highlight {
326
+ background-color: #1e1e1e;
327
+ color: #d4d4d4;
328
+ font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
329
+ font-size: 14px;
330
+ padding: 10px;
331
+ border-radius: 4px;
332
+ border: 1px solid #252526;
333
+ white-space: pre-wrap;
334
+ margin-top: 10px;
335
+ overflow-x: auto;
336
+ }
337
+
338
+ /* Syntax highlighting for different LaTeX elements */
339
+ .syntax-highlight .command {
340
+ color: #569cd6; /* Blue for commands */
341
+ }
342
+
343
+ .syntax-highlight .environment {
344
+ color: #4ec9b0; /* Teal for environments */
345
+ }
346
+
347
+ .syntax-highlight .bracket {
348
+ color: #d4d4d4; /* White for brackets */
349
+ }
350
+
351
+ .syntax-highlight .math {
352
+ color: #c586c0; /* Purple for math */
353
+ }
354
+
355
+ .syntax-highlight .comment {
356
+ color: #6a9955; /* Green for comments */
357
+ }
358
+
359
+ .syntax-highlight .package {
360
+ color: #dcdcaa; /* Yellow for package imports */
361
+ }
362
+
363
  /* VS Code-like editor container */
364
  .editor-container {
365
  background-color: #1e1e1e;
 
634
  .info-value {
635
  text-align: right;
636
  }
637
+
638
+ /* Packages panel */
639
+ .packages-panel {
640
+ background-color: #252526;
641
+ border: 1px solid #2d2d2d;
642
+ border-radius: 4px;
643
+ margin-top: 10px;
644
+ padding: 0;
645
+ }
646
+
647
+ .packages-header {
648
+ background-color: #2d2d2d;
649
+ padding: 5px 10px;
650
+ font-weight: bold;
651
+ font-size: 13px;
652
+ }
653
+
654
+ .package-item {
655
+ padding: 5px 10px;
656
+ border-bottom: 1px solid #2d2d2d;
657
+ display: flex;
658
+ align-items: center;
659
+ }
660
+
661
+ .package-name {
662
+ color: #dcdcaa;
663
+ margin-right: 10px;
664
+ font-family: monospace;
665
+ }
666
+
667
+ /* Environment analyzer */
668
+ .environments-panel {
669
+ background-color: #252526;
670
+ border: 1px solid #2d2d2d;
671
+ border-radius: 4px;
672
+ margin-top: 10px;
673
+ padding: 0;
674
+ }
675
+
676
+ .environments-header {
677
+ background-color: #2d2d2d;
678
+ padding: 5px 10px;
679
+ font-weight: bold;
680
+ font-size: 13px;
681
+ }
682
+
683
+ .environment-item {
684
+ padding: 5px 10px;
685
+ border-bottom: 1px solid #2d2d2d;
686
+ }
687
+
688
+ .environment-name {
689
+ color: #4ec9b0;
690
+ font-family: monospace;
691
+ font-weight: bold;
692
+ }
693
+
694
+ /* Syntax highlight code preview */
695
+ .code-preview {
696
+ background-color: #1e1e1e;
697
+ border: 1px solid #2d2d2d;
698
+ border-radius: 4px;
699
+ margin-top: 10px;
700
+ padding: 10px;
701
+ font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
702
+ font-size: 14px;
703
+ line-height: 1.5;
704
+ overflow-x: auto;
705
+ white-space: pre-wrap;
706
+ }
707
+
708
+ /* Custom select styling */
709
+ .stSelectbox [data-baseweb="select"] {
710
+ background-color: #3c3c3c;
711
+ border-color: #3c3c3c;
712
+ }
713
+
714
+ .stSelectbox [data-baseweb="select"] > div {
715
+ color: #cccccc;
716
+ }
717
+
718
+ /* Keyboard shortcuts display */
719
+ .shortcuts-container {
720
+ background-color: #252526;
721
+ border: 1px solid #2d2d2d;
722
+ border-radius: 4px;
723
+ margin-top: 10px;
724
+ padding: 10px;
725
+ }
726
+
727
+ .shortcut-row {
728
+ display: flex;
729
+ justify-content: space-between;
730
+ margin-bottom: 8px;
731
+ border-bottom: 1px solid #333;
732
+ padding-bottom: 8px;
733
+ }
734
+
735
+ .shortcut-keys {
736
+ background-color: #3c3c3c;
737
+ padding: 2px 8px;
738
+ border-radius: 3px;
739
+ font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
740
+ font-size: 12px;
741
+ }
742
+
743
+ .shortcut-description {
744
+ color: #cccccc;
745
+ font-size: 13px;
746
+ }
747
  </style>
748
  """, unsafe_allow_html=True)
749
 
750
+ # Function to create a functional VS Code-like toolbar
751
+ def render_functional_toolbar():
 
 
 
 
 
 
 
 
 
 
 
752
  toolbar_html = """
753
  <div class="toolbar">
754
+ <button class="toolbar-button" title="Bold" onclick="insertAtCursor('\\\\textbf{', '}')">
755
  <strong>B</strong>
756
  </button>
757
+ <button class="toolbar-button" title="Italic" onclick="insertAtCursor('\\\\textit{', '}')">
758
  <em>I</em>
759
  </button>
760
+ <button class="toolbar-button" title="Inline Math" onclick="insertAtCursor('$', '$')">
761
 
762
  </button>
763
  <div class="toolbar-separator"></div>
764
+ <button class="toolbar-button" title="Section" onclick="insertAtCursor('\\\\section{', '}')">
765
  §
766
  </button>
767
+ <button class="toolbar-button" title="Subsection" onclick="insertAtCursor('\\\\subsection{', '}')">
768
  §§
769
  </button>
770
  <div class="toolbar-separator"></div>
771
+ <button class="toolbar-button" title="Itemize" onclick="insertAtCursor('\\\\begin{itemize}\\n \\\\item ', '\\n\\\\end{itemize}')">
772
 
773
  </button>
774
+ <button class="toolbar-button" title="Enumerate" onclick="insertAtCursor('\\\\begin{enumerate}\\n \\\\item ', '\\n\\\\end{enumerate}')">
775
  1.
776
  </button>
777
  <div class="toolbar-separator"></div>
778
+ <button class="toolbar-button" title="Equation" onclick="insertAtCursor('\\\\begin{equation}\\n ', '\\n\\\\end{equation}')">
779
  =
780
  </button>
781
+ <button class="toolbar-button" title="Align" onclick="insertAtCursor('\\\\begin{align}\\n ', '\\n\\\\end{align}')">
782
+
783
+ </button>
784
+ <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}')">
785
  🖼
786
  </button>
787
+ <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}')">
788
 
789
  </button>
790
+ <div class="toolbar-separator"></div>
791
+ <button class="toolbar-button" title="Fraction" onclick="insertAtCursor('\\\\frac{', '}{denominator}')">
792
+
793
+ </button>
794
+ <button class="toolbar-button" title="Square Root" onclick="insertAtCursor('\\\\sqrt{', '}')">
795
+
796
+ </button>
797
+ <button class="toolbar-button" title="Add Package" onclick="insertAtCursor('\\\\usepackage{', '}')">
798
+ 📦
799
+ </button>
800
  </div>
801
+
802
+ <script>
803
+ function insertAtCursor(before, after) {
804
+ // Find the textarea element
805
+ var textarea = document.querySelector('textarea');
806
+ if (!textarea) return;
807
+
808
+ // Get current cursor position
809
+ var startPos = textarea.selectionStart;
810
+ var endPos = textarea.selectionEnd;
811
+
812
+ // Get text before and after selection
813
+ var textBefore = textarea.value.substring(0, startPos);
814
+ var textSelected = textarea.value.substring(startPos, endPos);
815
+ var textAfter = textarea.value.substring(endPos);
816
+
817
+ // Insert the text
818
+ var newText;
819
+ if (textSelected) {
820
+ // If text is selected, wrap it with before and after
821
+ newText = textBefore + before + textSelected + after + textAfter;
822
+ } else {
823
+ // If no text is selected, just insert before and after
824
+ newText = textBefore + before + after + textAfter;
825
+ // Put cursor between before and after
826
+ var newCursorPos = startPos + before.length;
827
+ }
828
+
829
+ // Update textarea value
830
+ textarea.value = newText;
831
+
832
+ // Set selection range to position cursor appropriately
833
+ if (textSelected) {
834
+ // If text was selected, select the wrapped text
835
+ textarea.setSelectionRange(startPos, endPos + before.length + after.length);
836
+ } else {
837
+ // Otherwise position cursor between before and after
838
+ textarea.setSelectionRange(newCursorPos, newCursorPos);
839
+ }
840
+
841
+ // Focus on textarea
842
+ textarea.focus();
843
+
844
+ // Trigger an input event to update Streamlit
845
+ var event = new Event('input', { bubbles: true });
846
+ textarea.dispatchEvent(event);
847
+
848
+ // Trigger change event to update Streamlit session state
849
+ var changeEvent = new Event('change', { bubbles: true });
850
+ textarea.dispatchEvent(changeEvent);
851
+ }
852
+ </script>
853
  """
854
  st.markdown(toolbar_html, unsafe_allow_html=True)
855
 
856
+ # VS Code-style editor tabs
857
+ def render_editor_tabs(active_tab="document.tex"):
858
+ tab_html = f"""
859
+ <div class="tab-bar">
860
+ <div class="tab active">
861
+ <span class="tab-icon">📄</span> {active_tab}
862
+ </div>
863
+ </div>
864
+ """
865
+ st.markdown(tab_html, unsafe_allow_html=True)
866
+
867
  # VS Code-style status bar
868
  def render_status_bar():
869
  status_html = """
 
875
  """
876
  st.markdown(status_html, unsafe_allow_html=True)
877
 
878
+ # Create syntax highlighting for the code preview
879
+ def syntax_highlight_latex(latex_code):
880
+ if not isinstance(latex_code, str):
881
+ try:
882
+ latex_code = str(latex_code)
883
+ except:
884
+ return "<pre>Invalid code</pre>"
885
+
886
+ # Replace special HTML characters
887
+ latex_code = latex_code.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;")
888
+
889
+ # Highlight LaTeX commands (starting with \)
890
+ latex_code = re.sub(r'(\\[a-zA-Z]+)(\{|\[|\s|$)', r'<span class="command">\1</span>\2', latex_code)
891
+
892
+ # Highlight environment tags
893
+ latex_code = re.sub(r'(\\begin\{[^}]+\}|\\end\{[^}]+\})', r'<span class="environment">\1</span>', latex_code)
894
+
895
+ # Highlight math modes
896
+ latex_code = re.sub(r'(\$\$.*?\$\$|\$.*?\$)', r'<span class="math">\1</span>', latex_code)
897
+
898
+ # Highlight comments
899
+ latex_code = re.sub(r'(%.*$)', r'<span class="comment">\1</span>', latex_code)
900
+
901
+ # Highlight package imports
902
+ latex_code = re.sub(r'(\\usepackage(\[.*?\])?\{[^}]+\})', r'<span class="package">\1</span>', latex_code)
903
+
904
+ # Highlight brackets
905
+ latex_code = re.sub(r'(\{|\}|\[|\])', r'<span class="bracket">\1</span>', latex_code)
906
+
907
+ return f'<div class="syntax-highlight">{latex_code}</div>'
908
+
909
+ # Function to display the code with syntax highlighting
910
+ def display_code_with_syntax_highlighting(latex_code):
911
+ highlighted_code = syntax_highlight_latex(latex_code)
912
+ st.markdown(highlighted_code, unsafe_allow_html=True)
913
+
914
  # Render a document outline based on section hierarchy
915
  def render_document_outline(structure):
916
  if not structure:
 
994
 
995
  # Count equations
996
  equation_count = len(re.findall(r'\\begin\{equation', latex_code))
997
+ align_count = len(re.findall(r'\\begin\{align', latex_code))
998
 
999
  # Count figures
1000
  figure_count = len(re.findall(r'\\begin\{figure', latex_code))
 
1002
  # Count tables
1003
  table_count = len(re.findall(r'\\begin\{table', latex_code))
1004
 
1005
+ # Count custom command definitions
1006
+ command_count = len(re.findall(r'\\newcommand', latex_code))
1007
+
1008
+ # Count references
1009
+ ref_count = len(re.findall(r'\\ref\{', latex_code))
1010
+ cite_count = len(re.findall(r'\\cite\{', latex_code))
1011
+
1012
  # Render the info panel
1013
  st.markdown('<div class="document-info">', unsafe_allow_html=True)
1014
 
 
1018
  ("Character Count", char_count),
1019
  ("Line Count", line_count),
1020
  ("Equations", equation_count),
1021
+ ("Align Environments", align_count),
1022
  ("Figures", figure_count),
1023
+ ("Tables", table_count),
1024
+ ("Custom Commands", command_count),
1025
+ ("References", ref_count),
1026
+ ("Citations", cite_count)
1027
  ]
1028
 
1029
  for label, value in info_rows:
 
1037
 
1038
  st.markdown('</div>', unsafe_allow_html=True)
1039
 
1040
+ # Display the packages used in the document
1041
+ def render_packages_panel(packages):
1042
+ if not packages:
1043
+ return
1044
+
1045
+ st.markdown('<div class="packages-panel">', unsafe_allow_html=True)
1046
+ st.markdown('<div class="packages-header">Imported Packages</div>', unsafe_allow_html=True)
1047
+
1048
+ for package in packages:
1049
+ st.markdown(
1050
+ f'<div class="package-item">'
1051
+ f'<span class="package-name">\\usepackage{{{package}}}</span>'
1052
+ f'</div>',
1053
+ unsafe_allow_html=True
1054
+ )
1055
+
1056
+ st.markdown('</div>', unsafe_allow_html=True)
1057
+
1058
+ # Display environments in the document
1059
+ def render_environments_panel(environments):
1060
+ if not environments:
1061
+ return
1062
+
1063
+ st.markdown('<div class="environments-panel">', unsafe_allow_html=True)
1064
+ st.markdown('<div class="environments-header">Environments</div>', unsafe_allow_html=True)
1065
+
1066
+ # Count environment types
1067
+ env_counts = {}
1068
+ for env in environments:
1069
+ env_name = env['name']
1070
+ if env_name in env_counts:
1071
+ env_counts[env_name] += 1
1072
+ else:
1073
+ env_counts[env_name] = 1
1074
+
1075
+ # Display counts
1076
+ for env_name, count in env_counts.items():
1077
+ st.markdown(
1078
+ f'<div class="environment-item">'
1079
+ f'<span class="environment-name">\\begin{{{env_name}}}</span> - {count} instances'
1080
+ f'</div>',
1081
+ unsafe_allow_html=True
1082
+ )
1083
+
1084
+ st.markdown('</div>', unsafe_allow_html=True)
1085
+
1086
+ # Display keyboard shortcuts
1087
+ def render_keyboard_shortcuts():
1088
+ st.markdown('<div class="shortcuts-container">', unsafe_allow_html=True)
1089
+ st.markdown('<div style="font-weight:bold;margin-bottom:10px;">Keyboard Shortcuts</div>', unsafe_allow_html=True)
1090
+
1091
+ shortcuts = [
1092
+ ("Ctrl+B", "Insert bold text"),
1093
+ ("Ctrl+I", "Insert italic text"),
1094
+ ("Ctrl+M", "Insert inline math"),
1095
+ ("Ctrl+E", "Insert equation"),
1096
+ ("Ctrl+L", "Insert list"),
1097
+ ("Ctrl+F", "Insert fraction"),
1098
+ ("F5", "Compile document"),
1099
+ ("Ctrl+S", "Save document"),
1100
+ ("Ctrl+/", "Toggle comment"),
1101
+ ("Tab", "Indent")
1102
+ ]
1103
+
1104
+ for key, description in shortcuts:
1105
+ st.markdown(
1106
+ f'<div class="shortcut-row">'
1107
+ f'<span class="shortcut-keys">{key}</span>'
1108
+ f'<span class="shortcut-description">{description}</span>'
1109
+ f'</div>',
1110
+ unsafe_allow_html=True
1111
+ )
1112
+
1113
+ st.markdown('</div>', unsafe_allow_html=True)
1114
+
1115
  # Main application
1116
  def main():
1117
  # Initialize session state
 
1125
  st.session_state.errors = []
1126
  if 'warnings' not in st.session_state:
1127
  st.session_state.warnings = []
1128
+ if 'show_syntax_highlight' not in st.session_state:
1129
+ st.session_state.show_syntax_highlight = False
1130
 
1131
  # Check installation status
1132
  if not is_pdflatex_installed():
 
1137
 
1138
  with col1:
1139
  # Create tabs for main editing area with VS Code style
1140
+ editor_tabs = st.tabs(["Editor", "Preview", "Settings"])
1141
 
1142
  with editor_tabs[0]:
1143
  # VS Code-like editor interface
 
1146
  # Tab bar
1147
  render_editor_tabs()
1148
 
1149
+ # Toolbar with functional buttons
1150
+ render_functional_toolbar()
1151
 
1152
+ # Editor with VS Code styling
1153
+ st.markdown('<div class="editor-area">', unsafe_allow_html=True)
1154
  latex_code = st.text_area(
1155
  "",
1156
  value=st.session_state.latex_code,
 
1158
  key="latex_editor",
1159
  label_visibility="collapsed"
1160
  )
1161
+ st.markdown('</div>', unsafe_allow_html=True)
1162
  st.session_state.latex_code = latex_code
1163
 
1164
  # Status bar
 
1187
  st.rerun()
1188
 
1189
  with editor_tabs[1]:
1190
+ # Show syntax highlighted preview
1191
+ st.markdown("<h3>Syntax Highlighted Preview</h3>", unsafe_allow_html=True)
1192
+ st.markdown("<p>This shows your LaTeX code with syntax highlighting</p>", unsafe_allow_html=True)
1193
+
1194
+ # Display code with syntax highlighting
1195
+ display_code_with_syntax_highlighting(st.session_state.latex_code)
1196
+
1197
+ with editor_tabs[2]:
1198
  st.markdown("<h3>LaTeX Settings</h3>", unsafe_allow_html=True)
1199
 
1200
  st.markdown('<div class="control-panel">', unsafe_allow_html=True)
 
1204
  st.checkbox("Auto-compile on save", value=False, key="auto_compile")
1205
  st.checkbox("Use pdflatex", value=True, key="use_pdflatex")
1206
  st.checkbox("Enable BibTeX", value=False, key="use_bibtex")
1207
+ st.checkbox("Show line numbers", value=True, key="show_line_numbers")
1208
 
1209
  with col_b:
1210
  st.selectbox("Document Class",
 
1213
  st.selectbox("PDF Engine",
1214
  ["pdflatex", "xelatex", "lualatex"],
1215
  index=0, key="pdf_engine")
1216
+ st.selectbox("Editor Theme",
1217
+ ["Dark", "Light", "High Contrast"],
1218
+ index=0, key="editor_theme")
1219
 
1220
  st.markdown('</div>', unsafe_allow_html=True)
1221
+
1222
+ # Display keyboard shortcuts
1223
+ render_keyboard_shortcuts()
1224
 
1225
  with col2:
1226
  # Output tabs with VS Code style
1227
+ output_tabs = st.tabs(["Output", "Outline", "Analysis", "Problems"])
1228
 
1229
  with output_tabs[0]:
1230
  # PDF compilation and output
 
1318
  structure = extract_document_structure(st.session_state.latex_code)
1319
  else:
1320
  structure = []
1321
+
1322
+ if structure:
1323
+ render_document_outline(structure)
1324
+ else:
1325
+ st.info("No document structure detected. Add sections using the toolbar.")
1326
 
1327
  with output_tabs[2]:
1328
+ # Document analysis features
1329
+
1330
+ # Document info
1331
+ render_document_info(st.session_state.latex_code)
1332
+
1333
+ # Package analysis
1334
+ packages = analyze_packages(st.session_state.latex_code)
1335
+ if packages:
1336
+ render_packages_panel(packages)
1337
+ else:
1338
+ st.info("No packages detected. Add packages using \\usepackage{}.")
1339
+
1340
+ # Environment analysis
1341
+ environments = find_environments(st.session_state.latex_code)
1342
+ if environments:
1343
+ render_environments_panel(environments)
1344
+
1345
+ with output_tabs[3]:
1346
  # Problems panel (errors & warnings)
1347
  if st.session_state.errors or st.session_state.warnings:
1348
  render_problems(st.session_state.errors, st.session_state.warnings)
1349
  else:
1350
+ st.info("No problems detected in the document.")
 
 
 
 
1351
 
1352
  if __name__ == "__main__":
1353
  main()