on master help sign in
Refactor symbol picker to share code
4e1b3b1Blaž Hrastnik
helix-term/src/commands.rs+58−64
@@ -3474,6 +3474,58 @@ fn buffer_picker(cx: &mut Context) {
3474 cx.push_layer(Box::new(overlayed(picker)));
3474 cx.push_layer(Box::new(overlayed(picker)));
3475}
3475}
3476
3476
3477+fn sym_picker(
3478+ symbols: Vec<lsp::SymbolInformation>,
3479+ current_path: Option<lsp::Url>,
3480+ offset_encoding: OffsetEncoding,
3481+) -> FilePicker<lsp::SymbolInformation> {
3482+ // TODO: drop current_path comparison and instead use workspace: bool flag?
3483+ let current_path2 = current_path.clone();
3484+ let mut picker = FilePicker::new(
3485+ symbols,
3486+ move |symbol| {
3487+ if current_path.as_ref() == Some(&symbol.location.uri) {
3488+ symbol.name.as_str().into()
3489+ } else {
3490+ let path = symbol.location.uri.to_file_path().unwrap();
3491+ let relative_path = helix_core::path::get_relative_path(path.as_path())
3492+ .to_string_lossy()
3493+ .into_owned();
3494+ format!("{} ({})", &symbol.name, relative_path).into()
3495+ }
3496+ },
3497+ move |cx, symbol, action| {
3498+ if current_path2.as_ref() == Some(&symbol.location.uri) {
3499+ push_jump(cx.editor);
3500+ } else {
3501+ let path = symbol.location.uri.to_file_path().unwrap();
3502+ cx.editor.open(path, action).expect("editor.open failed");
3503+ }
3504+
3505+ let (view, doc) = current!(cx.editor);
3506+
3507+ if let Some(range) =
3508+ lsp_range_to_range(doc.text(), symbol.location.range, offset_encoding)
3509+ {
3510+ // we flip the range so that the cursor sits on the start of the symbol
3511+ // (for example start of the function).
3512+ doc.set_selection(view.id, Selection::single(range.head, range.anchor));
3513+ align_view(doc, view, Align::Center);
3514+ }
3515+ },
3516+ move |_editor, symbol| {
3517+ let path = symbol.location.uri.to_file_path().unwrap();
3518+ let line = Some((
3519+ symbol.location.range.start.line as usize,
3520+ symbol.location.range.end.line as usize,
3521+ ));
3522+ Some((path, line))
3523+ },
3524+ );
3525+ picker.truncate_start = false;
3526+ picker
3527+}
3528+
3477fn symbol_picker(cx: &mut Context) {
3529fn symbol_picker(cx: &mut Context) {
3478 fn nested_to_flat(
3530 fn nested_to_flat(
3479 list: &mut Vec<lsp::SymbolInformation>,
3531 list: &mut Vec<lsp::SymbolInformation>,
@@ -3499,6 +3551,7 @@ fn symbol_picker(cx: &mut Context) {
3499 Some(language_server) => language_server,
3551 Some(language_server) => language_server,
3500 None => return,
3552 None => return,
3501 };
3553 };
3554+ let current_url = doc.url();
3502 let offset_encoding = language_server.offset_encoding();
3555 let offset_encoding = language_server.offset_encoding();
3503
3556
3504 let future = language_server.document_symbols(doc.identifier());
3557 let future = language_server.document_symbols(doc.identifier());
@@ -3523,32 +3576,7 @@ fn symbol_picker(cx: &mut Context) {
3523 }
3576 }
3524 };
3577 };
3525
3578
3526− let mut picker = FilePicker::new(
3579+ let picker = sym_picker(symbols, current_url, offset_encoding);
3527− symbols,
3528− |symbol| (&symbol.name).into(),
3529− move |cx, symbol, _action| {
3530− push_jump(cx.editor);
3531− let (view, doc) = current!(cx.editor);
3532−
3533− if let Some(range) =
3534− lsp_range_to_range(doc.text(), symbol.location.range, offset_encoding)
3535− {
3536− // we flip the range so that the cursor sits on the start of the symbol
3537− // (for example start of the function).
3538− doc.set_selection(view.id, Selection::single(range.head, range.anchor));
3539− align_view(doc, view, Align::Center);
3540− }
3541− },
3542− move |_editor, symbol| {
3543− let path = symbol.location.uri.to_file_path().unwrap();
3544− let line = Some((
3545− symbol.location.range.start.line as usize,
3546− symbol.location.range.end.line as usize,
3547− ));
3548− Some((path, line))
3549− },
3550− );
3551− picker.truncate_start = false;
3552 compositor.push(Box::new(overlayed(picker)))
3580 compositor.push(Box::new(overlayed(picker)))
3553 }
3581 }
3554 },
3582 },
@@ -3557,7 +3585,7 @@ fn symbol_picker(cx: &mut Context) {
3557
3585
3558fn workspace_symbol_picker(cx: &mut Context) {
3586fn workspace_symbol_picker(cx: &mut Context) {
3559 let doc = doc!(cx.editor);
3587 let doc = doc!(cx.editor);
3560− let current_path = doc.path().cloned();
3588+ let current_url = doc.url();
3561 let language_server = match doc.language_server() {
3589 let language_server = match doc.language_server() {
3562 Some(language_server) => language_server,
3590 Some(language_server) => language_server,
3563 None => return,
3591 None => return,
@@ -3571,43 +3599,7 @@ fn workspace_symbol_picker(cx: &mut Context) {
3571 compositor: &mut Compositor,
3599 compositor: &mut Compositor,
3572 response: Option<Vec<lsp::SymbolInformation>>| {
3600 response: Option<Vec<lsp::SymbolInformation>>| {
3573 if let Some(symbols) = response {
3601 if let Some(symbols) = response {
3574− let mut picker = FilePicker::new(
3602+ let picker = sym_picker(symbols, current_url, offset_encoding);
3575− symbols,
3576− move |symbol| {
3577− let path = symbol.location.uri.to_file_path().unwrap();
3578− if current_path.as_ref().map(|p| p == &path).unwrap_or(false) {
3579− (&symbol.name).into()
3580− } else {
3581− let relative_path = helix_core::path::get_relative_path(path.as_path())
3582− .to_string_lossy()
3583− .into_owned();
3584− format!("{} ({})", &symbol.name, relative_path).into()
3585− }
3586− },
3587− move |cx, symbol, action| {
3588− let path = symbol.location.uri.to_file_path().unwrap();
3589− cx.editor.open(path, action).expect("editor.open failed");
3590− let (view, doc) = current!(cx.editor);
3591−
3592− if let Some(range) =
3593− lsp_range_to_range(doc.text(), symbol.location.range, offset_encoding)
3594− {
3595− // we flip the range so that the cursor sits on the start of the symbol
3596− // (for example start of the function).
3597− doc.set_selection(view.id, Selection::single(range.head, range.anchor));
3598− align_view(doc, view, Align::Center);
3599− }
3600− },
3601− move |_editor, symbol| {
3602− let path = symbol.location.uri.to_file_path().unwrap();
3603− let line = Some((
3604− symbol.location.range.start.line as usize,
3605− symbol.location.range.end.line as usize,
3606− ));
3607− Some((path, line))
3608− },
3609− );
3610− picker.truncate_start = false;
3611 compositor.push(Box::new(overlayed(picker)))
3603 compositor.push(Box::new(overlayed(picker)))
3612 }
3604 }
3613 },
3605 },
@@ -4266,6 +4258,7 @@ fn goto_impl(
4266) {
4258) {
4267 push_jump(editor);
4259 push_jump(editor);
4268
4260
4261+ // TODO: share with symbol picker(symbol.location)
4269 fn jump_to(
4262 fn jump_to(
4270 editor: &mut Editor,
4263 editor: &mut Editor,
4271 location: &lsp::Location,
4264 location: &lsp::Location,
@@ -4324,6 +4317,7 @@ fn goto_impl(
4324 },
4317 },
4325 move |cx, location, action| jump_to(cx.editor, location, offset_encoding, action),
4318 move |cx, location, action| jump_to(cx.editor, location, offset_encoding, action),
4326 |_editor, location| {
4319 |_editor, location| {
4320+ // TODO: share code for symbol.location and location
4327 let path = location.uri.to_file_path().unwrap();
4321 let path = location.uri.to_file_path().unwrap();
4328 let line = Some((
4322 let line = Some((
4329 location.range.start.line as usize,
4323 location.range.start.line as usize,
helix-term/src/commands/dap.rs+1−1
@@ -792,7 +792,7 @@ pub fn dap_switch_stack_frame(cx: &mut Context) {
792
792
793 let picker = FilePicker::new(
793 let picker = FilePicker::new(
794 frames,
794 frames,
795− |frame| frame.name.clone().into(), // TODO: include thread_states in the label
795+ |frame| frame.name.as_str().into(), // TODO: include thread_states in the label
796 move |cx, frame, _action| {
796 move |cx, frame, _action| {
797 let debugger = debugger!(cx.editor);
797 let debugger = debugger!(cx.editor);
798 // TODO: this should be simpler to find
798 // TODO: this should be simpler to find