@@ -45,7 +45,7 @@ impl Console {
let mut editor = Editor::multi_line(window, cx);
editor.move_to_end(&editor::actions::MoveToEnd, window, cx);
editor.set_read_only(true);
- editor.set_show_gutter(true, cx);
+ editor.set_show_gutter(false, cx);
editor.set_show_runnables(false, cx);
editor.set_show_breakpoints(false, cx);
editor.set_show_code_actions(false, cx);
@@ -57,6 +57,8 @@ impl Console {
editor.set_show_wrap_guides(false, cx);
editor.set_show_indent_guides(false, cx);
editor.set_show_edit_predictions(Some(false), window, cx);
+ editor.set_use_modal_editing(false);
+ editor.set_soft_wrap_mode(language::language_settings::SoftWrap::EditorWidth, cx);
editor
});
let focus_handle = cx.focus_handle();
@@ -146,6 +148,23 @@ impl Console {
expression
});
+ self.add_messages(
+ [OutputEvent {
+ category: None,
+ output: format!("> {expression}"),
+ group: None,
+ variables_reference: None,
+ source: None,
+ line: None,
+ column: None,
+ data: None,
+ location_reference: None,
+ }]
+ .iter(),
+ window,
+ cx,
+ );
+
self.session.update(cx, |session, cx| {
session
.evaluate(
@@ -160,6 +179,10 @@ impl Console {
}
fn render_console(&self, cx: &Context<Self>) -> impl IntoElement {
+ EditorElement::new(&self.console, self.editor_style(cx))
+ }
+
+ fn editor_style(&self, cx: &Context<Self>) -> EditorStyle {
let settings = ThemeSettings::get_global(cx);
let text_style = TextStyle {
color: if self.console.read(cx).read_only(cx) {
@@ -174,44 +197,16 @@ impl Console {
line_height: relative(settings.buffer_line_height.value()),
..Default::default()
};
-
- EditorElement::new(
- &self.console,
- EditorStyle {
- background: cx.theme().colors().editor_background,
- local_player: cx.theme().players().local(),
- text: text_style,
- ..Default::default()
- },
- )
+ EditorStyle {
+ background: cx.theme().colors().editor_background,
+ local_player: cx.theme().players().local(),
+ text: text_style,
+ ..Default::default()
+ }
}
fn render_query_bar(&self, cx: &Context<Self>) -> impl IntoElement {
- let settings = ThemeSettings::get_global(cx);
- let text_style = TextStyle {
- color: if self.console.read(cx).read_only(cx) {
- cx.theme().colors().text_disabled
- } else {
- cx.theme().colors().text
- },
- font_family: settings.ui_font.family.clone(),
- font_features: settings.ui_font.features.clone(),
- font_fallbacks: settings.ui_font.fallbacks.clone(),
- font_size: TextSize::Editor.rems(cx).into(),
- font_weight: settings.ui_font.weight,
- line_height: relative(1.3),
- ..Default::default()
- };
-
- EditorElement::new(
- &self.query_bar,
- EditorStyle {
- background: cx.theme().colors().editor_background,
- local_player: cx.theme().players().local(),
- text: text_style,
- ..Default::default()
- },
- )
+ EditorElement::new(&self.query_bar, self.editor_style(cx))
}
}
@@ -20,9 +20,7 @@ use dap::{
client::{DebugAdapterClient, SessionId},
messages::{Events, Message},
};
-use dap::{
- EvaluateResponse, ExceptionBreakpointsFilter, ExceptionFilterOptions, OutputEventCategory,
-};
+use dap::{ExceptionBreakpointsFilter, ExceptionFilterOptions, OutputEventCategory};
use futures::channel::oneshot;
use futures::{FutureExt, future::Shared};
use gpui::{
@@ -115,7 +113,7 @@ impl From<dap::Thread> for Thread {
}
}
-enum Mode {
+pub enum Mode {
Building,
Running(LocalMode),
}
@@ -127,6 +125,7 @@ pub struct LocalMode {
pub(crate) breakpoint_store: Entity<BreakpointStore>,
tmp_breakpoint: Option<SourceBreakpoint>,
worktree: WeakEntity<Worktree>,
+ executor: BackgroundExecutor,
}
fn client_source(abs_path: &Path) -> dap::Source {
@@ -179,6 +178,7 @@ impl LocalMode {
worktree,
tmp_breakpoint: None,
binary,
+ executor: cx.background_executor().clone(),
})
}
@@ -190,14 +190,11 @@ impl LocalMode {
let tasks: Vec<_> = paths
.into_iter()
.map(|path| {
- self.request(
- dap_command::SetBreakpoints {
- source: client_source(path),
- source_modified: None,
- breakpoints: vec![],
- },
- cx.background_executor().clone(),
- )
+ self.request(dap_command::SetBreakpoints {
+ source: client_source(path),
+ source_modified: None,
+ breakpoints: vec![],
+ })
})
.collect();
@@ -229,14 +226,11 @@ impl LocalMode {
.map(Into::into)
.collect();
- let task = self.request(
- dap_command::SetBreakpoints {
- source: client_source(&abs_path),
- source_modified: Some(matches!(reason, BreakpointUpdatedReason::FileSaved)),
- breakpoints,
- },
- cx.background_executor().clone(),
- );
+ let task = self.request(dap_command::SetBreakpoints {
+ source: client_source(&abs_path),
+ source_modified: Some(matches!(reason, BreakpointUpdatedReason::FileSaved)),
+ breakpoints,
+ });
cx.background_spawn(async move {
match task.await {
@@ -250,7 +244,6 @@ impl LocalMode {
&self,
filters: Vec<ExceptionBreakpointsFilter>,
supports_filter_options: bool,
- cx: &App,
) -> Task<Result<Vec<dap::Breakpoint>>> {
let arg = if supports_filter_options {
SetExceptionBreakpoints::WithOptions {
@@ -268,7 +261,7 @@ impl LocalMode {
filters: filters.into_iter().map(|filter| filter.filter).collect(),
}
};
- self.request(arg, cx.background_executor().clone())
+ self.request(arg)
}
fn send_source_breakpoints(
@@ -293,14 +286,11 @@ impl LocalMode {
};
breakpoint_tasks.push(
- self.request(
- dap_command::SetBreakpoints {
- source: client_source(&path),
- source_modified: Some(false),
- breakpoints,
- },
- cx.background_executor().clone(),
- )
+ self.request(dap_command::SetBreakpoints {
+ source: client_source(&path),
+ source_modified: Some(false),
+ breakpoints,
+ })
.map(|result| result.map_err(|e| (path, e))),
);
}
@@ -331,18 +321,12 @@ impl LocalMode {
// Of relevance: https://github.com/microsoft/vscode/issues/4902#issuecomment-368583522
let launch = match raw.request {
- dap::StartDebuggingRequestArgumentsRequest::Launch => self.request(
- Launch {
- raw: raw.configuration,
- },
- cx.background_executor().clone(),
- ),
- dap::StartDebuggingRequestArgumentsRequest::Attach => self.request(
- Attach {
- raw: raw.configuration,
- },
- cx.background_executor().clone(),
- ),
+ dap::StartDebuggingRequestArgumentsRequest::Launch => self.request(Launch {
+ raw: raw.configuration,
+ }),
+ dap::StartDebuggingRequestArgumentsRequest::Attach => self.request(Attach {
+ raw: raw.configuration,
+ }),
};
let configuration_done_supported = ConfigurationDone::is_supported(capabilities);
@@ -396,17 +380,11 @@ impl LocalMode {
}
})?;
- cx.update(|cx| {
- this.send_exception_breakpoints(
- exception_filters,
- supports_exception_filters,
- cx,
- )
- })?
- .await
- .ok();
+ this.send_exception_breakpoints(exception_filters, supports_exception_filters)
+ .await
+ .ok();
let ret = if configuration_done_supported {
- this.request(ConfigurationDone {}, cx.background_executor().clone())
+ this.request(ConfigurationDone {})
} else {
Task::ready(Ok(()))
}
@@ -421,11 +399,7 @@ impl LocalMode {
})
}
- fn request<R: LocalDapCommand>(
- &self,
- request: R,
- executor: BackgroundExecutor,
- ) -> Task<Result<R::Response>>
+ fn request<R: LocalDapCommand>(&self, request: R) -> Task<Result<R::Response>>
where
<R::DapRequest as dap::requests::Request>::Response: 'static,
<R::DapRequest as dap::requests::Request>::Arguments: 'static + Send,
@@ -434,32 +408,22 @@ impl LocalMode {
let request_clone = request.clone();
let connection = self.client.clone();
- let request_task = executor.spawn(async move {
+ self.executor.spawn(async move {
let args = request_clone.to_dap();
- connection.request::<R::DapRequest>(args).await
- });
-
- executor.spawn(async move {
- let response = request.response_from_dap(request_task.await?);
- response
+ let response = connection.request::<R::DapRequest>(args).await?;
+ request.response_from_dap(response)
})
}
}
impl Mode {
- fn request_dap<R: DapCommand>(
- &self,
- request: R,
- cx: &mut Context<Session>,
- ) -> Task<Result<R::Response>>
+ pub(super) fn request_dap<R: DapCommand>(&self, request: R) -> Task<Result<R::Response>>
where
<R::DapRequest as dap::requests::Request>::Response: 'static,
<R::DapRequest as dap::requests::Request>::Arguments: 'static + Send,
{
match self {
- Mode::Running(debug_adapter_client) => {
- debug_adapter_client.request(request, cx.background_executor().clone())
- }
+ Mode::Running(debug_adapter_client) => debug_adapter_client.request(request),
Mode::Building => Task::ready(Err(anyhow!(
"no adapter running to send request: {:?}",
request
@@ -539,7 +503,7 @@ type IsEnabled = bool;
pub struct OutputToken(pub usize);
/// Represents a current state of a single debug adapter and provides ways to mutate it.
pub struct Session {
- mode: Mode,
+ pub mode: Mode,
definition: DebugTaskDefinition,
pub(super) capabilities: Capabilities,
id: SessionId,
@@ -871,7 +835,7 @@ impl Session {
let request = Initialize { adapter_id };
match &self.mode {
Mode::Running(local_mode) => {
- let capabilities = local_mode.request(request, cx.background_executor().clone());
+ let capabilities = local_mode.request(request);
cx.spawn(async move |this, cx| {
let capabilities = capabilities.await?;
@@ -1196,6 +1160,17 @@ impl Session {
}
}
+ pub async fn request2<T: DapCommand + PartialEq + Eq + Hash>(
+ &self,
+ request: T,
+ ) -> Result<T::Response> {
+ if !T::is_supported(&self.capabilities) {
+ anyhow::bail!("DAP request {:?} is not supported", request);
+ }
+
+ self.mode.request_dap(request).await
+ }
+
fn request_inner<T: DapCommand + PartialEq + Eq + Hash>(
capabilities: &Capabilities,
mode: &Mode,
@@ -1223,7 +1198,7 @@ impl Session {
});
}
- let request = mode.request_dap(request, cx);
+ let request = mode.request_dap(request);
cx.spawn(async move |this, cx| {
let result = request.await;
this.update(cx, |this, cx| process_result(this, result, cx))
@@ -1377,7 +1352,7 @@ impl Session {
.supports_exception_filter_options
.unwrap_or_default();
local
- .send_exception_breakpoints(exception_filters, supports_exception_filters, cx)
+ .send_exception_breakpoints(exception_filters, supports_exception_filters)
.detach_and_log_err(cx);
} else {
debug_assert!(false, "Not implemented");
@@ -1878,35 +1853,51 @@ impl Session {
frame_id: Option<u64>,
source: Option<Source>,
cx: &mut Context<Self>,
- ) -> Task<Option<EvaluateResponse>> {
- self.request(
- EvaluateCommand {
- expression,
- context,
- frame_id,
- source,
- },
- |this, response, cx| {
- let response = response.log_err()?;
- this.output_token.0 += 1;
- this.output.push_back(dap::OutputEvent {
- category: None,
- output: response.result.clone(),
- group: None,
- variables_reference: Some(response.variables_reference),
- source: None,
- line: None,
- column: None,
- data: None,
- location_reference: None,
- });
-
+ ) -> Task<()> {
+ let request = self.mode.request_dap(EvaluateCommand {
+ expression,
+ context,
+ frame_id,
+ source,
+ });
+ cx.spawn(async move |this, cx| {
+ let response = request.await;
+ this.update(cx, |this, cx| {
+ match response {
+ Ok(response) => {
+ this.output_token.0 += 1;
+ this.output.push_back(dap::OutputEvent {
+ category: None,
+ output: format!("< {}", &response.result),
+ group: None,
+ variables_reference: Some(response.variables_reference),
+ source: None,
+ line: None,
+ column: None,
+ data: None,
+ location_reference: None,
+ });
+ }
+ Err(e) => {
+ this.output_token.0 += 1;
+ this.output.push_back(dap::OutputEvent {
+ category: None,
+ output: format!("{}", e),
+ group: None,
+ variables_reference: None,
+ source: None,
+ line: None,
+ column: None,
+ data: None,
+ location_reference: None,
+ });
+ }
+ };
this.invalidate_command_type::<ScopesCommand>();
cx.notify();
- Some(response)
- },
- cx,
- )
+ })
+ .ok();
+ })
}
pub fn location(