@@ -6,6 +6,7 @@ use gpui::{
AnyView, App, Context, Corner, Entity, EventEmitter, FocusHandle, Focusable, IntoElement,
ParentElement, Render, Styled, Subscription, WeakEntity, Window, actions, div,
};
+use itertools::Itertools;
use language::{LanguageServerId, language_settings::SoftWrap};
use lsp::{
IoKind, LanguageServer, LanguageServerName, MessageType, SetTraceParams, TraceValue,
@@ -20,8 +21,8 @@ use workspace::{
searchable::{Direction, SearchEvent, SearchableItem, SearchableItemHandle},
};
-const SEND_LINE: &str = "// Send:\n";
-const RECEIVE_LINE: &str = "// Receive:\n";
+const SEND_LINE: &str = "\n// Send:";
+const RECEIVE_LINE: &str = "\n// Receive:";
const MAX_STORED_LOG_ENTRIES: usize = 2000;
pub struct LogStore {
@@ -421,7 +422,7 @@ impl LogStore {
log_lines,
id,
LogMessage {
- message: message.trim_end().to_string(),
+ message: message.trim().to_string(),
typ,
},
language_server_state.log_level,
@@ -444,7 +445,7 @@ impl LogStore {
log_lines,
id,
TraceMessage {
- message: message.trim_end().to_string(),
+ message: message.trim().to_string(),
},
(),
LogKind::Trace,
@@ -461,15 +462,15 @@ impl LogStore {
kind: LogKind,
cx: &mut Context<Self>,
) {
- while log_lines.len() >= MAX_STORED_LOG_ENTRIES {
+ while log_lines.len() + 1 >= MAX_STORED_LOG_ENTRIES {
log_lines.pop_front();
}
- let entry = format!("{}\n", message.as_ref().trim());
+ let text = message.as_ref().to_string();
let visible = message.should_include(current_severity);
log_lines.push_back(message);
if visible {
- cx.emit(Event::NewServerLogEntry { id, entry, kind });
+ cx.emit(Event::NewServerLogEntry { id, kind, text });
cx.notify();
}
}
@@ -556,6 +557,9 @@ impl LogStore {
let rpc_log_lines = &mut state.rpc_messages;
if state.last_message_kind != Some(kind) {
+ while rpc_log_lines.len() + 1 >= MAX_STORED_LOG_ENTRIES {
+ rpc_log_lines.pop_front();
+ }
let line_before_message = match kind {
MessageKind::Send => SEND_LINE,
MessageKind::Receive => RECEIVE_LINE,
@@ -565,22 +569,23 @@ impl LogStore {
});
cx.emit(Event::NewServerLogEntry {
id: language_server_id,
- entry: line_before_message.to_string(),
kind: LogKind::Rpc,
+ text: line_before_message.to_string(),
});
}
- while rpc_log_lines.len() >= MAX_STORED_LOG_ENTRIES {
+ while rpc_log_lines.len() + 1 >= MAX_STORED_LOG_ENTRIES {
rpc_log_lines.pop_front();
}
+
let message = message.trim();
rpc_log_lines.push_back(RpcMessage {
message: message.to_string(),
});
cx.emit(Event::NewServerLogEntry {
id: language_server_id,
- entry: format!("{}\n\n", message),
kind: LogKind::Rpc,
+ text: message.to_string(),
});
cx.notify();
Some(())
@@ -634,24 +639,37 @@ impl LspLogView {
&log_store,
window,
move |log_view, _, e, window, cx| match e {
- Event::NewServerLogEntry { id, entry, kind } => {
+ Event::NewServerLogEntry { id, kind, text } => {
if log_view.current_server_id == Some(*id)
&& *kind == log_view.active_entry_kind
{
log_view.editor.update(cx, |editor, cx| {
editor.set_read_only(false);
- let last_point = editor.buffer().read(cx).len(cx);
+ let last_offset = editor.buffer().read(cx).len(cx);
let newest_cursor_is_at_end =
- editor.selections.newest::<usize>(cx).start >= last_point;
- editor.edit(vec![(last_point..last_point, entry.as_str())], cx);
- let entry_length = entry.len();
- if entry_length > 1024 {
- editor.fold_ranges(
- vec![last_point + 1024..last_point + entry_length],
- false,
- window,
- cx,
- );
+ editor.selections.newest::<usize>(cx).start >= last_offset;
+ editor.edit(
+ vec![
+ (last_offset..last_offset, text.as_str()),
+ (last_offset..last_offset, "\n"),
+ ],
+ cx,
+ );
+ if text.len() > 1024 {
+ if let Some((fold_offset, _)) =
+ text.char_indices().dropping(1024).next()
+ {
+ if fold_offset < text.len() {
+ editor.fold_ranges(
+ vec![
+ last_offset + fold_offset..last_offset + text.len(),
+ ],
+ false,
+ window,
+ cx,
+ );
+ }
+ }
}
if newest_cursor_is_at_end {
@@ -997,23 +1015,12 @@ impl LspLogView {
}
}
-fn log_filter<T: Message>(line: &T, cmp: <T as Message>::Level) -> Option<&str> {
- if line.should_include(cmp) {
- Some(line.as_ref())
- } else {
- None
- }
-}
-
-fn log_contents<T: Message>(lines: &VecDeque<T>, cmp: <T as Message>::Level) -> String {
- let (a, b) = lines.as_slices();
- let a = a.iter().filter_map(move |v| log_filter(v, cmp));
- let b = b.iter().filter_map(move |v| log_filter(v, cmp));
- a.chain(b).fold(String::new(), |mut acc, el| {
- acc.push_str(el);
- acc.push('\n');
- acc
- })
+fn log_contents<T: Message>(lines: &VecDeque<T>, level: <T as Message>::Level) -> String {
+ lines
+ .iter()
+ .filter(|message| message.should_include(level))
+ .flat_map(|message| [message.as_ref(), "\n"])
+ .collect()
}
impl Render for LspLogView {
@@ -1597,8 +1604,8 @@ impl LspLogToolbarItemView {
pub enum Event {
NewServerLogEntry {
id: LanguageServerId,
- entry: String,
kind: LogKind,
+ text: String,
},
}