Skip to content

Commit

Permalink
✨ Add syntax highlighting. I think I broke like everything else in th…
Browse files Browse the repository at this point in the history
…e process though

Please help me
  • Loading branch information
darkdarcool committed Feb 13, 2024
1 parent a04b1a2 commit e515c11
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 15 deletions.
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,5 @@ futures = "0.3.30"
homedir = "0.2.1"
repair_json = "0.1.0"
oxc_allocator = "0.7.0"
syntect = "5.0"
crossterm = "0.27.0"
72 changes: 60 additions & 12 deletions src/copilot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,17 @@ use crate::{
gh,
headers::{CopilotCompletionHeaders, Headers},
utils,
term
};

use futures::StreamExt;
use reqwest::Client;
use serde::{Deserialize, Serialize};
use serde_json::json;

// crossterm for writing


#[derive(Serialize, Deserialize, Debug)]
struct ContentFilterResult {
filtered: bool,
Expand Down Expand Up @@ -72,6 +77,7 @@ pub struct CopilotManager<'a, 'alloc> {
client: &'a Client,
allocator: &'alloc oxc_allocator::Allocator,
history: Vec<Message<'alloc>>,
full_message: String,
}

impl<'a, 'alloc> CopilotManager<'a, 'alloc> {
Expand Down Expand Up @@ -101,9 +107,11 @@ impl<'a, 'alloc> CopilotManager<'a, 'alloc> {
client,
allocator,
history,
full_message: String::new(),
}
}

#[allow(unused_assignments)]
pub async fn ask(&mut self, prompt: &String, log: bool) -> Completion {
let url = "https://api.githubcopilot.com/chat/completions";
let headers = CopilotCompletionHeaders {
Expand All @@ -113,12 +121,18 @@ impl<'a, 'alloc> CopilotManager<'a, 'alloc> {
}
.to_headers();

let history = &mut self.history;
let mut transport_history = Vec::new();

history.push(Message {
content: self.allocator.alloc_str(prompt),
role: self.allocator.alloc_str("user"),
});
{
let history = &mut self.history;

history.push(Message {
content: self.allocator.alloc_str(prompt),
role: self.allocator.alloc_str("user"),
});

transport_history = history.clone();
}

// no chat history for this
let data = json!({
Expand All @@ -128,7 +142,7 @@ impl<'a, 'alloc> CopilotManager<'a, 'alloc> {
"stream": true,
"temperature": 0.1,
"top_p": 1,
"messages": history
"messages": transport_history
});

// we need to stream the response
Expand Down Expand Up @@ -181,8 +195,9 @@ impl<'a, 'alloc> CopilotManager<'a, 'alloc> {
// There might be content in the delta, let's handle it
let delta = &choice.delta;
if let Some(content) = &delta.content {
print!("{}", content);
std::io::stdout().flush().unwrap();
if log {
self.handle_content(content).await;
}//std::io::stdout().flush().unwrap();
message.push_str(content);
}
}
Expand All @@ -203,14 +218,47 @@ impl<'a, 'alloc> CopilotManager<'a, 'alloc> {
}

// add the response to the history
history.push(Message {
content: self.allocator.alloc_str(&message),
role: self.allocator.alloc_str("system"),
});
{
let history = &mut self.history;

history.push(Message {
content: self.allocator.alloc_str(&message),
role: self.allocator.alloc_str("system"),
});
}

self.full_message = String::new();

Completion {
content: message,
finish_reason,
}
}

async fn handle_content(&mut self, content: &String) {
// tokio sleep for 10 ms
// tokio::time::sleep(tokio::time::Duration::from_millis(10)).await;

self.full_message.push_str(content);
let line_count = self.full_message.split("\n").count();

if self.full_message.ends_with("\n") {
let highlighted = term::highlight_line(&self.full_message);
let escaped: Vec<String> = term::to_terminal_escaped(&highlighted)
.split("\n")
.filter(|s| !s.is_empty())
.map(|s| s.to_string())
.collect();

let mut escaped_len = escaped.len();
while line_count > escaped_len {
print!("\n");
escaped_len += 1;
}

print!("{}", escaped.last().unwrap());
std::io::stdout().flush().unwrap();
// self.full_message = String::new();
}
}
}
29 changes: 26 additions & 3 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,27 @@ mod headers;
mod prompts;
mod urls;
mod utils;
mod term;

use crossterm::{
execute,
terminal::{EnterAlternateScreen, LeaveAlternateScreen},
};
use std::io::{stdout, Write};

use oxc_allocator;
use rustyline::DefaultEditor;

fn move_up_one_line() {
print!("\x1b[1A");
std::io::stdout().flush().unwrap();
}

#[tokio::main]
async fn main() {
// enter alternate screen
execute!(stdout(), EnterAlternateScreen).unwrap();

let auth_manager = gh::AuthenticationManager::new();
let auth = auth_manager.cache_auth().await.unwrap();

Expand All @@ -24,13 +39,21 @@ async fn main() {
loop {
let input = rl.readline("You: ").unwrap();

move_up_one_line();

if input == "exit" {
break;
}

let msg = copilot_m.ask(&input, true).await;
let _msg = copilot_m.ask(&input, true).await;
// reset the forground color
print!("\033[0m");
// syntax highlighting
// let highlighted = term::highlight_text(&msg.content);
// println!("{}", highlighted);

println!("===COPILOT===");
println!("{:#?}", msg);
}

// leave alternate screen
execute!(stdout(), LeaveAlternateScreen).unwrap();
}
19 changes: 19 additions & 0 deletions src/term.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
use syntect::{self, highlighting::Style};

pub fn highlight_line(text: &String) -> Vec<(Style, &str)> {
// using syntect, apply markdown syntax highlighting to the text
let syntax_set = syntect::parsing::SyntaxSet::load_defaults_newlines();
let syntax = syntax_set.find_syntax_by_extension("md").unwrap();
let h = syntect::highlighting::ThemeSet::load_defaults();
let mut highlighter = syntect::easy::HighlightLines::new(syntax, &h.themes["base16-mocha.dark"]);

let highlighted = highlighter.highlight_line(text, &syntax_set).unwrap();
// let escaped = syntect::util::as_24_bit_terminal_escaped(&highlighted, false);
highlighted
}

pub fn to_terminal_escaped(highlighted: &Vec<(Style, &str)>) -> String {
// convert the highlighted text to a string with terminal escape sequences
let escaped = syntect::util::as_24_bit_terminal_escaped(highlighted, false);
escaped
}

0 comments on commit e515c11

Please sign in to comment.