-
Notifications
You must be signed in to change notification settings - Fork 326
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Show Visualisation Preview when Selecting Item on Searcher #3691
Changes from all commits
b09c6ae
c200c14
0853b27
33bd774
3afd1ca
4a8935e
c85e8ac
2794f3f
0c6151f
6babdff
27651d0
e13d48f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -49,6 +49,7 @@ pub const ASSIGN_NAMES_FOR_NODES: bool = true; | |
const ENSO_PROJECT_SPECIAL_MODULE: &str = | ||
concatcp!(project::STANDARD_BASE_LIBRARY_PATH, ".Enso_Project"); | ||
|
||
const MINIMUM_PATTERN_OFFSET: usize = 1; | ||
|
||
|
||
// ============== | ||
|
@@ -606,7 +607,7 @@ impl Searcher { | |
/// in a new action list (the appropriate notification will be emitted). | ||
#[profile(Debug)] | ||
pub fn set_input(&self, new_input: String) -> FallibleResult { | ||
tracing::debug!("Manually setting input to {}.", new_input); | ||
tracing::debug!("Manually setting input to {new_input}."); | ||
let parsed_input = ParsedInput::new(new_input, self.ide.parser())?; | ||
let old_expr = self.data.borrow().input.expression.repr(); | ||
let new_expr = parsed_input.expression.repr(); | ||
|
@@ -648,37 +649,48 @@ impl Searcher { | |
/// searcher's input will be updated and returned by this function. | ||
#[profile(Debug)] | ||
pub fn use_suggestion(&self, picked_suggestion: action::Suggestion) -> FallibleResult<String> { | ||
tracing::info!("Picking suggestion: {:?}", picked_suggestion); | ||
tracing::info!("Picking suggestion: {picked_suggestion:?}."); | ||
let id = self.data.borrow().input.next_completion_id(); | ||
let picked_completion = FragmentAddedByPickingSuggestion { id, picked_suggestion }; | ||
let code_to_insert = self.code_to_insert(&picked_completion).code; | ||
tracing::debug!("Code to insert: \"{}\"", code_to_insert); | ||
tracing::debug!("Code to insert: \"{code_to_insert}\""); | ||
let added_ast = self.ide.parser().parse_line_ast(&code_to_insert)?; | ||
let pattern_offset = self.data.borrow().input.pattern_offset; | ||
let new_expression = match self.data.borrow_mut().input.expression.take() { | ||
let new_expression_chain = self.create_new_expression_chain(added_ast, pattern_offset); | ||
let new_parsed_input = ParsedInput { | ||
expression: Some(new_expression_chain), | ||
pattern_offset: 1, | ||
pattern: "".to_string(), | ||
}; | ||
let new_input = new_parsed_input.repr(); | ||
self.data.borrow_mut().input = new_parsed_input; | ||
self.data.borrow_mut().fragments_added_by_picking.push(picked_completion); | ||
self.reload_list(); | ||
Ok(new_input) | ||
} | ||
|
||
fn create_new_expression_chain( | ||
&self, | ||
added_ast: Ast, | ||
pattern_offset: usize, | ||
) -> ast::Shifted<ast::prefix::Chain> { | ||
match self.data.borrow_mut().input.expression.take() { | ||
None => { | ||
let ast = ast::prefix::Chain::from_ast_non_strict(&added_ast); | ||
ast::Shifted::new(pattern_offset, ast) | ||
} | ||
Some(mut expression) => { | ||
let new_argument = ast::prefix::Argument { | ||
sast: ast::Shifted::new(pattern_offset.max(1), added_ast), | ||
sast: ast::Shifted::new( | ||
pattern_offset.max(MINIMUM_PATTERN_OFFSET), | ||
added_ast, | ||
Comment on lines
+684
to
+686
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. export to var to make it shorter. |
||
), | ||
prefix_id: default(), | ||
}; | ||
expression.args.push(new_argument); | ||
expression | ||
} | ||
}; | ||
let new_parsed_input = ParsedInput { | ||
expression: Some(new_expression), | ||
pattern_offset: 1, | ||
pattern: "".to_string(), | ||
}; | ||
let new_input = new_parsed_input.repr(); | ||
self.data.borrow_mut().input = new_parsed_input; | ||
self.data.borrow_mut().fragments_added_by_picking.push(picked_completion); | ||
self.reload_list(); | ||
Ok(new_input) | ||
} | ||
} | ||
|
||
/// Use action at given index as a suggestion. The exact outcome depends on the action's type. | ||
|
@@ -696,15 +708,43 @@ impl Searcher { | |
} | ||
|
||
/// Preview the suggestion in the searcher. | ||
pub fn preview_entry_as_suggestion(&self, index: usize) { | ||
tracing::debug!("Previewing entry: {:?}", index); | ||
//TODO[MM] the actual functionality here will be implemented as part of task #182634050. | ||
pub fn preview_entry_as_suggestion(&self, index: usize) -> FallibleResult { | ||
tracing::debug!("Previewing entry: {index:?}."); | ||
let error = || NoSuchAction { index }; | ||
let suggestion = { | ||
let data = self.data.borrow(); | ||
let list = data.actions.list().ok_or_else(error)?; | ||
list.get_cloned(index).ok_or_else(error)?.action | ||
}; | ||
if let Action::Suggestion(picked_suggestion) = suggestion { | ||
self.preview_suggestion(picked_suggestion)?; | ||
}; | ||
|
||
Ok(()) | ||
} | ||
|
||
/// Use action at given index as a suggestion. The exact outcome depends on the action's type. | ||
pub fn preview_suggestion(&self, selected_suggestion: action::Suggestion) { | ||
//TODO[MM] the actual functionality here will be implemented as part of task #182634050. | ||
tracing::debug!("Previewing suggestion: {:?}", selected_suggestion); | ||
pub fn preview_suggestion(&self, picked_suggestion: action::Suggestion) -> FallibleResult { | ||
tracing::debug!("Previewing suggestion: \"{picked_suggestion:?}\"."); | ||
|
||
let id = self.data.borrow().input.next_completion_id(); | ||
let picked_completion = FragmentAddedByPickingSuggestion { id, picked_suggestion }; | ||
let code_to_insert = self.code_to_insert(&picked_completion).code; | ||
tracing::debug!("Code to insert: \"{code_to_insert}\".",); | ||
let added_ast = self.ide.parser().parse_line_ast(&code_to_insert)?; | ||
let pattern_offset = self.data.borrow().input.pattern_offset; | ||
let new_expression_chain = self.create_new_expression_chain(added_ast, pattern_offset); | ||
let expression = self.get_expression(Some(new_expression_chain)); | ||
let intended_method = self.intended_method(); | ||
|
||
self.graph.graph().module.with_node_metadata( | ||
self.mode.node_id(), | ||
Box::new(|md| md.intended_method = intended_method), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just to make sure: is this restored after editing aborting? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Now it is. |
||
)?; | ||
tracing::debug!("Previewing expression: \"{:?}\".", expression); | ||
self.graph.graph().set_expression(self.mode.node_id(), expression)?; | ||
|
||
Ok(()) | ||
} | ||
|
||
/// Execute given action. | ||
|
@@ -775,7 +815,7 @@ impl Searcher { | |
let list = data.actions.list().ok_or_else(error)?; | ||
list.get_cloned(index).ok_or_else(error)?.action | ||
}; | ||
tracing::debug!("Previewing action: {:?}", action); | ||
tracing::debug!("Previewing action: {action:?}"); | ||
Ok(()) | ||
} | ||
|
||
|
@@ -804,24 +844,15 @@ impl Searcher { | |
if let Some(guard) = self.node_edit_guard.deref().as_ref() { | ||
guard.prevent_revert() | ||
} | ||
let expr_and_method = || { | ||
let input_chain = self.data.borrow().input.as_prefix_chain(self.ide.parser()); | ||
|
||
let expression = match (self.this_var(), input_chain) { | ||
(Some(this_var), Some(input)) => | ||
apply_this_argument(this_var, &input.wrapped.into_ast()).repr(), | ||
(None, Some(input)) => input.wrapped.into_ast().repr(), | ||
(_, None) => "".to_owned(), | ||
}; | ||
let intended_method = self.intended_method(); | ||
(expression, intended_method) | ||
}; | ||
|
||
let node_id = self.mode.node_id(); | ||
// We add the required imports before we edit its content. This way, we avoid an | ||
// intermediate state where imports would already be in use but not yet available. | ||
self.add_required_imports()?; | ||
let (expression, intended_method) = expr_and_method(); | ||
|
||
let node_id = self.mode.node_id(); | ||
let input_chain = self.data.borrow().input.as_prefix_chain(self.ide.parser()); | ||
let expression = self.get_expression(input_chain); | ||
let intended_method = self.intended_method(); | ||
self.graph.graph().set_expression(node_id, expression)?; | ||
if let Mode::NewNode { .. } = self.mode.as_ref() { | ||
self.graph.graph().introduce_name_on(node_id)?; | ||
|
@@ -837,6 +868,16 @@ impl Searcher { | |
Ok(node_id) | ||
} | ||
|
||
fn get_expression(&self, input_chain: Option<ast::Shifted<ast::prefix::Chain>>) -> String { | ||
let expression = match (self.this_var(), input_chain) { | ||
(Some(this_var), Some(input)) => | ||
apply_this_argument(this_var, &input.wrapped.into_ast()).repr(), | ||
(None, Some(input)) => input.wrapped.into_ast().repr(), | ||
(_, None) => "".to_owned(), | ||
}; | ||
expression | ||
} | ||
|
||
/// Adds an example to the graph. | ||
/// | ||
/// The example piece of code will be inserted as a new function definition, and in current | ||
|
@@ -1268,7 +1309,11 @@ impl EditGuard { | |
module.with_node_metadata( | ||
self.node_id, | ||
Box::new(|metadata| { | ||
metadata.edit_status = Some(NodeEditStatus::Edited { previous_expression }); | ||
let previous_intended_method = metadata.intended_method.clone(); | ||
metadata.edit_status = Some(NodeEditStatus::Edited { | ||
previous_expression, | ||
previous_intended_method, | ||
}); | ||
}), | ||
) | ||
} | ||
|
@@ -1311,14 +1356,21 @@ impl EditGuard { | |
tracing::debug!("Deleting temporary node {} after aborting edit.", self.node_id); | ||
self.graph.graph().remove_node(self.node_id)?; | ||
} | ||
Some(NodeEditStatus::Edited { previous_expression }) => { | ||
Some(NodeEditStatus::Edited { previous_expression, previous_intended_method }) => { | ||
tracing::debug!( | ||
"Reverting expression of node {} to {} after aborting edit.", | ||
self.node_id, | ||
&previous_expression | ||
); | ||
let graph = self.graph.graph(); | ||
graph.set_expression(self.node_id, previous_expression)?; | ||
let module = &self.graph.graph().module; | ||
module.with_node_metadata( | ||
self.node_id, | ||
Box::new(|metadata| { | ||
metadata.intended_method = previous_intended_method; | ||
}), | ||
)?; | ||
} | ||
}; | ||
Ok(()) | ||
|
@@ -1330,8 +1382,7 @@ impl Drop for EditGuard { | |
if self.revert_expression.get() { | ||
self.revert_node_expression_edit().unwrap_or_else(|e| { | ||
tracing::error!( | ||
"Failed to revert node edit after editing ended because of an error: {}", | ||
e | ||
"Failed to revert node edit after editing ended because of an error: {e}" | ||
) | ||
}); | ||
} else { | ||
|
@@ -1340,8 +1391,7 @@ impl Drop for EditGuard { | |
if self.graph.graph().node_exists(self.node_id) { | ||
self.clear_node_edit_metadata().unwrap_or_else(|e| { | ||
tracing::error!( | ||
"Failed to clear node edit metadata after editing ended because of an error: {}", | ||
e | ||
"Failed to clear node edit metadata after editing ended because of an error: {e}" | ||
) | ||
}); | ||
} | ||
|
@@ -2412,7 +2462,8 @@ pub mod test { | |
assert_eq!( | ||
metadata.edit_status, | ||
Some(NodeEditStatus::Edited { | ||
previous_expression: node.info.expression().to_string(), | ||
previous_expression: node.info.expression().to_string(), | ||
previous_intended_method: None, | ||
}) | ||
); | ||
}), | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No docs, and the name does not explain what it is.