mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-11 20:58:54 +00:00
Add emacs function for extend shirnk selection
This commit is contained in:
parent
79293d2593
commit
d6c7030aeb
4 changed files with 123 additions and 3 deletions
|
@ -7,6 +7,7 @@ publish = false
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = "2.32.0"
|
clap = "2.32.0"
|
||||||
failure = "0.1.1"
|
failure = "0.1.1"
|
||||||
|
join_to_string = "0.1.1"
|
||||||
ra_syntax = { path = "../ra_syntax" }
|
ra_syntax = { path = "../ra_syntax" }
|
||||||
ra_editor = { path = "../ra_editor" }
|
ra_editor = { path = "../ra_editor" }
|
||||||
tools = { path = "../tools" }
|
tools = { path = "../tools" }
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
extern crate clap;
|
extern crate clap;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate failure;
|
extern crate failure;
|
||||||
|
extern crate join_to_string;
|
||||||
extern crate ra_syntax;
|
extern crate ra_syntax;
|
||||||
extern crate ra_editor;
|
extern crate ra_editor;
|
||||||
extern crate tools;
|
extern crate tools;
|
||||||
|
@ -10,9 +11,10 @@ use std::{
|
||||||
time::Instant
|
time::Instant
|
||||||
};
|
};
|
||||||
use clap::{App, Arg, SubCommand};
|
use clap::{App, Arg, SubCommand};
|
||||||
|
use join_to_string::join;
|
||||||
use tools::collect_tests;
|
use tools::collect_tests;
|
||||||
use ra_syntax::File;
|
use ra_syntax::{TextRange, File};
|
||||||
use ra_editor::{syntax_tree, file_structure};
|
use ra_editor::{syntax_tree, file_structure, extend_selection};
|
||||||
|
|
||||||
type Result<T> = ::std::result::Result<T, failure::Error>;
|
type Result<T> = ::std::result::Result<T, failure::Error>;
|
||||||
|
|
||||||
|
@ -39,6 +41,10 @@ fn main() -> Result<()> {
|
||||||
.arg(Arg::with_name("no-dump").long("--no-dump"))
|
.arg(Arg::with_name("no-dump").long("--no-dump"))
|
||||||
)
|
)
|
||||||
.subcommand(SubCommand::with_name("symbols"))
|
.subcommand(SubCommand::with_name("symbols"))
|
||||||
|
.subcommand(SubCommand::with_name("extend-selection")
|
||||||
|
.arg(Arg::with_name("start"))
|
||||||
|
.arg(Arg::with_name("end"))
|
||||||
|
)
|
||||||
.get_matches();
|
.get_matches();
|
||||||
match matches.subcommand() {
|
match matches.subcommand() {
|
||||||
("parse", Some(matches)) => {
|
("parse", Some(matches)) => {
|
||||||
|
@ -65,6 +71,13 @@ fn main() -> Result<()> {
|
||||||
let (test, tree) = render_test(file, line)?;
|
let (test, tree) = render_test(file, line)?;
|
||||||
println!("{}\n{}", test, tree);
|
println!("{}\n{}", test, tree);
|
||||||
}
|
}
|
||||||
|
("extend-selection", Some(matches)) => {
|
||||||
|
let start: u32 = matches.value_of("start").unwrap().parse()?;
|
||||||
|
let end: u32 = matches.value_of("end").unwrap().parse()?;
|
||||||
|
let file = file()?;
|
||||||
|
let sels = selections(&file, start, end);
|
||||||
|
println!("{}", sels)
|
||||||
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -95,3 +108,19 @@ fn render_test(file: &Path, line: usize) -> Result<(String, String)> {
|
||||||
let tree = syntax_tree(&file);
|
let tree = syntax_tree(&file);
|
||||||
Ok((test.text, tree))
|
Ok((test.text, tree))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn selections(file: &File, start: u32, end: u32) -> String {
|
||||||
|
let mut ranges = Vec::new();
|
||||||
|
let mut cur = Some(TextRange::from_to((start - 1).into(), (end - 1).into()));
|
||||||
|
while let Some(r) = cur {
|
||||||
|
ranges.push(r);
|
||||||
|
cur = extend_selection(&file, r);
|
||||||
|
}
|
||||||
|
let ranges = ranges.iter()
|
||||||
|
.map(|r| (1 + u32::from(r.start()), 1 + u32::from(r.end())))
|
||||||
|
.map(|(s, e)| format!("({} {})", s, e));
|
||||||
|
join(ranges)
|
||||||
|
.separator(" ")
|
||||||
|
.surround_with("(", ")")
|
||||||
|
.to_string()
|
||||||
|
}
|
||||||
|
|
|
@ -78,7 +78,11 @@ impl<'f> Iterator for LeafAtOffset<'f> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn find_covering_node(root: SyntaxNodeRef, range: TextRange) -> SyntaxNodeRef {
|
pub fn find_covering_node(root: SyntaxNodeRef, range: TextRange) -> SyntaxNodeRef {
|
||||||
assert!(is_subrange(root.range(), range));
|
assert!(
|
||||||
|
is_subrange(root.range(), range),
|
||||||
|
"node range: {:?}, target range: {:?}",
|
||||||
|
root.range(), range,
|
||||||
|
);
|
||||||
let (left, right) = match (
|
let (left, right) = match (
|
||||||
find_leaf_at_offset(root, range.start()).right_biased(),
|
find_leaf_at_offset(root, range.start()).right_biased(),
|
||||||
find_leaf_at_offset(root, range.end()).left_biased()
|
find_leaf_at_offset(root, range.end()).left_biased()
|
||||||
|
|
86
editors/emacs/ra.el
Normal file
86
editors/emacs/ra.el
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
;;; ra.el --- Rust analyzer emacs bindings -*- lexical-binding: t; -*-
|
||||||
|
;;; Commentary:
|
||||||
|
;;; Small utilities for interacting with Rust analyzer.
|
||||||
|
;;; Run
|
||||||
|
;;; cargo install --git https://github.com/matklad/rust-analyzer/ --bin ra_cli
|
||||||
|
;;; to install the binary, copy-paste the bellow code to your `.init.el` and use
|
||||||
|
;;; `ra-extend-selection` and `ra-shrink-selection` functions
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
|
||||||
|
(defvar ra--selections-cache '(0 0 ()))
|
||||||
|
(defun ra--cache-tick ()
|
||||||
|
"Get buffer modification count for cache."
|
||||||
|
(nth 0 ra--selections-cache))
|
||||||
|
(defun ra--cache-sel ()
|
||||||
|
"Get current selection for cache."
|
||||||
|
(nth 1 ra--selections-cache))
|
||||||
|
(defun ra--cache-nth-sel (n)
|
||||||
|
"Get Nth selection."
|
||||||
|
(nth n (nth 2 ra--selections-cache)))
|
||||||
|
(defun ra--cache-set-nth-sel (n)
|
||||||
|
"Get Nth selection."
|
||||||
|
(setf (nth 1 ra--selections-cache) n)
|
||||||
|
(nth n (nth 2 ra--selections-cache)))
|
||||||
|
|
||||||
|
|
||||||
|
(defun ra-extend-selection ()
|
||||||
|
"Extend START END region to contain the encompassing syntactic construct."
|
||||||
|
(interactive)
|
||||||
|
(let* ((p (point))
|
||||||
|
(m (or (and mark-active (mark)) p))
|
||||||
|
(start (min p m))
|
||||||
|
(end (max p m)))
|
||||||
|
(ra--extend-selection start end)))
|
||||||
|
|
||||||
|
|
||||||
|
(defun ra-shrink-selection (start end)
|
||||||
|
"Shrink START END region to contain previous selection."
|
||||||
|
(interactive "r")
|
||||||
|
(ra--freshen-cache start end)
|
||||||
|
(let ((sel-id (ra--cache-sel)))
|
||||||
|
(if (not (= 0 sel-id))
|
||||||
|
(let* ((r (ra--cache-set-nth-sel (- sel-id 1))))
|
||||||
|
(push-mark (nth 0 r) t t)
|
||||||
|
(goto-char (nth 1 r))
|
||||||
|
(setq deactivate-mark nil)))))
|
||||||
|
|
||||||
|
; Add this to setup keybinding
|
||||||
|
; (require 'rust-mode)
|
||||||
|
; (define-key rust-mode-map (kbd "C-w") 'ra-extend-selection)
|
||||||
|
; (define-key rust-mode-map (kbd "C-S-w") 'ra-shrink-selection)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
(defun ra--extend-selection (start end)
|
||||||
|
"Extend START END region to contain the encompassing syntactic construct."
|
||||||
|
(ra--freshen-cache start end)
|
||||||
|
(let* ((next-sel-idx (+ 1 (ra--cache-sel)))
|
||||||
|
(r (ra--cache-set-nth-sel next-sel-idx)))
|
||||||
|
(push-mark (nth 0 r) t t)
|
||||||
|
(goto-char (nth 1 r))
|
||||||
|
(setq deactivate-mark nil)))
|
||||||
|
|
||||||
|
(defun ra--selections (start end)
|
||||||
|
"Get list of selections for START END from Rust analyzer."
|
||||||
|
(read (with-output-to-string
|
||||||
|
(call-process-region
|
||||||
|
(point-min) (point-max)
|
||||||
|
"ra_cli" nil standard-output nil
|
||||||
|
"extend-selection"
|
||||||
|
(number-to-string start)
|
||||||
|
(number-to-string end)))))
|
||||||
|
|
||||||
|
(defun ra--freshen-cache (start end)
|
||||||
|
"Make selection cache up-to-date for current buffer state and START END."
|
||||||
|
(if (not (and
|
||||||
|
(= (buffer-modified-tick) (ra--cache-tick))
|
||||||
|
(equal `(,start ,end) (ra--cache-nth-sel (ra--cache-sel)))))
|
||||||
|
(ra--set-cache start end)))
|
||||||
|
|
||||||
|
(defun ra--set-cache (start end)
|
||||||
|
"Set selections cache for current buffer state and START END."
|
||||||
|
(setq ra--selections-cache `(,(buffer-modified-tick) 0 ,(ra--selections start end))))
|
||||||
|
|
||||||
|
(provide 'ra)
|
||||||
|
;;; ra.el ends here
|
Loading…
Reference in a new issue