mirror of
https://github.com/enso-org/enso.git
synced 2024-12-23 17:03:32 +03:00
Reload externally changed file on a keypress (#7217)
part of #7178 Changelog: - add: `cmd+alt+y` keybinding that re-opens the file, applies new content, and re-executes the program This is the first part of the task to support the external edits. The next step will be to reload the module contents by the notification from the language server. # Important Notes https://github.com/enso-org/enso/assets/357683/79917e22-b846-4bd9-b03a-33a48d5f75b9
This commit is contained in:
parent
70f79b1df4
commit
e7a0312298
@ -380,6 +380,21 @@ impl Handle {
|
||||
}
|
||||
}
|
||||
|
||||
/// Reload the main file and restart the program execution.
|
||||
///
|
||||
/// ### Errors
|
||||
/// - Fails if the project is in read-only mode.
|
||||
pub async fn reload_and_restart(&self) -> FallibleResult {
|
||||
if self.project.read_only() {
|
||||
Err(ReadOnly.into())
|
||||
} else {
|
||||
let model = self.project.main_module_model().await?;
|
||||
model.reopen_externally_changed_file().await?;
|
||||
self.execution_ctx.restart().await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the current call stack frames.
|
||||
pub fn call_stack(&self) -> Vec<LocalCall> {
|
||||
self.execution_ctx.stack_items().collect()
|
||||
|
@ -673,6 +673,9 @@ pub trait API: Debug + model::undo_redo::Aware {
|
||||
|
||||
/// Reopen file in language server.
|
||||
fn reopen_file_in_language_server(&self) -> BoxFuture<FallibleResult>;
|
||||
|
||||
/// Reopen externally changed file.
|
||||
fn reopen_externally_changed_file(&self) -> BoxFuture<FallibleResult>;
|
||||
}
|
||||
|
||||
/// Trait for methods that cannot be defined in `API` because it is a trait object.
|
||||
|
@ -311,6 +311,11 @@ impl model::module::API for Module {
|
||||
info!("Ignoring request for reopening file in the Language Server, because it's not connected");
|
||||
future::ready_boxed(Ok(()))
|
||||
}
|
||||
|
||||
fn reopen_externally_changed_file(&self) -> BoxFuture<FallibleResult> {
|
||||
info!("Ignoring request for reopening externally changed file in the Language Server, because it's not connected");
|
||||
future::ready_boxed(Ok(()))
|
||||
}
|
||||
}
|
||||
|
||||
impl model::undo_redo::Aware for Module {
|
||||
|
@ -206,13 +206,8 @@ impl Module {
|
||||
/// Reopen file in the Language Server.
|
||||
///
|
||||
/// After reopening we update the LS state with the model's current content.
|
||||
pub async fn reopen_file(&self, new_file: SourceFile) -> FallibleResult {
|
||||
let file_path = self.path();
|
||||
info!("Reopening file {file_path}.");
|
||||
if let Err(error) = self.language_server.client.close_text_file(file_path).await {
|
||||
error!("Error while reopening file {file_path}: Closing operation failed: {error} Trying to open the file anyway.");
|
||||
}
|
||||
let opened = self.language_server.client.open_text_file(file_path).await?;
|
||||
pub async fn reopen_file_and_invalidate(&self, new_file: SourceFile) -> FallibleResult {
|
||||
let opened = self.reopen_file().await?;
|
||||
let content = opened.content.into();
|
||||
let summary = ContentSummary::new(&content);
|
||||
|
||||
@ -220,6 +215,18 @@ impl Module {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Reopen file in the Language Server.
|
||||
///
|
||||
/// After reopening we update the model's current content with the LS state.
|
||||
pub async fn reopen_file_and_set_content(&self) -> FallibleResult {
|
||||
let opened = self.reopen_file().await?;
|
||||
let content = opened.content.into();
|
||||
|
||||
self.set_module_content_from_ls(content).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Apply text changes received from the language server.
|
||||
pub async fn apply_text_change_from_ls(&self, edits: Vec<TextEdit>) -> FallibleResult {
|
||||
let mut content: text::Rope = self.serialized_content()?.content.into();
|
||||
@ -260,6 +267,17 @@ impl Module {
|
||||
notify_ls.await;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Reopen file in the Language Server.
|
||||
async fn reopen_file(&self) -> FallibleResult<language_server::response::OpenTextFile> {
|
||||
let file_path = self.path();
|
||||
info!("Reopening file {file_path}.");
|
||||
if let Err(error) = self.language_server.client.close_text_file(file_path).await {
|
||||
error!("Error while reopening file {file_path}: Closing operation failed: {error} Trying to open the file anyway.");
|
||||
}
|
||||
let opened = self.language_server.client.open_text_file(file_path).await?;
|
||||
Ok(opened)
|
||||
}
|
||||
}
|
||||
|
||||
impl API for Module {
|
||||
@ -357,7 +375,11 @@ impl API for Module {
|
||||
|
||||
fn reopen_file_in_language_server(&self) -> BoxFuture<FallibleResult> {
|
||||
let file = self.model.content().borrow().serialize();
|
||||
async { self.reopen_file(file?).await }.boxed_local()
|
||||
async { self.reopen_file_and_invalidate(file?).await }.boxed_local()
|
||||
}
|
||||
|
||||
fn reopen_externally_changed_file(&self) -> BoxFuture<FallibleResult> {
|
||||
async { self.reopen_file_and_set_content().await }.boxed_local()
|
||||
}
|
||||
}
|
||||
|
||||
@ -396,7 +418,9 @@ impl Module {
|
||||
debug!("Handling notification when known LS content is {current_ls_content:?}.");
|
||||
match current_ls_content {
|
||||
LanguageServerContent::Unknown => {
|
||||
if let Err(error) = profiler::await_!(self.reopen_file(new_file), _profiler) {
|
||||
if let Err(error) =
|
||||
profiler::await_!(self.reopen_file_and_invalidate(new_file), _profiler)
|
||||
{
|
||||
error!("Error while reloading module model: {error}");
|
||||
}
|
||||
}
|
||||
|
@ -248,6 +248,15 @@ impl Model {
|
||||
})
|
||||
}
|
||||
|
||||
fn execution_context_reload_and_restart(&self) {
|
||||
let controller = self.graph_controller.clone_ref();
|
||||
executor::global::spawn(async move {
|
||||
if let Err(err) = controller.reload_and_restart().await {
|
||||
error!("Error reloading and restarting execution context: {err}");
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Prepare a list of projects to display in the Open Project dialog.
|
||||
fn project_list_opened(&self, project_list_ready: frp::Source<()>) {
|
||||
let controller = self.ide_controller.clone_ref();
|
||||
@ -374,6 +383,7 @@ impl Project {
|
||||
eval_ view.execution_context_interrupt(model.execution_context_interrupt());
|
||||
|
||||
eval_ view.execution_context_restart(model.execution_context_restart());
|
||||
eval_ view.execution_context_reload_and_restart(model.execution_context_reload_and_restart());
|
||||
|
||||
view.set_read_only <+ view.toggle_read_only.map(f_!(model.toggle_read_only()));
|
||||
eval graph_view.execution_environment((env) model.execution_environment_changed(*env));
|
||||
|
@ -107,6 +107,8 @@ ensogl::define_endpoints! {
|
||||
execution_context_interrupt(),
|
||||
/// Restart the program execution.
|
||||
execution_context_restart(),
|
||||
/// Reload the main module and restart the program execution.
|
||||
execution_context_reload_and_restart(),
|
||||
toggle_read_only(),
|
||||
set_read_only(bool),
|
||||
}
|
||||
@ -759,6 +761,9 @@ impl application::View for View {
|
||||
(Press, "debug_mode", DEBUG_MODE_SHORTCUT, "disable_debug_mode"),
|
||||
(Press, "", "cmd alt t", "execution_context_interrupt"),
|
||||
(Press, "", "cmd alt r", "execution_context_restart"),
|
||||
// TODO(#7178): Remove this temporary shortcut when the modified-on-disk notification
|
||||
// is ready.
|
||||
(Press, "", "cmd alt y", "execution_context_reload_and_restart"),
|
||||
// TODO(#6179): Remove this temporary shortcut when Play button is ready.
|
||||
(Press, "", "ctrl shift b", "toggle_read_only"),
|
||||
]
|
||||
|
Loading…
Reference in New Issue
Block a user