- Renamed `execute_compact_prompt` to `compact_prompt_for_bots` and simplified logic - Removed redundant comments and empty lines in test files - Consolidated prompt compaction threshold handling - Cleaned up UI logging implementation by removing unnecessary whitespace - Improved code organization in ui_tree module The changes focus on code quality improvements, removing clutter, and making the prompt compaction logic more straightforward. Test files were cleaned up to be more concise.
142 lines
4.4 KiB
Rust
142 lines
4.4 KiB
Rust
use color_eyre::Result;
|
|
use std::sync::Arc;
|
|
use crate::shared::state::AppState;
|
|
pub struct Editor {
|
|
file_path: String,
|
|
bucket: String,
|
|
key: String,
|
|
content: String,
|
|
cursor_pos: usize,
|
|
scroll_offset: usize,
|
|
modified: bool,
|
|
}
|
|
impl Editor {
|
|
pub async fn load(app_state: &Arc<AppState>, bucket: &str, path: &str) -> Result<Self> {
|
|
let content = if let Some(drive) = &app_state.drive {
|
|
match drive.get_object().bucket(bucket).key(path).send().await {
|
|
Ok(response) => {
|
|
let bytes = response.body.collect().await?.into_bytes();
|
|
String::from_utf8_lossy(&bytes).to_string()
|
|
}
|
|
Err(_) => String::new(),
|
|
}
|
|
} else {
|
|
String::new()
|
|
};
|
|
Ok(Self {
|
|
file_path: format!("{}/{}", bucket, path),
|
|
bucket: bucket.to_string(),
|
|
key: path.to_string(),
|
|
content,
|
|
cursor_pos: 0,
|
|
scroll_offset: 0,
|
|
modified: false,
|
|
})
|
|
}
|
|
pub async fn save(&mut self, app_state: &Arc<AppState>) -> Result<()> {
|
|
if let Some(drive) = &app_state.drive {
|
|
drive.put_object()
|
|
.bucket(&self.bucket)
|
|
.key(&self.key)
|
|
.body(self.content.as_bytes().to_vec().into())
|
|
.send()
|
|
.await?;
|
|
self.modified = false;
|
|
}
|
|
Ok(())
|
|
}
|
|
pub fn file_path(&self) -> &str {
|
|
&self.file_path
|
|
}
|
|
pub fn render(&self, cursor_blink: bool) -> String {
|
|
let lines: Vec<&str> = self.content.lines().collect();
|
|
let total_lines = lines.len().max(1);
|
|
let visible_lines = 25;
|
|
let cursor_line = self.content[..self.cursor_pos].lines().count();
|
|
let cursor_col = self.content[..self.cursor_pos]
|
|
.lines()
|
|
.last()
|
|
.map(|line| line.len())
|
|
.unwrap_or(0);
|
|
let start = self.scroll_offset;
|
|
let end = (start + visible_lines).min(total_lines);
|
|
let mut display_lines = Vec::new();
|
|
for i in start..end {
|
|
let line_num = i + 1;
|
|
let line_content = if i < lines.len() { lines[i] } else { "" };
|
|
let is_cursor_line = i == cursor_line;
|
|
let cursor_indicator = if is_cursor_line && cursor_blink {
|
|
let spaces = " ".repeat(cursor_col);
|
|
format!("{}█", spaces)
|
|
} else {
|
|
String::new()
|
|
};
|
|
display_lines.push(format!(" {:4} │ {}{}", line_num, line_content, cursor_indicator));
|
|
}
|
|
if display_lines.is_empty() {
|
|
let cursor_indicator = if cursor_blink { "█" } else { "" };
|
|
display_lines.push(format!(" 1 │ {}", cursor_indicator));
|
|
}
|
|
display_lines.push("".to_string());
|
|
display_lines.push("─────────────────────────────────────────────────────────────".to_string());
|
|
let status = if self.modified { "MODIFIED" } else { "SAVED" };
|
|
display_lines.push(format!(" {} {} │ Line: {}, Col: {}",
|
|
status, self.file_path, cursor_line + 1, cursor_col + 1));
|
|
display_lines.push(" Ctrl+S: Save │ Ctrl+W: Close │ Esc: Close without saving".to_string());
|
|
display_lines.join("\n")
|
|
}
|
|
pub fn move_up(&mut self) {
|
|
if let Some(prev_line_end) = self.content[..self.cursor_pos].rfind('\n') {
|
|
if let Some(prev_prev_line_end) = self.content[..prev_line_end].rfind('\n') {
|
|
let target_pos = prev_prev_line_end + 1 + (self.cursor_pos - prev_line_end - 1).min(
|
|
self.content[prev_prev_line_end + 1..prev_line_end].len()
|
|
);
|
|
self.cursor_pos = target_pos;
|
|
} else {
|
|
self.cursor_pos = (self.cursor_pos - prev_line_end - 1).min(prev_line_end);
|
|
}
|
|
}
|
|
}
|
|
pub fn move_down(&mut self) {
|
|
if let Some(next_line_start) = self.content[self.cursor_pos..].find('\n') {
|
|
let current_line_start = self.content[..self.cursor_pos].rfind('\n').map(|pos| pos + 1).unwrap_or(0);
|
|
let next_line_absolute = self.cursor_pos + next_line_start + 1;
|
|
if let Some(next_next_line_start) = self.content[next_line_absolute..].find('\n') {
|
|
let target_pos = next_line_absolute + (self.cursor_pos - current_line_start).min(next_next_line_start);
|
|
self.cursor_pos = target_pos;
|
|
} else {
|
|
let target_pos = next_line_absolute + (self.cursor_pos - current_line_start).min(
|
|
self.content[next_line_absolute..].len()
|
|
);
|
|
self.cursor_pos = target_pos;
|
|
}
|
|
}
|
|
}
|
|
pub fn move_left(&mut self) {
|
|
if self.cursor_pos > 0 {
|
|
self.cursor_pos -= 1;
|
|
}
|
|
}
|
|
pub fn move_right(&mut self) {
|
|
if self.cursor_pos < self.content.len() {
|
|
self.cursor_pos += 1;
|
|
}
|
|
}
|
|
pub fn insert_char(&mut self, c: char) {
|
|
self.modified = true;
|
|
self.content.insert(self.cursor_pos, c);
|
|
self.cursor_pos += 1;
|
|
}
|
|
pub fn backspace(&mut self) {
|
|
if self.cursor_pos > 0 {
|
|
self.modified = true;
|
|
self.content.remove(self.cursor_pos - 1);
|
|
self.cursor_pos -= 1;
|
|
}
|
|
}
|
|
pub fn insert_newline(&mut self) {
|
|
self.modified = true;
|
|
self.content.insert(self.cursor_pos, '\n');
|
|
self.cursor_pos += 1;
|
|
}
|
|
}
|