mirror of
https://github.com/helix-editor/helix.git
synced 2024-11-26 03:13:29 +04:00
commands: = as range formatting (via lsp)
This commit is contained in:
parent
7162632eb7
commit
1ae7c43391
1
TODO.md
1
TODO.md
@ -17,7 +17,6 @@
|
|||||||
- [x] retain horiz when moving vertically
|
- [x] retain horiz when moving vertically
|
||||||
- [w] retain horiz when moving via ctrl-u/d
|
- [w] retain horiz when moving via ctrl-u/d
|
||||||
- [x] deindent
|
- [x] deindent
|
||||||
- [ ] ensure_cursor_in_view always before rendering? or always in app after event process?
|
|
||||||
- [x] update lsp on redo/undo
|
- [x] update lsp on redo/undo
|
||||||
- [ ] Implement marks (superset of Selection/Range)
|
- [ ] Implement marks (superset of Selection/Range)
|
||||||
- [ ] ctrl-v/ctrl-x on file picker
|
- [ ] ctrl-v/ctrl-x on file picker
|
||||||
|
@ -506,4 +506,71 @@ pub async fn text_document_hover(
|
|||||||
|
|
||||||
Ok(response)
|
Ok(response)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// formatting
|
||||||
|
|
||||||
|
pub async fn text_document_formatting(
|
||||||
|
&self,
|
||||||
|
text_document: lsp::TextDocumentIdentifier,
|
||||||
|
options: lsp::FormattingOptions,
|
||||||
|
) -> anyhow::Result<Vec<lsp::TextEdit>> {
|
||||||
|
let capabilities = self.capabilities.as_ref().unwrap(); // TODO: needs post init
|
||||||
|
|
||||||
|
// check if we're able to format
|
||||||
|
let _capabilities = match capabilities.document_formatting_provider {
|
||||||
|
Some(lsp::OneOf::Left(true)) => (),
|
||||||
|
Some(lsp::OneOf::Right(_)) => (),
|
||||||
|
// None | Some(false)
|
||||||
|
_ => return Ok(Vec::new()),
|
||||||
|
};
|
||||||
|
// TODO: return err::unavailable so we can fall back to tree sitter formatting
|
||||||
|
|
||||||
|
let params = lsp::DocumentFormattingParams {
|
||||||
|
text_document,
|
||||||
|
options,
|
||||||
|
// TODO: support these tokens
|
||||||
|
work_done_progress_params: lsp::WorkDoneProgressParams {
|
||||||
|
work_done_token: None,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let response = self.request::<lsp::request::Formatting>(params).await?;
|
||||||
|
|
||||||
|
Ok(response.unwrap_or_default())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn text_document_range_formatting(
|
||||||
|
&self,
|
||||||
|
text_document: lsp::TextDocumentIdentifier,
|
||||||
|
range: lsp::Range,
|
||||||
|
options: lsp::FormattingOptions,
|
||||||
|
) -> anyhow::Result<Vec<lsp::TextEdit>> {
|
||||||
|
let capabilities = self.capabilities.as_ref().unwrap(); // TODO: needs post init
|
||||||
|
|
||||||
|
log::info!("{:?}", capabilities.document_range_formatting_provider);
|
||||||
|
// check if we're able to format
|
||||||
|
let _capabilities = match capabilities.document_range_formatting_provider {
|
||||||
|
Some(lsp::OneOf::Left(true)) => (),
|
||||||
|
Some(lsp::OneOf::Right(_)) => (),
|
||||||
|
// None | Some(false)
|
||||||
|
_ => return Ok(Vec::new()),
|
||||||
|
};
|
||||||
|
// TODO: return err::unavailable so we can fall back to tree sitter formatting
|
||||||
|
|
||||||
|
let params = lsp::DocumentRangeFormattingParams {
|
||||||
|
text_document,
|
||||||
|
range,
|
||||||
|
options,
|
||||||
|
// TODO: support these tokens
|
||||||
|
work_done_progress_params: lsp::WorkDoneProgressParams {
|
||||||
|
work_done_token: None,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let response = self
|
||||||
|
.request::<lsp::request::RangeFormatting>(params)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(response.unwrap_or_default())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ pub enum Error {
|
|||||||
|
|
||||||
pub mod util {
|
pub mod util {
|
||||||
use super::*;
|
use super::*;
|
||||||
use helix_core::{RopeSlice, State, Transaction};
|
use helix_core::{Range, RopeSlice, State, Transaction};
|
||||||
|
|
||||||
pub fn lsp_pos_to_pos(doc: RopeSlice, pos: lsp::Position) -> usize {
|
pub fn lsp_pos_to_pos(doc: RopeSlice, pos: lsp::Position) -> usize {
|
||||||
let line = doc.line_to_char(pos.line as usize);
|
let line = doc.line_to_char(pos.line as usize);
|
||||||
@ -43,6 +43,13 @@ pub fn pos_to_lsp_pos(doc: RopeSlice, pos: usize) -> lsp::Position {
|
|||||||
lsp::Position::new(line as u32, col as u32)
|
lsp::Position::new(line as u32, col as u32)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn range_to_lsp_range(doc: RopeSlice, range: Range) -> lsp::Range {
|
||||||
|
let start = pos_to_lsp_pos(doc, range.from());
|
||||||
|
let end = pos_to_lsp_pos(doc, range.to());
|
||||||
|
|
||||||
|
lsp::Range::new(start, end)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn generate_transaction_from_edits(
|
pub fn generate_transaction_from_edits(
|
||||||
state: &State,
|
state: &State,
|
||||||
edits: Vec<lsp::TextEdit>,
|
edits: Vec<lsp::TextEdit>,
|
||||||
|
@ -888,6 +888,47 @@ pub fn unindent(cx: &mut Context) {
|
|||||||
doc.append_changes_to_history();
|
doc.append_changes_to_history();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn format_selections(cx: &mut Context) {
|
||||||
|
use helix_lsp::lsp;
|
||||||
|
let doc = cx.doc();
|
||||||
|
|
||||||
|
// via lsp if available
|
||||||
|
// else via tree-sitter indentation calculations
|
||||||
|
|
||||||
|
// TODO: blocking here is not ideal
|
||||||
|
|
||||||
|
let ranges: Vec<lsp::Range> = doc
|
||||||
|
.selection()
|
||||||
|
.ranges()
|
||||||
|
.iter()
|
||||||
|
.map(|range| {
|
||||||
|
helix_lsp::util::range_to_lsp_range(doc.text().slice(..), doc.selection().primary())
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
for range in ranges {
|
||||||
|
let language_server = match doc.language_server.as_ref() {
|
||||||
|
Some(language_server) => language_server,
|
||||||
|
None => return,
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: handle fails
|
||||||
|
// TODO: concurrent map
|
||||||
|
let edits = smol::block_on(language_server.text_document_range_formatting(
|
||||||
|
doc.identifier(),
|
||||||
|
range,
|
||||||
|
lsp::FormattingOptions::default(),
|
||||||
|
))
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
let transaction = helix_lsp::util::generate_transaction_from_edits(&doc.state, edits);
|
||||||
|
|
||||||
|
doc.apply(&transaction);
|
||||||
|
}
|
||||||
|
|
||||||
|
doc.append_changes_to_history();
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
pub fn save(cx: &mut Context) {
|
pub fn save(cx: &mut Context) {
|
||||||
|
@ -178,6 +178,7 @@ pub fn default() -> Keymaps {
|
|||||||
vec![key!('p')] => commands::paste,
|
vec![key!('p')] => commands::paste,
|
||||||
vec![key!('>')] => commands::indent,
|
vec![key!('>')] => commands::indent,
|
||||||
vec![key!('<')] => commands::unindent,
|
vec![key!('<')] => commands::unindent,
|
||||||
|
vec![key!('=')] => commands::format_selections,
|
||||||
vec![key!(':')] => commands::command_mode,
|
vec![key!(':')] => commands::command_mode,
|
||||||
vec![Key {
|
vec![Key {
|
||||||
code: KeyCode::Esc,
|
code: KeyCode::Esc,
|
||||||
|
Loading…
Reference in New Issue
Block a user