mirror of
https://github.com/helix-editor/helix.git
synced 2025-10-06 08:23:27 +02:00
Compare commits
44 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
7e8603247d | ||
|
7140908f6e | ||
|
6dba1e7ec7 | ||
|
c0332bd935 | ||
|
3c7729906c | ||
|
1b67fae9f4 | ||
|
f0018280cb | ||
|
7202953e69 | ||
|
7761c88d61 | ||
|
68f5031dcc | ||
|
83031564db | ||
|
eab6e53511 | ||
|
f5f46b1fed | ||
|
5f49bafbe8 | ||
|
2719a35123 | ||
|
0a6672c626 | ||
|
b51111a364 | ||
|
78980f575b | ||
|
0bb375bafa | ||
|
c960bcfc24 | ||
|
e88383d990 | ||
|
312b29f712 | ||
|
f4560cb68a | ||
|
cbb3ebafdc | ||
|
0851110d10 | ||
|
3ace581191 | ||
|
c0264b9f7f | ||
|
22dad592b8 | ||
|
ca042a4bde | ||
|
67b1cd32c7 | ||
|
4d12c7c3cf | ||
|
4f56a8e248 | ||
|
dbc392d92c | ||
|
7967d312c0 | ||
|
db48d22384 | ||
|
533ff61d0e | ||
|
b1ce969d80 | ||
|
01bf363446 | ||
|
cc323f7665 | ||
|
60caaf7fc4 | ||
|
ea824ed05d | ||
|
cfae07e7ba | ||
|
56dbc60840 | ||
|
c2e6b9f506 |
4
.gitmodules
vendored
4
.gitmodules
vendored
@@ -82,3 +82,7 @@
|
|||||||
path = helix-syntax/languages/tree-sitter-toml
|
path = helix-syntax/languages/tree-sitter-toml
|
||||||
url = https://github.com/ikatyang/tree-sitter-toml
|
url = https://github.com/ikatyang/tree-sitter-toml
|
||||||
shallow = true
|
shallow = true
|
||||||
|
[submodule "helix-syntax/languages/tree-sitter-elixir"]
|
||||||
|
path = helix-syntax/languages/tree-sitter-elixir
|
||||||
|
url = https://github.com/IceDragon200/tree-sitter-elixir
|
||||||
|
shallow = true
|
||||||
|
7
Cargo.lock
generated
7
Cargo.lock
generated
@@ -326,7 +326,6 @@ dependencies = [
|
|||||||
"log",
|
"log",
|
||||||
"num_cpus",
|
"num_cpus",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"pico-args",
|
|
||||||
"pulldown-cmark",
|
"pulldown-cmark",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
@@ -607,12 +606,6 @@ version = "2.1.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
|
checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pico-args"
|
|
||||||
version = "0.4.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7d7afeb98c5a10e0bffcc7fc16e105b04d06729fac5fd6384aebf7ff5cb5a67d"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pin-project-lite"
|
name = "pin-project-lite"
|
||||||
version = "0.2.6"
|
version = "0.2.6"
|
||||||
|
15
README.md
15
README.md
@@ -42,6 +42,14 @@ Now copy the `runtime/` directory somewhere. Helix will by default look for the
|
|||||||
runtime inside the same folder as the executable, but that can be overriden via
|
runtime inside the same folder as the executable, but that can be overriden via
|
||||||
the `HELIX_RUNTIME` environment variable.
|
the `HELIX_RUNTIME` environment variable.
|
||||||
|
|
||||||
|
> NOTE: You should set this to <path to repository>/runtime in development (if
|
||||||
|
> running via cargo).
|
||||||
|
|
||||||
|
## Arch Linux
|
||||||
|
There are two packages available from AUR:
|
||||||
|
- `helix-bin`: contains prebuilt binary from GitHub releases
|
||||||
|
- `helix-git`: builds the master branch of this repository
|
||||||
|
|
||||||
# Contributing
|
# Contributing
|
||||||
|
|
||||||
Contributors are very welcome! **No contribution is too small and all contributions are valued.**
|
Contributors are very welcome! **No contribution is too small and all contributions are valued.**
|
||||||
@@ -57,6 +65,13 @@ Some suggestions to get started:
|
|||||||
We provide an [architecture.md](./docs/architecture.md) that should give you
|
We provide an [architecture.md](./docs/architecture.md) that should give you
|
||||||
a good overview of the internals.
|
a good overview of the internals.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Keyboard shortcuts / Keymap
|
||||||
|
|
||||||
|
All shortcuts/keymaps can be found in the documentation on the website:
|
||||||
|
- https://docs.helix-editor.com/keymap.html
|
||||||
|
|
||||||
# Getting help
|
# Getting help
|
||||||
|
|
||||||
Discuss the project on the community [Matrix channel](https://matrix.to/#/#helix-community:matrix.org).
|
Discuss the project on the community [Matrix channel](https://matrix.to/#/#helix-community:matrix.org).
|
||||||
|
@@ -4,3 +4,6 @@ language = "en"
|
|||||||
multilingual = false
|
multilingual = false
|
||||||
src = "src"
|
src = "src"
|
||||||
theme = "colibri"
|
theme = "colibri"
|
||||||
|
|
||||||
|
[output.html]
|
||||||
|
cname = "docs.helix-editor.com"
|
||||||
|
@@ -6,10 +6,7 @@ We provide pre-built binaries on the [GitHub Releases page](https://github.com/h
|
|||||||
|
|
||||||
TODO: brew tap
|
TODO: brew tap
|
||||||
|
|
||||||
```
|
Please use a pre-built binary release for the time being.
|
||||||
$ brew tap helix-editor/helix
|
|
||||||
$ brew install helix
|
|
||||||
```
|
|
||||||
|
|
||||||
## Linux
|
## Linux
|
||||||
|
|
||||||
@@ -21,7 +18,9 @@ shell for working on Helix.
|
|||||||
|
|
||||||
### Arch Linux
|
### Arch Linux
|
||||||
|
|
||||||
A binary package is available on AUR as [helix-bin](https://aur.archlinux.org/packages/helix-bin/).
|
Binary packages are available on AUR:
|
||||||
|
- [helix-bin](https://aur.archlinux.org/packages/helix-bin/) contains the pre-built release
|
||||||
|
- [helix-git](https://aur.archlinux.org/packages/helix-git/) builds the master branch
|
||||||
|
|
||||||
## Build from source
|
## Build from source
|
||||||
|
|
||||||
|
@@ -118,7 +118,7 @@ Jumps to various locations.
|
|||||||
|-----|-----------|
|
|-----|-----------|
|
||||||
| g | Go to the start of the file |
|
| g | Go to the start of the file |
|
||||||
| e | Go to the end of the file |
|
| e | Go to the end of the file |
|
||||||
| e | Go to definition |
|
| d | Go to definition |
|
||||||
| t | Go to type definition |
|
| t | Go to type definition |
|
||||||
| r | Go to references |
|
| r | Go to references |
|
||||||
| i | Go to implementation |
|
| i | Go to implementation |
|
||||||
|
@@ -65,9 +65,7 @@ impl History {
|
|||||||
self.cursor == 0
|
self.cursor == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: I'd like to pass Transaction by reference but it fights with the borrowck
|
pub fn undo(&mut self) -> Option<&Transaction> {
|
||||||
|
|
||||||
pub fn undo(&mut self) -> Option<Transaction> {
|
|
||||||
if self.at_root() {
|
if self.at_root() {
|
||||||
// We're at the root of undo, nothing to do.
|
// We're at the root of undo, nothing to do.
|
||||||
return None;
|
return None;
|
||||||
@@ -77,17 +75,17 @@ impl History {
|
|||||||
|
|
||||||
self.cursor = current_revision.parent;
|
self.cursor = current_revision.parent;
|
||||||
|
|
||||||
Some(current_revision.revert.clone())
|
Some(¤t_revision.revert)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn redo(&mut self) -> Option<Transaction> {
|
pub fn redo(&mut self) -> Option<&Transaction> {
|
||||||
let current_revision = &self.revisions[self.cursor];
|
let current_revision = &self.revisions[self.cursor];
|
||||||
|
|
||||||
// for now, simply pick the latest child (linear undo / redo)
|
// for now, simply pick the latest child (linear undo / redo)
|
||||||
if let Some((index, transaction)) = current_revision.children.last() {
|
if let Some((index, transaction)) = current_revision.children.last() {
|
||||||
self.cursor = *index;
|
self.cursor = *index;
|
||||||
|
|
||||||
return Some(transaction.clone());
|
return Some(&transaction);
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@@ -45,7 +45,7 @@ pub fn move_vertically(
|
|||||||
|
|
||||||
let new_line = match dir {
|
let new_line = match dir {
|
||||||
Direction::Backward => row.saturating_sub(count),
|
Direction::Backward => row.saturating_sub(count),
|
||||||
Direction::Forward => std::cmp::min(row.saturating_add(count), text.len_lines() - 1),
|
Direction::Forward => std::cmp::min(row.saturating_add(count), text.len_lines() - 2),
|
||||||
};
|
};
|
||||||
|
|
||||||
// convert to 0-indexed, subtract another 1 because len_chars() counts \n
|
// convert to 0-indexed, subtract another 1 because len_chars() counts \n
|
||||||
@@ -76,8 +76,9 @@ pub fn move_next_word_start(slice: RopeSlice, mut begin: usize, count: usize) ->
|
|||||||
begin += 1;
|
begin += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// return if not skip while?
|
if !skip_over_next(slice, &mut begin, |ch| ch == '\n') {
|
||||||
skip_over_next(slice, &mut begin, |ch| ch == '\n');
|
return None;
|
||||||
|
};
|
||||||
ch = slice.char(begin);
|
ch = slice.char(begin);
|
||||||
|
|
||||||
end = begin + 1;
|
end = begin + 1;
|
||||||
@@ -134,7 +135,7 @@ pub fn move_next_word_end(slice: RopeSlice, mut begin: usize, count: usize) -> O
|
|||||||
let mut end = begin;
|
let mut end = begin;
|
||||||
|
|
||||||
for _ in 0..count {
|
for _ in 0..count {
|
||||||
if begin + 1 == slice.len_chars() {
|
if begin + 2 >= slice.len_chars() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,8 +146,9 @@ pub fn move_next_word_end(slice: RopeSlice, mut begin: usize, count: usize) -> O
|
|||||||
begin += 1;
|
begin += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// return if not skip while?
|
if !skip_over_next(slice, &mut begin, |ch| ch == '\n') {
|
||||||
skip_over_next(slice, &mut begin, |ch| ch == '\n');
|
return None;
|
||||||
|
};
|
||||||
|
|
||||||
end = begin;
|
end = begin;
|
||||||
|
|
||||||
@@ -199,18 +201,20 @@ fn categorize(ch: char) -> Category {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn skip_over_next<F>(slice: RopeSlice, pos: &mut usize, fun: F)
|
/// Returns true if there are more characters left after the new position.
|
||||||
|
pub fn skip_over_next<F>(slice: RopeSlice, pos: &mut usize, fun: F) -> bool
|
||||||
where
|
where
|
||||||
F: Fn(char) -> bool,
|
F: Fn(char) -> bool,
|
||||||
{
|
{
|
||||||
let mut chars = slice.chars_at(*pos);
|
let mut chars = slice.chars_at(*pos);
|
||||||
|
|
||||||
for ch in chars {
|
while let Some(ch) = chars.next() {
|
||||||
if !fun(ch) {
|
if !fun(ch) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
*pos += 1;
|
*pos += 1;
|
||||||
}
|
}
|
||||||
|
chars.next().is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@@ -7,6 +7,10 @@ pub fn find_nth_next(
|
|||||||
n: usize,
|
n: usize,
|
||||||
inclusive: bool,
|
inclusive: bool,
|
||||||
) -> Option<usize> {
|
) -> Option<usize> {
|
||||||
|
if pos >= text.len_chars() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
// start searching right after pos
|
// start searching right after pos
|
||||||
let mut chars = text.chars_at(pos + 1);
|
let mut chars = text.chars_at(pos + 1);
|
||||||
|
|
||||||
|
@@ -415,7 +415,7 @@ impl ChangeSet {
|
|||||||
|
|
||||||
/// Transaction represents a single undoable unit of changes. Several changes can be grouped into
|
/// Transaction represents a single undoable unit of changes. Several changes can be grouped into
|
||||||
/// a single transaction.
|
/// a single transaction.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Default, Clone)]
|
||||||
pub struct Transaction {
|
pub struct Transaction {
|
||||||
changes: ChangeSet,
|
changes: ChangeSet,
|
||||||
selection: Option<Selection>,
|
selection: Option<Selection>,
|
||||||
|
@@ -107,7 +107,10 @@ fn build_dir(dir: &str, language: &str) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let ignore = vec!["tree-sitter-typescript".to_string()];
|
let ignore = vec![
|
||||||
|
"tree-sitter-typescript".to_string(),
|
||||||
|
".DS_Store".to_string(),
|
||||||
|
];
|
||||||
let dirs = collect_tree_sitter_dirs(&ignore);
|
let dirs = collect_tree_sitter_dirs(&ignore);
|
||||||
|
|
||||||
let mut n_jobs = 0;
|
let mut n_jobs = 0;
|
||||||
|
1
helix-syntax/languages/tree-sitter-elixir
Submodule
1
helix-syntax/languages/tree-sitter-elixir
Submodule
Submodule helix-syntax/languages/tree-sitter-elixir added at 295e62a43b
@@ -72,6 +72,7 @@ mk_langs!(
|
|||||||
(CSharp, tree_sitter_c_sharp),
|
(CSharp, tree_sitter_c_sharp),
|
||||||
(Cpp, tree_sitter_cpp),
|
(Cpp, tree_sitter_cpp),
|
||||||
(Css, tree_sitter_css),
|
(Css, tree_sitter_css),
|
||||||
|
(Elixir, tree_sitter_elixir),
|
||||||
(Go, tree_sitter_go),
|
(Go, tree_sitter_go),
|
||||||
// (Haskell, tree_sitter_haskell),
|
// (Haskell, tree_sitter_haskell),
|
||||||
(Html, tree_sitter_html),
|
(Html, tree_sitter_html),
|
||||||
|
@@ -24,7 +24,6 @@ tokio = { version = "1", features = ["full"] }
|
|||||||
num_cpus = "1"
|
num_cpus = "1"
|
||||||
tui = { path = "../helix-tui", package = "helix-tui", default-features = false, features = ["crossterm"] }
|
tui = { path = "../helix-tui", package = "helix-tui", default-features = false, features = ["crossterm"] }
|
||||||
crossterm = { version = "0.19", features = ["event-stream"] }
|
crossterm = { version = "0.19", features = ["event-stream"] }
|
||||||
pico-args = "0.4"
|
|
||||||
|
|
||||||
futures-util = { version = "0.3", features = ["std", "async-await"], default-features = false }
|
futures-util = { version = "0.3", features = ["std", "async-await"], default-features = false }
|
||||||
|
|
||||||
|
@@ -473,10 +473,10 @@ fn scroll(cx: &mut Context, offset: usize, direction: Direction) {
|
|||||||
let last_line = view.last_line(doc);
|
let last_line = view.last_line(doc);
|
||||||
|
|
||||||
// clamp into viewport
|
// clamp into viewport
|
||||||
let line = cursor.row.clamp(
|
let line = cursor
|
||||||
view.first_line + scrolloff,
|
.row
|
||||||
last_line.saturating_sub(scrolloff),
|
.min(view.first_line + scrolloff)
|
||||||
);
|
.max(last_line.saturating_sub(scrolloff));
|
||||||
|
|
||||||
let text = doc.text().slice(..);
|
let text = doc.text().slice(..);
|
||||||
let pos = pos_at_coords(text, Position::new(line, cursor.col)); // this func will properly truncate to line end
|
let pos = pos_at_coords(text, Position::new(line, cursor.col)); // this func will properly truncate to line end
|
||||||
@@ -1031,6 +1031,9 @@ pub fn command_mode(cx: &mut Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let parts = input.split_ascii_whitespace().collect::<Vec<&str>>();
|
let parts = input.split_ascii_whitespace().collect::<Vec<&str>>();
|
||||||
|
if parts.is_empty() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(cmd) = cmd::COMMANDS.get(parts[0]) {
|
if let Some(cmd) = cmd::COMMANDS.get(parts[0]) {
|
||||||
(cmd.fun)(editor, &parts[1..], event);
|
(cmd.fun)(editor, &parts[1..], event);
|
||||||
|
@@ -122,9 +122,17 @@ impl Compositor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn render(&mut self, cx: &mut Context) {
|
pub fn render(&mut self, cx: &mut Context) {
|
||||||
let area = self.size();
|
let area = self
|
||||||
|
.terminal
|
||||||
|
.autoresize()
|
||||||
|
.expect("Unable to determine terminal size");
|
||||||
|
|
||||||
|
// TODO: need to recalculate view tree if necessary
|
||||||
|
|
||||||
let surface = self.terminal.current_buffer_mut();
|
let surface = self.terminal.current_buffer_mut();
|
||||||
|
|
||||||
|
let area = *surface.area();
|
||||||
|
|
||||||
for layer in &self.layers {
|
for layer in &self.layers {
|
||||||
layer.render(area, surface, cx)
|
layer.render(area, surface, cx)
|
||||||
}
|
}
|
||||||
|
@@ -240,10 +240,12 @@ pub fn default() -> Keymaps {
|
|||||||
code: KeyCode::PageUp,
|
code: KeyCode::PageUp,
|
||||||
modifiers: KeyModifiers::NONE
|
modifiers: KeyModifiers::NONE
|
||||||
} => commands::page_up,
|
} => commands::page_up,
|
||||||
|
ctrl!('b') => commands::page_up,
|
||||||
KeyEvent {
|
KeyEvent {
|
||||||
code: KeyCode::PageDown,
|
code: KeyCode::PageDown,
|
||||||
modifiers: KeyModifiers::NONE
|
modifiers: KeyModifiers::NONE
|
||||||
} => commands::page_down,
|
} => commands::page_down,
|
||||||
|
ctrl!('f') => commands::page_down,
|
||||||
ctrl!('u') => commands::half_page_up,
|
ctrl!('u') => commands::half_page_up,
|
||||||
ctrl!('d') => commands::half_page_down,
|
ctrl!('d') => commands::half_page_down,
|
||||||
|
|
||||||
|
@@ -8,11 +8,13 @@ mod ui;
|
|||||||
|
|
||||||
use application::Application;
|
use application::Application;
|
||||||
|
|
||||||
|
use helix_core::config_dir;
|
||||||
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use anyhow::Error;
|
use anyhow::{Context, Error, Result};
|
||||||
|
|
||||||
fn setup_logging(verbosity: u64) -> Result<(), fern::InitError> {
|
fn setup_logging(verbosity: u64) -> Result<()> {
|
||||||
let mut base_config = fern::Dispatch::new();
|
let mut base_config = fern::Dispatch::new();
|
||||||
|
|
||||||
// Let's say we depend on something which whose "info" level messages are too
|
// Let's say we depend on something which whose "info" level messages are too
|
||||||
@@ -27,8 +29,6 @@ fn setup_logging(verbosity: u64) -> Result<(), fern::InitError> {
|
|||||||
_3_or_more => base_config.level(log::LevelFilter::Trace),
|
_3_or_more => base_config.level(log::LevelFilter::Trace),
|
||||||
};
|
};
|
||||||
|
|
||||||
let home = dirs_next::home_dir().expect("can't find the home directory");
|
|
||||||
|
|
||||||
// Separate file config so we can include year, month and day in file logs
|
// Separate file config so we can include year, month and day in file logs
|
||||||
let file_config = fern::Dispatch::new()
|
let file_config = fern::Dispatch::new()
|
||||||
.format(|out, message, record| {
|
.format(|out, message, record| {
|
||||||
@@ -40,7 +40,7 @@ fn setup_logging(verbosity: u64) -> Result<(), fern::InitError> {
|
|||||||
message
|
message
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
.chain(fern::log_file(home.join("helix.log"))?);
|
.chain(fern::log_file(config_dir().join("helix.log"))?);
|
||||||
|
|
||||||
base_config.chain(file_config).apply()?;
|
base_config.chain(file_config).apply()?;
|
||||||
|
|
||||||
@@ -48,10 +48,54 @@ fn setup_logging(verbosity: u64) -> Result<(), fern::InitError> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct Args {
|
pub struct Args {
|
||||||
|
display_help: bool,
|
||||||
|
display_version: bool,
|
||||||
|
verbosity: u64,
|
||||||
files: Vec<PathBuf>,
|
files: Vec<PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn parse_args(mut args: Args) -> Result<Args> {
|
||||||
|
let argv: Vec<String> = std::env::args().collect();
|
||||||
|
let mut iter = argv.iter();
|
||||||
|
|
||||||
|
iter.next(); // skip the program, we don't care about that
|
||||||
|
|
||||||
|
while let Some(arg) = iter.next() {
|
||||||
|
match arg.as_str() {
|
||||||
|
"--" => break, // stop parsing at this point treat the remaining as files
|
||||||
|
"--version" => args.display_version = true,
|
||||||
|
"--help" => args.display_help = true,
|
||||||
|
arg if arg.starts_with("--") => {
|
||||||
|
return Err(Error::msg(format!(
|
||||||
|
"unexpected double dash argument: {}",
|
||||||
|
arg
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
arg if arg.starts_with('-') => {
|
||||||
|
let arg = arg.get(1..).unwrap().chars();
|
||||||
|
for chr in arg {
|
||||||
|
match chr {
|
||||||
|
'v' => args.verbosity += 1,
|
||||||
|
'V' => args.display_version = true,
|
||||||
|
'h' => args.display_help = true,
|
||||||
|
_ => return Err(Error::msg(format!("unexpected short arg {}", chr))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
arg => args.files.push(PathBuf::from(arg)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// push the remaining args, if any to the files
|
||||||
|
for filename in iter {
|
||||||
|
args.files.push(PathBuf::from(filename));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(args)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() -> Result<()> {
|
||||||
let help = format!(
|
let help = format!(
|
||||||
"\
|
"\
|
||||||
{} {}
|
{} {}
|
||||||
@@ -75,28 +119,35 @@ FLAGS:
|
|||||||
env!("CARGO_PKG_DESCRIPTION"),
|
env!("CARGO_PKG_DESCRIPTION"),
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut pargs = pico_args::Arguments::from_env();
|
let mut args: Args = Args {
|
||||||
|
display_help: false,
|
||||||
|
display_version: false,
|
||||||
|
verbosity: 0,
|
||||||
|
files: [].to_vec(),
|
||||||
|
};
|
||||||
|
|
||||||
|
args = parse_args(args).context("could not parse arguments")?;
|
||||||
|
|
||||||
// Help has a higher priority and should be handled separately.
|
// Help has a higher priority and should be handled separately.
|
||||||
if pargs.contains(["-h", "--help"]) {
|
if args.display_help {
|
||||||
print!("{}", help);
|
print!("{}", help);
|
||||||
std::process::exit(0);
|
std::process::exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut verbosity: u64 = 0;
|
if args.display_version {
|
||||||
|
println!("{} {}", env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION"));
|
||||||
if pargs.contains("-v") {
|
std::process::exit(0);
|
||||||
verbosity = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setup_logging(verbosity).expect("failed to initialize logging.");
|
let conf_dir = config_dir();
|
||||||
|
|
||||||
let args = Args {
|
if !conf_dir.exists() {
|
||||||
files: pargs.finish().into_iter().map(|arg| arg.into()).collect(),
|
std::fs::create_dir(&conf_dir);
|
||||||
};
|
}
|
||||||
|
|
||||||
|
setup_logging(args.verbosity).context("failed to initialize logging")?;
|
||||||
|
|
||||||
// initialize language registry
|
// initialize language registry
|
||||||
use helix_core::config_dir;
|
|
||||||
use helix_core::syntax::{Loader, LOADER};
|
use helix_core::syntax::{Loader, LOADER};
|
||||||
|
|
||||||
// load $HOME/.config/helix/languages.toml, fallback to default config
|
// load $HOME/.config/helix/languages.toml, fallback to default config
|
||||||
@@ -105,17 +156,12 @@ FLAGS:
|
|||||||
.as_deref()
|
.as_deref()
|
||||||
.unwrap_or(include_bytes!("../../languages.toml"));
|
.unwrap_or(include_bytes!("../../languages.toml"));
|
||||||
|
|
||||||
LOADER.get_or_init(|| {
|
let config = toml::from_slice(toml).context("Could not parse languages.toml")?;
|
||||||
let config = toml::from_slice(toml).expect("Could not parse languages.toml");
|
LOADER.get_or_init(|| Loader::new(config));
|
||||||
Loader::new(config)
|
|
||||||
});
|
|
||||||
|
|
||||||
let runtime = tokio::runtime::Runtime::new().unwrap();
|
|
||||||
|
|
||||||
// TODO: use the thread local executor to spawn the application task separately from the work pool
|
// TODO: use the thread local executor to spawn the application task separately from the work pool
|
||||||
runtime.block_on(async move {
|
let mut app = Application::new(args).context("unable to create new appliction")?;
|
||||||
let mut app = Application::new(args).unwrap();
|
app.run().await;
|
||||||
|
|
||||||
app.run().await;
|
Ok(())
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
@@ -240,7 +240,7 @@ impl EditorView {
|
|||||||
for selection in doc
|
for selection in doc
|
||||||
.selection(view.id)
|
.selection(view.id)
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|range| range.overlaps(&screen))
|
.filter(|range| screen.overlaps(&range))
|
||||||
{
|
{
|
||||||
// TODO: render also if only one of the ranges is in viewport
|
// TODO: render also if only one of the ranges is in viewport
|
||||||
let mut start = view.screen_coords_at_pos(doc, text, selection.anchor);
|
let mut start = view.screen_coords_at_pos(doc, text, selection.anchor);
|
||||||
@@ -261,7 +261,7 @@ impl EditorView {
|
|||||||
Rect::new(
|
Rect::new(
|
||||||
viewport.x + start.col as u16,
|
viewport.x + start.col as u16,
|
||||||
viewport.y + start.row as u16,
|
viewport.y + start.row as u16,
|
||||||
(end.col - start.col) as u16 + 1,
|
((end.col - start.col) as u16 + 1).min(viewport.width),
|
||||||
1,
|
1,
|
||||||
),
|
),
|
||||||
selection_style,
|
selection_style,
|
||||||
@@ -633,6 +633,10 @@ impl Component for EditorView {
|
|||||||
// clear with background color
|
// clear with background color
|
||||||
surface.set_style(area, cx.editor.theme.get("ui.background"));
|
surface.set_style(area, cx.editor.theme.get("ui.background"));
|
||||||
|
|
||||||
|
// if the terminal size suddenly changed, we need to trigger a resize
|
||||||
|
cx.editor
|
||||||
|
.resize(Rect::new(area.x, area.y, area.width, area.height - 1)); // - 1 to account for commandline
|
||||||
|
|
||||||
for (view, is_focused) in cx.editor.tree.views() {
|
for (view, is_focused) in cx.editor.tree.views() {
|
||||||
let doc = cx.editor.document(view.doc).unwrap();
|
let doc = cx.editor.document(view.doc).unwrap();
|
||||||
self.render_view(doc, view, area, surface, &cx.editor.theme, is_focused);
|
self.render_view(doc, view, area, surface, &cx.editor.theme, is_focused);
|
||||||
|
@@ -160,7 +160,13 @@ impl Prompt {
|
|||||||
if let Some(doc) = (self.doc_fn)(&self.line) {
|
if let Some(doc) = (self.doc_fn)(&self.line) {
|
||||||
let text = ui::Text::new(doc.to_string());
|
let text = ui::Text::new(doc.to_string());
|
||||||
|
|
||||||
let area = Rect::new(completion_area.x, completion_area.y - 3, BASE_WIDTH * 3, 3);
|
let viewport = area;
|
||||||
|
let area = viewport.intersection(Rect::new(
|
||||||
|
completion_area.x,
|
||||||
|
completion_area.y - 3,
|
||||||
|
BASE_WIDTH * 3,
|
||||||
|
3,
|
||||||
|
));
|
||||||
|
|
||||||
let background = theme.get("ui.help");
|
let background = theme.get("ui.help");
|
||||||
surface.clear_with(area, background);
|
surface.clear_with(area, background);
|
||||||
|
@@ -137,14 +137,12 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Queries the backend for size and resizes if it doesn't match the previous size.
|
/// Queries the backend for size and resizes if it doesn't match the previous size.
|
||||||
pub fn autoresize(&mut self) -> io::Result<()> {
|
pub fn autoresize(&mut self) -> io::Result<Rect> {
|
||||||
if self.viewport.resize_behavior == ResizeBehavior::Auto {
|
let size = self.size()?;
|
||||||
let size = self.size()?;
|
if size != self.viewport.area {
|
||||||
if size != self.viewport.area {
|
self.resize(size)?;
|
||||||
self.resize(size)?;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
Ok(())
|
Ok(size)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Synchronizes terminal size, calls the rendering closure, flushes the current internal state
|
/// Synchronizes terminal size, calls the rendering closure, flushes the current internal state
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
use anyhow::{Context, Error};
|
use anyhow::{Context, Error};
|
||||||
|
use std::cell::Cell;
|
||||||
use std::future::Future;
|
use std::future::Future;
|
||||||
use std::path::{Component, Path, PathBuf};
|
use std::path::{Component, Path, PathBuf};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
@@ -40,7 +41,10 @@ pub struct Document {
|
|||||||
/// State at last commit. Used for calculating reverts.
|
/// State at last commit. Used for calculating reverts.
|
||||||
old_state: Option<State>,
|
old_state: Option<State>,
|
||||||
/// Undo tree.
|
/// Undo tree.
|
||||||
history: History,
|
// It can be used as a cell where we will take it out to get some parts of the history and put
|
||||||
|
// it back as it separated from the edits. We could split out the parts manually but that will
|
||||||
|
// be more troublesome.
|
||||||
|
history: Cell<History>,
|
||||||
last_saved_revision: usize,
|
last_saved_revision: usize,
|
||||||
version: i32, // should be usize?
|
version: i32, // should be usize?
|
||||||
|
|
||||||
@@ -121,7 +125,7 @@ impl Document {
|
|||||||
old_state,
|
old_state,
|
||||||
diagnostics: Vec::new(),
|
diagnostics: Vec::new(),
|
||||||
version: 0,
|
version: 0,
|
||||||
history: History::default(),
|
history: Cell::new(History::default()),
|
||||||
last_saved_revision: 0,
|
last_saved_revision: 0,
|
||||||
language_server: None,
|
language_server: None,
|
||||||
}
|
}
|
||||||
@@ -190,7 +194,9 @@ impl Document {
|
|||||||
let language_server = self.language_server.clone();
|
let language_server = self.language_server.clone();
|
||||||
|
|
||||||
// reset the modified flag
|
// reset the modified flag
|
||||||
self.last_saved_revision = self.history.current_revision();
|
let history = self.history.take();
|
||||||
|
self.last_saved_revision = history.current_revision();
|
||||||
|
self.history.set(history);
|
||||||
|
|
||||||
async move {
|
async move {
|
||||||
use tokio::{fs::File, io::AsyncWriteExt};
|
use tokio::{fs::File, io::AsyncWriteExt};
|
||||||
@@ -335,7 +341,8 @@ impl Document {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn undo(&mut self, view_id: ViewId) -> bool {
|
pub fn undo(&mut self, view_id: ViewId) -> bool {
|
||||||
if let Some(transaction) = self.history.undo() {
|
let mut history = self.history.take();
|
||||||
|
if let Some(transaction) = history.undo() {
|
||||||
let success = self._apply(&transaction, view_id);
|
let success = self._apply(&transaction, view_id);
|
||||||
|
|
||||||
// reset changeset to fix len
|
// reset changeset to fix len
|
||||||
@@ -343,11 +350,13 @@ impl Document {
|
|||||||
|
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
self.history.set(history);
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn redo(&mut self, view_id: ViewId) -> bool {
|
pub fn redo(&mut self, view_id: ViewId) -> bool {
|
||||||
if let Some(transaction) = self.history.redo() {
|
let mut history = self.history.take();
|
||||||
|
if let Some(transaction) = history.redo() {
|
||||||
let success = self._apply(&transaction, view_id);
|
let success = self._apply(&transaction, view_id);
|
||||||
|
|
||||||
// reset changeset to fix len
|
// reset changeset to fix len
|
||||||
@@ -355,6 +364,7 @@ impl Document {
|
|||||||
|
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
self.history.set(history);
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -373,7 +383,9 @@ impl Document {
|
|||||||
// HAXX: we need to reconstruct the state as it was before the changes..
|
// HAXX: we need to reconstruct the state as it was before the changes..
|
||||||
let old_state = self.old_state.take().expect("no old_state available");
|
let old_state = self.old_state.take().expect("no old_state available");
|
||||||
|
|
||||||
self.history.commit_revision(&transaction, &old_state);
|
let mut history = self.history.take();
|
||||||
|
history.commit_revision(&transaction, &old_state);
|
||||||
|
self.history.set(history);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@@ -383,9 +395,11 @@ impl Document {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_modified(&self) -> bool {
|
pub fn is_modified(&self) -> bool {
|
||||||
|
let history = self.history.take();
|
||||||
|
let current_revision = history.current_revision();
|
||||||
|
self.history.set(history);
|
||||||
self.path.is_some()
|
self.path.is_some()
|
||||||
&& (self.history.current_revision() != self.last_saved_revision
|
&& (current_revision != self.last_saved_revision || !self.changes.is_empty())
|
||||||
|| !self.changes.is_empty())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@@ -194,8 +194,9 @@ impl Editor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn resize(&mut self, area: Rect) {
|
pub fn resize(&mut self, area: Rect) {
|
||||||
self.tree.resize(area);
|
if self.tree.resize(area) {
|
||||||
self._refresh();
|
self._refresh();
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn focus_next(&mut self) {
|
pub fn focus_next(&mut self) {
|
||||||
|
@@ -293,9 +293,13 @@ impl Tree {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resize(&mut self, area: Rect) {
|
pub fn resize(&mut self, area: Rect) -> bool {
|
||||||
self.area = area;
|
if self.area != area {
|
||||||
self.recalculate();
|
self.area = area;
|
||||||
|
self.recalculate();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn recalculate(&mut self) {
|
pub fn recalculate(&mut self) {
|
||||||
|
@@ -143,8 +143,9 @@ impl View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let row = line - self.first_line as usize;
|
// It is possible for underflow to occur if the buffer length is larger than the terminal width.
|
||||||
let col = col - self.first_col as usize;
|
let row = line.saturating_sub(self.first_line);
|
||||||
|
let col = col.saturating_sub(self.first_col);
|
||||||
|
|
||||||
Some(Position::new(row, col))
|
Some(Position::new(row, col))
|
||||||
}
|
}
|
||||||
|
@@ -17,6 +17,15 @@ roots = []
|
|||||||
|
|
||||||
indent = { tab-width = 2, unit = " " }
|
indent = { tab-width = 2, unit = " " }
|
||||||
|
|
||||||
|
[[language]]
|
||||||
|
name = "elixir"
|
||||||
|
scope = "source.elixir"
|
||||||
|
injection-regex = "elixir"
|
||||||
|
file-types = ["ex", "exs"]
|
||||||
|
roots = []
|
||||||
|
|
||||||
|
indent = { tab-width = 2, unit = " " }
|
||||||
|
|
||||||
[[language]]
|
[[language]]
|
||||||
name = "json"
|
name = "json"
|
||||||
scope = "source.json"
|
scope = "source.json"
|
||||||
@@ -65,6 +74,17 @@ roots = []
|
|||||||
|
|
||||||
indent = { tab-width = 2, unit = " " }
|
indent = { tab-width = 2, unit = " " }
|
||||||
|
|
||||||
|
[[language]]
|
||||||
|
name = "typescript"
|
||||||
|
scope = "source.ts"
|
||||||
|
injection-regex = "^(ts|typescript)$"
|
||||||
|
file-types = ["ts"]
|
||||||
|
roots = []
|
||||||
|
# TODO: highlights-jsx, highlights-params
|
||||||
|
|
||||||
|
language-server = { command = "typescript-language-server", args = ["--stdio"] }
|
||||||
|
indent = { tab-width = 2, unit = " " }
|
||||||
|
|
||||||
[[language]]
|
[[language]]
|
||||||
name = "css"
|
name = "css"
|
||||||
scope = "source.css"
|
scope = "source.css"
|
||||||
|
146
runtime/queries/elixir/highlights.scm
Normal file
146
runtime/queries/elixir/highlights.scm
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
["when" "and" "or" "not in" "not" "in" "fn" "do" "end" "catch" "rescue" "after" "else"] @keyword
|
||||||
|
|
||||||
|
[(true) (false) (nil)] @constant.builtin
|
||||||
|
|
||||||
|
(keyword
|
||||||
|
[(keyword_literal)
|
||||||
|
":"] @tag)
|
||||||
|
|
||||||
|
(keyword
|
||||||
|
(keyword_string
|
||||||
|
[(string_start)
|
||||||
|
(string_content)
|
||||||
|
(string_end)] @tag))
|
||||||
|
|
||||||
|
[(atom_literal)
|
||||||
|
(atom_start)
|
||||||
|
(atom_content)
|
||||||
|
(atom_end)] @tag
|
||||||
|
|
||||||
|
(comment) @comment
|
||||||
|
|
||||||
|
(escape_sequence) @escape
|
||||||
|
|
||||||
|
(call function: (function_identifier) @keyword
|
||||||
|
(#match? @keyword "^(defmodule|defexception|defp|def|with|case|cond|raise|import|require|use|defmacrop|defmacro|defguardp|defguard|defdelegate|defstruct|alias|defimpl|defprotocol|defoverridable|receive|if|for|try|throw|unless|reraise|super|quote|unquote|unquote_splicing)$"))
|
||||||
|
|
||||||
|
(call function: (function_identifier) @keyword
|
||||||
|
[(call
|
||||||
|
function: (function_identifier) @function
|
||||||
|
(arguments
|
||||||
|
[(identifier) @variable.parameter
|
||||||
|
(_ (identifier) @variable.parameter)
|
||||||
|
(_ (_ (identifier) @variable.parameter))
|
||||||
|
(_ (_ (_ (identifier) @variable.parameter)))
|
||||||
|
(_ (_ (_ (_ (identifier) @variable.parameter))))
|
||||||
|
(_ (_ (_ (_ (_ (identifier) @variable.parameter)))))]))
|
||||||
|
(binary_op
|
||||||
|
left:
|
||||||
|
(call
|
||||||
|
function: (function_identifier) @function
|
||||||
|
(arguments
|
||||||
|
[(identifier) @variable.parameter
|
||||||
|
(_ (identifier) @variable.parameter)
|
||||||
|
(_ (_ (identifier) @variable.parameter))
|
||||||
|
(_ (_ (_ (identifier) @variable.parameter)))
|
||||||
|
(_ (_ (_ (_ (identifier) @variable.parameter))))
|
||||||
|
(_ (_ (_ (_ (_ (identifier) @variable.parameter)))))]))
|
||||||
|
operator: "when")
|
||||||
|
(binary_op
|
||||||
|
left: (identifier) @variable.parameter
|
||||||
|
operator: _ @function
|
||||||
|
right: (identifier) @variable.parameter)]
|
||||||
|
(#match? @keyword "^(defp|def|defmacrop|defmacro|defguardp|defguard|defdelegate)$")
|
||||||
|
(#match? @variable.parameter "^[^_]"))
|
||||||
|
|
||||||
|
(call (function_identifier) @keyword
|
||||||
|
[(call
|
||||||
|
function: (function_identifier) @function)
|
||||||
|
(identifier) @function
|
||||||
|
(binary_op
|
||||||
|
left:
|
||||||
|
[(call
|
||||||
|
function: (function_identifier) @function)
|
||||||
|
(identifier) @function]
|
||||||
|
operator: "when")]
|
||||||
|
(#match? @keyword "^(defp|def|defmacrop|defmacro|defguardp|defguard|defdelegate)$"))
|
||||||
|
|
||||||
|
(anonymous_function
|
||||||
|
(stab_expression
|
||||||
|
left: (bare_arguments
|
||||||
|
[(identifier) @variable.parameter
|
||||||
|
(_ (identifier) @variable.parameter)
|
||||||
|
(_ (_ (identifier) @variable.parameter))
|
||||||
|
(_ (_ (_ (identifier) @variable.parameter)))
|
||||||
|
(_ (_ (_ (_ (identifier) @variable.parameter))))
|
||||||
|
(_ (_ (_ (_ (_ (identifier) @variable.parameter)))))]))
|
||||||
|
(#match? @variable.parameter "^[^_]"))
|
||||||
|
|
||||||
|
(unary_op
|
||||||
|
operator: "@"
|
||||||
|
(call (identifier) @attribute
|
||||||
|
(heredoc
|
||||||
|
[(heredoc_start)
|
||||||
|
(heredoc_content)
|
||||||
|
(heredoc_end)] @doc))
|
||||||
|
(#match? @attribute "^(doc|moduledoc)$"))
|
||||||
|
|
||||||
|
(module) @type
|
||||||
|
|
||||||
|
(unary_op
|
||||||
|
operator: "@" @attribute
|
||||||
|
[(call
|
||||||
|
function: (function_identifier) @attribute)
|
||||||
|
(identifier) @attribute])
|
||||||
|
|
||||||
|
(unary_op
|
||||||
|
operator: _ @operator)
|
||||||
|
|
||||||
|
(binary_op
|
||||||
|
operator: _ @operator)
|
||||||
|
|
||||||
|
(heredoc
|
||||||
|
[(heredoc_start)
|
||||||
|
(heredoc_content)
|
||||||
|
(heredoc_end)] @string)
|
||||||
|
|
||||||
|
(string
|
||||||
|
[(string_start)
|
||||||
|
(string_content)
|
||||||
|
(string_end)] @string)
|
||||||
|
|
||||||
|
(sigil_start) @string.special
|
||||||
|
(sigil_content) @string
|
||||||
|
(sigil_end) @string.special
|
||||||
|
|
||||||
|
(interpolation
|
||||||
|
"#{" @punctuation.special
|
||||||
|
"}" @punctuation.special)
|
||||||
|
|
||||||
|
[
|
||||||
|
","
|
||||||
|
"->"
|
||||||
|
"."
|
||||||
|
] @punctuation.delimiter
|
||||||
|
|
||||||
|
[
|
||||||
|
"("
|
||||||
|
")"
|
||||||
|
"["
|
||||||
|
"]"
|
||||||
|
"{"
|
||||||
|
"}"
|
||||||
|
"<<"
|
||||||
|
">>"
|
||||||
|
] @punctuation.bracket
|
||||||
|
|
||||||
|
[(identifier) @function.special
|
||||||
|
(#match? @function.special "^__.+__$")]
|
||||||
|
|
||||||
|
[(remote_identifier) @function.special
|
||||||
|
(#match? @function.special "^__.+__$")]
|
||||||
|
|
||||||
|
[(identifier) @comment
|
||||||
|
(#match? @comment "^_")]
|
||||||
|
|
||||||
|
(ERROR) @warning
|
28
runtime/queries/javascript/indents.toml
Normal file
28
runtime/queries/javascript/indents.toml
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
indent = [
|
||||||
|
"array",
|
||||||
|
"object",
|
||||||
|
"arguments",
|
||||||
|
"formal_parameters",
|
||||||
|
|
||||||
|
"statement_block",
|
||||||
|
"object_pattern",
|
||||||
|
"class_body",
|
||||||
|
"named_imports",
|
||||||
|
|
||||||
|
"binary_expression",
|
||||||
|
"return_statement",
|
||||||
|
"template_substitution",
|
||||||
|
# (expression_statement (call_expression))
|
||||||
|
"export_clause",
|
||||||
|
|
||||||
|
# typescript
|
||||||
|
"enum_declaration",
|
||||||
|
"interface_declaration",
|
||||||
|
"object_type",
|
||||||
|
]
|
||||||
|
|
||||||
|
outdent = [
|
||||||
|
"}",
|
||||||
|
"]",
|
||||||
|
")"
|
||||||
|
]
|
36
runtime/queries/typescript/highlights.scm
Normal file
36
runtime/queries/typescript/highlights.scm
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
; inherits: javascript
|
||||||
|
|
||||||
|
; Types
|
||||||
|
|
||||||
|
(type_identifier) @type
|
||||||
|
(predefined_type) @type.builtin
|
||||||
|
|
||||||
|
((identifier) @type
|
||||||
|
(#match? @type "^[A-Z]"))
|
||||||
|
|
||||||
|
(type_arguments
|
||||||
|
"<" @punctuation.bracket
|
||||||
|
">" @punctuation.bracket)
|
||||||
|
|
||||||
|
; Variables
|
||||||
|
|
||||||
|
(required_parameter (identifier) @variable.parameter)
|
||||||
|
(optional_parameter (identifier) @variable.parameter)
|
||||||
|
|
||||||
|
; Keywords
|
||||||
|
|
||||||
|
[
|
||||||
|
"abstract"
|
||||||
|
"declare"
|
||||||
|
"enum"
|
||||||
|
"export"
|
||||||
|
"implements"
|
||||||
|
"interface"
|
||||||
|
"keyof"
|
||||||
|
"namespace"
|
||||||
|
"private"
|
||||||
|
"protected"
|
||||||
|
"public"
|
||||||
|
"type"
|
||||||
|
"readonly"
|
||||||
|
] @keyword
|
1
runtime/queries/typescript/indents.toml
Symbolic link
1
runtime/queries/typescript/indents.toml
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../javascript/indents.toml
|
2
runtime/queries/typescript/locals.scm
Normal file
2
runtime/queries/typescript/locals.scm
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
(required_parameter (identifier) @local.definition)
|
||||||
|
(optional_parameter (identifier) @local.definition)
|
23
runtime/queries/typescript/tags.scm
Normal file
23
runtime/queries/typescript/tags.scm
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
(function_signature
|
||||||
|
name: (identifier) @name) @definition.function
|
||||||
|
|
||||||
|
(method_signature
|
||||||
|
name: (property_identifier) @name) @definition.method
|
||||||
|
|
||||||
|
(abstract_method_signature
|
||||||
|
name: (property_identifier) @name) @definition.method
|
||||||
|
|
||||||
|
(abstract_class_declaration
|
||||||
|
name: (type_identifier) @name) @definition.class
|
||||||
|
|
||||||
|
(module
|
||||||
|
name: (identifier) @name) @definition.module
|
||||||
|
|
||||||
|
(interface_declaration
|
||||||
|
name: (type_identifier) @name) @definition.interface
|
||||||
|
|
||||||
|
(type_annotation
|
||||||
|
(type_identifier) @name) @reference.type
|
||||||
|
|
||||||
|
(new_expression
|
||||||
|
constructor: (identifier) @name) @reference.class
|
@@ -4,6 +4,8 @@ pkgs.mkShell {
|
|||||||
nativeBuildInputs = with pkgs; [
|
nativeBuildInputs = with pkgs; [
|
||||||
(rust-bin.stable.latest.default.override { extensions = ["rust-src"]; })
|
(rust-bin.stable.latest.default.override { extensions = ["rust-src"]; })
|
||||||
lld_10
|
lld_10
|
||||||
|
lldb
|
||||||
|
# pythonPackages.six
|
||||||
stdenv.cc.cc.lib
|
stdenv.cc.cc.lib
|
||||||
# pkg-config
|
# pkg-config
|
||||||
];
|
];
|
||||||
@@ -12,7 +14,7 @@ pkgs.mkShell {
|
|||||||
# https://github.com/rust-lang/rust/issues/55979
|
# https://github.com/rust-lang/rust/issues/55979
|
||||||
LD_LIBRARY_PATH="${stdenv.cc.cc.lib}/lib64:$LD_LIBRARY_PATH";
|
LD_LIBRARY_PATH="${stdenv.cc.cc.lib}/lib64:$LD_LIBRARY_PATH";
|
||||||
|
|
||||||
# HELIX_RUNTIME=./runtime;
|
shellHook = ''
|
||||||
HELIX_RUNTIME="/home/speed/src/helix/runtime";
|
export HELIX_RUNTIME=$PWD/runtime
|
||||||
|
'';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user