Spaces:
Running
Running
File size: 4,853 Bytes
77bf0e5 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 |
"""
Code Viewer Component - Displays file content with syntax highlighting.
"""
import streamlit as st
from pathlib import Path
from pygments import highlight
from pygments.lexers import get_lexer_for_filename, TextLexer
from pygments.formatters import HtmlFormatter
from typing import Optional
def get_language_from_extension(filename: str) -> str:
"""Get language name from file extension for display."""
ext = Path(filename).suffix.lower()
languages = {
".py": "Python",
".js": "JavaScript",
".ts": "TypeScript",
".jsx": "React JSX",
".tsx": "React TSX",
".html": "HTML",
".css": "CSS",
".json": "JSON",
".md": "Markdown",
".yaml": "YAML",
".yml": "YAML",
".toml": "TOML",
".sql": "SQL",
".sh": "Shell",
".bash": "Bash",
".txt": "Plain Text",
}
return languages.get(ext, "Code")
def read_file_content(file_path: str) -> Optional[str]:
"""Read and return file content."""
try:
with open(file_path, 'r', encoding='utf-8', errors='ignore') as f:
return f.read()
except Exception as e:
return f"Error reading file: {e}"
def render_code_with_syntax_highlighting(content: str, filename: str):
"""Render code with Pygments syntax highlighting."""
try:
lexer = get_lexer_for_filename(filename)
except:
lexer = TextLexer()
# Custom CSS for dark theme
formatter = HtmlFormatter(
style='monokai',
linenos=True,
lineanchors='line',
cssclass='source',
wrapcode=True
)
highlighted = highlight(content, lexer, formatter)
# Custom CSS
css = """
<style>
.source {
background-color: #1E1E1E !important;
padding: 10px;
border-radius: 8px;
overflow-x: auto;
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
font-size: 13px;
line-height: 1.5;
}
.source pre {
margin: 0;
background-color: transparent !important;
}
.source .linenos {
color: #6e7681;
padding-right: 15px;
border-right: 1px solid #3d3d3d;
margin-right: 15px;
user-select: none;
}
.source .code {
color: #e6e6e6;
}
</style>
"""
st.markdown(css + highlighted, unsafe_allow_html=True)
def render_code_viewer(file_path: Optional[str] = None):
"""
Render the code viewer panel.
Args:
file_path: Path to the file to display
"""
if not file_path:
# Show placeholder when no file is selected
st.markdown("### π Code Viewer")
st.info("π Select a file from the tree to view its contents")
return
# File header
filename = Path(file_path).name
language = get_language_from_extension(filename)
st.markdown(f"### π {filename}")
st.caption(f"π {file_path} β’ {language}")
# Read and display content
content = read_file_content(file_path)
if content:
# Add line count
line_count = content.count('\n') + 1
st.caption(f"{line_count} lines")
# Render with syntax highlighting
render_code_with_syntax_highlighting(content, filename)
else:
st.error("Could not read file contents")
def render_code_viewer_simple(file_path: Optional[str] = None):
"""
Simpler code viewer using Streamlit's built-in code component.
More reliable than custom HTML rendering.
"""
if not file_path:
st.markdown("### π Code Viewer")
st.info("π Select a file from the tree to view its contents")
return
filename = Path(file_path).name
language = get_language_from_extension(filename)
ext = Path(filename).suffix.lower().lstrip('.')
st.markdown(f"### π {filename}")
st.caption(f"π `{file_path}` β’ {language}")
content = read_file_content(file_path)
if content:
line_count = content.count('\n') + 1
st.caption(f"{line_count} lines")
# Use Streamlit's native code component
# Map extensions to language names for st.code
lang_map = {
"py": "python",
"js": "javascript",
"ts": "typescript",
"jsx": "javascript",
"tsx": "typescript",
"json": "json",
"md": "markdown",
"yaml": "yaml",
"yml": "yaml",
"sh": "bash",
"bash": "bash",
"sql": "sql",
"html": "html",
"css": "css",
}
lang = lang_map.get(ext, "")
st.code(content, language=lang, line_numbers=True)
else:
st.error("Could not read file contents")
|