Compare commits

..

2280 Commits

Author SHA1 Message Date
Michael Davis
2dbec4c933 Add a document for the runtime directory
This help topic should otherwise belong under `runtime/help/topics`
but it should be accessible if the runtime directory is not correctly
installed.

This article shows up under `:help topics` because of the symlink
but can also be accessed by `:help runtime` if necessary.
2022-12-12 21:41:31 -06:00
Michael Davis
233b10f7fc Use markdown instead of text for help files 2022-12-12 20:27:33 -06:00
Michael Davis
0e037802c2 Use an overlayed component for the topics picker
This prevents the topics file picker from consuming the whole screen
and makes it consistent with the standard file and buffer pickers.
2022-12-12 20:22:04 -06:00
Michael Davis
19111e1478 Use doc_mut! macro for document accesses 2022-12-12 20:21:44 -06:00
Michael Davis
816dfee64a Bail on zero-arg :help invocation 2022-12-12 20:06:07 -06:00
Omnikar
321fce3ba6 Add :help command 2022-12-12 20:02:36 -06:00
dependabot[bot]
fa436fa680 build(deps): bump tokio from 1.22.0 to 1.23.0 (#5137)
Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.22.0 to 1.23.0.
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.22.0...tokio-1.23.0)

---
updated-dependencies:
- dependency-name: tokio
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-12 17:25:05 -06:00
dependabot[bot]
f995f2610b build(deps): bump serde from 1.0.149 to 1.0.150 (#5138)
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.149 to 1.0.150.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.149...v1.0.150)

---
updated-dependencies:
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-12 17:20:26 -06:00
Blaž Hrastnik
bae890d8fa Update tree-sitter-scheme 2022-12-12 17:50:12 +09:00
Alexander Schlögl
0b96021643 Add :pipe-to typable command that ignores shell output (#4931) 2022-12-11 20:06:24 -06:00
Marco Ieni
d5ab974d38 chore(book): link repository (#5101) 2022-12-11 19:59:53 -06:00
garlic0x1
a34ba071be Fix commonlisp filetypes typo and auto-pairs (#5091) 2022-12-11 19:59:27 -06:00
Slug
c5bfb792b2 update(theme): adjust base16_transparent and dark_high_contrast (#5105) 2022-12-11 12:14:10 -06:00
Michael Davis
cdc54f50a2 Reset mode when changing buffers (#5072)
* Reset mode when changing buffers

This is similar to the change in
e4c9d4082a: reset the editor to normal
mode when changing buffers. Usually the editor is already in normal
mode but it's possible to setup insert-mode keybindings that change
buffers.

* Move normal mode entering code to Editor

This should be called internally in the Editor when changing documents
(Editor::switch) or changing focuses (Editor::focus).
2022-12-12 00:04:08 +09:00
Pascal Kuthe
70d78123b9 properly handle detachted git worktrees (#5097) 2022-12-11 19:20:34 +09:00
Ollie Charles
0e8ea13696 Add Haskell text objects (#5061) 2022-12-10 14:03:18 -06:00
Danilo Spinella
f323ffabcc Treat patches as diff files (#5085) 2022-12-09 18:40:27 -06:00
Felipe S. S. Schneider
d14de27709 Add support for the BibTeX file format (#5064) 2022-12-08 22:33:08 -06:00
two-six
37e7dd1df5 Update diagnostic.error background for acme theme (#5019) 2022-12-08 22:11:25 -06:00
TotalKrill
16e13b9789 allow specifying environment for language servers in language.toml (#4004)
Signed-off-by: Stephen Wakely <fungus.humungus@gmail.com>
Co-authored-by: Stephen Wakely <fungus.humungus@gmail.com>
Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
2022-12-08 22:09:23 -06:00
Jummit
2ea20a23e2 Fix LSP completions ignoring auto-completion option (#5042) 2022-12-08 22:02:34 -06:00
Matouš Dzivjak
8abed3bd78 feat(lsp): pass client_info on initialization (#4904)
Pass client name ('helix') and client version (version / git hash)
to LSP server on initialization.
2022-12-08 21:57:03 -06:00
ath3
6798a6651f Only write newlines in menu selection popup if the lsp returns detail (#4902) 2022-12-08 21:55:15 -06:00
cor
d914642089 use curl underlines for gruvbox_dark_hard (#5066) 2022-12-08 21:48:56 -06:00
LeoniePhiline
36eff1da8c fix(tutor): Capitalize first letter of a sentence (#5075) 2022-12-08 20:58:15 -06:00
Jens Getreu
f8b75a245a Autumn theme: use new features (#5051)
Co-authored-by: Jens Getreu <jens.getreu@dlh.lu>
2022-12-08 10:48:01 +09:00
Alexander Brevig
a4de86e7af fix(theme): git gutter for flatwhite (#5036) 2022-12-07 20:30:46 +09:00
Alexander Brevig
9d4236941d fix(theme): serika toml syntax valid (#5038) 2022-12-07 20:29:56 +09:00
Michael Davis
96ff64a84a Add changelog notes for 22.12 (#4822)
* Add changelog notes for 22.12

* Bump VERSION to 22.12
2022-12-07 11:54:50 +09:00
Jonathan LEI
d3f670c0e2 Use OSC 52 for tmux copy (#5027) 2022-12-07 11:11:45 +09:00
Kristoffer Flottorp
e9d43c284b Fleetish theme renamed to fleet dark and adjusted to match official theme. (#4997)
* remove fleetish.toml

* add fleet_dark.toml

* adjust colors for tags and markup lists

* Add type.enum.variant

* correct color for focused elements

* adjust builtins and keywords

Co-authored-by: krfl <kr.fl@outlook.com>
2022-12-07 10:08:34 +09:00
Pascal Kuthe
af532147c9 Add command/keybinding to jump between hunks (#4650)
* add command and keybding to jump to next/prev hunk

* add textobject for change

* Update helix-vcs/src/diff.rs

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>

* select entire hunk instead of first char

* fix selection range

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2022-12-06 23:18:33 +09:00
Narazaki Shuji
453a75a373 fix: align view after jumplist_picker (#3743)
* Add `View::ensure_cursor_in_view_center` to adjust view after searching and jumping

Also `offset_coodrs_to_in_view` was refactored to reduce duplicated position calculations.

* Fix a wrong offset calculation in `offset_coords_to_in_view_center`

It ignored `scrolloff` if `centering` is false.
2022-12-06 11:16:08 +09:00
dependabot[bot]
952f292d25 build(deps): bump serde from 1.0.148 to 1.0.149 (#5017)
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.148 to 1.0.149.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.148...v1.0.149)

---
updated-dependencies:
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-06 10:30:11 +09:00
dependabot[bot]
dbed90c5a6 build(deps): bump git-repository from 0.26.0 to 0.29.0 (#5016)
Bumps [git-repository](https://github.com/Byron/gitoxide) from 0.26.0 to 0.29.0.
- [Release notes](https://github.com/Byron/gitoxide/releases)
- [Changelog](https://github.com/Byron/gitoxide/blob/main/CHANGELOG.md)
- [Commits](https://github.com/Byron/gitoxide/compare/git-repository-v0.26.0...git-repository-v0.29.0)

---
updated-dependencies:
- dependency-name: git-repository
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-06 10:30:04 +09:00
Michael Davis
2077f5e26a Apply completion edits to all cursors (#4496)
Completion edits - either basic `insert_text` strings or structured
`text_edit`s - are assumed by the LSP spec to apply to the current
cursor (or at least the trigger point). We can use the range (if any)
and text given by the Language Server to create a transaction that
changes all ranges in the current selection though, allowing auto-
complete to affect multiple cursors.
2022-12-06 10:29:40 +09:00
nosa
7210c58a51 Change default TS object bindings (#3782)
* Change default TS object bindings

Changes 'match inside/around' bindings for:
- type definition from `c` to `t`
- comments from `o` to `c`
- tests from `t` to `T`

Also changes those for the `]` / `[` bindings.

* Update docs for changed keybinds

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2022-12-06 10:13:41 +09:00
VuiMuich
5691ada822 Change diff colors for serika themes (#5015) 2022-12-05 16:28:20 -06:00
Matouš Dzivjak
5781aa0264 feat(highlights): go builtin funcs and types (#5010)
Add highlight scopes for golang built-in functions and types.
Based on https://pkg.go.dev/builtin.
2022-12-06 00:16:25 +09:00
two-six
f712d316e5 Update Acme and Nord Light for git gutters (#4999)
* Update acme.toml

* Update nord_light.toml

* Update runtime/themes/nord_light.toml

Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>

* Update acme.toml

Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
2022-12-05 22:48:20 +09:00
Pascal Kuthe
b0f20f13e3 fix git diff when core.autocrlf is enabled (#4995) 2022-12-05 22:46:59 +09:00
Pascal Kuthe
1e31bc3f77 Reduce log message about diff timeout from warn to info (#5012) 2022-12-05 22:18:42 +09:00
Blaž Hrastnik
03ca18b377 Update language support docs 2022-12-05 15:02:13 +09:00
Blaž Hrastnik
417676953b Add basic support for common lisp 2022-12-05 14:40:41 +09:00
farwyler
59cfe95776 Add support for single-line comments to scss (#5003) 2022-12-04 09:45:31 -06:00
Michael Davis
c13c6d56b6 Use logo for contrib icon (#4982) 2022-12-04 11:07:17 +09:00
PORTALSURFER
e9d0645f66 Adjusted hex themes for new gutter diff colors (#4990)
* added 2 themes

* diff feature fixes

adjusted the skin to better work with the new diff coloring features

propagates to child skins like
- hex_toxic

* fine tuning so it all is a bit softer

* fine tuning to be softer

* added new version, lavender
2022-12-04 11:06:40 +09:00
Jens Getreu
326a0dab06 Autumn theme: adjust some gray colors (#4996) 2022-12-04 11:03:42 +09:00
Aleksey Kuznetsov
2123e91e56 Enable auto format for css and scss files (#4987)
provideFormatter enables capability in LS and
auto-format performs format on save
2022-12-03 08:24:43 -06:00
Michael Davis
bcdb475b71 Fix transaction composition order in History::changes_since (#4981)
* Add a undo/redo split test case for crossing branches

* history: Switch up/down transaction chaining order

The old code tends to work in practice because, usually, either up_txns
or down_txns are empty. When both have contents though, we can run into
a panic trying to compose them all since they will disagree on the
length of the text. This fixes the panic test case in the parent
commit.
2022-12-03 12:09:08 +09:00
Luna
dc00291b48 Update Doom Acario for git gutters (#4979)
Edited the diff.delta from green to blue.
2022-12-03 11:26:10 +09:00
Anton Romanov
224a024d39 Update zenburn theme for git gutters (#4977) 2022-12-03 11:26:01 +09:00
Pascal Kuthe
b677c6a019 Add logo with text included (#4973) 2022-12-03 11:05:15 +09:00
alex 孙欣乐
59b886cf5e nightfox theme: Use brighter colors for diff scopes (#4966) 2022-12-02 08:24:00 -06:00
Matouš Dzivjak
d0bc38d6fa feat(lang): bump tree-sitter-go (#4969)
Update tree-sitter-go to latest with updated support for generics.

See: 0fa917a702..05900faa3c
for full diff.
2022-12-02 08:06:35 -06:00
lesleyrs
39ce82b7a5 Add Ctrl-i alias for Windows (#4961) 2022-12-02 08:02:29 -06:00
Michael Davis
8c2692caf1 Use the logo as the favicon for the docs book (#4971) 2022-12-02 22:45:06 +09:00
Matouš Dzivjak
c38519c57a feat(docs): style readme & add badges (#4970)
Centre Helix title and logo and add badge with latest
release and link to matrix chat.
2022-12-02 20:56:36 +09:00
Blaž Hrastnik
98c121c9fc Detect WezTerm and mark it as undercurl/Smulx capable 2022-12-02 17:42:10 +09:00
Blaž Hrastnik
e92651816d Forgot to set the height 2022-12-02 12:07:08 +09:00
Blaž Hrastnik
dc1ec56322 Add the new logo! 2022-12-02 12:06:17 +09:00
Blaž Hrastnik
700f8ba252 Use cargo fmt's --check 2022-12-02 10:33:53 +09:00
sigmaSd
4960c41f18 feat(lsp): add support for lsp Diagnostic{}.data (#4935) 2022-12-02 10:18:45 +09:00
Michael Davis
8291654326 reload_all: Ensure view is synced with doc history before reload (#4965) 2022-12-02 10:18:32 +09:00
Bertrand Bousquet
71a3a23f42 Varua theme updates (cursorline, statusline) (#4964) 2022-12-02 10:18:18 +09:00
Tshepang Mbambo
e3f05603ac tutor: Clarify space searching instructions (#4953) 2022-12-01 15:55:52 -06:00
Tshepang Mbambo
a8a54be6bc Fix nightly clippy lints (#4954) 2022-12-01 10:37:38 -06:00
Pascal Kuthe
5a3ff74221 Show (git) diff signs in gutter (#3890)
* Show (git) diff signs in gutter (#3890)

Avoid string allocation when git diffing

Incrementally diff using changesets

refactor diffs to be provider indepndent and improve git implementation

remove dependency on zlib-ng

switch to asynchronus diffing with similar

Update helix-vcs/Cargo.toml

fix toml formatting

Co-authored-by: Ivan Tham <pickfire@riseup.net>

fix typo in documentation

use ropey reexpors from helix-core

fix crash when creating new file

remove useless use if io::Cursor

fix spelling mistakes

implement suggested improvement to repository loading

improve git test isolation

remove lefover comments

Co-authored-by: univerz <univerz@fu-solution.com>

fixed spelling mistake

minor cosmetic changes

fix: set self.differ to None if decoding the diff_base fails

fixup formatting

Co-authored-by: Ivan Tham <pickfire@riseup.net>

reload diff_base when file is reloaded from disk

switch to imara-diff

Fixup formatting

Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>

Redraw buffer whenever a diff is updated.

Only store hunks instead of changes for individual lines to easily allow
jumping between them

Update to latest gitoxide version

Change default diff gutter position

Only update gutter after timeout

* update diff gutter synchronously, with a timeout

* Apply suggestions from code review

Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>

* address review comments and ensure lock is always aquired

* remove configuration for redraw timeout

Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2022-12-01 17:35:23 +09:00
Michael Davis
67415e096e Fix file-types declaration for racket (#4915)
Both the racket and scheme entries used the rkt file-extension. This
commit removes that entry for scheme and so that the racket entry takes
precedence. We explicitly point to the scheme grammar now and setup
queries that inherit from scheme. This should enable using the racket
language server configuration.
2022-11-30 23:27:08 +09:00
André Sá
664d08e70d Fix ayu theme cursor issue (#4764) 2022-11-29 17:30:06 -06:00
Michael Davis
607c74efde Handle disambiguated keycodes (#4887)
Media keys are sent despite `DISAMBIGUATE_ESCAPE_CODES` being unset.
Previously we panicked on these. This change translates the
disambiguated keys from crossterm so that they do not cause a panic.
2022-11-30 01:15:55 +09:00
Michael Davis
260341ed80 Sync all document changes on view focus 2022-11-30 01:15:20 +09:00
Michael Davis
4802f26a23 Add a test case for undo/redo across splits 2022-11-30 01:15:20 +09:00
Michael Davis
9387dfafed Use lowest common ancestor search in History::changes_since 2022-11-30 01:15:20 +09:00
Michael Davis
9a9e462183 Call View::apply within Document::append_changes_to_history 2022-11-30 01:15:20 +09:00
Michael Davis
2709ce3332 Sync changes with view in undo/redo/earlier/later 2022-11-30 01:15:20 +09:00
Michael Davis
53c2855643 Remove calls to View::apply in undo/redo/earlier/later 2022-11-30 01:15:20 +09:00
Michael Davis
056a19a003 Sync changes between doc and view on switch 2022-11-30 01:15:20 +09:00
Michael Davis
4d1f5389f9 Revert "Don't apply transactions to Views in undo/redo"
This reverts commit fd00f3a70e.
2022-11-30 01:15:20 +09:00
Michael Davis
df5457a6e7 Remove eager application of transactions to all views 2022-11-30 01:15:20 +09:00
Kirawi
04df9e4445 delete outdated reference to cessen/ropey#25 (#4928) 2022-11-28 19:07:47 -06:00
Erik Bünnig
5c213f7de4 fix(grammar): Add block_comment and comment_environment injection for latex comments (#4922) 2022-11-28 09:19:16 -06:00
Pascal Kuthe
da355a3231 Significantly improve performance of :reload (#4457)
* bump ropey to 1.5.1-alpha

* significantly improve performance of :reload
2022-11-28 11:20:54 +09:00
Pascal Kuthe
a549328ef2 bump ropey to 1.5.1-alpha 2022-11-28 02:51:26 +01:00
Chickenkeeper
bf908cc4a1 Update CSS syntax highlighting (#4882) 2022-11-27 19:11:12 -06:00
gavincrawford
583c2a5456 Fix Go variable indentation (#4906) 2022-11-27 09:36:52 -06:00
Filipe Azevedo
f0f295a667 reload-all: Only update viewport when view focuses on the doc (#4901) 2022-11-26 14:40:43 -06:00
Lennard Hofmann
fc811726e0 Update tree-sitter-java and add Java textobjects (#4886) 2022-11-26 10:17:10 -06:00
Michael Davis
8529d756fa Remove selections for closed views on all documents (#4888)
Previously we removed selections for a closed view on only the
currently focused document. A view might have selections in other
documents though, so the view needs to be removed from all documents.
2022-11-26 11:52:22 +09:00
Matouš Dzivjak
4e52d4d6f4 feat(themes): improve fleetish (#4813)
Small adjustements to the fleetish theme to improve readability
in certain cases. Specifically:

- use darker background for menues as it (purely subjectively) loooks
  better
- use different color for `constant.buildin.boolean` and
  `keyword` to make statements such as `return true` read better
- use different colors for different markup link parts
- destructure the config where appliable
2022-11-26 10:52:34 +09:00
Chickenkeeper
f2a55331d0 Bump tree-sitter-html version (#4881) 2022-11-25 19:43:41 -06:00
Jan Scheer
6cdc567372 add theme nightfox (#4769)
This theme is an adaptation of
github.com/EdenEast/nightfox.nvim
2022-11-25 19:41:37 -06:00
Michael Davis
2271c3aed9 Clear line on <ret> when line is all whitespace (#4854)
This matches the insert-mode behavior for Vim and Kakoune: if the
current line is empty except for whitespace, `<ret>` should insert a
line ending at the beginning of the line, moving any indentation to the
next line.
2022-11-25 11:40:48 +09:00
Michael Davis
e6dad960cf Drain pending requests on language server termination (#4852)
This prevents a freeze while shutting down when using `efm-langserver`.
`efm-langserver` exits immediately after seeing a shutdown request,
without responding to the request. We block awaiting the reply to the
shutdown request which will never come, so we time out.

This change responds to any pending requests with `Err` saying that the
stream has been closed.
2022-11-24 11:07:42 +09:00
Jonathan LEI
1d21683321 Exit select mode on surround commands (#4858) 2022-11-24 11:07:19 +09:00
Michael Davis
ee06d4d337 Update tree-sitter-gleam
This update includes a handful of fixes, a new binary concatenation
operator (already highlighted by the `binary_operator` rule), and a
new `use` language construct. The nodes are backwards compatible but
this update introduces two new nodes for highlighting: `use` and `<-`.
2022-11-24 11:07:05 +09:00
Michael Davis
cbc72e84d7 Update tree-sitter-heex
tree-sitter-heex split out the ending_expression_value from the
partial_expression value which can help with indentation.
2022-11-24 11:07:05 +09:00
Michael Davis
5a1bed2b70 Add parameter highlights to Erlang
This doesn't work robustly (within pattern matches). Only regular
bindings are highlighted as parameters. In order to highlight all
parameters even in matches, we would need an arbitrary nesting operator
in queries which doesn't exist yet in tree-sitter.
2022-11-24 11:07:05 +09:00
Michael Davis
452f7d071c Improve Edoc highlighting within Erlang
This highlights edoc within Erlang comments. The trick was to have
the Erlang grammar consume newlines and then give them to EDoc in the
injection to use so that line-wise elements could be parsed accurately.
2022-11-24 11:07:05 +09:00
Michael Davis
a3f321a531 Follow parent links when calculating changes since a revision
The 'revisions' field on History can't be treated as linear: each
Revision in the revisions Vec has a parent link and an optional child
link. We can follow those to unroll the recent history.
2022-11-24 10:57:12 +09:00
Michael Davis
4a103db622 Apply inversions to Views on undo/redo
When using undo/redo, the history revision can be decremented. In that
case we should apply the inversions since the given revision in
History::changes_since. This prevents panics with jumplist operations
when a session uses undo/redo to move the jumplist selection outside
of the document.
2022-11-24 10:57:12 +09:00
Michael Davis
fd00f3a70e Don't apply transactions to Views in undo/redo
View::apply should only be called by EditorView after
42e37a571e. This change removes the
duplicate calls within undo/redo which could cause a panic.
2022-11-24 10:57:12 +09:00
Michael Davis
94eb3de776 Add test case that panics on undo
This case panics since undo/redo call View::apply and here, the edit
that moves the jumplist selection out-of-bounds is not yet applied when
View::apply is called in undo/redo. View::apply should only be called
by the EditorView now.
2022-11-24 10:57:12 +09:00
Tshepang Mbambo
590a628460 tutor: Add missing quotes (#4832) 2022-11-22 21:51:17 -06:00
alois31
26ec1cf39a Add QML language support (#4842)
Fixes https://github.com/helix-editor/helix/issues/2771
2022-11-22 21:49:02 -06:00
Michael Davis
42e37a571e Apply transactions to all views (#4733)
* Add a test case for updating jumplists across windows

* Apply transactions to all views on history changes

This ensures that jumplist selections follow changes in documents, even
when there are multiple views (for example a split where both windows
edit the same document).

* Leave TODOs for cleaning up View::apply

* Use Iterator::reduce to compose history transactions

Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>

Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
2022-11-23 12:28:49 +09:00
dependabot[bot]
642a961c03 build(deps): bump tokio from 1.21.2 to 1.22.0 (#4846)
Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.21.2 to 1.22.0.
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.21.2...tokio-1.22.0)

---
updated-dependencies:
- dependency-name: tokio
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-22 13:24:37 -06:00
dependabot[bot]
5ad3befe9a build(deps): bump Swatinem/rust-cache from 1 to 2 (#4843)
Bumps [Swatinem/rust-cache](https://github.com/Swatinem/rust-cache) from 1 to 2.
- [Release notes](https://github.com/Swatinem/rust-cache/releases)
- [Changelog](https://github.com/Swatinem/rust-cache/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Swatinem/rust-cache/compare/v1...v2)

---
updated-dependencies:
- dependency-name: Swatinem/rust-cache
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-22 18:15:36 +09:00
Blaž Hrastnik
6aa345a6ce ci: Simplify tag name fetching (set-output is deprecated) 2022-11-22 18:08:11 +09:00
Blaž Hrastnik
33ae498e9f ci: Remove a bunch of actions-rs/cargo uses 2022-11-22 18:08:11 +09:00
Pascal Kuthe
f538b69759 significantly improve treesitter performance while editing large files (#4716)
* significantly improve treesitter performance while editing large files

* Apply stylistic suggestions from code review

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>

* use PartialEq and Hash instead of a freestanding function

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2022-11-22 11:54:22 +09:00
Michael Davis
9059c65a53 lsp: Check server provider capabilities (#3554)
Language Servers may signal that they do not support a method in
the initialization result (server capabilities). We can check these
when making LSP requests and hint in the status line when a method
is not supported by the server. This can also prevent crashes in
servers which assume that clients do not send requests for methods
which are disabled in the server capabilities.

There is an existing pattern the LSP client module where a method
returns `Option<impl Future<Output = Result<_>>>` with `None` signaling
no support in the server. This change extends this pattern to the rest
of the client functions. And we log an error to the statusline for
manually triggered LSP calls which return `None`.
2022-11-22 11:52:23 +09:00
Bob
1db01caec7 remove duplicated shell calls (#3465) 2022-11-22 10:55:46 +09:00
Michael Davis
8102c3224f Limit the number of items in the jumplist (#4750)
Previously, jumplists could grow unchecked. Every transaction is
applied to jumplist selections to ensure that they are up to date
and within document bounds, so this would cause every edit to become
more expensive as jumplist lengths increased throughout a session.
Setting a maximum number of entries limits the cost.

Vim and Neovim limit their jumplists:

* b298fe6cba/src/structs.h (L141)
* e8cc489acc/src/nvim/mark_defs.h (L57)

Notably, Kakoune does not. In Kakoune, changes are applied to jumplist
entries lazily as you hit `<C-o>`/`<C-i>` though, so Kakoune doesn't
have the same growing cost concerns. Kakoune also does not have a
concept of a View which limits the cost further.

Vim and Neovim limit to 100. This seems unreasonably high to me so I've
set this to 30 to start. We can increase if this is problematically
low.
2022-11-22 10:54:50 +09:00
dependabot[bot]
4443885b38 build(deps): bump cc from 1.0.76 to 1.0.77 (#4844)
Bumps [cc](https://github.com/rust-lang/cc-rs) from 1.0.76 to 1.0.77.
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Commits](https://github.com/rust-lang/cc-rs/compare/1.0.76...1.0.77)

---
updated-dependencies:
- dependency-name: cc
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-21 17:47:45 -06:00
dependabot[bot]
4ef6621c24 build(deps): bump serde_json from 1.0.87 to 1.0.88 (#4845)
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.87 to 1.0.88.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.87...v1.0.88)

---
updated-dependencies:
- dependency-name: serde_json
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-21 17:46:59 -06:00
Yusuf Bera Ertan
48e44720e4 build(nix): don't run tests in builds since CI runs them already, update inputs (#4834) 2022-11-21 09:06:43 -06:00
Michael Davis
0b2bb061b9 Bump TREE_SITTER_MATCH_LIMIT to 256 (#4830)
The limit of 64 breaks some highlighting in Erlang files with
complicated record definitions. Bumping to 256  seems to work on all
files I have seen.
2022-11-21 18:13:59 +09:00
Michael Davis
bbde897ac3 Select new pasted text in normal mode only (#4824)
d6323b7cbc changed the behavior of paste
to select the newly inserted text. This is preferrable in normal mode
because it's useful to be able to act on the new text. This behavior
is worse for insert or select mode though:

* In insert mode, the cursor ends up on the last character of the newly
  selected text, so further typing inserts text before the last
  character.
* In select mode, the current selection is replaced with the new text
  selection which doesn't extend the current selection. With this
  change, the selection is extended to include the new text.

This aligns the behavior more closely with Kakoune, but it's
coincidental instead of intentional: Kakoune doesn't implement
bracketed paste (AFAIK) which causes this behavior in insert mode,
and Kakoune doesn't have a select mode.
2022-11-21 11:49:44 +09:00
A-Walrus
2f9ca3840a Add preview for scratch buffers in buffer picker (#3454) 2022-11-20 19:58:35 -06:00
Sora
420e33a600 Implement simple indents.scm for Elixir (#4821) 2022-11-20 18:36:19 -06:00
Chickenkeeper
117239ea45 Fix broken html doctype highlighting (#4829) 2022-11-20 12:51:58 -06:00
Filipe Azevedo
8dac863a5b Add :reload-all command (#4663) 2022-11-20 12:39:26 -06:00
Matthew Toohey
46eb185d45 build(nix): update nci (#4823) 2022-11-19 19:54:47 -06:00
Lennard Hofmann
0e23e4f882 Make r<tab> and f<tab> work (#4817)
Previously, commands such as `r<tab>` (replace with tab) or `t<tab>`
(select till tab) had no effect. This is because `KeyCode::Tab` needs
special treatment (like `KeyCode::Enter`).
2022-11-19 11:08:03 -06:00
Blaž Hrastnik
7e99087fa3 minor: render_diagnostics doesn't require &self either 2022-11-19 15:41:55 +09:00
Blaž Hrastnik
a640ab6b1f Avoid repeatedly loading config 2022-11-19 15:41:03 +09:00
Michael Davis
8be2d1dcbf Handle language server termination (#4797)
This change handles a language server exiting. This was a UX sore-spot:
if a language server crashed, Helix did not recognize the exit and
continued to send requests to it. All requests would timeout since they
would not receive responses. This would also hold-up Helix closing
itself down since it would try to gracefully shutdown the server which
is implemented in the LSP spec as a request.

We could attempt to automatically restart the language server on crash.
I left this for future work since that change will need to be slightly
complicated: it will need to cover the case of a language server
repeatedly crashing.
2022-11-19 13:14:36 +09:00
ath3
598bd8bf11 Update tree-sitter-cmake (#4809) 2022-11-18 14:13:13 -06:00
Michael Davis
89efb4f711 lsp: Resolve completion item asynchronously on idle-timeout (#4781)
d7d0d5ffb7 resolves completion items on
the idle-timeout event. The `Completion::resolve_completion_item`
function blocks on the LSP request though, which blocks the compositor
and in turn blocks the event loop. So until the language server returns
the resolved completion item, Helix is unable to respond to keypresses
or other LSP messages.

This is typically ok since the resolution request is fast but for some
language servers this can be problematic, and ideally we shouldn't be
blocking like this anyways.

When receiving a `completionItem/resolve` request, the Volar server
sends a `workspace/configuration` request to Helix and blocks itself
on the response, leading to a deadlock. Eventually the resolve request
times out within Helix but Helix is locked up and unresponsive in that
window.

This change resolves the completion item without blocking the
compositor.
2022-11-19 03:27:46 +09:00
Ollie Charles
eada6d534e Match .hs-boot files to Haskell (#4800)
Haskell source files are now either `.hs` (as before) or `.hs-boot`, which is a type of Haskell file that only contains type declarations (https://downloads.haskell.org/ghc/latest/docs/users_guide/separate_compilation.html#how-to-compile-mutually-recursive-modules)
2022-11-18 08:36:40 -06:00
Rohit K Viswanath
58e7e1c5e3 Theme: Mellow (#4770) 2022-11-18 08:33:55 -06:00
wes adams
19694877aa When buffer closes, focus on parent buffer (#4766) 2022-11-17 20:53:49 -06:00
Austen Adler
1569d2000b Select surrounding characters when using match/surround (m) mode (#4752)
Co-authored-by: Austen Adler <agadler@austenadler.com>
2022-11-17 20:46:03 -06:00
Felipe S. S. Schneider
9a4e6fdf25 Add support for color modes with Monokai Pro (#4789) 2022-11-17 20:22:49 -06:00
Blaž Hrastnik
767b179839 Update lang-support doc 2022-11-18 10:53:08 +09:00
Blaž Hrastnik
433ccef3fc Make nil the preferred language server over rnix-lsp 2022-11-18 09:52:05 +09:00
ChrHorn
322e957ea1 Remove prefix filtering from autocomplete menu (#4578)
PR #4134 switched the autocomplete menu from alphabetical to fuzzy
sorting. This commit removes the still existing filtering by prefix and
should enable full fuzzy sorting of the autocomplete menu.

closes #3084, #1807

Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
2022-11-17 10:16:03 +09:00
kristopherbullinger
7483c76222 update x_offset calculation in Buffer::set_string_truncated (#3839)
when `truncate_start` is `true`, the `x_offset` is now properly updated
according to the width of the content or the truncated length.
2022-11-17 10:06:50 +09:00
Michael Davis
94346356e7 Use TreeCursor to pretty-print :tree-sitter-subtree (#4606)
The current `:tree-sitter-subtree` has a bug for field-names when the
field name belongs to an unnamed child node. Take this ruby example:

    def self.method_name
      true
    end

The subtree given by tree-sitter-cli is:

    (singleton_method [2, 0] - [4, 3]
      object: (self [2, 4] - [2, 8])
      name: (identifier [2, 9] - [2, 20])
      body: (body_statement [3, 2] - [3, 6]
        (true [3, 2] - [3, 6])))

But the `:tree-sitter-subtree` output was

    (singleton_method
      object: (self)
      body: (identifier)
      (body_statement (true)))

The `singleton_method` rule defines the `name` and `body` fields in an
unnamed helper rule `_method_rest` and the old implementation of
`pretty_print_tree_impl` would pass the `field_name` down from the
named `singleton_method` node.

To fix it we switch to the [TreeCursor] API which is recommended by
the tree-sitter docs for traversing the tree. `TreeCursor::field_name`
accurately determines the field name for the current cursor position
even when the node is unnamed.

[TreeCursor]: https://docs.rs/tree-sitter/0.20.9/tree_sitter/struct.TreeCursor.html
2022-11-17 10:03:02 +09:00
Michael Davis
c6b83368b3 Capture word parts while calculating shellwords (#4632)
This fixes an edge case for completing shellwords. With a file
"a b.txt" in the current directory, the sequence `:open a\<tab>`
will result in the prompt containing `:open aa\ b.txt`. This is
because the length of the input which is trimmed when replacing with
completion is calculated on the part of the input which is parsed by
shellwords and then escaped (in a separate operation), which is lossy.
In this case it loses the trailing backslash.

The fix provided here refactors shellwords to track both the _words_
(shellwords with quotes and escapes resolved) and the _parts_ (chunks
of the input which turned into each word, with separating whitespace
removed). When calculating how much of the input to delete when
replacing with the completion item, we now use the length of the last
part.

This also allows us to eliminate the duplicate work done in the
`ends_with_whitespace` check.
2022-11-17 10:00:48 +09:00
Michael Davis
b474ee1843 Factor out common code for focusing the next view (#4607)
There is some common code between Editor::focus_next and Editor::focus
that can be eliminated by refactoring Tree::focus_next into a function
that only returns the next ViewId.
2022-11-17 09:59:59 +09:00
Michael Davis
6eec14ee37 Use key-sequence format for command palette keybinds (#4712)
The text within the command palette used a custom format to display
the keybinding for a command. This change switches to the key sequence
format that we use for pending keys and macros.
2022-11-17 09:58:54 +09:00
Pascal Kuthe
4b89177e53 sort fuzzy matches with equal score by length in picker (#4698) 2022-11-16 17:28:20 -06:00
Blaž Hrastnik
fe11ae2218 minor: Simplify some command code 2022-11-16 18:14:30 +09:00
Blaž Hrastnik
a3173c2280 minor: cloning filter and using count() is wasteful here 2022-11-16 18:14:30 +09:00
Garrett D'Amore
f843967059 Improvements to Meson syntax. (#4572)
Co-authored-by: Garrett D'Amore <garrett.damore@weka.io>
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2022-11-15 20:17:03 -06:00
dependabot[bot]
70ebbd018a build(deps): bump chrono from 0.4.22 to 0.4.23 (#4747)
Bumps [chrono](https://github.com/chronotope/chrono) from 0.4.22 to 0.4.23.
- [Release notes](https://github.com/chronotope/chrono/releases)
- [Changelog](https://github.com/chronotope/chrono/blob/main/CHANGELOG.md)
- [Commits](https://github.com/chronotope/chrono/compare/v0.4.22...v0.4.23)

---
updated-dependencies:
- dependency-name: chrono
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-15 13:20:39 -06:00
dxtr85
888368dae9 Fix deprecation warnings for chrono 0.4.23 (#4738)
Co-authored-by: dxtr <dxtr@W540.mito>
2022-11-15 13:08:29 -06:00
Blaž Hrastnik
df6d04425d fix build 2022-11-15 23:34:00 +09:00
Armin Ronacher
392a018aeb Add command to add word boundaries to search (#4322)
* Add command to add word boundaries to search

* Calculate string capacity before building
2022-11-15 23:16:27 +09:00
Manos Mertzianis
77be98c783 Popup scrollbar (#4449)
* init

* cargo fmt

* optimisation of the scrollbar render both for Menu and Popup. Toggling off scrollbar for Popup<Menu>, since Menu has its own

* rendering scroll track

* removed unnecessary cast

* improve memory allocation

* small correction
2022-11-15 23:15:52 +09:00
ath3
3b7760dfb0 Refactor blackhole register (#4504) 2022-11-15 23:14:18 +09:00
Michael Davis
652497bdd6 Use tree-sitter-bicep fork with sources checked in (#4751) 2022-11-15 14:57:36 +09:00
Sora
506e8caba7 Remove Statement in Zig indentation query (#4745) 2022-11-14 19:46:38 -06:00
Gaurav Tyagi
91ff903bf3 Add global error/warning count statusline element (#4569) 2022-11-14 19:46:07 -06:00
Jonathan
1233c9a989 Add support for Bicep files (#4403) 2022-11-14 19:43:22 -06:00
dependabot[bot]
4791bd66b7 build(deps): bump cc from 1.0.74 to 1.0.76 (#4748)
Bumps [cc](https://github.com/rust-lang/cc-rs) from 1.0.74 to 1.0.76.
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Commits](https://github.com/rust-lang/cc-rs/compare/1.0.74...1.0.76)

---
updated-dependencies:
- dependency-name: cc
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-14 18:24:32 -06:00
dependabot[bot]
4f924f4771 build(deps): bump similar from 2.2.0 to 2.2.1 (#4746)
Bumps [similar](https://github.com/mitsuhiko/similar) from 2.2.0 to 2.2.1.
- [Release notes](https://github.com/mitsuhiko/similar/releases)
- [Changelog](https://github.com/mitsuhiko/similar/blob/main/CHANGELOG.md)
- [Commits](https://github.com/mitsuhiko/similar/compare/2.2.0...2.2.1)

---
updated-dependencies:
- dependency-name: similar
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-14 18:23:17 -06:00
Michael Davis
c74b97447f Fix range offsets for multiple shell insertions (#4619)
d6323b7cbc introduced a regression for
shell commands like `|`, `!`, and `<A-!>` which caused the new
selections to be incorrect. This caused a panic when piping (`|`)
would cause the new range to extend past the document end.

The paste version of this bug was fixed in
48a3965ab4.

This change also inherits the direction of the new range from the old
range and adds integration tests to ensure that the behavior isn't
broken in the future.
2022-11-14 09:45:52 +09:00
wes adams
fd585c1ee4 Statusline indicator to show number of selected chars (#4682)
Co-authored-by: wes adams <wadams@grayshift.com>
2022-11-12 11:31:09 -06:00
asvln
1f72d34249 rename description for goto_line_end_newline 2022-11-11 19:14:08 -06:00
asvln
7468fa28fd add extend_prev_word_end command 2022-11-11 19:14:08 -06:00
Alexis (Poliorcetics) Bourget
e232333d4a fix: Outdated Rust queries after TS update
Ref: 3ddebf46e6
2022-11-11 18:43:55 -06:00
Alexis (Poliorcetics) Bourget
53b70d821e deps: Update tree-sitter-rust (supports let-else && let-chains) 2022-11-11 18:43:55 -06:00
Bruce Hopkins
bc0a3037ea feat(commands): increment by range (#4418) 2022-11-11 13:50:25 -05:00
Anton Romanov
5b73c8c724 Add port of VIM's Zenburn, a low-contrast color scheme for Vim (#4613) 2022-11-11 08:15:22 -06:00
Chris Kipp
d7be5463c5 update scala roots (#4701)
This adds in a couple more roots that are common in Scala.

- `build.sc` which is used in Mill
- `build.gradle` for Scala Gradle projects
- `.scala-build` for scala-cli projects
2022-11-11 07:49:56 -06:00
Gabriel Dinner-David
7367abd6c6 Update typescript grammar and queries (#4703)
* fix(grammars): update treesitter grammar and queries

* add override keyword

* Update runtime/queries/typescript/highlights.scm

Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
2022-11-11 14:42:56 +09:00
Pascal Kuthe
bb5a122cde improve performance of tree sitter query captures (for text object motions in particular) (#4707)
* add tree sitter match limit to avoid slowdowns for larger files

Affects all tree sitter queries and should speedup both
syntax highlighting and text object queries.
This has been shown to fix significant slowdowns with textobjects
for rust files as small as 3k loc.

* Apply suggestions from code review

Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>

Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
2022-11-11 10:47:12 +09:00
Philip Giuliani
e17ad2722a Enable elixir-ls for heex language (#4679) 2022-11-10 09:21:31 -06:00
janos-r
bc52b0369b theme dark_plus color-modes insert and select (#4678) 2022-11-10 09:18:38 -06:00
Chris Kipp
183d1fadf4 feat: add sc to filetypes for Scala (#4697)
Files ending in `.sc` are known as "Scala Scripts". The scalac compiler
knows how to handle these, popular tools like
[Ammonite](https://github.com/com-lihaoyi/Ammonite) and
[scala-cli](https://github.com/Virtuslab/scala-cli) use them, and even
some Scala build tools like [mill](https://github.com/com-lihaoyi/mill)
use them as their build files (`build.sc`). This change just makes sure
that they are treated as Scala files so Metals kicks in.
2022-11-10 09:17:01 -06:00
André Sá
d7136d691a Update ayu themes (#4662) 2022-11-09 18:42:44 -06:00
Blaž Hrastnik
758bace221 fix test compilation 2022-11-09 22:17:14 +09:00
Blaž Hrastnik
264a455c18 Move terminal out of compositor 2022-11-09 22:10:49 +09:00
Blaž Hrastnik
00d7b18097 This term specific behavior really doesn't belong to compositor 2022-11-09 21:47:46 +09:00
Blaž Hrastnik
b2e7171fed Drop terminal interaction in compositor.size() 2022-11-09 21:37:56 +09:00
Blaž Hrastnik
d4f5cab7b5 Re-enable format_selections for a single selection range 2022-11-09 18:17:23 +09:00
Matthias Deiml
dee5b2a983 Add LSP workspace command picker (#3140)
* Add workspace command picker

* Make command typable

* Add optional argument to lsp-workspace-command
2022-11-09 18:17:09 +09:00
Michael Davis
3e84434c69 Fix panic from indenting on tree with errors
`deepest_preceding` is known to be a descendant of `node`. Repeated
calls of `Node::parent` _should_ eventually turn `deepest_preceding`
into `node`, but when the node is errored (the tree contains a syntax
error), `Node::parent` returns None.

In the typescript case:

    if(true) &&true
    //      ^ press enter here

The tree is:

    (program [0, 0] - [1, 0]
      (if_statement [0, 0] - [0, 15]
        condition: (parenthesized_expression [0, 2] - [0, 8]
          (true [0, 3] - [0, 7]))
        consequence: (expression_statement [0, 8] - [0, 15]
          (binary_expression [0, 8] - [0, 15]
            left: (identifier [0, 8] - [0, 8])
            right: (true [0, 11] - [0, 15])))))

`node` is the `program` node and `deepest_preceding` is the
`binary_expression`. The tree is errored on the `binary_expression`
node with `(MISSING identifier [0, 8] - [0, 8])`.

In the C++ case:

    ; <<
    // press enter after the ';'

The tree is:

    (translation_unit [0, 0] - [1, 0]
      (expression_statement [0, 0] - [0, 1])
      (ERROR [0, 1] - [0, 4]
        (identifier [0, 1] - [0, 1])))

`node` is the `translation_unit` and `deepest_preceding` is the `ERROR`
node.

In both cases, `Node::parent` on the errored node returns None.
2022-11-09 12:41:07 +09:00
Michael Davis
260ae3a0f4 style: Only call extend_nodes when deepest_preceding is Some 2022-11-09 12:41:07 +09:00
Kirawi
a19eee6450 Update dark_plus diff colors (#4661) 2022-11-08 15:06:27 -06:00
Anton Romanov
07d3157273 [rust highlights] fix scoped attribute macro matching (#4659)
Without this scoped attribute macros are not matched as macros.
Eg
```
  #[path::macro]
```
2022-11-08 13:41:09 -06:00
Marko Klobučar Ledinšćak
d8e9c85f5e error! on unknown CompletionItemKind (#4658) 2022-11-08 12:36:01 -06:00
Zhizhen He
0c30aeea5b fix typo (#4656) 2022-11-08 11:02:49 -06:00
0xflotus
75d7e0555e fix: small error (#4651) 2022-11-08 08:29:48 -06:00
Max Hille
64359f8b48 bash completion: use builtin filenames option (#4648)
Use a builtin bash option which detects filenames in completion outputs
and reflects this in sensible <tab> completion behaviour.
2022-11-08 07:50:17 -06:00
Blaž Hrastnik
bb303cf41d fix tests 2022-11-08 22:20:32 +09:00
Blaž Hrastnik
cd8bbbc044 fix tests 2022-11-08 21:48:56 +09:00
Doug Kelkhoff
7ed9e9cf25 Dynamically resize line number gutter width (#3469)
* dynamically resize line number gutter width

* removing digits lower-bound, permitting spacer

* removing max line num char limit; adding notes; qualified successors; notes

* updating tests to use new line number width when testing views

* linenr width based on document line count

* using min width of 2 so line numbers relative is useful

* lint rolling; removing unnecessary type parameter lifetime

* merge change resolution

* reformat code

* rename row_styler to style; add int_log resource

* adding spacer to gutters default; updating book config entry

* adding view.inner_height(), swap for loop for iterator

* reverting change of current! to view! now that doc is not needed
2022-11-08 21:19:59 +09:00
Blaž Hrastnik
c94feed83d core: Move state into the history module 2022-11-08 21:03:54 +09:00
Blaž Hrastnik
13126823f8 lsp: Support insertReplace
Fixes #4473
2022-11-08 20:50:49 +09:00
Danillo Melo
188aff059b Improve Ruby TextObjects (#4601) 2022-11-07 19:43:00 -06:00
dependabot[bot]
535cf90093 build(deps): bump regex from 1.6.0 to 1.7.0 (#4640)
Bumps [regex](https://github.com/rust-lang/regex) from 1.6.0 to 1.7.0.
- [Release notes](https://github.com/rust-lang/regex/releases)
- [Changelog](https://github.com/rust-lang/regex/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/regex/compare/1.6.0...1.7.0)

---
updated-dependencies:
- dependency-name: regex
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-07 18:07:21 -06:00
dependabot[bot]
5bfe84fb4f build(deps): bump libloading from 0.7.3 to 0.7.4 (#4639)
Bumps [libloading](https://github.com/nagisa/rust_libloading) from 0.7.3 to 0.7.4.
- [Release notes](https://github.com/nagisa/rust_libloading/releases)
- [Commits](https://github.com/nagisa/rust_libloading/compare/0.7.3...0.7.4)

---
updated-dependencies:
- dependency-name: libloading
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-07 18:06:05 -06:00
Tobias Kohlbau
6cafd81e41 tutor: fix wording in recap for chapter 5 (#4629)
In recap for chapter 5.1 specify that the cursor is duplicted to the next suitable line
instead of the next line.

Signed-off-by: Tobias Kohlbau <tobias@kohlbau.de>
2022-11-07 07:53:29 -06:00
Ryan Palmer
da8f29eaa7 Fixed disorienting selection palette on Gruvbox theme (#4626)
Co-authored-by: ryan.palmer <ryan.palmer@servicenow.com>
2022-11-07 07:32:40 -06:00
Jonathan LEI
eddf9f0b7f Run clippy on workspace in CI (#4614) 2022-11-07 13:39:18 +09:00
Michael Davis
140df92d79 Fix command-mode completion behavior when input is escaped
If `a\ b.txt` were a local file, `:o a\ <tab>` would fill the prompt
with `:o aa\ b.txt` because the replacement range was calculated using
the shellwords-parsed part. Escaping the part before calculating its
length fixes this edge-case.
2022-11-07 13:38:16 +09:00
Michael Davis
3d283b2ca4 Escape filenames in command completion
This changes the completion items to be rendered with shellword
escaping, so a file `a b.txt` is rendered as `a\ b.txt` which matches
how it should be inputted.
2022-11-07 13:38:16 +09:00
Michael Davis
1536a65289 Fix whitespace handling in command-mode completion
8584b38cfb switched to shellwords for
completion in command-mode. This changes the conditions for choosing
whether to complete the command or use the command's completer.

This change processes the input as shellwords up-front and uses
shellword logic about whitespace to determine whether the command
or argument should be completed.
2022-11-07 13:38:16 +09:00
Michael Davis
48a3965ab4 Fix range offsets in multi-selection paste (#4608)
* Fix range offsets in multi-selection paste

d6323b7cbc introduced a regression with
multi-selection paste where pasting would not adjust the ranges
correctly. To fix it, we need to track the total number of characters
inserted in each changed selection and use that offset to slide each
new range forwards.

* Inherit selection directions on paste

* Add an integration-test for multi-selection pasting
2022-11-06 23:56:45 +09:00
ChrHorn
4ec2a21c6e Update Julia grammar, queries (#4588) 2022-11-05 13:30:40 -05:00
Michael Davis
3814987298 Fix panic on paste from blackhole register (#4497)
The sequence "_y"_p panics because the blackhole register contains an
empty values vec. This causes a panic when pasting since it unwraps
a `slice::last`.
2022-11-05 01:04:16 +09:00
Michael Davis
d6323b7cbc Select text inserted by shell or paste (#4458)
This follows changes in Kakoune to the same effects:

* p/<space>p: 266d1c37d0
* !/<A-!>: 85b78dda2e

Selecting the new data inserted by shell or pasting is often more
useful than retaining a selection of the pre-paste/insert content.
2022-11-05 01:02:19 +09:00
Blaž Hrastnik
9a898be959 nix: Bump flake dependencies 2022-11-04 21:06:28 +09:00
Blaž Hrastnik
c2c1280f02 Resolve a bunch of upcoming clippy lints 2022-11-04 21:06:28 +09:00
Antoine Stevan
921d351013 bump up LhKipp/tree-sitter-nu's version to latest (#4583) 2022-11-03 21:20:14 -05:00
throwaway-helix-zsh
d357f1673f Use language=bash when shebang line uses zsh (#4582)
This PR makes the editor use language=bash when the shebang line uses
zsh. This is in the same line as using language=bash for zsh related
file (~/.zshrc, ~/.zshenv etc.) as we already do.
2022-11-03 21:18:24 -05:00
ChrHorn
c667ff8da3 Increase default language server timeout for Julia (#4575) 2022-11-03 21:17:06 -05:00
Michael Davis
ba394dca6d Fix panic from two windows editing the same document (#4570)
* Clamp highlighting range to be within document

This fixes a panic possible when two vsplits of the same document
exist and enough lines are deleted from the document so that one of
the windows focuses past the end of the document.

* Ensure cursor is in view on window change

If two windows are editing the same document, one may delete enough of
the document so that the other window is pointing at a blank page (past
the document end). In this change we ensure that the cursor is within
view whenever we switch to a new window (for example with `<C-w>w`).

* Update helix-term/src/ui/editor.rs

Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>

Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
2022-11-03 15:09:21 +09:00
Charlie Groves
1bed2f3043 Use OSC 52 as a fallback for setting the system clipboard (#3220)
This adds a simple base64 implementation to keep us from adding a crate for one function. It's
mostly based on
a675443d32/src/engine/naive.rs (L42)
2022-11-02 10:12:40 +09:00
Yuriy
b156f57618 Add indentation for Python pattern matching
Add indentation for `match` and `case`.
2022-11-01 20:10:11 -05:00
Yuriy
e0b034dcd1 Add syntax highlighting for Python pattern matching
Add syntax highlighting for `match` and `case` keywords in Python
(https://peps.python.org/pep-0636/).
2022-11-01 20:10:11 -05:00
Jonathan LEI
db3383c76e Exit select mode on replace commands (#4554) 2022-11-01 20:08:25 -05:00
Garrett D'Amore
185236c3a4 Fix D unittest injection query. (#4562) 2022-11-01 19:44:56 -05:00
Yuriy Gabuev
c803ef8753 Fix delete_char_backward for paired characters (#4558)
When backward-deleting a character, if this character and the following
character form a Pair, we want to delete both. However, there is a bug
that deletes both characters also if both characters are closers of some
Pair.

This commit fixes that by adding an additional check that the deleted
character should be an opener in a Pair.

Closes https://github.com/helix-editor/helix/issues/4544.
2022-11-01 23:48:43 +09:00
Poliorcetics
8ff92c7492 Add missed test attribute in #4316 (#4557) 2022-11-01 21:37:19 +09:00
Armin Ronacher
8584b38cfb Correctly handle escaping in completion (#4316)
* Correctly handle escaping in completion

* Added escaping tests
2022-11-01 20:48:37 +09:00
Yusuf Bera Ertan
3881fef39d build(nix): update nci, fixup flake (#4537) 2022-10-31 19:52:03 -05:00
dependabot[bot]
e5319ea8c5 build(deps): bump once_cell from 1.15.0 to 1.16.0 (#4548)
Bumps [once_cell](https://github.com/matklad/once_cell) from 1.15.0 to 1.16.0.
- [Release notes](https://github.com/matklad/once_cell/releases)
- [Changelog](https://github.com/matklad/once_cell/blob/master/CHANGELOG.md)
- [Commits](https://github.com/matklad/once_cell/compare/v1.15.0...v1.16.0)

---
updated-dependencies:
- dependency-name: once_cell
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-31 19:31:08 -05:00
Jonas Everaert
79c7203a38 Added missing keywords to wat (wasm) hightlights (#4542)
added "if", "then", "else", "block", "loop", "end" and "mut" to the wat highlights.
2022-10-31 19:30:08 -05:00
dependabot[bot]
3792d9ebb7 build(deps): bump lsp-types from 0.93.1 to 0.93.2 (#4550)
Bumps [lsp-types](https://github.com/gluon-lang/lsp-types) from 0.93.1 to 0.93.2.
- [Release notes](https://github.com/gluon-lang/lsp-types/releases)
- [Changelog](https://github.com/gluon-lang/lsp-types/blob/master/CHANGELOG.md)
- [Commits](https://github.com/gluon-lang/lsp-types/compare/v0.93.1...v0.93.2)

---
updated-dependencies:
- dependency-name: lsp-types
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-31 19:29:32 -05:00
dependabot[bot]
92b13f9e71 build(deps): bump cc from 1.0.73 to 1.0.74 (#4549)
Bumps [cc](https://github.com/rust-lang/cc-rs) from 1.0.73 to 1.0.74.
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Commits](https://github.com/rust-lang/cc-rs/compare/1.0.73...1.0.74)

---
updated-dependencies:
- dependency-name: cc
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-31 19:29:01 -05:00
Sebastian Hoß
9b247b1104 Update SSH client config grammar & highlight queries (#4538)
Co-authored-by: Sebastian Hoß <seb@hoß.de>
2022-10-31 19:27:53 -05:00
seshotake
ed7ea8c9ba add highlights for env and ini file formats (#4536) 2022-10-31 19:23:09 -05:00
hh9527
9df4358492 Support WIT grammar (#4525) 2022-10-31 18:48:01 -05:00
dependabot[bot]
df3c6412ac build(deps): bump cachix/cachix-action from 11 to 12 (#4547)
Bumps [cachix/cachix-action](https://github.com/cachix/cachix-action) from 11 to 12.
- [Release notes](https://github.com/cachix/cachix-action/releases)
- [Commits](https://github.com/cachix/cachix-action/compare/v11...v12)

---
updated-dependencies:
- dependency-name: cachix/cachix-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-31 18:21:51 -05:00
Konstantin Podsvirov
f41f28b662 Update windows install instructions (#4530) 2022-10-30 11:55:31 -05:00
seshotake
f6710879d1 Update SQL grammar (#4529) 2022-10-30 11:54:37 -05:00
Triton171
908529ccac Update LaTex grammar (#4528)
Fix comment injection & add highlighting for math delimiters.
2022-10-30 11:45:58 -05:00
Matthew Toohey
00cf12f571 fix: make scroll aware of tabs and wide characters (#4519) 2022-10-29 16:23:18 -05:00
Matthew Toohey
f054a3f3ed feat(lang): add xml (#4518) 2022-10-29 15:41:28 -05:00
Poliorcetics
2935e9da19 feat: Categorize Rust's keywords using more specific scopes (#4510) 2022-10-29 10:36:26 -05:00
Kristoffer Flottorp
e3eaad1479 Fleetish: Adjustments to resemble official theme and reworked diagnostics to reduce subconjunctival hemorrhage (#4487) 2022-10-29 10:35:35 -05:00
Jaden
b5e7501935 feat(lang): add kdl grammar (#4481) 2022-10-29 10:33:23 -05:00
Matthias Deiml
5e256e4a98 Make shell_impl concurrent (#3180) 2022-10-29 10:24:33 -05:00
Poliorcetics
c58e1729ce fix: Never create automatic doc popups outside of Insert mode (#4456) 2022-10-28 18:20:55 -05:00
rsteube
26f21da531 language: added vhs (#4486) 2022-10-28 08:22:41 -05:00
Michael Davis
cefdface3b Include colons for typable commands in command palette (#4495)
Before:

    Goto next buffer. [buffer-next]

After:

    Goto next buffer. [:buffer-next]
2022-10-28 21:42:40 +09:00
Dario Oddenino
6752c7d347 Trim quotes and braces from paths in goto_file_impl (#4370)
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2022-10-27 20:31:28 -05:00
Sora
de5b100556 Add the debugger for Zig (#4492) 2022-10-27 20:19:01 -05:00
lazytanuki
b4a3dd8f89 feat(lsp): LSP preselected items appear first in completion menu (#4480)
* feat(lsp): LSP preselected items appear first in completion menu

* fix: shorter diff
2022-10-27 23:16:55 +09:00
Matthias Deiml
b1ffbbd49f Include unnamed children for html injected into inline markdown (#4478) 2022-10-27 08:40:47 -05:00
Matthias Deiml
27217bb435 Update tree-sitter markdown grammar (#4483) 2022-10-27 08:39:22 -05:00
A-Walrus
c4d7cde6c8 Allow the area to be bigger than u16 (width and height remain u16) (#4318)
Now the editor can fill **very** large terminals.
Changed/removed tests which check the truncating behaviour.
2022-10-26 12:00:13 +09:00
James O. D. Hunt
ac0fe29867 commands: Make no arg ':theme' show name (#3740)
Most commands that accept an argument show their current value if no
argument is specified. The `:theme` command previously displayed an
error message in the status bar if not provided with an argument:

```
Theme name not provided
```

It now shows the current theme name in the status bar if no argument is
specified.

Signed-off-by: James O. D. Hunt <jamesodhunt@gmail.com>

Signed-off-by: James O. D. Hunt <jamesodhunt@gmail.com>
2022-10-26 11:59:50 +09:00
Gaurav Tyagi
ba9e50e93b Add :update that will write the changes if the file has been modified. (#4426)
* add command update that will write the changes if file hasn been modified

* add docs

* update the docs
2022-10-26 11:58:49 +09:00
Michał Zabielski
65edf9c198 fix: repeating repeat operator (#4450) 2022-10-25 21:15:46 -05:00
GabrielDertoni
9fae4b8118 fix: terminal freezing on shell_insert_output
This bug occurs on `shell_insert_output` and `shell_append_output`
commands.

The previous implementation would create a child process using the Rust
stdlib's `Command` builder. However, when nothing should be piped in
from the editor, the default value for `stdin` would be used. According
to the Rust stdlib documentation that is `Stdio::inherit` which will
make the child process inherit the parent process' stdin. This would
cause the terminal to freeze.

This change will set the child process' stdin to `Stdio::null` whenever
it doesn't pipe it. In the `if` statement where this change was made
there was an extra condition for windows that I am not sure if would
require some special treatment.
2022-10-25 20:24:44 -05:00
Michael Davis
c47ca33137 Render diagnostics in the file picker preview (#4324)
This is mostly for the sake of the diagnostics pickers: without
rendering the diagnostic styles, it's hard to tell where the entries
in the picker are pointing to.
2022-10-25 21:03:35 +09:00
dependabot[bot]
001e4e304b build(deps): bump serde from 1.0.145 to 1.0.147 (#4463)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-24 18:37:25 -05:00
dependabot[bot]
6aacdaaf9f build(deps): bump futures-executor from 0.3.24 to 0.3.25 (#4464)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-24 18:35:12 -05:00
dependabot[bot]
02385599e1 build(deps): bump serde_json from 1.0.86 to 1.0.87 (#4462)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-24 18:18:50 -05:00
dependabot[bot]
093842988b build(deps): bump termini from 0.1.2 to 0.1.4 (#4461)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-24 18:18:41 -05:00
dependabot[bot]
6ea2c54152 build(deps): bump futures-util from 0.3.24 to 0.3.25 (#4460)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-24 18:14:27 -05:00
dependabot[bot]
45da569a4c build(deps): bump anyhow from 1.0.65 to 1.0.66 (#4459)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-24 18:14:05 -05:00
Owen Lynch
d8ffa02255 Update scala treesitter grammar (#4353) 2022-10-24 17:44:36 -05:00
Mike Trinkala
801984c7fc Update textwrap to 0.16.0 (#4437) 2022-10-23 18:02:58 -05:00
Mr. E
ce469abfe2 feat(themes): add mode-specific styles to the tokyonight themes (#4415)
Co-authored-by: SoraTenshi <dream@neoncity.dev>
2022-10-22 14:25:41 -05:00
Michael Davis
d7d0d5ffb7 lsp: Resolve completion items missing documentation on idle (#4406)
Some language servers may not send the `documentation` field if it
is expensive to compute. Clients can request the missing field with
a completionItem/resolve request.

In this change we use the idle-timeout event to ensure that the current
completion item is resolved.
2022-10-22 10:04:50 +09:00
Michael Davis
17daf6ac0a Change syntax for suffix file-types configurations (#4414)
The change in d801a6693c to search for
suffixes in `file-types` is too permissive: files like the tutor or
`*.txt` files are now mistakenly interpreted as R or perl,
respectively.

This change changes the syntax for specifying a file-types entry that
matches by suffix:

```toml
file-types = [{ suffix = ".git/config" }]
```

And changes the file-type detection to first search for any non-suffix
patterns and then search for suffixes only with the file-types entries
marked explicitly as suffixes.
2022-10-22 09:34:15 +09:00
Mehedi Hasan
131d8392bb Theme: Papercolor: Fixed cursorline background (#4317) 2022-10-21 17:37:10 -05:00
PORTALSURFER
a449192ee9 Added 2 new themes (#4367) 2022-10-21 17:35:02 -05:00
Sora
664064b3cc Add textobjects.scm for zig (#4409) 2022-10-21 17:32:29 -05:00
Christian Speich
79ef39ab3a syntax: Don't force lower-case for filenames (#4346)
Just like for grammars we currently force a lower-case of the name for
some actions (like filesystem lookup). To make this consistent and less
surprising for users, we remove this lower-casing here.

Note: it is still the preferred way to name both language and grammar in
lower-case

Signed-off-by: Christian Speich <cspeich@emlix.com>
2022-10-21 08:11:25 -05:00
Christian Speich
4b85aeb2b6 grammar: Don't require lower-case (#4346)
Currently we always lower-case the grammar name when loading it. While it
is somewhat of an convention to name tree-sitter grammars in lowercase
there is no rule to enforce it.

This patch removes the lower-casing to allow all possible grammar names.

Signed-off-by: Christian Speich <cspeich@emlix.com>
2022-10-21 08:11:25 -05:00
Alexis (Poliorcetics) Bourget
34389e1d54 nit: Do less allocations in ui::menu::Item::label implementations
This complicates the code a little but it often divides by two the number of allocations done by
the functions. LSP labels especially can easily be called dozens of time in a single menu popup,
when listing references for example.
2022-10-21 07:42:33 -05:00
Alexis (Poliorcetics) Bourget
3aea33a415 nit: move an allocation to happen after a continue, making sure it's
not done for nothing
2022-10-21 07:42:33 -05:00
Skyler Hawthorne
5a848344a9 fix: write-all crash (#4384)
When we do auto formatting, the code that takes the LSP's response and applies
the changes to the document are just getting the currently focused view and
giving that to the function, basically always assuming that the document that
we're applying the change to is in focus, and not in a background view.

This is usually fine for a single view, even if it's a buffer in the
background, because it's still the same view and the selection will get updated
accordingly for when you switch back to it. But it's obviously a problem for
when there are multiple views, because if you don't have the target document in
focus, it will ask the document to update the wrong view, hence the crash.

The problem with this is picking which view to apply any selection change to.
In the absence of any more data points on the views themselves, we simply pick
the first view associated with the document we are saving.
2022-10-21 16:43:22 +09:00
Nimrod
bad49ef2d0 Fix unexpected behavior in delete_word_backward and delete_word_forward (#4392) 2022-10-21 15:08:37 +09:00
Skyler Hawthorne
f486f34ebe flush writes on force quit (#4397)
When force quitting, we need to block on the pending writes to ensure
that write commands succeed before exiting, and also to avoid a crash
when all the views are gone before the auto format call returns from
the LS.
2022-10-21 13:28:29 +09:00
Blaž Hrastnik
74a6a2282e Add undercurl styles to the default theme 2022-10-21 13:27:05 +09:00
Blaž Hrastnik
511d9d8a52 cargo fmt 2022-10-21 13:26:22 +09:00
Charlie Groves
7e29ee6dae Autosave all when the terminal loses focus (#3178)
* Autosave all when the terminal loses focus

* Correct comment on focus config

Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>

* Need a block_try_flush_writes in all quit_all paths

Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
2022-10-21 10:35:02 +09:00
A-Walrus
4ff5feeb0c Fix shellwords delimiter handling (#4098)
* Fix shellwords delimiter handling

This allows commands such as `:set statusline.center ["file-type"]` to
work. Before the quotes within the list would mess it up.
Also added a test to ensure correct behavior

* Rename Delimiter -> OnWhitespace
2022-10-21 10:06:57 +09:00
Pascal Kuthe
9af7c1c9f3 Sort by fixed diagnostics/is_preffered within codeaction categories 2022-10-21 10:03:00 +09:00
Pascal Kuthe
189aa0bfcf never sort menu items when no fuzzy matching is possible 2022-10-21 10:03:00 +09:00
Pascal Kuthe
dc3527f52d use permalink to vscode repo 2022-10-21 10:03:00 +09:00
Pascal Kuthe
8d8b5d6624 use stable sort instead of allocating new vectors 2022-10-21 10:03:00 +09:00
Pascal Kuthe
c70d762a7b sort autocompletins by fuzzy match 2022-10-21 10:03:00 +09:00
Pascal Kuthe
8673c1ec0c sort codeaction by their kind instead of alphabetically 2022-10-21 10:03:00 +09:00
Kirawi
ce399471f0 simplify encoding test macro (#4385) 2022-10-21 09:58:13 +09:00
Greg Troszak
fbf8078611 Clarify use of HELIX_RUNTIME (#4382) 2022-10-20 19:39:30 -05:00
Skyler Hawthorne
6a0b450f55 Fix multi byte auto pairs (#4024)
* Fix test::print for Unicode

The print function was not generating correct translations when
the input has Unicode (non-ASCII) in it. This is due to its use of
String::len, which gives the length in bytes, not chars.

* Fix multi-code point auto pairs

The current code for auto pairs is counting offsets by summing the
length of the open and closing chars with char::len_utf8. Unfortunately,
this gives back bytes, and the offset needs to be in chars.

Additionally, it was discovered that there was a preexisting bug where
the selection was not computed correctly in the case that the cursor
was:

1. a single grapheme in width
2. this grapheme was more than one char
3. the direction of the cursor is backwards
4. a secondary range

In this case, the offset was not being added into the anchor. This was
fixed.

* migrate auto pairs tests to integration

* review comments
2022-10-21 09:22:20 +09:00
Matouš Dzivjak
e25af1f744 feat(view): re-use align_view function (#4390) 2022-10-20 18:53:05 -05:00
Michael Davis
66238e8556 Silence dead_code warning on AppBuilder::with_config
This function is not currently used but is likely to be useful in
the future, so this change silences the dead_code warning.
2022-10-21 08:43:15 +09:00
Michael Davis
313579d27c Remove language-server configuration in integration tests
This change removes language server configuration from the default
languages.toml config for integration tests. No integration-tests
currently depend on the availability of a language server but if any
future test needs to, it may provide a language server configuration
by passing an override into the `test_syntax_conf` helper.

Language-servers in integration tests cause false-positive failures
when running integration tests in GitHub Actions CI. The Windows
runner appears to have `clangd` installed and all OS runners have
the `R` binary installed but not the `R` language server package.
If a test file created by `tempfile::NamedTempFile` happens to have a
file extension of `r`, the test will most likely fail because the
R language server will fail to start and will become a broken pipe,
meaning that it will fail to shutdown within the timeout, causing a
false-positive failure. This happens surprisingly often in practice.

Language servers (especially rust-analyzer) also emit unnecessary
log output when initializing, which this change silences.
2022-10-21 08:43:15 +09:00
Michael Davis
1243db11a5 Use helix_view::apply_transaction in integration-tests
`helix_view::apply_transaction` closes over `Document::apply` and
`View::apply` to ensure that jumplist entries are updated when a
document changes from a transaction. `Document::apply` shouldn't
be called directly - this helper function should be used instead.
2022-10-21 08:43:15 +09:00
Matouš Dzivjak
4cff625054 chore(view): remove indent_unit helper fn (#4389) 2022-10-20 17:05:04 -05:00
Garrett D'Amore
36f97b6aad Add support for D (#4372)
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2022-10-20 16:54:17 -05:00
Jared Ramirez
de607830a2 Upgrade rescript tree sitter & highlights (#4356)
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2022-10-20 16:30:16 -05:00
Matouš Dzivjak
eee8362015 fix(commands): no last picker error (#4387) 2022-10-20 15:50:54 -05:00
midnightexigent
d801a6693c Allow using path suffixes to associate language file-types (#2455)
* feat(syntax): add strategy to associate file to language through pattern

File path will match if it ends with any of the file types provided in the config.
Also used this feature to add support for the .git/config and .ssh/config files

* Add /etc/ssh/ssh_config to languages.toml

* cargo xtask docgen

* Update languages.md

* Update languages.md

* Update book/src/languages.md

Co-authored-by: Ivan Tham <pickfire@riseup.net>

* Update book/src/languages.md

Co-authored-by: Ivan Tham <pickfire@riseup.net>

Co-authored-by: Ivan Tham <pickfire@riseup.net>
2022-10-20 23:13:56 +09:00
Blaž Hrastnik
78c0cdc519 Merge pull request #2267 from dead10ck/fix-write-fail
Write path fixes
2022-10-20 23:11:22 +09:00
Alex
8c9bb23650 Update windows install instructions (#4351) 2022-10-19 17:19:03 -05:00
Fisher Darling
4174b25b3d Pretty print tree-sitter-subtree expression (#4295) 2022-10-19 17:17:50 -05:00
Sukera
a7e7c2cc05 Add roots for julia to languages.toml (#4361) 2022-10-19 07:53:22 -05:00
Blaž Hrastnik
418a622db9 Merge pull request #4061 from pascalkuthe/undercurl-modifier
Support different kinds of underline rendering (updated)
2022-10-19 13:51:13 +09:00
Skyler Hawthorne
756253b43f fix tree_sitter_scopes 2022-10-19 00:01:00 -04:00
Skyler Hawthorne
9a406b569b reduce LSP timeout to 3s 2022-10-18 22:31:39 -04:00
Skyler Hawthorne
759d55cc81 fail if doc save sender is closed 2022-10-18 22:31:39 -04:00
Skyler Hawthorne
e645804b0a Editor::flush_writes returns an error 2022-10-18 22:31:39 -04:00
Blaž Hrastnik
52ba550098 Use flush_writes in application.close() 2022-10-18 22:31:39 -04:00
Blaž Hrastnik
2a43ee0164 doc.close() now unused 2022-10-18 22:31:39 -04:00
Blaž Hrastnik
1b6f7319cd Wire up save_queue as a part of new_document rather than open 2022-10-18 22:31:39 -04:00
Blaž Hrastnik
55b50d9e83 Seems like this flush is unnecessary 2022-10-18 22:31:39 -04:00
Blaž Hrastnik
b155e861ad Use a write_count to determine how many writes left to flush 2022-10-18 22:31:39 -04:00
Blaž Hrastnik
b0212b3611 Deduplicate flush_writes 2022-10-18 22:31:39 -04:00
Blaž Hrastnik
30c93994b5 Use a single save_queue on the editor 2022-10-18 22:31:39 -04:00
Skyler Hawthorne
beb3427bfb improve app close failure display 2022-10-18 22:31:39 -04:00
Skyler Hawthorne
bf378e71b0 fix tests 2022-10-18 22:31:39 -04:00
Skyler Hawthorne
31d1bbfddb review comments 2022-10-18 22:31:39 -04:00
Skyler Hawthorne
9e64974f13 remove Document::format_and_save 2022-10-18 22:31:39 -04:00
Skyler Hawthorne
3f07885b35 document should save even if formatter fails 2022-10-18 22:31:39 -04:00
Skyler Hawthorne
b530a86d1f remove Callback::Compositor variant
To reduce likelihood of accidental discarding of important callbacks
2022-10-18 22:31:39 -04:00
Skyler Hawthorne
b3fc31a211 move language server refresh to document saved event handler 2022-10-18 22:31:39 -04:00
Skyler Hawthorne
af03df3413 fix write scratch buffer to file 2022-10-18 22:31:39 -04:00
Skyler Hawthorne
18c32118b1 Save text in document saved events, use in status message 2022-10-18 22:31:39 -04:00
Skyler Hawthorne
f82a551b98 Rename doc save event names to past tense 2022-10-18 22:31:39 -04:00
Skyler Hawthorne
6cffc7f05d Add note about log level for integration tests 2022-10-18 22:31:39 -04:00
Skyler Hawthorne
57de4e6251 various fixes in write-all path 2022-10-18 22:31:39 -04:00
Skyler Hawthorne
7b11e9ac69 fix erroneous write sender close
This was not distinguishing the error types when trying a receive on an empty
receiver, which was erroneously causing the sender to be closed when trying to
flush the writes when there were none
2022-10-18 22:31:39 -04:00
Skyler Hawthorne
d544376590 reset idle timer for all events 2022-10-18 22:31:39 -04:00
Skyler Hawthorne
e5fd5e2a9c fix panic when view of pending write is closed 2022-10-18 22:31:39 -04:00
Skyler Hawthorne
faa00d4cc3 increase LSP shutdown timeout
The Clang LAP takes a long time to shut down on Windows
2022-10-18 22:31:39 -04:00
Skyler Hawthorne
8c667ef8de factor editor event handling into function 2022-10-18 22:31:39 -04:00
Skyler Hawthorne
aaa1450678 fix write-quit with auto format
write-quit will now save all files successfully even when there is auto
formatting
2022-10-18 22:31:39 -04:00
Skyler Hawthorne
c9418582d2 fix modified status with auto format 2022-10-18 22:31:38 -04:00
Skyler Hawthorne
cb23399dee improve reliability of shutdown 2022-10-18 22:31:38 -04:00
Skyler Hawthorne
b8a07f7d15 add conditional noop render back
It makes it much slower without stubbing this out
2022-10-18 22:31:38 -04:00
Skyler Hawthorne
69c9e44ef2 update write-quit to wait for saves 2022-10-18 22:31:38 -04:00
Skyler Hawthorne
e1f7bdb1d2 fix buffer-close 2022-10-18 22:31:38 -04:00
Skyler Hawthorne
83b6042b97 fix(write): do not set new path on document until write succeeds
If a document is written with a new path, currently, in the event that
the write fails, the document still gets its path changed. This fixes
it so that the path is not updated unless the write succeeds.
2022-10-18 22:31:38 -04:00
Skyler Hawthorne
a5a93182cd fix: buffer-close ensuring writes
Make sure buffer-close waits for the document to finish its writes.
2022-10-18 22:31:38 -04:00
Skyler Hawthorne
d706194597 chore(write): serialize write operations within a Document
The way that document writes are handled are by submitting them to the
async job pool, which are all executed opportunistically out of order. It
was discovered that this can lead to write inconsistencies when there
are multiple writes to the same file in quick succession.

This seeks to fix this problem by removing document writes from the
general pool of jobs and into its own specialized event. Now when a
user submits a write with one of the write commands, a request is simply
queued up in a new mpsc channel that each Document makes to handle its own
writes. This way, if multiple writes are submitted on the same document,
they are executed in order, while still allowing concurrent writes for
different documents.
2022-10-18 22:31:38 -04:00
Peter Phillips
faf0c521d1 Fix link to textobjects usage from keymap documentation (#4357) 2022-10-18 21:16:44 -05:00
Jonathan LEI
1a772d1b67 Fix deleting word from end of buffer (#4328) 2022-10-18 19:53:58 -05:00
zetashift
0c14d9f869 Add a first version of kanagawa theme (#4300) 2022-10-18 19:32:02 -05:00
Roberto Vidal
1f74cf45d4 display tree sitter scopes in a popup (#4337) 2022-10-19 00:00:00 +05:30
Philipp Mildenberger
d17ffc47f0 Use the same WalkBuilder configuration for the global search file picker as the default file picker (#4334)
Skip searching .git in global search, similar to how file picker skips listing files in .git.
2022-10-18 22:58:16 +05:30
dependabot[bot]
fee5db161b build(deps): bump cachix/install-nix-action from 17 to 18 (#4340)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-17 20:03:04 -05:00
dependabot[bot]
414214f883 build(deps): bump tokio-stream from 0.1.10 to 0.1.11 (#4341)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-17 19:56:29 -05:00
dependabot[bot]
38746b04b4 build(deps): bump cachix/cachix-action from 10 to 11 (#4339)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-17 19:55:15 -05:00
Clay
b07ef6bec3 Bump tree-sitter-elixir (#4333) 2022-10-18 01:05:14 +09:00
A-Walrus
8bbddf90ff Replace in_bounds with calculation of end_indent
Instead of repeatedly checking if it is in_bounds, calculate the
max_indent beforehand and just loop. I added a debug_assert to "prove"
that it never tries drawing out of bounds.
2022-10-18 00:38:16 +09:00
A-Walrus
1de02a147c Only draw indent guides within bounds
Better performance, and otherwise very long lines with lots of tabs
will wrap around the u16 and come back on the other side, messing up
the beginning skip_levels.
2022-10-18 00:38:16 +09:00
A-Walrus
2c36e33e0a Make skip_levels a u8 2022-10-18 00:38:16 +09:00
A-Walrus
3ba665d804 Fix rendering of lines longer than 2^16
Before things would be cast to u16 earlier than needed, which would
cause problems for insanely long lines (longer than 2^16 ~ 65 thousand)
2022-10-18 00:38:16 +09:00
Gokul Soumya
4e691d6247 Change diagnostic picker keybind to <space>d (#4229)
Also changes workspace diagnostic picker bindings to <space>D and
changes the debug menu keybind to <space>g, the previous diagnostic
picker keybind. This brings the diagnostic picker bindings more in
line with the jump to next/previous diagnostic bindings which are
currently on ]d and [d.
2022-10-17 16:45:42 +09:00
Blaž Hrastnik
09a6df199e Support Cairo 0.10 syntax 2022-10-17 10:35:15 +09:00
Blaž Hrastnik
431f9c14f3 Support Cairo 0.10 syntax 2022-10-17 10:35:15 +09:00
Jonathan LEI
17488f14d6 Fix Cairo comment token 2022-10-17 10:35:15 +09:00
echoriiku
b29531ceab Fix readability of highlighted text on the rose_pine themes using official palettes (#4221) 2022-10-17 10:34:38 +09:00
Brandon Dong
a330b5d224 Fix selecting pop dark theme (#4323) 2022-10-16 19:19:19 -05:00
Michael Davis
50b191a7df Log failures to load tree-sitter parsers as error (#4315)
Info logs don't show up in the log file by default, but this line
should: failures to load tree-sitter parser objects are useful errors.
A parser might fail to load it is misconfigured
(https://github.com/helix-editor/helix/pull/4303#discussion_r996448543)
or if the file does not exist.
2022-10-17 01:29:57 +05:30
Michael Davis
5f4f171b73 Fix debug assertion for diagnostic sort order (#4319)
The debug assertion that document diagnostics are sorted incorrectly
panics for cases like `[161..164, 162..162]`. The merging behavior
in the following lines that relies on the assertion only needs the
input ranges to be sorted by `range.start`, so this change simplifies
the assertion to only catch violations of that assumption.
2022-10-17 01:22:04 +05:30
Ben White-Horne
63fe423710 Show keys required to enter each minor mode (#4302)
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2022-10-16 11:58:18 -05:00
Filip Dutescu
2457111bf0 feat(csharp,debug): add C# debugger support (#4213) 2022-10-15 15:33:57 -05:00
Wojciech Kępka
661f48d62f themes: Add bogster_light theme (#4265)
Co-authored-by: Wojciech Kępka <wojciech.kepka@softax.pl>
2022-10-15 12:12:14 -05:00
Wojciech Kępka
05ca21cb1b themes: Update bogster theme (#4264)
Co-authored-by: Wojciech Kępka <wojciech.kepka@softax.pl>
2022-10-15 12:08:13 -05:00
Chickenkeeper
1c08c80e4f C# syntax highlight tweaks (#4285) 2022-10-15 11:29:50 -05:00
Sora
f444ba8beb Fixup Zig Indent Queries (#4281) 2022-10-15 11:10:16 -05:00
ZJPzjp
0e8e7cae3b fix :insert-output doc: inserting output **before** each selection (#4286) 2022-10-15 11:07:42 -05:00
Sam McCall
aef37d43d7 c/c++ highlighting: various tweaks
- treat `restrict`/`_Atomic` like `const`/`volatile` => @keyword.storage.modifier
- highlight `unsigned int` as builtin => @type.builtin
- recognize `static_cast` and friends => @keyword
- `template` is a kind of entity like `typename` => @keyword.storage.type
- many declaration modifiers have nothing to do with storage/types
  (explicit, friend, access specifiers, inline in C++) => @keyword
- fix floats highlighted as integer => @constant.numeric
2022-10-15 09:33:43 -05:00
Sam McCall
a3ed9169df c/c++ highlights: *& are @type or @operator based on context (#4278) 2022-10-14 20:05:39 -05:00
Poliorcetics
45e038f4d5 nit: remove a String allocation that is immediately used as an &str (#4277) 2022-10-14 17:35:00 -05:00
Nathaniel Graham
e80beaa7b0 Changed Selection Yank Message (#4275)
Co-authored-by: Nathaniel Graham <ngraham@protonmail.com>
2022-10-14 12:51:15 -05:00
Dario Oddenino
2d958d6c50 Add support for Purescript language (#4242) 2022-10-14 11:57:52 -05:00
IrishMaestro
13d81b7478 Created heisenberg theme for helix editor (#4209) 2022-10-13 20:35:02 -05:00
Chickenkeeper
b4e795d704 Fix C++ syntax highlighting, and improve C & WGSL highlighting (#4079) 2022-10-13 20:31:32 -05:00
Ben Lee-Cohen
cf4a5cca96 Monokai Pro Octagon statusline modes (#4247) 2022-10-13 20:26:03 -05:00
Pascal Kuthe
66a49080bc merge underline-style and underline-color into a single table 2022-10-13 19:03:58 +02:00
Tim Siegel
5077ce76b3 tutor: Normalize key names, capitalization, etc. 2022-10-12 18:12:54 -05:00
Tim Siegel
425df93fb8 book: Refer to keys by key names, not representations
This is an attempt to clean up the inconsistent way that keys are
written in various places. These rules require the fewest changes to the
existing text.

Use the "Key name", as defined in remapping.md, which uses
"Some-Modifiers-PascalCaseKey". The "Representation", which uses
"S-M-lowercasekey", is only used for configuration entries.

For key combinations which do not present a popup, just present the keys
one after the other, with no intervening space, like `]p`.

For key combinations which present a popup, separate them with ` + `,
like `Space + f`.

The Ctrl modifier is called Ctrl, not Control.
2022-10-12 18:12:54 -05:00
Tim Siegel
e542f2e08f tutor: Minor grammar fix
No need to say additionally, as well, also, etc. One is enough.
2022-10-12 18:12:54 -05:00
Tim Siegel
f5f4d3dc2a tutor: Clarify forward reference to "primary selection" 2022-10-12 18:12:54 -05:00
Tim Siegel
0571fa4d56 tutor: Clarify first multi-cursor example
If the reader is unfortunate enough to place the cursor at the beginning
of the line on step #1, subsequent steps will fail.
2022-10-12 18:12:54 -05:00
Tim Siegel
6db39eacd3 tutor: Clarify forward reference to "select command"
The phrase "Like the select command" suggests that the reader has been
introduced to select already. That doesn't happen until the next
chapter.
2022-10-12 18:12:54 -05:00
Michael Davis
e16c632760 Apply transactions to the jumplist for undo/redo (#4227)
Undo/redo/earlier/later call `Document::apply_impl` which applies
transactions to the document. These transactions also need to be
applied to the view as in 0aedef0.
2022-10-13 00:57:40 +09:00
Armin Ronacher
7f75458e6f Fix some commands not showing names in palette (#4223) 2022-10-12 09:02:10 -05:00
Lennard Hofmann
a24fae3b3c Update tree-sitter-lua and add textobjects for Lua (#3552) 2022-10-12 08:45:56 -05:00
Graic
68909dcef4 Fix append cursor location when selection anchor is at end of document (#4147) 2022-10-12 08:34:35 -05:00
Pascal Kuthe
963a0ac0bb fix terminfo detection 2022-10-12 11:33:48 +02:00
Jacob Kiesel
c54a0363bb Rearrange README.md slightly (#4206) 2022-10-11 18:54:18 -05:00
Brian Orwe
f4d96b2ca3 Fix confusion with using --hsplit --vsplit on startup at same time (#4202) 2022-10-11 09:25:42 -04:00
Pascal Kuthe
328c4d002f adress review comments 2022-10-11 12:11:33 +02:00
Daniel Ebert
081327695f Rename extend indent captures.
Clarify comments in indent code.
2022-10-11 16:48:04 +09:00
Daniel Ebert
dc443487d4 Slightly change the behavior of the @stop-extend capture.
This improves the behavior in case of multiple nested extensions.
2022-10-11 16:48:04 +09:00
Daniel Ebert
2b02785f19 Improve code style for tree-sitter indentation.
Split extend logic into a separate file.
2022-10-11 16:48:04 +09:00
Triton171
05832f90cb Fix a bug that caused the indent for the line below to also be added in rare cases at the beginning of a file. 2022-10-11 16:48:04 +09:00
Triton171
1ceecbd062 Fix clippy warning. 2022-10-11 16:48:04 +09:00
Triton171
8f19956218 Add python indentation support to docs.
Document @extend-indented and @stop-extend captures for indent queries.
2022-10-11 16:48:04 +09:00
Triton171
3ab9abb642 Add extend-indented and stop-extend captures for indent queries.
Improve and re-enable python indent queries.
2022-10-11 16:48:04 +09:00
Alex
8c4ae4df1c update everforest theme (#3998) 2022-10-11 16:43:52 +09:00
Stuart Baker
ce2a5b6d9f Add colours "color-modes" to ayu_light theme (#4109)
* Rename "dark gray" to "light gray"

* Add colours for statusline modes

* Use UI background for inactive panes
2022-10-11 15:48:55 +09:00
Pascal Kuthe
543d75da23 do not reparse unmodified injections (#4146) 2022-10-11 15:48:12 +09:00
Alexis (Poliorcetics) Bourget
b58899bc8e fix: remove unneeded allocations when calling helix_view::Info::new 2022-10-11 15:47:11 +09:00
Alexis (Poliorcetics) Bourget
28cb89eadb chore: fix clippy linting 2022-10-11 15:47:11 +09:00
Michael Davis
65febe0cf4 Overlay all diagnostics with highest severity on top (#4113)
Here we separate the diagnostics by severity and then overlay the Vec
of spans for each severity on top of the highlights. The error
diagnostics end up overlaid on the warning diagnostics, which are
overlaid on the hints, overlaid on info, overlaid on any other severity
(default), then overlaid on the syntax highlights.

This fixes two things:

* Error diagnostics are now always visible when overlapped with other
  diagnostics.
* Ghost text is eliminated.
    * Ghost text was caused by duplicate diagnostics at the EOF:
      overlaps within the merged `Vec<(usize, Range<usize>)>` violate
      assumptions in `helix_core::syntax::Merge`.
    * When we push a new range, we check it against the last range and
      merge the two if they overlap. This is safe because they both
      have the same severity and therefore highlight.

The actual merge is skipped for any of these when they are empty, so
this is very fast in practice. For some data, I threw together an FPS
counter which renders as fast as possible and logs the renders per
second.

With no diagnostics, I see an FPS gain from this change from 868 FPS
to 878 (+1.1%) on a release build on a Rust file. On an Erlang file
with 12 error diagnostics and 6 warnings in view (233 errors and 66
warnings total), I see a decrease in average FPS from 795 to 790
(-0.6%) on a release build.
2022-10-11 15:46:47 +09:00
Pascal Kuthe
1a87cbd508 remove filterting with C-space from picker 2022-10-11 12:25:28 +09:00
Pascal Kuthe
7af599e0af Treat space as a seperator instead of a character in fuzzy picker 2022-10-11 12:25:28 +09:00
Michael Davis
c388e16e09 Add a helper function for applying transactions
It is easy to forget to call `Document::apply` and/or `View::apply` in
the correct order. This commit introduces a helper function which
closes over both calls.
2022-10-11 12:17:32 +09:00
Michael Davis
0aedef0333 Apply transactions to Views
This change adds View::apply calls for all Document::apply call-sites,
ensuring that changes to a document do not leave invalid entries in
the View's jumplist.
2022-10-11 12:17:32 +09:00
Michael Davis
d418f0795d Add View::apply for adjusting jumplist ranges
Applying a transaction to a View adjusts the ranges in the jumplist
to ensure that they remain within the text of the document and follow
regular selection invariants (for example, must be have a width of at
least one).
2022-10-11 12:17:32 +09:00
Blaž Hrastnik
a85e386298 picker: Highlight the document on idle timeout 2022-10-11 09:53:55 +09:00
Gokul Soumya
001858b11f Propagate idle timeout event to components (#3172) 2022-10-11 09:10:01 +09:00
dependabot[bot]
5e1c589d43 build(deps): bump serde_json from 1.0.85 to 1.0.86 (#4187)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-10 18:44:40 -05:00
gbprod
9f36468b15 Change twig tree-sitter grammar (#4176) 2022-10-10 16:27:14 -05:00
Sumit Sahrawat
a079f2c9bd Add some vertical characters to the editor.indent-guides documentation (#4163)
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2022-10-10 16:23:14 -05:00
David
7af7dadd17 Add instructions for gnome desktop support using the .desktop file (#4165) 2022-10-10 12:23:36 -05:00
Brandon Dong
530f9e3c53 Fix goto/view center mismatch (#4135) 2022-10-10 12:12:48 -05:00
Chickenkeeper
8e8ba06f60 Improve C# syntax highlighting (#4118) 2022-10-10 12:07:14 -05:00
S1m
d27551d814 Use different cursor color for primary cursor for ayu_mirage (#4140) 2022-10-10 10:26:10 -05:00
Mike Sampson
9b7f349f5c tutor: 5.5 add missing words (#4160) 2022-10-09 14:15:28 -05:00
A-Walrus
c15f1ea274 Add cursorcolumn (#4084)
* Implement cursorcolumn

* Add documentation

* Separate column style from line with fallback

* Fallback to cursorcolumn first

* Switch to non-fallback try_get_exact

Add new function `try_get_exact`, which doesn't perform fallback,
and use that instead because the fallback behaviour is being handled
manually.
2022-10-09 03:28:42 +09:00
Pascal Kuthe
2f7088c1f3 fix typo
Co-authored-by: Omnikar <omkar.subramaniam@icloud.com>
2022-10-08 17:43:32 +02:00
pascalkuthe
ad0eb4094b add deprectation not for underlined modifier to docs 2022-10-08 16:39:02 +02:00
Brandon Dong
18cfe864f4 Fix incorrect scrolloff default in documentation (#4136) 2022-10-08 03:22:35 +09:00
Pascal Kuthe
4c36c067b0 avoid visual artificats on terminal emulators that do not support underline colors 2022-10-07 00:18:49 +02:00
Pascal Kuthe
7bc324fde9 make casing consistent with other configuration 2022-10-06 20:50:54 +02:00
Pascal Kuthe
114610f7dc switch to termini for terminfo 2022-10-06 20:46:24 +02:00
Oleksii Dorozhkin
4d4be0e880 Update sonokai.toml (#4089) 2022-10-07 00:53:05 +09:00
allanderek
9ca4ac6901 Pallettise the bogster theme and, more importantly, add support for color-modes to the bogster theme. (#4121) 2022-10-07 00:52:10 +09:00
Jonathan
4595683622 Fix tutor typo (#4116) 2022-10-06 05:04:01 +09:00
A-Walrus
c927d61791 Fix bugs in search wraparound message (#4101) 2022-10-04 16:49:43 -05:00
Jaden
ccb38e7696 doc: add theme inheritance example (#4096) 2022-10-04 16:33:45 -05:00
Poliorcetics
ed5febf4b3 doc: add example to disable arrow keys in insert mode (#4088) 2022-10-04 09:40:51 -05:00
dependabot[bot]
581fe5c675 build(deps): bump thiserror from 1.0.36 to 1.0.37 (#4095)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-03 18:38:56 -05:00
dependabot[bot]
6b0fffb647 build(deps): bump tokio from 1.21.1 to 1.21.2 (#4094)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-03 18:38:43 -05:00
dependabot[bot]
7c33b9c76d build(deps): bump smallvec from 1.9.0 to 1.10.0 (#4093)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-03 18:38:24 -05:00
Skyler Hawthorne
27b70696df Exit gracefully when close operation fails (#4081)
If the close method fails, the editor will quit before restoring the
terminal. This causes the shell to break if, e.g. the LS times out
shutting down.

This fixes this by always restoring the terminal after closing, and
printing out a message to stderr if there is an error.
2022-10-04 00:35:42 +09:00
Michael Davis
6cca7375ec Automatically track pseudo-pending text (#4077)
This change automatically tracks pending text for for commands which use
on-next-key callbacks. For example, `t` will await the next key event
and "t" will be shown in the bottom right-hand corner to show that we're
in a pending state.

Previously, the text for these on-next-key commands needed to be
hard-coded into the command definition which had some drawbacks:

* It was easy to forget to write and clear the pending text.
* If a command was remapped in a custom config, the pending text would
  still show the old key.

With this change, pending text is automatically tracked based on the
key events that lead to the command being executed. This works even
when the command is remapped in config and when the on-next-key
callback is nested under some key sequence (for example `mi`).
2022-10-04 00:14:57 +09:00
Karsten Gebbert
9124c231f4 respond to SIGUSR1 by reloading config (#3952)
* respond to SIGUSR1 by reloading config

* document USR1 signal handling
2022-10-04 00:08:32 +09:00
Ivan Tham
3d59d3f8be Keep arrow and special keys in insert (#3915)
* Keep arrow and special keys in insert

Advanced users won't need it and is useful for beginners.
Revert part of #3671.

* Change text for insert mode section

Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>

* Remove ctrl-up/down in insert

* Reorganize insert keys and docs

* Improve page up experience on last tutor

The last tutor page can page down multiple times and it will break the
heading on the 80x24 screen paging when reaching the last page, this
keeps the style the same and make sure page up and down won't break it.

Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
2022-10-04 00:08:15 +09:00
A-Walrus
1d8bb2249b Change focus to modified docs on quit (#3872)
* Change focus to modified docs on quit

When quitting with modified documents, automatically switch focus to
one of them.

* Update helix-term/src/commands/typed.rs

Co-authored-by: Poliorcetics <poliorcetics@users.noreply.github.com>

* Make it work with buffer-close-all and the like

* Cleanup

Use Cow instead of String, and rename DoesntExist -> DoesNotExist

Co-authored-by: Poliorcetics <poliorcetics@users.noreply.github.com>
2022-10-04 00:07:21 +09:00
Robin
6764744ce9 Add option to skip the first indent guide (#3819)
* Add option to skip the first indent guide

* reorder skip_first option

* change indent-guides.skip_first to a number

* rename skip -> skip_levels

* add skip_levels to the book

* Update book/src/configuration.md

Co-authored-by: A-Walrus <58790821+A-Walrus@users.noreply.github.com>

* Update helix-term/src/ui/editor.rs

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>

Co-authored-by: Robin <robinvandijk@klippa.com>
Co-authored-by: A-Walrus <58790821+A-Walrus@users.noreply.github.com>
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2022-10-04 00:07:04 +09:00
Michael Davis
dbec057363 Rename I/A "Insert at start/end of line" (#3753)
* keymap: Rename A "Insert at end of line"

The language for the `A` binding is potentially confusing because
`A` behaves like `i` done at the end of the line rather than `a`.
This change renames the command to match Kakoune's language[^1].

[^1]: 021da117cf/src/normal.cc (L2229)

* keymap: Rename I `insert_at_line_start`
2022-10-04 00:05:08 +09:00
Kirawi
772af7ffb1 remove split-debuginfo setting (#3691)
According to [the rustc book](https://doc.rust-lang.org/rustc/codegen-options/index.html#split-debuginfo), this is not supported on Windows. It also prevents Helix from compiling on the latest nightly.
2022-10-04 00:04:19 +09:00
ath3
7c9809eeb2 Find workspace from document path (#3553) 2022-10-04 00:02:49 +09:00
Ivan Tham
66bbba9024 Select inserted space after join (#3549)
* Select inserted space after join

* Split join_selections with space selection to A-J

Kakoune does that too and some users may still want to retain their selections.

* Update join_selections docs
2022-10-04 00:02:14 +09:00
Michael Davis
4a3b776b78 rust: Highlight function signatures as functions (#4073)
This stanza highlights functions within trait definitions. For example,
in:

    pub trait Widget {
        fn render(self, area: Rect, buf: &mut Buffer);
    }

`render` is currently highlighted as a variable. With this change it's
highlighted as a function.
2022-10-03 23:56:50 +09:00
nuid32
576c34f84e Add command names to command palette (#4071) 2022-10-03 23:56:43 +09:00
Ivan Tham
93f26a3048 Fix signature help panic when too large (#4030)
When signature help is too large it may cause a panic when it is too
large, now I just make the hover do an intersection with surface to make
sure it never overflow.
2022-10-03 23:56:24 +09:00
greg-enbala
63ff9309ce goto_window_* extends selection (#3985)
* goto_window_* extends selection

* Don't push to the jumplist
2022-10-03 23:55:26 +09:00
Alexis Kalabura
b9ff5d0e0a [lsp-restart]: call the force_shutdown method for the old_client (#3972)
* [lsp-restart]: call the shutdown_and_exit method for the old_client

* change shutdown_and_exit to force_shutdown

* remove extra log
2022-10-03 23:54:46 +09:00
Joshua Pauline
c144cc0b04 feat(statusline): add option to show total line numbers in file (#3960)
* feat(statusline): add option to show total line numbers in file

* feat(line numbers): add config to doc book
2022-10-03 23:54:00 +09:00
Slug
519857d632 Add dark high contrast theme refer to vscode (#3312)
* Add dark high contrast theme

* Add my sign

* Fix typo

* Change gray to white for comment and remove Italic
2022-10-03 23:45:56 +09:00
PeepNSheep
77f33e7b20 Add configureable statusline mode names (#3311)
* Added 'long-mode' statusline element

* Added customizable statusline mode names

* Removed a string clone

* Added documentation

* Updated documentation, moved modenames to a seperate section

* Update configuration.md

* Documentation update

* Documentation update

* Documentation update

* Update configuration.md

* Update configuration.md

* Fixed merge error

* Update configuration.md

* Update configuration.md
2022-10-03 23:45:32 +09:00
ChrHorn
589d17c758 Add ui.gutter.selected option for themes (#3303)
* add `ui.gutter.selected`

* add `ui.gutter`, `ui.gutter.selected` to docs
2022-10-03 23:44:45 +09:00
Michael Davis
6939dd3adb Add tests for select-mode TS textobjects 2022-10-03 10:44:08 -04:00
Michael Davis
c253139790 Extend textobject selections in select mode 2022-10-03 10:44:08 -04:00
Michael Davis
032d76ccf2 Use Range::with_direction consistently 2022-10-03 10:44:08 -04:00
Michael Davis
274f2ea459 Use requested direction for new textobject selection range
This changes the behavior of operations like `]f`/`[f` to set the
direction of the new range to the direction of the action.

The original behavior was to always use the head of the next function.
This is inconsistent with the behavior of goto_next_paragraph and makes
it impossible to create extend variants of the textobject motions.

This causes a behavior change when there are nested functions. The
behavior in the parent commit is that repeated uses of `]f` will
select every function in the file even if nested. With this commit,
functions are skipped.

It's notable that it's possible to emulate the original behavior by
using the `ensure_selections_forward` (A-:) command between invocations
of `]f`.
2022-10-03 10:44:08 -04:00
A-Walrus
f3958aa1fd Cycled to end/beginning + no more matches msgs (#3176)
* Show status msg when next/prev cycles around

* Add msg when there is no wraparound

* Cleanup code

* Change msg to "Wrapped around document"
2022-10-03 23:43:26 +09:00
Christoph Schmidler
2fac9e24e5 Inherit theme (#3067)
* Add RawTheme to handle inheritance with theme palette

* Add a intermediate step in theme loading

it uses RawTheme struct to load the original ThemePalette, so we can merge it with the inherited one.

* Load default themes via RawThemes, remove Theme deserialization

* Allow naming custom theme same as inherited one

* Remove RawTheme and use toml::Value directly

* Resolve all review changes resulting in a cleaner code

* Simplify return for Loader::load

* Add  implementation to avoid extra step for loading of base themes
2022-10-03 23:34:29 +09:00
A-Walrus
57dc5fbe3a Show "Invalid regex" message on enter (Validate) (#3049)
* Show "Invalid regex" message on enter (Validate)

* Reset selection on invalid regex

* Add popup for invalid regex

* Replace set_position with position

* Make popup auto close
2022-10-03 23:33:48 +09:00
Joe
bcba5d67f9 Add goto preview (#2982) 2022-10-03 23:33:20 +09:00
David
18f6ec7a8e Update treesitter markdown (#4078)
* Update treesitter markdown

* Update inline and add table injections
2022-10-03 23:14:16 +09:00
Matt Freitas-Stavola
9d1793c45b Add pseudo_pending for t/T/f/F (#4062) 2022-10-02 14:32:30 -05:00
Kirawi
8c2cc43017 diff full-doc LSP edits (#4041)
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2022-10-02 14:23:23 -05:00
nuid32
6caa7a7f56 Onedarker theme: some improvements (#4069) 2022-10-02 11:19:55 -05:00
Pascal Kuthe
71ee589bbc make underline_style a seperate option
Underline styles are mutally exclusive and overwrite each other.
Therefore implementing as an modifier lead to incorrect behaviour
when the underline style is overwritten.

For backwards compatability the "underline" modified is retained (but
deprecated). Instead the "underline_style" and "underline_color"
optios should be used to style underlines.
2022-10-01 19:29:46 +02:00
nuid32
5b5f1bd39a Adjust light-gray in onedarker theme (#4060) 2022-10-01 10:37:18 -05:00
Gokul Soumya
79d3d44c3d Detect extended underline support using terminfo
The cxterminfo crate has been used over popular alternatives
like `term` since it supports querying for extended capabilities
and also for it's small codebase size (which will make it easy
to inline it into helix in the future if required).
2022-10-01 17:00:40 +02:00
A-Walrus
de72b9c04c Update theme documentation 2022-10-01 17:00:36 +02:00
A-Walrus
79a39c1063 Fix failing tests
Add underline field to doctests, and fix bugs
2022-10-01 17:00:35 +02:00
A-Walrus
3ad7d543ca Add separate color for underlines 2022-10-01 17:00:34 +02:00
Gokul Soumya
999b45b28c Support different kinds of underline rendering
Adds four new  modifiers that can be used in themes:

- undercurled
- underdashed
- underdotted
- double-underline
2022-10-01 17:00:32 +02:00
zensayyy
c9584251f3 Ensure cursor in view after format (#4047)
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2022-10-01 09:32:09 -05:00
Roberto Vidal
cc257e9bf9 Add support for webassembly text format (#4040) 2022-10-01 09:13:52 -05:00
nuid32
2113b1bb2f themes: Add onedarker (#3980) 2022-10-01 09:11:15 -05:00
Chickenkeeper
60aa7d3607 WGSL syntax highlighting fix (#3996) 2022-09-30 17:43:07 -05:00
Maximilian Muecke
8a7a6e4cff Add comment injection for R (#4031) 2022-09-29 13:11:45 -05:00
joleaf
c4aec0a5c5 tutor: missing <ESC> before removing the second cursor (#4027)
This step was missing in section 5.2 of tutor.
2022-09-29 11:02:55 -04:00
Sora
038ad6289f Fix tutor typo favourite to favorite (#4007) 2022-09-28 18:50:24 -05:00
Sven-Hendrik Haase
5dbca0fc08 Add gruvbox dark (#3948)
* Add gruvbox dark

* fixup! Add gruvbox dark
2022-09-28 22:50:53 +08:00
Erin Kim
bdc7b35214 nix: replace runCommandNoCC with runCommand (#3992) 2022-09-27 08:01:58 -05:00
dependabot[bot]
8fc493137d build(deps): bump serde from 1.0.144 to 1.0.145 (#3989)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-09-26 18:43:30 -05:00
dependabot[bot]
cc0018a7d3 build(deps): bump thiserror from 1.0.35 to 1.0.36 (#3991)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-09-26 18:43:14 -05:00
dependabot[bot]
e3fbeeb789 build(deps): bump unicode-general-category from 0.5.1 to 0.6.0 (#3990)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-09-26 18:36:40 -05:00
Jacob Chandler
90468ad6c5 fix: Improve JSX and TSX tag highlighting (#3973) 2022-09-26 18:27:54 -05:00
dependabot[bot]
d2bb7f5a09 build(deps): bump tokio-stream from 0.1.9 to 0.1.10 (#3988)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-09-26 18:22:48 -05:00
dependabot[bot]
fd4cdf0b1f build(deps): bump once_cell from 1.14.0 to 1.15.0 (#3987)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-09-26 18:19:50 -05:00
Oskar Köök
98dd9c4f2b Remove do_block from Ruby indents (#3976)
`do_block` and `block` seem to conflict, causing double-indentation in some cases. Removing `do_block` does not seem to have any negative effect, while fixing the double-indentation issue.
2022-09-26 13:04:32 -04:00
Oskar Köök
c196a90684 Add documentation for max-line-length (#3974) 2022-09-26 07:56:07 -05:00
Poliorcetics
e8f0886b21 chore: remove unneeded attribute after MSRV bump to 1.61 (#3961) 2022-09-25 08:12:33 -05:00
Clay
1a4a9b86d7 heex: upgrade grammar, add roots matching elixir (#3959) 2022-09-25 15:51:25 +09:00
Invader Zim
42e30e7afa Add bufferline colors to 15 themes (#3881)
Themes:

* acme
* ayu_dark
* ayu_light
* ayu_mirage
* base16_default_dark
* base16_default_light
* bogster
* catppuccin_frappe
* catppuccin_latte
* catppuccin_macchiato
* catppuccin_mocha
* darcula
* dark_plus
* doom_acario_dark
* emacs
2022-09-23 14:32:37 -05:00
adrian5
0d8d8a4ed6 docs: Punctuation on tutor (#3888) 2022-09-23 12:01:41 -05:00
Riccardo Binetti
3a245fe792 Add mix.exs and mix.lock as Elixir root markers (#3917) 2022-09-23 11:40:16 -05:00
Riccardo Binetti
888f4fef6f Split helix_core::find_root and helix_loader::find_local_config_dirs (#3929)
* Split helix_core::find_root and helix_loader::find_local_config_dirs

The documentation of find_root described the following priority for
detecting a project root:
- Top-most folder containing a root marker in current git repository
- Git repository root if no marker detected
- Top-most folder containing a root marker if not git repository detected
- Current working directory as fallback

The commit contained in https://github.com/helix-editor/helix/pull/1249
extracted and changed the implementation of find_root in find_root_impl,
actually reversing its result order (since that is the order that made
sense for the local configuration merge, from innermost to outermost
ancestors).

Since the two uses of find_root_impl have different requirements (and
it's not a matter of reversing the order of results since, e.g., the top
repository dir should be used by find_root only if there's not marker in
other dirs), this PR splits the two implementations in two different
specialized functions.

In doing so, find_root_impl is removed and the implementation is moved
back in find_root, moving it closer to the documented behaviour thus
making it easier to verify it's actually correct

* helix-core: remove Option from find_root return type

It always returns some result, so Option is not needed
2022-09-23 17:04:07 +09:00
Pascal Kuthe
4133f1f424 Document MSRV policy (#3913) 2022-09-23 15:58:00 +09:00
A-Walrus
eb6fd283dc Deduplicate regexes in search_selection command (#3941) 2022-09-22 23:33:30 +08:00
Henrik Tjäder
e621848d07 Theme: Papercolor: Tune inactive statusline (#3938) 2022-09-22 07:28:05 -05:00
Michael Davis
6e168b5099 Improve keymap errors from command typos (#3931)
* Improve keymap errors from command typos

Currently, opening helix with a config containing a bad command mapping
fails with a cryptic error. For example, say we have a config (bad.toml)
with a command name that doesn't exist:

    [keys.normal]
    b = "buffer_close" # should be ":buffer-close"

When we `hx -c bad.toml`, we get...

> Bad config: data did not match any variant of untagged enum KeyTrie for key `keys.normal` at line 1 column 1
> Press <ENTER> to continue with default config

This is because of the way that Serde tries to deserialize untagged
enums such as `helix_term::keymap::KeyTrie`. From the Serde docs[^1]:

> Serde will try to match the data against each variant in order and the
> first one that deserializes successfully is the one returned.

`MappableCommand::deserialize` fails (returns an Err variant) when a
command does not exist. Serde interprets this as the `KeyTrie::Leaf`
variant failing to match and declares that the input data doesn't
"match any variant of untagged enum KeyTrie."

Luckily the variants of KeyTrie are orthogonal in structure: we can tell
them apart by the type hints from a `serde:🇩🇪:Visitor`. This change
uses a custom Deserialize implementation along with a Visitor that
discerns which variant of the KeyTrie applies. With this change, the
above failure becomes:

> Bad config: No command named 'buffer_close' for key `keys.normal.b` at line 2 column 5
> Press <ENTER> to continue with default config

We also provide more explicit information about the expectations on
the field. A config with an unexpected type produces a message with
that information and the expectation:

    [keys.normal]
    b = 1

> Bad config: invalid type: integer `1`, expected a command, list of commands, or sub-keymap for key `keys.normal.b` at line 2 column 5
> Press <ENTER> to continue with default config

[^1]: https://serde.rs/enum-representations.html#untagged

* Update helix-term/src/keymap.rs

Co-authored-by: Ivan Tham <pickfire@riseup.net>

Co-authored-by: Ivan Tham <pickfire@riseup.net>
2022-09-22 09:30:42 +08:00
gavincrawford
1dd1476a9e Fix highlighting on single-character Rust consts (#3927)
Co-authored-by: Kirawi <67773714+kirawi@users.noreply.github.com>
Co-authored-by: Gavin Crawford <gavincrawford@users.noreply.github.com>
2022-09-21 17:55:28 -05:00
taupiqueur
75362dce83 Fix the picker’s keymap documentation (#3925) 2022-09-21 13:51:48 -05:00
Benedikt Müller
5467c65f82 fix fish completions for --config & --log (#3912) 2022-09-20 07:35:00 -05:00
Filipe Azevedo
385ccdfc9c add :lsp-restart command (#3435) 2022-09-20 16:44:36 +09:00
Joe
aa00a470f3 Fix preview bug (#3644)
* Fix preview bug

* Add comment to empty case
2022-09-20 16:40:48 +09:00
Blaž Hrastnik
1df32c917c diagnostics: Use Vec<Tag> instead of Option<Vec<Tag>> 2022-09-20 16:28:00 +09:00
Luke Cycon
64b0745413 Track source and tags in diagnostics (#3898) 2022-09-20 16:21:15 +09:00
Tobias Hunger
130793dfd0 Add command line parameter to specify log file (#3807)
* Add command line parameter to specify log file

I had the logs of my debug helix mixed in with the logs from the
production helix.

Add a `--log` command line argument to redirect any logs to other
files, making my debugging easier :-)

* Update completion files with `--log` argument
2022-09-20 16:11:30 +09:00
Michael Davis
8988c1ecc7 Re-sort diagnostics after transaction transform (#3895)
Applying document-change transactions to diagnostic ranges is not stable
with respect to the ordering of diagnostics. This can cause diagnostics
to become temporarily unordered with some edits to a document, which can
eventually break some invariants/assumptions in syntax::merge.

With this change, Document::diagnostics are always sorted.
2022-09-20 16:08:58 +09:00
dependabot[bot]
947ff63e6d build(deps): bump textwrap from 0.15.0 to 0.15.1 (#3906)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-09-19 18:29:00 -05:00
dependabot[bot]
26c3c99330 build(deps): bump unicode-segmentation from 1.9.0 to 1.10.0 (#3903)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-09-19 18:28:38 -05:00
dependabot[bot]
674bfec984 build(deps): bump unicode-width from 0.1.9 to 0.1.10 (#3902)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-09-19 18:28:12 -05:00
dependabot[bot]
2450166927 build(deps): bump tokio from 1.21.0 to 1.21.1 (#3904)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-09-19 18:27:04 -05:00
dependabot[bot]
3acdf9fdf9 build(deps): bump thiserror from 1.0.34 to 1.0.35 (#3905)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-09-19 18:26:18 -05:00
dependabot[bot]
e85d6c37d4 build(deps): bump anyhow from 1.0.64 to 1.0.65 (#3907)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-09-19 18:25:22 -05:00
Alexander Brevig
08b2ecc99a feat: xtask themelint (#3234)
* feat: cargo xtask themelint <theme>

* fix: add docs and print json error status

* fix: refactor paths -> path

* fix: remove unused function

* fix: only report one err per scope (ui.statusline is reported if none of ui.statusline.* is recognized)

* fix: save work for later

* fix: finally decided on a design

* fix: ready for discussion

* fix: better rules

* fix: lint precision

* fix: String -> &'static str

* fix: allowlist not denylist for file type

* fix: add missing and indication of what's needed

* fix: copy pasteable errors

* fix: use Loader:read_names

* Update xtask/src/helpers.rs

Co-authored-by: Ivan Tham <pickfire@riseup.net>

* fix: remove into and clone for str

* Update book/src/themes.md

Co-authored-by: Ivan Tham <pickfire@riseup.net>

* fix: better lint output

* fix: cleaner logic for lint reporting

* style: use explicit imports

* Pascal support (#3542)

* fix: add difference check for statusline normal,insert,select

* fix: fg for whitespace and early exit if and one is ok

* chore: cleaning up, no idea how these got here or how this will look

* chore: revert from older commit?

* refactor: use static fn to equalize api between difference and existance

* refactor: querycheck and clippy

* refactor: clippy fixes

* fix: query-check behaves as before

* fix: error with x of y message, not total count

* fix: consistent reporting and less mutable state

* fix: selection difference ref #3942 ref #1833

Co-authored-by: Ivan Tham <pickfire@riseup.net>
Co-authored-by: ath3 <45574139+ath3@users.noreply.github.com>
2022-09-19 21:38:20 +08:00
Pascal Kuthe
5ea7855977 raise msrv to 1.59 (#3896) 2022-09-19 12:03:51 +09:00
Alex Suraci
ea25ed6431 add bass language + highlighting (#3771) 2022-09-18 12:06:51 -05:00
Artem Pyanykh
08937fc00e Add Markdown LSP via Marksman
Marksman is an LSP server for Markdown: https://github.com/artempyanykh/marksman
It supports a bunch of LSP features: symbols, references, rename, diag,
etc. and already has integrations with emacs, neovim, and vscode.
2022-09-17 20:58:42 +02:00
taupiqueur
a73e83ef4d Fix typos (#3858) 2022-09-17 06:34:48 -05:00
Nick Ogden
19384cc3a1 Add darcula theme based upon Intelij Darcula (#3739) 2022-09-16 11:21:56 -05:00
Benjamin Streit
714db9c666 fix: Improving JSX and TSX indents (#3853) 2022-09-16 16:51:19 +09:00
Kristoffer Flottorp
111d2dafd3 Improve flatwhite theme (#3843)
Co-authored-by: krfl <kr.fl@outlook.com>
2022-09-16 11:39:06 +09:00
Kristoffer Flottorp
73f8e9902b improve fleetish theme (#3844)
Co-authored-by: krfl <kr.fl@outlook.com>
2022-09-16 11:38:54 +09:00
Ben Noordhuis
b5be72bff7 Canonicalize executable path
When looking up the runtime/ directory relative to the executable path,
canonicalize the path first in case the executable is a symbolic link.

Fixes #3768
2022-09-13 17:50:02 -04:00
Michael Davis
ec81ec1e8d flake: Fix devShell on aarch64-darwin (#3810)
LLDB is marked broken on all arches except for x86_64-linux. With this
change, I can use `nix develop` on aarch64-darwin.
2022-09-13 22:50:53 +09:00
A-Walrus
d38950bdf9 Remove border from code actions popup (#3444) 2022-09-13 05:24:48 -04:00
A-Walrus
ac460ac837 Render html <code> tags as code in markdown (#3425) 2022-09-13 05:14:16 -04:00
Benjamin Streit
ffb41a94f0 feat: Syntax highlighting for Astro files (#3829) 2022-09-13 01:53:55 -05:00
Skyler Hawthorne
0d8ffa6b4a add example config for all removed insert mode bindings (#3827) 2022-09-13 01:49:18 -05:00
Alexander Brevig
16b9a1841f fix: map_err()? instead of unwrap (#3826) 2022-09-13 15:08:23 +09:00
dependabot[bot]
800a490676 build(deps): bump url from 2.2.2 to 2.3.1 (#3828)
Bumps [url](https://github.com/servo/rust-url) from 2.2.2 to 2.3.1.
- [Release notes](https://github.com/servo/rust-url/releases)
- [Commits](https://github.com/servo/rust-url/compare/v2.2.2...v2.3.1)

---
updated-dependencies:
- dependency-name: url
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-09-13 10:01:38 +09:00
Alex Mayer
23027a454a Clean Up Nord Theme (#3792)
- Add markup styles
- Replace custom colors with Nord colors
- Clean up code spacing
2022-09-12 23:32:24 +09:00
Michael Davis
936ad884eb Remove arrow key recommendation from tutor (#3811) 2022-09-12 23:15:54 +09:00
Fanda Vacek
865a1a4cb3 Make whitespace in monokai-pro-spectrum theme one step dimmer to avoid (#3814)
the white space confusion with hyphen

Co-authored-by: Fanda Vacek <fvacek@elektroline.cz>
2022-09-12 23:15:41 +09:00
Pablo Ovelleiro Corral
03612174ee Update usage.md with paragraph textobject(#3797) 2022-09-11 16:41:35 +05:30
yvt
b191ecf828 Strip release binary by setting profile.release.strip in a pre-build step (#3780)
* chore(ci): remove the strip step from the release CI workflow

* chore(ci): set `profile.release.strip = true` in the release CI workflow
2022-09-11 11:15:07 +09:00
Blaž Hrastnik
c2e41082e4 Remove the .txt suffix from tutor
The tutor file is loaded as .txt which can potentially spawn a
language server. Then the path is unset, but the LS remains active.
This can cause panics since updates are now submitted for a doc
with no path.

As a quick workaround we remove the extension which should avoid
detection.

Fixes #3730
2022-09-11 11:11:07 +09:00
Erasin
a15420ed1c Add textobject for gdscript (#3760) 2022-09-10 08:47:08 -05:00
Erasin
54e78dd24f Add godot resource support (#3759)
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2022-09-10 08:45:52 -05:00
yvt
5489c9ad4e chore: rename .cargo/{config -> config.toml} 2022-09-10 08:44:31 -05:00
yvt
02d6102540 chore(ci): upgrade actions/upload-artifact to v3
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2022-09-10 08:36:48 -05:00
yvt
0090a2d86f chore(ci): support "preview" release CI runs
Expands the trigger sources of the release CI workflow (`release.yml`),
allowing the developers to test changes to `.github/workflows/release.yml`
easily. The new trigger sources start the workflow in a "preview" mode, in
which it publishes build outputs as a CI artifact instead of creating a new
release so that they can be manually inspected.

The following events trigger the preview mode:

- Pushing to any branch matching the glob pattern `patch/ci-release-*`.
- Opening a pull request that modifies `.github/workflows/release.yml`.
- Pushing versioning tags to a forked repository.
2022-09-10 08:36:48 -05:00
yvt
29fe0c3862 Enable CI builds for riscv64-linux (#3685) 2022-09-10 08:35:35 -05:00
A-Walrus
9c627c65e5 Improve error handling for config-reload (#3668)
* Don't change config to default when refreshing invalid config

* Propely handle theme errors with config-reload

* Extract refresh theme into seperate function
2022-09-10 22:32:49 +09:00
A-Walrus
75e6a64327 Switch to Result for invalid language 2022-09-10 22:23:38 +09:00
A-Walrus
e8add6f46d Add error handling to set language command
If you type a nonexistant language an appropriate message will show,
and the language won't be changed.
2022-09-10 22:23:38 +09:00
A-Walrus
cc47d3fb9d Add text to language completer 2022-09-10 22:23:38 +09:00
Evan Richter
01ee42bb14 ordinals instead of indexes when listing grammar fetch errors (#3773) 2022-09-10 14:14:03 +09:00
Soc Virnyl S. Estela
fae9203c3e Add papercolor dark variant (#3742) 2022-09-08 19:02:06 -05:00
Matouš Dzivjak
321cce3f13 enable lint option
Enable lint option to highlight unused vars, etc.
and take full advantage of the running language server.
2022-09-08 18:38:41 -05:00
Matouš Dzivjak
76b3f502c4 feat(lsp): jsonnet-language-server
Add jsonnet-language-server for jsonnet language.
See: https://github.com/grafana/jsonnet-language-server
2022-09-08 18:38:41 -05:00
ChemicalXandco
7210b39587 change to openscad-lsp (#3750) 2022-09-08 18:36:03 -05:00
Akseli
8a1047c844 Add "markdown" as a possible filetype (#3749) 2022-09-08 18:29:36 -05:00
Skyler Hawthorne
e12690e2f5 Remove default insert mode movement bindings
Helix is first and foremost a modal editor. Willingness to support non-modal
editing is there, but it is not one that should be encouraged with the default
settings. There are an increasing number of users who are stumbling because
they are trying to use Helix as a non-modal editor, so this is an effort to
encourage new users to stop and take notice that Helix has a different paradigm
than VSCode, Sublime, etc. Users can still add these bindings back to their own
configs if they wish.
2022-09-08 17:36:04 -05:00
Matouš Dzivjak
5ab85283e9 feat(languages): jsonnet (#3714)
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2022-09-08 09:04:18 -05:00
Benoît Cortier
16ce036bdf Add good default rulers when editing git messages (#3738)
Around 50 columns for the summary is good because it is often used as
heading or as subject in emails. 72 columns for the body is generally
good because some tools do not wrap long lines (`git log` with pager
`less` is a good example). Helix's `:reflow` command is really good to
help with the second point.

Linux kernel documentation says:

> For these reasons, the ``summary`` must be no more than 70-75
> characters, and it must describe both what the patch changes, as well
> as why the patch might be necessary.  It is challenging to be both
> succinct and descriptive, but that is what a well-written summary
> should do.

Source:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/process/submitting-patches.rst#n627

tpope:
https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html

Commit message style guide for Git:
https://commit.style/
2022-09-07 16:29:41 -04:00
Giorbo
5b1113766d Add syntax highlighting for SML (#3692)
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2022-09-07 13:13:06 -05:00
A-Walrus
e14b48af2e Fix :reflow panic by enusring cursor in view (#3733) 2022-09-07 12:50:54 -05:00
Blaž Hrastnik
a123fb6057 Remove LspNotDefined, instead return an Option<> 2022-09-07 16:42:33 +09:00
A-Walrus
fe37a66046 Handle formatter errors, and save anyway (#3684)
If formatting fails, report error to log and save without formatting.
2022-09-07 16:22:48 +09:00
Michael Davis
301f5d7cf7 Fix Rust attribute highlights (#3729) 2022-09-07 12:45:51 +09:00
Timothy DeHerrera
1fe32737fa nix: fix highlighting rules
* avoid coloring `identifier`s globally
* fix function application when not part of `select_expression`
* add `has_attribute_expression` highlighting
* fix precendence for interpolation, which should be after select
* highlight `@` as delimiter
2022-09-06 19:47:33 -05:00
yvt
b7380313a5 chore(ci): build AppImage for aarch64-linux 2022-09-06 18:42:02 -05:00
yvt
038a91d204 chore(ci): build binary for aarch64-linux 2022-09-06 18:42:02 -05:00
yvt
1fc97a9a20 chore(ci): install a pre-release version of Cross 2022-09-06 18:42:02 -05:00
Rohit K Viswanath
14f12c8a0b Theme: Rasmus (#3728) 2022-09-06 17:51:02 -05:00
Timothy DeHerrera
5ed751c67d remove ^$ from injection regexs 2022-09-06 17:39:41 -05:00
Timothy DeHerrera
665e27ff9d nix: add language injections
By simply placing a comment with the name of the desired language just
before a multi-line string, that language will be injected.

Also, common functions and attributes which are expected to be shell
code are automatically injected.
2022-09-06 17:39:41 -05:00
Michael Davis
43b31f702a Update tree-sitter-diff (#3708)
This change also renames the grammar from `git-diff` to `diff`.
The grammar covers regular diff syntax so I renamed the repository
a while ago.
2022-09-06 12:02:37 +09:00
dependabot[bot]
f7c216d497 build(deps): bump tokio from 1.20.1 to 1.21.0 (#3716)
Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.20.1 to 1.21.0.
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.20.1...tokio-1.21.0)

---
updated-dependencies:
- dependency-name: tokio
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-09-06 11:25:54 +09:00
dependabot[bot]
b85d0c597a build(deps): bump tree-sitter from 0.20.8 to 0.20.9 (#3719)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-09-05 18:51:33 -05:00
dependabot[bot]
8667a4d2be build(deps): bump anyhow from 1.0.63 to 1.0.64 (#3718)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-09-05 18:48:58 -05:00
dependabot[bot]
c34929b134 build(deps): bump thiserror from 1.0.33 to 1.0.34 (#3717)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-09-05 18:33:50 -05:00
dependabot[bot]
5e1296b888 build(deps): bump once_cell from 1.13.1 to 1.14.0 (#3715)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-09-05 18:33:01 -05:00
Kirawi
8882615483 Delete hooks.md (#3711) 2022-09-05 14:38:37 -05:00
Clay
da8071047a Elixir: update tree-sitter queries (#3645) 2022-09-05 08:49:41 -05:00
NotAgentBilly
df1ed0a5fd xcopy - assume destination is a directory (#3686) 2022-09-05 08:42:17 -05:00
Lennard Hofmann
fb92d71d08 Update tree-sitter-fish to latest commit (#3704) 2022-09-05 08:35:14 -05:00
Michael Kohl
16197664ab Add file_picker_in_current_directory to keymap.md (#3701) 2022-09-05 15:11:06 +09:00
Blaž Hrastnik
1acdfaa073 fix: View needs to retain the original scroll offset on split 2022-09-05 11:58:00 +09:00
Michael Davis
9c3c6a1c22 Fix off-by-one in extend_line_above (#3689)
`extend_line_above` (and `extend_line` when facing backwards) skip
a line when the current range does not fully cover a line.

Before this change:

    foo
    b#[|a]#r
    baz

With `extend_line_above` or `extend_line` selected the line above.

    #[|foo
    bar]#
    baz

Which is inconsistent with `extend_line_below`. This commit changes
the behavior to select the current line when it is not already
selected.

    foo
    #[|bar]#
    baz

Then further calls of `extend_line_above` extend the selection up
line-wise.
2022-09-05 11:34:49 +09:00
Blaž Hrastnik
20ed8c2595 tree-sitter-solidity: Use upstream, update queries 2022-09-05 10:50:32 +09:00
Blaž Hrastnik
44b447947c fix: lsp: Don't send didOpen events for documents with no URL
Fixes #3683
2022-09-04 17:28:17 +09:00
Blaž Hrastnik
cc4b71274a minor: Simplify another document_mut statement 2022-09-04 17:27:15 +09:00
Michael Davis
f0d1caafcf Look for the external formatter before invoking it (#3670)
Currently it is not possible to save a file with a language that
has an external formatter configuration unless the external
formatter is installed, even if the language has a Language Server
configuration capable of auto-format. This change checks that the
external formatter exists before using it to create a formatting
callback.
2022-09-04 09:59:20 +05:30
Fangrui Song
0d76775453 Fix typos in tutor (#3664) 2022-09-03 17:30:03 -05:00
A-Walrus
c93d52cc8a Fix cargo doc warnings, and add GitHub action to ensure it (#3650) 2022-09-03 09:58:16 -05:00
Yusuf Bera Ertan
59f7b07c86 build(nix): update flake deps (#3663) 2022-09-03 13:16:34 +09:00
Blaž Hrastnik
6ec4017a8d Expand doc/view macros to allow fetching specific id
This simplifies the code and hides away unwraps
2022-09-03 12:36:06 +09:00
Blaž Hrastnik
1caba2d3e8 lsp: Don't log "LSP not defined" errors in the logfile 2022-09-03 12:18:08 +09:00
Yusuf Bera Ertan
e917a8e0be build(nix): update nci, refactor flake, seperate wrapping, add source filtering (#3657) 2022-09-02 17:54:07 -05:00
bootra
3c38fe9c70 update boo_berry theme for statusline and indent-guide (#3653) 2022-09-02 17:34:22 -05:00
Charles Hall
b3b164f0d5 Highlight SQL in sqlx::{query,query_as}!() in Rust (#3647) 2022-09-02 17:26:42 -05:00
voroskoi
6e5e38c2ba update zig grammar and highlight rules (#3621) 2022-09-02 17:22:07 -05:00
aaron404
e8730ca5fd initial implementation of bufferline (#2759)
* initial implementation of bufferline

* fixed lint

* changed to 'bufferline', added enum for config modes, some cleanup

* fixed lint

* added file modification indicator

* removed redundant code, added proper themeing with fallback, changed 'file modified' indicator

* remove commented code

* Update helix-term/src/ui/editor.rs

simplify text and offset computation

Co-authored-by: Gokul Soumya <gokulps15@gmail.com>

* add ui.bufferline.background key for themes

Co-authored-by: lazytanuki <43273245+lazytanuki@users.noreply.github.com>

* address PR comments

* Update helix-term/src/ui/editor.rs

* simplify computation of editor area:

* change to set_stringn to avoid overflow

* Update configuration.md

Updates documentation to reflect decision re: defaulting to never showing bufferline.

* addressed pr comments

* fix build error

* address pr comments

* revert accidental change

Co-authored-by: Gokul Soumya <gokulps15@gmail.com>
Co-authored-by: lazytanuki <43273245+lazytanuki@users.noreply.github.com>
Co-authored-by: Seth Bromberger <sbromberger@users.noreply.github.com>
2022-09-02 11:39:38 +09:00
Bertrand Bousquet
04a4033b6c theme: Add Varua color scheme (#3610) 2022-09-01 19:57:37 -05:00
Michael Davis
66276ce630 Changelog notes for 22.08.1 (#3639) 2022-09-01 12:07:46 -05:00
A-Walrus
45dbcb6783 Fix closing buffer with custom keymap (#3633)
* Fix closing buffer with custom keymap

* Add comment explaining if
2022-09-02 01:59:39 +09:00
Fanda Vacek
ec28b2b5cc Change MonokaiProSpectrum theme error background from red to magenta. (#3627)
Co-authored-by: Fanda Vacek <fvacek@elektroline.cz>
2022-09-01 07:45:22 -05:00
Charles Hall
04e1cbe33f fix: typo in tutor about searching compared to vim (#3625) 2022-09-01 07:41:15 -05:00
Blaž Hrastnik
5c2b77b41f Make mode editor-wide rather than per-document 2022-09-01 16:14:38 +09:00
Blaž Hrastnik
10d9355b34 Update deps 2022-09-01 16:00:19 +09:00
Saber Haj Rabiee
1cbf552554 fix: prevents storing last prompt if is top of stack (#3609) 2022-09-01 10:29:15 +09:00
Michael Davis
ee94031fc4 Bump VERSION to 22.08 2022-08-31 11:43:51 -05:00
Michael Davis
22c5f2474d Add changelog entries for 22.08 2022-08-31 11:37:17 -05:00
Michael Davis
7c34f20dca Fix Prompt::handle_event compilation 2022-08-31 11:37:17 -05:00
Frojdholm
4c9f144dac fix: Recalculate completion when going through prompt history (#3193)
* fix: Recalculate completion when going through prompt history

* Update completion when the prompt line is changed

It should not be possible to update the line without also updating the
completion since the completion holds an index into the line.

* Fix Prompt::with_line recalculate completion

with_line was the last function where recalculate completion had to be
done manually. This function now also recalculates the completion so
that it's impossible to forget.

* Exit selection when recalculating completion

Keeping the selection index when the completion has been recalculated
doesn't make sense. This clears the selection automatically, removing
most needs to manually clear it.

* Remove &mut on save_filter

Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
2022-09-01 01:26:21 +09:00
Gokul Soumya
e3e71fa36b Show clipboard info in --health output (#2947)
* Show clipboard info in --health output

* health: Separate 'languages' category from 'all'

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2022-09-01 01:23:45 +09:00
Charlie Groves
5c3f43a7f0 Share the restore_term code between panic and normal exits (#3612)
It was starting to diverge as the normal exit code was restoring the prompt but the panic code
wasn't, and the panic code was disabling bracketed paste but the normal code wasn't.

This changes the panic path slightly in that we won't disable raw mode if exiting alternate screen
and disabling bracketed paste fails. If that happens, things are so busted I don't think it matters
anyway.
2022-09-01 01:23:21 +09:00
Michael Davis
93c6a337c4 Avoid command execution hooks on closed docs (#3613)
Fixes a panic with a config like:

    [keys.normal.space]
    x = [":buffer-close"]

by bailing out of the command-execution handling if the document
doesn't exist after handling a command.
2022-09-01 01:20:55 +09:00
Michael Davis
83f177d270 Refactor goto_ts_object_impl as a motion (#3264)
This refactor changes the overall structure of the goto_ts_object_impl
command without removing any functionality from its behavior. The
refactored motion:

* acts on all selections instead of reducing to one selection
* may be repeated with the `repeat_last_motion` (A-.) command
* informs the user when the syntax-tree is not accessible in the current buffer
2022-08-31 17:48:33 +09:00
Michael Davis
7547a961bb Discard LSP publishDiagnostic when LS is not initialized (#3403)
This is invalid according to the [LSP spec]:

> In addition the server is not allowed to send any requests
> or notifications to the client until it has responded with an
> InitializeResult, with the exception that during the initialize
> request the server is allowed to send the notifications
> window/showMessage, window/logMessage and telemetry/event as well
> as the window/showMessageRequest request to the client.

So we should discard the message when the language server is not
yet initialized. This can happen if the server sends
textDocument/publishDiagnostics before responding to the initialize
request. clojure-lsp appears to exhibit this behavior in the wild.

[LSP Spec]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#initialize
2022-08-31 17:47:18 +09:00
Michael Davis
03f0ef93ac Update tree-sitter-rust to latest
There don't appear to be any regressions from the updates.
Also included is a fix which highlights the "#" as in attributes
as punctuation. This was previously unhighlighted.
2022-08-31 17:46:34 +09:00
Michael Davis
ac669ade05 erlang: Fix highlighting of empty records
For example

    -record(state, {})

Would not highlight `state` as a type since the alternation didn't
allow for an empty tuple. Allowing the inner atom of the tuple to be
optional fixes this case.
2022-08-31 17:46:34 +09:00
Michael Davis
acf3599723 erlang: Use Edoc style auto-pairs
Specifically this changes backtic's right-hand-side pair character
to single-quote which is the syntax for inline and block code in
Edoc.
2022-08-31 17:46:34 +09:00
Michael Davis
00d88e540e Fix missing C highlights
* "const" keyword
* booleans
* <=/>= operators
2022-08-31 17:46:34 +09:00
Michael Davis
d7d9ca37e5 Reword the feature_request issue template as enhancement (#3481) 2022-08-31 17:45:49 +09:00
Michael Davis
e441b1c472 packaging: Point to homebrew-core instead of tap (#3513) 2022-08-31 17:45:38 +09:00
Michael Davis
73d5bd739e Delete invalid indents.scm queries 2022-08-31 17:45:23 +09:00
Michael Davis
4e4c6da3bf Add query-check xtask 2022-08-31 17:45:23 +09:00
Michael Davis
fa1dc7e508 tree-sitter: Prevent panic on loading queries 2022-08-31 17:45:23 +09:00
Michael Davis
4c789cfbda tree-sitter: Refactor lazy query loading
The code for loading queries can be shared between indent and
textobjects queries. In both cases we want to kick an error
message out to the logs.
2022-08-31 17:45:23 +09:00
Blaž Hrastnik
12ddd03d3b fix: Don't translate mouse up events as down 2022-08-31 11:36:18 +09:00
Michael Davis
701cea54d2 jumplist: Add documents to view history (#3593)
This change adds documents to the view's document history Vec.
(This is used by `ga` for example to access the last buffer.)

Previously, a sequence like so would have confusing behavior:

1. Open file A: any document with an active language server
2. Find some definition that lives in another file - file B - with `gd`
3. Jump back in the jumplist with `C-o` to file A
4. Use `ga` intending to switch back to file B

The behavior prior to this change was that `ga` would switch to file
A: you could not use `ga` to switch to file B.
2022-08-31 10:45:47 +09:00
Lucy
404db2ebee Move mode transition logic to handle_keymap_event() (#2634)
Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>

Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
2022-08-31 10:44:06 +09:00
A-Walrus
78189dd9c1 Fix extra selection with regex anchors (^,$) (#3598)
Also added a bunch of tests to ensure correct behaviour
2022-08-31 10:42:58 +09:00
Michael Davis
9e24f2aa81 Use the original document and view for mode transition hooks (#3508)
When changing focus, the lookup with `current!` may change the
view and end up executing mode transition hooks on the newly
focused view. We should use the same view and document to execute
mode transition hooks so that switching away from a view triggers
history save points.
2022-08-31 10:34:04 +09:00
Alexander Brevig
16525349db Themes update (#3587)
* lint: snazzy

* lint: pop-dark

* lint: penumbra+

* lint: noctis_bordo

* lint: ingrid

* lint: flatwhite

* lint: doom_acario_dark

* lint: dark_plus

* lint: boo_berry

* fix: use 47345E per author instruction

* lint: bogster

* lint: everforest

* lint: acme

* lint: serika

* fix: use nasty_red per author suggestion

* lint: nord

* lint: dracula

* lint: gruvbox

* fix: cursorline gruvbox

* lint: autumn

* fix: no fg for cursorline

* lint: ayu

* lint: rose_pine

* lint: monokai

* lint: solarized

* lint: spacebones

* fix: penumbra bg!=sky

* Update runtime/themes/ayu_light.toml

Co-authored-by: Ivan Tham <pickfire@riseup.net>

* Update runtime/themes/ayu_light.toml

Co-authored-by: Ivan Tham <pickfire@riseup.net>

* fix: fg for ui.help thanks @pickfire

* fix: ingrid with input from @intarga

Co-authored-by: Ivan Tham <pickfire@riseup.net>
2022-08-31 10:27:40 +09:00
dependabot[bot]
86b80e6ce6 build(deps): bump iana-time-zone from 0.1.44 to 0.1.47 (#3611)
Bumps [iana-time-zone](https://github.com/strawlab/iana-time-zone) from 0.1.44 to 0.1.47.
- [Release notes](https://github.com/strawlab/iana-time-zone/releases)
- [Changelog](https://github.com/strawlab/iana-time-zone/blob/main/CHANGELOG.md)
- [Commits](https://github.com/strawlab/iana-time-zone/compare/0.1.44...v0.1.47)

---
updated-dependencies:
- dependency-name: iana-time-zone
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-08-31 08:47:03 +09:00
Kristoffer Flottorp
1de17a2530 Fix fleetish theme (#3607)
Co-authored-by: krfl <kr.fl@outlook.com>
2022-08-30 08:15:38 -05:00
Blaž Hrastnik
e77b7d147c fix: Recalculate completion after pasting into prompt 2022-08-30 12:27:04 +09:00
Blaž Hrastnik
8a4fbf6daf completion: remove_follow links on filename_impl
We don't need to follow links since we're only scanning the current
directory level (non-recursive).
2022-08-30 12:23:49 +09:00
PiergiorgioZagaria
d2cec25395 Fix process spawning error handling (#3349)
* Fix process spawning error handling

* Log stderr in any case
2022-08-30 11:02:34 +09:00
Michael Davis
5f043dde56 Derive Document language name from languages.toml name key (#3338)
* Derive Document language name from `languages.toml` `name` key

This changes switches from deriving the language name from the
`languages.toml` `scope` key to `name` (`language_id` in the
`LanguageConfiguration` type). For the most part it works to derive the
language name from scope by chopping off `source.` or `rsplit_once` on
`.` but for some languages we have now like html (`text.html.basic`),
it doesn't. This also should be a more accurate fallback for the
`language_id` method which is used in LSP and currently uses the
`rsplit_once` strategy.

Here we expose the language's name as `language_name` on `Document` and
replace ad-hoc calculations of the language name with the new method.

This is most impactful for the `file-type` statusline element which is
using `language_id`.

* Use `Document::language_name` for the `file-type` statusline element

The `file-type` indicator element in the statusline was using
`Document::language_id` which is meant to be used to for telling
Language Servers what language we're using. That works for languages
with `language-server` configurations in `languages.toml` but shows
text otherwise. The new `Document::language_name` method from the
parent commit is a more accurate way to determine the language.
2022-08-30 10:59:45 +09:00
A-Walrus
ae81fbdbf6 Allow less than and greater than in macros (#3556)
* Allow less than and greater than in macros

* Fix failing test
2022-08-30 10:58:51 +09:00
dependabot[bot]
841766ef82 build(deps): bump futures-executor from 0.3.23 to 0.3.24 (#3602)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-08-29 18:55:26 -05:00
dependabot[bot]
50d5463f90 build(deps): bump futures-util from 0.3.23 to 0.3.24 (#3603)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-08-29 18:54:58 -05:00
dependabot[bot]
ca4b6eab74 build(deps): bump lsp-types from 0.93.0 to 0.93.1 (#3601)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-08-29 18:54:24 -05:00
Roman Chumak
ab67788e76 Sonokai (#3595)
Co-authored-by: Roman Chumak <p4ymak@yandex.ru>
2022-08-29 09:00:43 -05:00
Bob
411c5e4871 let extend-line respect range direction (#3046)
* let extend-line respect range direction

* fix extend above logic

* keep `x` existing binding

* Update book/src/keymap.md

Co-authored-by: Ivan Tham <pickfire@riseup.net>

Co-authored-by: Ivan Tham <pickfire@riseup.net>
2022-08-29 10:00:40 +09:00
Charlie Groves
f38ede8631 Add bracketed paste (#3233) 2022-08-29 09:48:49 +09:00
unrelentingtech
51b62230da Add wezterm to get_terminal_provider (#3588)
https://github.com/wez/wezterm is a terminal emulator with its own built-in multiplexer
2022-08-29 09:24:22 +09:00
Kristoffer Flottorp
eeb0a9f504 Add fleetish theme. Based on the unreleased JetBrains Fleet editor (#3591)
Co-authored-by: krfl <kr.fl@outlook.com>
2022-08-29 09:23:54 +09:00
Soc Virnyl S. Estela
abb9f139c5 update colors for papercolor-light (#3585)
* theme: add papercolor light

* fix typo

* add markup highlighting

* theme: added diff colors 

forgot to add it to PaperColor Light

* fix some ui colors

* assign more color for markup headings

* change heading color to bright7
2022-08-29 07:58:05 +08:00
David
db18206795 Fix rust text objects (#3590) 2022-08-28 16:03:39 -05:00
Gustavo Bogarín
e066782782 Add c-sharp textobjects (#3494)
Co-authored-by: Gustavo Bogarín <gbogarin@outlook.com>
Co-authored-by: Gustavo Bogarín <gbogarin@posibillian.tech>
2022-08-27 09:24:47 -05:00
ath3
86a8ea57bb Pascal support (#3542) 2022-08-25 17:59:02 -05:00
Luna
f0fb3407d2 Fixed Doom acario theme (#3533) (#3539)
Changed the `namespace` style to fix the issue (#3533).

I also made the theme look a little closer to how it looks in Emacs, I did however opt to still have it slightly different as I found it easier to read with my port than on the original in Emacs.
I also sorted most keys (mainly from line 8 to 28) for the theme to be in alphabetical order, so it's easier to have a quick glance where they are.
2022-08-25 23:35:43 +08:00
Michael Davis
28c5e2170e Update tree-sitter-ruby (#3527) 2022-08-25 09:15:44 +09:00
ath3
0a22148559 AWK Regex injection (#3535) 2022-08-24 16:14:56 -05:00
ath3
45add73fb1 AWK support (#3528) 2022-08-24 11:58:15 -05:00
Christoph Horn
facde9f18c Julia queries: fix non-consecutive docstring highlight 2022-08-24 11:55:47 -05:00
Christoph Horn
26b2f0a1b5 Julia queries: prevent constructors to be highlighted as functions
Also improves the captures of the remaining identifiers.
2022-08-24 11:55:47 -05:00
Christoph Horn
5806db1e5c Julia queries: limit markdown highlighting to docstrings 2022-08-24 11:55:47 -05:00
Christoph Horn
f5c00b9bc9 Julia queries: major refactoring of highlights.scm, add regex injections, locals 2022-08-24 11:55:47 -05:00
Christoph Horn
77f11bf272 Julia queries: update grammar, fix breaking changes 2022-08-24 11:55:47 -05:00
Jaden
2b16fd43f9 feat(lang): Add esdl grammar (#3526) 2022-08-24 09:51:10 -05:00
seb-bl
ccae718a67 Improve dart indent (#3419) 2022-08-23 21:35:57 -05:00
ChemicalXandco
6b912b8641 add syntax highlights for xit (#3521) 2022-08-23 20:52:01 -05:00
Clay
99b1e8ad89 Fix markdown indented code block rendering (#3503) 2022-08-24 09:12:04 +09:00
Blaž Hrastnik
e4c9d4082a fix: Reset document mode when losing focus
Fixes #3090
2022-08-23 14:07:50 +09:00
Blaž Hrastnik
7b8e4ac95a Editor: remove duplication for view focus/swap commands 2022-08-23 11:44:10 +09:00
Ivan Tham
dd2b9e55a2 Reduce health tick width
Use the same tick as book to reduce margin of whitespace errors.
2022-08-22 19:27:26 -05:00
dependabot[bot]
f32f451b98 build(deps): bump once_cell from 1.13.0 to 1.13.1 (#3511)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-08-22 19:17:31 -05:00
dependabot[bot]
25f5e8c5d1 build(deps): bump serde_json from 1.0.83 to 1.0.85 (#3510)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-08-22 19:17:08 -05:00
dependabot[bot]
650cf76d44 build(deps): bump serde from 1.0.142 to 1.0.144 (#3512)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-08-22 19:16:36 -05:00
dependabot[bot]
f6a1078684 build(deps): bump anyhow from 1.0.61 to 1.0.62 (#3509)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-08-22 19:15:59 -05:00
Charlie Groves
18909aafe2 Update to crossterm-0.25 (#3390) 2022-08-22 10:29:30 +09:00
Blaž Hrastnik
d993c6349b One more windows fix... 2022-08-22 10:29:11 +09:00
Blaž Hrastnik
e863f6fe27 Fix compilation on windows 2022-08-22 10:18:53 +09:00
Blaž Hrastnik
cb7615e0ed Make external terminal provider configurable
Fixes #1699
2022-08-22 10:11:04 +09:00
ScribblyBirb
7e330697e1 Update tree-sitter-elm to latest commit (#3497) 2022-08-21 15:42:19 -05:00
A-Walrus
ed74e6d5d4 Switch to tabpad configuration option (#3458)
Virtual whitespace tabs are created from the `tab` character padded
with `tabpad` up to  the tab width.
2022-08-21 13:54:02 +09:00
Michael Davis
e61c0b461c Update tree-sitter-org (#3489)
The update fixes a bug that caused the external scanner to hang during
error recovery.

Looking at the diff, there are no structural changes in this update.
There are a few new fields and it looks like some edge-case fixes
but nothing that breaks compatibility with the current queries.
2022-08-21 13:52:52 +09:00
Vince Mutolo
59968d27a4 add penumbra+ theme (#3398)
Co-authored-by: Vince Mutolo <vince@mutolo.org>
2022-08-20 19:26:22 -05:00
Alexander Brevig
aef00a3ab6 feat: add taskwarrior to languages so task N edit is nice (#3468)
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2022-08-19 19:16:54 -05:00
jdrst
9b0fd51318 removes deprecated stdio flag for omnisharp (#3480) 2022-08-19 08:44:17 -05:00
Saber Haj Rabiee
1577a9d0ab style: fixes unused_parens warnings on nightly builds (#3471) 2022-08-18 18:07:18 -05:00
Soc Virnyl S. Estela
bdd1192a35 add diff colors in PaperColor Light (#3470) 2022-08-18 08:24:54 -05:00
Soc Virnyl S. Estela
c18b54263a theme: add papercolor light (#3426)
* theme: add papercolor light

* fix typo

* add markup highlighting
2022-08-17 22:31:17 +08:00
Daniel S Poulin
7711db3a3a Adjust m textobject description and minor code clarification (#3343)
* Update description of `m` textobject to its actual functionality

Sometime recently the functionality of `m` was changed to match the
nearest pair to the cursor, rather than the former functionality of
matching the pair only if the cursor was on one of the brace characters
directly.

* Rename surround methods to reflect that they work on pairs

The current naming suggests that they may work generally on any
textobject, whereas their implementation really focuses on pairs.

* Change description of m textobject to match actual functionality

The current implementation of `m` no longer merely looks at the pair
character the cursor is on, but actually will search for the pair
(defined in helix-core/src/surround.rs) that encloses the cursor, and
not the entire selection.

* Accept suggested wording change

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>

* Prefix pair surround for consistency

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2022-08-17 10:41:59 +09:00
Michael Davis
254d558907 Update tree-sitter-swift (#3461) 2022-08-17 10:40:21 +09:00
A-Walrus
d6e4fd15fc Fix failing test with unicode-lines feature (#3455) 2022-08-17 10:37:34 +09:00
Poliorcetics
6618cf2d68 feat: shorten output for grammar fetching and building (#3396)
New look:

```
Fetching 102 grammars
98 up to date git grammars
4 updated grammars
        bash      now on 275effdfc0edce774acf7d481f9ea195c6c403cd
        beancount now on 4cbd1f09cd07c1f1fabf867c2cf354f9da53cc4c
        c         now on f05e279aedde06a25801c3f2b2cc8ac17fac52ae
        c-sharp   now on 53a65a908167d6556e1fcdb67f1ee62aac101dda
```

```
Building 102 grammars
100 grammars already built
2 grammars built now
        ["bash", "rust"]
```
2022-08-17 10:37:10 +09:00
Yevgnen
956fbab488 Add emacs theme (#3410) 2022-08-16 19:57:28 -05:00
dependabot[bot]
2968756baf build(deps): bump futures-executor from 0.3.21 to 0.3.23 (#3446)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-08-15 18:29:32 -05:00
dependabot[bot]
941e023e97 build(deps): bump futures-util from 0.3.21 to 0.3.23 (#3448)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-08-15 18:28:57 -05:00
dependabot[bot]
f9dc1f33ea build(deps): bump chrono from 0.4.19 to 0.4.22 (#3447)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-08-15 18:23:26 -05:00
dependabot[bot]
52c8de55a0 build(deps): bump anyhow from 1.0.60 to 1.0.61 (#3449)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-08-15 18:20:33 -05:00
ChrHorn
a7ff39fe3e remove duplicate entries from theme picker (#3439) 2022-08-16 00:18:04 +09:00
Manuel Schmidbauer
8a75795472 Improved file-picker configuration documentation (#3422) 2022-08-14 13:36:08 -05:00
nosa
c5deb30814 Theme Related Fixes (#3412) 2022-08-14 08:35:15 -05:00
n0s4
8deaebde26 Fix typos in ayu themes, also remove trailing space 2022-08-12 10:57:03 -05:00
n0s4
b565fff0f2 Fix Typos in base16_transparent
Fixes #3373.
2022-08-12 10:57:03 -05:00
Erasin
1eeca10675 Fix Markdown Metadata (#3400) 2022-08-12 09:27:50 -05:00
Kyle L. Davis
21f2affa16 Fix conditional setting of stdin handle on Windows (#3379)
* Revert 3121353c6a

* Switch to conditional compilation

* Run formatter

* Switch from conditional compilation to compile-time bool
2022-08-12 11:27:18 +09:00
Vince Mutolo
7559b77d53 highlight closure pipes as brackets (#3397)
Co-authored-by: Vince Mutolo <vince@mutolo.org>
2022-08-11 19:00:03 -05:00
Itay123TheKing
80dde577b0 Fix hyperlink at the bottom of CONTRIBUTING.md (#3392) 2022-08-11 08:57:17 -05:00
notusknot
d773a6e5f2 Update keymap.md to have Tab and Shift-tab listed (#3365)
Co-authored-by: notusknot <notusknot@gmail.com>
2022-08-11 00:21:37 -05:00
Joshua Suskalo
d192d59753 Update Clojure language definition (#3387) 2022-08-10 16:57:23 -05:00
Erasin
921027fb32 Update tree-sitter-latex and highlights (#3370)
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2022-08-10 07:29:43 -05:00
jdrst
598aa7c424 adds xcopy param to recursively copy runtime folder (#3378) 2022-08-09 20:47:04 -05:00
dependabot[bot]
404defb59b build(deps): bump anyhow from 1.0.59 to 1.0.60 (#3363)
Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.59 to 1.0.60.
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.59...1.0.60)

---
updated-dependencies:
- dependency-name: anyhow
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-08-09 11:51:20 +09:00
Michael Davis
672ea98b05 Advertise WorkspaceSymbolClientCapabilities support (#3361) 2022-08-09 11:51:10 +09:00
Gokul Soumya
634b6d455f Add custom event type replacing crossterm's Event (#3169)
Ported over from 61365dfbf3 in the `gui` branch. This will allow
adding our own events, most notably an idle timer event (useful
for adding debounced input in [dynamic pickers][1] used by interactive
global search and workspace symbols).

[1]: https://github.com/helix-editor/helix/pull/3110

Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
2022-08-09 10:31:26 +09:00
Kyle L. Davis
4ce5a94552 Add language: beancount (#3297)
Co-authored-by: erasin <erasinoo@gmail.com>
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
Co-authored-by: Erasin <erasinoo@gmail.com>
2022-08-08 17:59:55 -05:00
Erasin
d9321134f6 slint indents 2022-08-08 17:57:08 -05:00
Erasin
f09d2bc56b Add slint-ui support
<https://slint-ui.com/>
lsp: <https://github.com/slint-ui/slint/tree/HEAD/tools/lsp>
tree-sitter-slint: <https://github.com/jrmoulton/tree-sitter-slint>
2022-08-08 17:57:08 -05:00
Skyler Hawthorne
3e11017ade revert chrono to 0.4.19
This is causing builds to fail when there is no time zone info, e.g. Alpine,
Android
2022-08-07 12:19:47 -05:00
A-Walrus
6b84344e20 Add completion for nested settings (#3183)
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2022-08-06 12:16:18 -05:00
Michael Davis
973c51c3e9 Remove C-n and C-p from the insert mode keymap (#3340)
These are read-line-like bindings which we'd like to minimize in
insert mode in general.

In particular these two are troublesome if you have a low
`editor.idle-timeout` config and are using LSP completions: the
behavior of C-n/C-p switches from moving down/up lines to moving
down/up the completion menu, so if you hit C-n too quickly
expecting to be in the completion menu, you'll end up moving down
a line instead. Using C-p moves you back up the line but doesn't
re-trigger the completion menu. This kind of timing related change
to behavior isn't realistically that big of a deal but it can be
annoying.
2022-08-07 01:25:09 +09:00
Matthias Deiml
ea04220874 Use split_parser branch for markdown grammar (#3108) 2022-08-06 10:56:48 -05:00
A-Walrus
c00b8f7ad7 Fix tab highlight when tab is partially visible (#3313)
* Fix tab highlight when tab is partially visible

* Make it style based, and not truncation based

Dealing with truncating is a mess, especially when it comes to wide
unicode graphemes. This way it should work no matter what.

* Inline style calculation into branches
2022-08-07 00:46:50 +09:00
A-Walrus
fdd8bbf16b Fix indent guide styling (#3324)
* Fix incorrect indent guide styling

Before the indent guides on top of whitespace inherited the theme
from them. Now they do not.

* Fix dark_plus theme indent_guides

* Use whitespace style as fallback for indent-guide

* Fix dark_plus theme indent_guides

* Move indent_guide style patching out of loop
2022-08-07 00:46:23 +09:00
Daniel S Poulin
4dd35777f4 Attempt to bring spacebones light up to speed with recent features (#3342) 2022-08-06 09:40:10 -05:00
A. Taha Baki
24f5a47cec Rosé Pine Moon Theme (#3229) 2022-08-06 07:14:13 -05:00
Luna
7176c84844 Add Doom's Acario dark theme. (#3308) 2022-08-06 07:07:14 -05:00
ChrHorn
23f4a40a7a Rust queries: add (function_item) as a local scope (#3345) 2022-08-06 05:58:06 -05:00
Kyle L. Davis
63ec10950f Fix comment (#3334) 2022-08-05 20:13:58 -05:00
Erasin
bf6f7042fe Fix php hightlight (#3317)
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2022-08-05 07:34:03 -05:00
Dario Oddenino
3121353c6a Avoid setting stdin handle when not necessary (#3248)
* Avoid setting stdin handle when not necessary

Avoid setting the stdin handle in `shell_impl` when the input argument
is None.

This permits to run commands with no stdin with :sh

* refactoring to avoid code duplication

* making clippy happy

* Process variable name fix
2022-08-05 11:15:50 +09:00
Alexander Brevig
c2a6d29ffc fix: add elvish completions (#3331) 2022-08-05 09:50:47 +09:00
A-Walrus
cfa882557e Fix nondeterministic highlighting (#3275)
* Fix nondeterministic highlighting

This is done by prefering matches in the begining, ie for
`keyword.function`, `keyword` is a better match than `function`.

* Use all positions and not just leftmost

Fixes possible edgecase with something like `function.method.builtin`
and the queries `function.builtin` and `function.method`

* Switch to bitmask for slightly better performance

* Make matches from the start of string

Also change comments to match new behaviour
2022-08-05 09:12:14 +09:00
Michael Davis
f32c05db85 Detect indent-style in :set-language (#3330)
Indent style may change when choosing a language with `:set-language`.
Line-endings most likely will not change, but `:set-language` should
have a similar effect as reloading a file (`:reload`), plus the two
are currently grouped in the implementation and line-ending detection
is not particularly expensive.
2022-08-05 09:11:31 +09:00
Blaž Hrastnik
ee1214d6e5 Update dependencies (chrono) 2022-08-05 09:10:07 +09:00
Matthias Deiml
0ee2061102 Avoid copying fragments (#3136)
* Avoid copying fragments

* Add slice / slices method

* Better documentation for fragment and slice methods
2022-08-04 14:44:43 +09:00
Omnikar
afd292e3b9 Resolve clippy lints (#3307) 2022-08-04 14:32:59 +09:00
Michael Davis
5d33dbacac add a CLI flag for specifying config file location (#2666) 2022-08-04 13:05:52 +09:00
PiergiorgioZagaria
219d2c2515 Change default formatter for any language (#2942)
* Change default formatter for any language

* Fix clippy error

* Close stdin for Stdio formatters

* Better indentation and pattern matching

* Return Result<Option<...>> for fn format instead of Option

* Remove unwrap for stdin

* Handle FormatterErrors instead of Result<Option<...>>

* Use Transaction instead of LspFormatting

* Use Transaction directly in Document::format

* Perform stdin type formatting asynchronously

* Rename formatter.type values to kebab-case

* Debug format for displaying io::ErrorKind (msrv fix)

* Solve conflict?

* Use only stdio type formatters

* Remove FormatterType enum

* Remove old comment

* Check if the formatter exited correctly

* Add formatter configuration to the book

* Avoid allocations when writing to stdin and formatting errors

* Remove unused import

Co-authored-by: Gokul Soumya <gokulps15@gmail.com>
2022-08-04 13:01:48 +09:00
Charlie Groves
c5f8a835f5 Add a .ignore file to make ripgrep more useful (#3315)
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2022-08-03 09:00:39 -05:00
Alexander Brevig
6e7774bb79 Add .gitattributes (#3318) 2022-08-03 08:21:51 -05:00
Charlie Groves
4b6c4ae6ee Fix LF line-endings (#3316) 2022-08-03 07:53:57 -05:00
Matthias Deiml
6b244e2fef Exclude only named children without injection.include-children (#3129)
* Exclude only named children without injection.include-children

* Add injection.include-unnamed-children parameter
2022-08-03 19:18:17 +09:00
Michael Davis
08b442f4cc Inherit javascript/typescript from common 'ecma' queries (#3301)
JavaScript queries now contain a few lines that prevent them from
being used whole-sale in typescript with `; inherits: javascript`.
Here we follow nvim-treesitter's way of using a fake 'ecma' language
as a common base for JavaScript and TypeScript to share as much as
we can.
2022-08-03 14:09:44 +09:00
Kirawi
69f84e2516 theme ui.virtual.indent-guide in dark_plus (#3302) 2022-08-02 10:13:22 -05:00
yvt
aa4394ce12 chore(ci): match *-macos by checking suffix
Simplifies a conditional expression in the CI workflow configuration.

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2022-08-02 12:04:09 +09:00
yvt
6d16d2cbc9 feat: support grammar cross-compilation 2022-08-02 12:04:09 +09:00
yvt
f6f054ae5b fix(loader): pass cc::Tool::args()
Certain targets, such as `aarch64-apple-*`, require additional compiler
flags to cross-compile for the intended target.
2022-08-02 12:04:09 +09:00
yvt
4461090c3d chore(ci): build binary for aarch64-macos
The tests are conditionally disabled for this target because the x86_64 CI
host is unable to run AArch64 binaries. (There is no officially-supported
reverse Rosetta 2.)
2022-08-02 12:04:09 +09:00
dependabot[bot]
eef9eff20d build(deps): bump pulldown-cmark from 0.9.1 to 0.9.2 (#3294)
Bumps [pulldown-cmark](https://github.com/raphlinus/pulldown-cmark) from 0.9.1 to 0.9.2.
- [Release notes](https://github.com/raphlinus/pulldown-cmark/releases)
- [Commits](https://github.com/raphlinus/pulldown-cmark/compare/v0.9.1...v0.9.2)

---
updated-dependencies:
- dependency-name: pulldown-cmark
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-08-02 10:07:01 +09:00
dependabot[bot]
f3a3b09337 build(deps): bump similar from 2.1.0 to 2.2.0 (#3293)
Bumps [similar](https://github.com/mitsuhiko/similar) from 2.1.0 to 2.2.0.
- [Release notes](https://github.com/mitsuhiko/similar/releases)
- [Changelog](https://github.com/mitsuhiko/similar/blob/main/CHANGELOG.md)
- [Commits](https://github.com/mitsuhiko/similar/compare/2.1.0...2.2.0)

---
updated-dependencies:
- dependency-name: similar
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-08-02 10:06:46 +09:00
dependabot[bot]
d07d694fe7 build(deps): bump serde from 1.0.140 to 1.0.141 (#3292)
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.140 to 1.0.141.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.140...v1.0.141)

---
updated-dependencies:
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-08-02 10:06:38 +09:00
dependabot[bot]
9643556376 build(deps): bump anyhow from 1.0.58 to 1.0.59 (#3291)
Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.58 to 1.0.59.
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.58...1.0.59)

---
updated-dependencies:
- dependency-name: anyhow
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-08-02 10:06:28 +09:00
dependabot[bot]
f4b1f9af9a build(deps): bump arc-swap from 1.5.0 to 1.5.1 (#3290)
Bumps [arc-swap](https://github.com/vorner/arc-swap) from 1.5.0 to 1.5.1.
- [Release notes](https://github.com/vorner/arc-swap/releases)
- [Changelog](https://github.com/vorner/arc-swap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/vorner/arc-swap/compare/v1.5.0...v1.5.1)

---
updated-dependencies:
- dependency-name: arc-swap
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-08-02 10:06:22 +09:00
Eric K
d693b37445 Modified restore_term fn in application.rs. Changed '\x1B[2 q' to '\x1B[0 q' to restore cursor to user default after exiting helix (#3289) 2022-08-02 10:05:45 +09:00
ChrHorn
11367488ac Improve Python queries, add locals (#3284) 2022-08-01 16:14:07 -05:00
ChrHorn
0c08ff1596 update catppuccin theme(s) to new palettes (#3281) 2022-08-01 15:23:23 -05:00
ChrHorn
59bf1669ec javascript queries: fix parameters (#3280) 2022-08-01 15:15:17 -05:00
Alexander Brevig
07019c3905 fix: gruvbox color modes (#3202)
* fix: gruvbox color modes

* increase contrast, and use blue and not purple
2022-08-01 12:21:37 +09:00
Charlie Groves
9f4802e101 Only add cargo-tarpaulin on x86_64 (#3252)
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2022-07-31 14:52:54 -05:00
A-Walrus
c15b494288 Fix align_selection behaviour with tabs (#3276) 2022-07-31 14:45:51 -05:00
Banst
7e06681413 feat: add cue support (#3262) 2022-07-31 07:04:57 -05:00
Danilo Spinella
110eb73045 Add cwd parameter which is not optional anymore (#3240) 2022-07-31 06:59:15 -05:00
Danilo Spinella
ab616ab718 Add rust-version (MSRV) to helix-term package (#3244) 2022-07-31 17:09:18 +09:00
Amit Beka
fe3a9a868e clipboard: add logging and healthcheck (#3271)
* add logging to clipboard setup

* healthcheck: add clipboard provider name

Co-authored-by: amitbeka <--->
2022-07-31 17:05:34 +09:00
Alexander Brevig
e405e88c86 Flatwhite Theme (#3236) 2022-07-30 12:35:39 -05:00
Erasin
919edfb323 Add Graphviz Dot lang support (#3241)
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2022-07-30 12:34:00 -05:00
A-Walrus
5ca98edfb1 Don't add empty prompt input to history (#3259) 2022-07-30 12:17:01 -05:00
Gokul Soumya
a8b123fe17 Fix byte index error in signature help highlighting
The language server sends a char offset range within the
signature help label text to highlight as the current parameter,
but helix uses byte offset ranges for rendering highlights. This
was brought up in the [review of the original signature help PR][1],
but the ranges were being highlighted correctly, and there were no
out of bound or indexing panics. Turns out rust-analyzer was
[incorrectly sending byte offsets] instead of char offsets and this
made it seem like all was well and good with offsets in helix during
initial testing.

[1]: https://github.com/helix-editor/helix/pull/1755#discussion_r906715371
[2]: https://github.com/rust-lang/rust-analyzer/pull/12272
2022-07-29 14:31:21 +09:00
Slug
14eca318a7 Add transparent theme based on base16_default (#3216) 2022-07-28 18:14:34 -05:00
Erasin
a1c969012d Fix cursorline and selection themes for onelight (#3226) 2022-07-28 16:58:04 -05:00
Erasin
681c0a91dc Add textobject for javascript (#3213) 2022-07-28 08:31:20 -05:00
Kyle L. Davis
cca83af3fd Update README command table (#3224) 2022-07-28 05:37:10 -05:00
Michael Davis
9ed9c3faca Remove let_declaration from Rust locals tracking (#3212) 2022-07-28 12:04:50 +09:00
Philipp Mildenberger
bf74a4652d JS/TS highlighting improvements (#3219) 2022-07-27 13:56:58 -05:00
Yusuf Bera Ertan
85a5df0391 build(nix): add a way to override what grammars get built (#3141) 2022-07-27 12:52:07 -05:00
Ricardo Silva
2f1d3d0899 Add LSP config for Odin (#3214) 2022-07-27 12:28:20 -05:00
MilanVasko
9a49623721 Use OR of all selections in search_selection command (#3138)
Closes #2312
2022-07-27 18:02:19 +09:00
Seth Bromberger
846a6b65c3 add configurable / theme-able statusline separator string (#3175)
* add configurable separator element to statusline

* themable separator

* clippy fixes

* changed default separator to │

* doc updates
2022-07-27 08:47:22 +09:00
A-Walrus
61856f1d64 Nord color modes (#3200)
* Add color modes to nord theme

* Add color-modes to nord_light theme and fixup

Fg color was not set in some places and defaulted incorrectly.
2022-07-26 22:43:39 +09:00
Erasin
df5ab8b40c Fix: Python hightlight (#3201) 2022-07-26 22:31:14 +09:00
Seth Bromberger
3dd2196e4f add position-percentage as a statusline indicator (#3168)
* added position-pct as a statusline indicator

* removed unnecessary mutable reference

* pct -> percent

* percent -> percentage
2022-07-26 15:05:12 +09:00
Gokul Soumya
de8ade8967 Shorten embedded command descriptions (#3070)
* Shorten embedded command descriptions

- Compact descriptions in command palette and infobox

* Shorten typed command descriptions

* Fix typo in decrement command description
2022-07-26 12:04:23 +09:00
Erasin
42115d02bc Suport diagnostic code (#3096)
* add code for diagnostic.

This PR provides a solution to resolve #2994. missing Code Actions for lsp

* remote unused import
2022-07-26 10:26:50 +09:00
n0s4
4f21f430e4 Remove vale from .gitignore 2022-07-26 10:22:28 +09:00
n0s4
d97c4ee217 Spacing 2022-07-26 10:22:28 +09:00
n0s4
d95c7eaa29 Fixes + consistency
Some lines went longer than the titlebars, fixed regex in
SPLITTING SELECTIONS which wasn't actually correct.
Changed 1 "bat" to a "cat" in ADDING SELECTION ON NEXT
SEARCH MATCH which makes it harder to do with a simple
s select.
2022-07-26 10:22:28 +09:00
n0s4
348951f6f9 Add SPLITTING SELECTIONS 2022-07-26 10:22:28 +09:00
n0s4
b0f8d74db9 Spelling 2022-07-26 10:22:28 +09:00
n0s4
771de41155 Add CYCLING AND REMOVING SELECTIONS 2022-07-26 10:22:28 +09:00
n0s4
9114672419 Move Jumplist section and add recap 2022-07-26 10:22:28 +09:00
n0s4
4e76436b20 Add 'ADDING SELECTION ON NEXT SEARCH MATCH' 2022-07-26 10:22:28 +09:00
n0s4
d2b292660d Add SEARCH FOR SELECTION 2022-07-26 10:22:28 +09:00
n0s4
c7f9caf6bd Add REGISTERS, update MACROS accordingly 2022-07-26 10:22:28 +09:00
n0s4
29ee7f6d01 Add REPLACING WITH YANKED TEXT and INCREMENTING/DECREMTING
Also some consistency issues
 - redundant/dated comment in JOINING LINES
 - spacing around slashes
 - etc.
2022-07-26 10:22:28 +09:00
n0s4
92d94e1f7e Add REPITITION section 2022-07-26 10:22:28 +09:00
n0s4
88902d1f59 Improve ALIGN SELECTIONS section 2022-07-26 10:22:28 +09:00
n0s4
ec4c2f3965 Reduce A-; section to a note on section 3.7
Also fixed consistency of capitalisation and spacing of notes.
2022-07-26 10:22:28 +09:00
n0s4
ce732ce664 Correct recap numbers. 2022-07-26 10:22:28 +09:00
n0s4
d0381d942d Line too long + grammar. 2022-07-26 10:22:28 +09:00
n0s4
5accb5cd58 Add vale to gitignore + spelling 2022-07-26 10:22:28 +09:00
n0s4
68acdbb9a2 Added REPLACE and moved SELECTING TO A CHARACTER into the same chapter. 2022-07-26 10:22:28 +09:00
n0s4
1fed3a2220 Add 'ALIGN SELECTIONS' and 'SPLIT SELECTIONS ON LINES' 2022-07-26 10:22:28 +09:00
n0s4
15e1a0ebf2 Move COLLAPSING SELECTION to MOTIONS AND SELECTIONS.
Also had to do a little rewording to fit the recap for MOTIONS AND SELECTIONS.
2022-07-26 10:22:28 +09:00
n0s4
aa5cebae22 Added Select mode section.
Also added a note about X on "SELECTING LINES".
2022-07-26 10:22:28 +09:00
n0s4
a0d01455ac Re-order sections. 2022-07-26 10:22:28 +09:00
Kirawi
0a2646e720 Improve python highlighting (#3103)
* improve python queries

* update python grammar to `0.20.2`

* fix variadic parameter scope

* add punctuation scopes

* fix order of punctuation scopes

* undo  `embedded` delete
2022-07-26 10:17:51 +09:00
Daniel Longeuay
2ede98c4b4 feat(tree-sitter): add go template support (#3091)
* feat(tree-sitter):  add go template support

* fix(tree-sitter): 🐛 go template highlight scope selectors

* chore(tree-sitter): 🔧 update go template grammar commit
2022-07-26 10:17:28 +09:00
Mr. E
d4a5413255 feat(themes): add mode-specific styles to the dracula themes (#3135) 2022-07-26 10:17:00 +09:00
Clay
b55573dc1d Add elixir & heex comment textobjects (#3179) 2022-07-26 10:14:45 +09:00
Blaž Hrastnik
255c1734cf Rename padding to spacer, remove by default 2022-07-26 10:10:06 +09:00
Ivan Tham
2f980471f8 Make gutters padding automatic (#3163)
Remove padding gutter type, and automatically add 1 padding if gutters is
non-empty.
2022-07-26 10:08:09 +09:00
Seth Bromberger
bfdcfec8c9 add spacer element to statusline (#3165)
* add spacer element to statusline

* docs
2022-07-26 10:07:59 +09:00
André Sá
742d16026e Add ayu themes (#3184) 2022-07-26 10:05:27 +09:00
Joe
d0c63409cc Add table of contents to keymap.md (#3174) 2022-07-26 09:41:09 +09:00
A-Walrus
cb142b5750 Highlight constructor in monokai theme (#3131) 2022-07-26 09:40:56 +09:00
Philipp Mildenberger
235237ddc4 Refactor 'helix-loader::merge_toml_values' to use a 'merge-depth' instead of 'merge_toplevel_arrays' (#3080)
- This ensures that other values than just the arrays are overridden, like nested objects, where it makes sense
- merge_depth is set to 3 so that top-level language features are merged (like 'scope'), but everything deeper is overridden with the user-config
2022-07-26 09:40:38 +09:00
bootra
b7fa9ba601 Fix non-msvc grammar compile on Windows (#3190) 2022-07-26 09:33:53 +09:00
dependabot[bot]
73a308c665 build(deps): bump serde from 1.0.139 to 1.0.140 (#3194)
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.139 to 1.0.140.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.139...v1.0.140)

---
updated-dependencies:
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-26 08:17:14 +08:00
bootradev
4db01b3f82 add support for rulers to boo_berry theme (#3191) 2022-07-26 00:03:15 +05:30
Erasin
dad6d0f3b2 Fix: svelte indets.scm (#3147) 2022-07-24 17:42:27 +09:00
Joe
d6fd93788c Add rabl/jbuilder/jb extensions for Ruby (#3173)
* Add rabl and jbuilder

* Add jb
2022-07-24 11:50:04 +09:00
Clay
ec85fb9ab6 Improve HEEx comment highlights, inject comment lang (#3170) 2022-07-24 11:49:52 +09:00
Kyle L. Davis
dfc31e74af Fix different document panic (#3160)
Would panic when given the view for the current document for a different document.
2022-07-23 18:42:28 +09:00
Andrey Tkachenko
1b3a10d906 Add vh verilog header file type to file-types (#3158) 2022-07-23 09:35:20 +05:30
Michael Davis
19e51c8264 add release checklist and changelog curation docs (#2598)
* add release checklist and changelog curation docs

* remove step for deleting '-dev' suffix from VERSION
2022-07-22 10:31:40 +09:00
Aiko Mastboom
4589111d12 helix_view::theme [WARN] Theme (#3119)
* helix_view::theme [WARN] Theme

* updated: warning, error, info, hint colours
https://github.com/catppuccin/catppuccin/blob/main/docs/style-guide.md#typography

Co-authored-by: Aiko Mastboom <git@aiko.sh>
2022-07-22 10:31:02 +09:00
Mr. E
b05fcaadad Indent with tabs by default (#3095) 2022-07-22 10:30:21 +09:00
Philipp Mildenberger
b6c700fce9 Replace '; inherits <language>' in treesitter queries with <language> queries instead of appending them (#2470)
Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
2022-07-22 10:28:32 +09:00
Houkime
52bb1103f8 Auto pair-removal (#2940)
* auto pair-removal

Fixes https://github.com/helix-editor/helix/issues/1673

* autopairs removal: use doc autopairs

* autopairs-removal: limit to one-char selections

* use single_grapheme() to check if range is one char

* fix errouneous deletes of " and other symmetric autopairs when at buffer start

Co-authored-by: Houkime <>
2022-07-22 10:23:52 +09:00
Robin
19b7864062 keep jump/file history when using :split (#3031)
* keep jump/file history when using :split

* move history cloning into the switch function

Co-authored-by: Robin <robinvandijk@klippa.com>
2022-07-22 10:23:00 +09:00
Bob
2f53644c6d jumplist picker (#3033)
* jumplist picker

* remove jumps slicing

Co-authored-by: Benoît Cortier <bcortier@proton.me>

* remove unnecessary deref format! parameter

Co-authored-by: Benoît Cortier <bcortier@proton.me>

Co-authored-by: Benoît Cortier <bcortier@proton.me>
2022-07-22 10:21:46 +09:00
Clay
e560212ec5 Gleam: add support for built-in language server (#3139)
* Add gleam lsp support

* Docgen gleam lsp support
2022-07-22 10:19:42 +09:00
0rphee
76756f0e5d add statusline.{mode} colors and tweak various settings (#3128) 2022-07-21 12:26:54 +05:30
Alexis Kalabura
8b2a14153b add statusline element to display file line endings (#3113)
* add statusline element to display file line endings

* run cargo fmt --all

* change the word *ending* from plural to singular

* support for the unicode-lines feature flag
2022-07-21 13:03:12 +09:00
Blaž Hrastnik
906259cc41 fix: Indent levels could bleed over on the left edge
Fixes #3087
Refs #3105
    #	modified:   theme.toml
2022-07-20 17:06:33 +09:00
Erasin
3b1ba7fb12 Add color-modes for onelight theme (#3104)
Add keyword.function and keyword.storage.type for TS
2022-07-20 11:55:22 +09:00
Mr. E
b6e06c8c0c feat(themes): add mode-specific styles to the onedark theme (#3098) 2022-07-20 11:55:08 +09:00
Michael Davis
9753da6ab7 Fix locals tracking in Rust closures (#3027)
The fix comes from the rewriting of the `closure_parameters` stanza:
it was capturing the entire `closure_parameters` node including
paretheses, whitespace, and commas. Capturing the identifiers within
fixes the tracking.

In order to make sure locals definitions from closure parameters don't
leak out of the body of the closure, though, we should also mark the
closure itself as a locals scope.
2022-07-20 11:51:35 +09:00
Gokul Soumya
791bf7e50a Add lsp signature help (#1755)
* Add lsp signature help

* Do not move signature help popup on multiple triggers

* Highlight current parameter in signature help

* Auto close signature help

* Position signature help above to not block completion

* Update signature help on backspace/insert mode delete

* Add lsp.auto-signature-help config option

* Add serde default annotation for LspConfig

* Show LSP inactive message only if signature help is invoked manually

* Do not assume valid signature help response from LSP

Malformed LSP responses are common, and these should not crash the
editor.

* Check signature help capability before sending request

* Reuse Open enum for PositionBias in popup

* Close signature popup and exit insert mode on escape

* Add config to control signature help docs display

* Use new Margin api in signature help

* Invoke signature help on changing to insert mode
2022-07-19 11:28:24 +09:00
dependabot[bot]
02f0099210 build(deps): bump grep-searcher from 0.1.8 to 0.1.10 (#3101)
Bumps [grep-searcher](https://github.com/BurntSushi/ripgrep) from 0.1.8 to 0.1.10.
- [Release notes](https://github.com/BurntSushi/ripgrep/releases)
- [Changelog](https://github.com/BurntSushi/ripgrep/blob/master/CHANGELOG.md)
- [Commits](https://github.com/BurntSushi/ripgrep/compare/grep-searcher-0.1.8...grep-searcher-0.1.10)

---
updated-dependencies:
- dependency-name: grep-searcher
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-19 11:24:03 +09:00
dependabot[bot]
ddc0ea751c build(deps): bump clipboard-win from 4.4.1 to 4.4.2 (#3100)
Bumps [clipboard-win](https://github.com/DoumanAsh/clipboard-win) from 4.4.1 to 4.4.2.
- [Release notes](https://github.com/DoumanAsh/clipboard-win/releases)
- [Commits](https://github.com/DoumanAsh/clipboard-win/commits)

---
updated-dependencies:
- dependency-name: clipboard-win
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-19 07:17:07 +05:30
dependabot[bot]
77e5890859 build(deps): bump grep-regex from 0.1.9 to 0.1.10 (#3102)
Bumps [grep-regex](https://github.com/BurntSushi/ripgrep) from 0.1.9 to 0.1.10.
- [Release notes](https://github.com/BurntSushi/ripgrep/releases)
- [Changelog](https://github.com/BurntSushi/ripgrep/blob/master/CHANGELOG.md)
- [Commits](https://github.com/BurntSushi/ripgrep/compare/grep-regex-0.1.9...grep-regex-0.1.10)

---
updated-dependencies:
- dependency-name: grep-regex
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-19 07:15:57 +05:30
Bob
e5c7aaed91 support prefilling prompt (#2459)
* support prefilling prompt

* introduce with_line builder method in Prompt

* extract show_prompt

* use textobject_word as fallback input
2022-07-18 10:17:13 +09:00
Narazaki Shuji
55b45ec4a4 Set the selection point of the first file correctly (#3073) 2022-07-18 10:14:36 +09:00
Ivan Tham
e8214fb1e6 Make gutters padding optional (#2996)
If all gutters are removed, there are still an extra one padding, would be nice
to remove that to save some space.
2022-07-18 10:13:47 +09:00
Bob
2a8d38c27b support toggling pickers' preview panel (#3021)
* support toggling pickers' preview panel

* add doc for toggling preview
2022-07-18 10:11:25 +09:00
Mr. E
dbf68e0370 Customizable/configurable status line (#2434)
* feat(statusline): add the file type (language id) to the status line

* refactor(statusline): move the statusline implementation into an own struct

* refactor(statusline): split the statusline implementation into different functions

* refactor(statusline): Append elements using a consistent API

This is a preparation for the configurability which is about to be
implemented.

* refactor(statusline): implement render_diagnostics()

This avoid cluttering the render() function and will simplify
configurability.

* feat(statusline): make the status line configurable

* refactor(statusline): make clippy happy

* refactor(statusline): avoid intermediate StatusLineObject

Use a more functional approach to obtain render functions and write to
the buffers, and avoid an intermediate StatusLineElement object.

* fix(statusline): avoid rendering the left elements twice

* refactor(statusline): make clippy happy again

* refactor(statusline): rename `buffer` into `parts`

* refactor(statusline): ensure the match is exhaustive

* fix(statusline): avoid an overflow when calculating the maximal center width

* chore(statusline): Describe the statusline configurability in the book

* chore(statusline): Correct and add documentation

* refactor(statusline): refactor some code following the code review

Avoid very small helper functions for the diagnositcs and inline them
instead.
Rename the config field `status_line` to `statusline` to remain
consistent with `bufferline`.

* chore(statusline): adjust documentation following the config field refactoring

* revert(statusline): revert regression introduced by c0a1870

* chore(statusline): slight adjustment in the configuration documentation

* feat(statusline): integrate changes from #2676 after rebasing

* refactor(statusline): remove the StatusLine struct

Because none of the functions need `Self` and all of them are in an own
file, there is no explicit need for the struct.

* fix(statusline): restore the configurability of color modes

The configuration was ignored after reintegrating the changes of #2676
in 8d28f95.

* fix(statusline): remove the spinner padding

* refactor(statusline): remove unnecessary format!()
2022-07-18 09:57:01 +09:00
Joe
43761d426c Remove .git extension from SCSS tree-sitter repo url (#3089) 2022-07-17 21:41:05 +05:30
Joe
0c9594e41e Add SCSS language support (#3074) 2022-07-17 17:55:20 +08:00
Alex Kim
bcacc703d7 fix wrong value for cursor shape config in the docs (#3081) 2022-07-15 20:21:34 +05:30
Benoît Cortier
333ab27837 feat(term): uniformize word-wise movement and deletion (#2500)
Ctrl-based shortcuts are common in numerous applications.

This change:
- Adds Ctrl+{Left/Right/Backspace/Delete} for word-wise movement/deletion in prompt, picker, …
- Removes Alt-Left and Alt-Right in prompt, picker, …
- Adds Alt-Delete in insert mode for forward word deletion

In some terminals, Alt-Backspace might not work because it is ambigous.
See: https://github.com/helix-editor/helix/pull/2193#issuecomment-1105042501
Hence, Alt alternative is not removed.
2022-07-15 21:59:00 +08:00
Bob
8681fb6d9e respect count in treesitter movement (#3058) 2022-07-14 08:08:09 +08:00
Bob
4418924ec3 respect count for selecting next/previous match (#3056) 2022-07-13 23:01:42 +08:00
Bob
e6a6e251c5 respect count for repeating motion (#3057) 2022-07-13 23:00:24 +08:00
Termina94
3cced1e3c8 Add cursorline colour to darkplus theme (#3054)
Co-authored-by: Dean Revell <revell@gmail.com>
2022-07-12 15:18:41 -05:00
0rphee
7951ebfd4d [Theme] Noctis (#3043) 2022-07-12 12:42:17 -05:00
Mateusz S. Szczygieł
5f69beb87f Add textobjects.scm to GLSL (#3051) 2022-07-12 10:13:57 -05:00
Philipp Mildenberger
e97b8607c1 Added ungrammar language support (#3048) 2022-07-12 10:06:53 -05:00
dependabot[bot]
fb62569785 build(deps): bump regex from 1.5.5 to 1.6.0 (#3041)
Bumps [regex](https://github.com/rust-lang/regex) from 1.5.5 to 1.6.0.
- [Release notes](https://github.com/rust-lang/regex/releases)
- [Changelog](https://github.com/rust-lang/regex/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/regex/compare/1.5.5...1.6.0)

---
updated-dependencies:
- dependency-name: regex
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-12 11:17:24 +09:00
dependabot[bot]
930f98053e build(deps): bump serde from 1.0.138 to 1.0.139 (#3040)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-12 07:44:00 +05:30
Austen LeBeau
0cb0c30618 add fortran language (#3025) 2022-07-10 11:27:44 -05:00
Slug
e109022bfd fix: error that caused usize to overflow (#3024)
* fix: error that caused usize to overflow

* update: changed check_sub to saturating_sub
2022-07-10 10:54:06 +02:00
Timothy DeHerrera
718c3baebe nix: pass makeWrapperArgs to wrapProgram (#3003) 2022-07-09 11:17:44 -05:00
Timothy DeHerrera
fefa4d8c59 nix flake: make the binary cache "just work" (#2999) 2022-07-09 11:09:37 -05:00
Amit Beka
6100b1ba08 book: add wiki links to the title page and install page (#3017)
Co-authored-by: amitbeka <--->
2022-07-09 11:08:47 -05:00
Gokul Soumya
21b66ba068 lsp: Add workspace/applyEdit to client capabilites (#3012)
The functionality already existed, but the capability wasn't being
reported correctly to the server:

230ba264bf/helix-term/src/application.rs (L716-L728)
2022-07-09 07:31:15 +09:00
Gokul Soumya
b7a3531b8f theme(onedark): Remove bg for window separator (#3011) 2022-07-08 15:24:09 -05:00
Jake Langford
230ba264bf Introduce storage highlighting for typescript/javascript (#2961) 2022-07-06 08:54:07 -05:00
Ivan Tham
e35abe38f3 Remove broken ledger tag highlight (#2988) 2022-07-06 07:35:36 -05:00
Gokul Soumya
af35c62407 Show file path only in workspace diagnostic picker 2022-07-06 13:06:46 +02:00
Gokul Soumya
a43bcc8765 Display error code only if not none 2022-07-06 13:06:46 +02:00
Gokul Soumya
0c104685c0 Sub sort diagnostics by line number 2022-07-06 13:06:46 +02:00
Gokul Soumya
2c37e25cb5 Display diagnostic text before code in picker 2022-07-06 13:06:46 +02:00
Gokul Soumya
c4e022971d Remove source from diagnostic picker display
It is usually the name of the LSP and doesn't add much
useful information.
2022-07-06 13:06:46 +02:00
Erin van der Veen
e0cf19c612 Update tree-sitter-nickel (#2987) 2022-07-06 13:05:51 +02:00
A-Walrus
1378b911b6 Fix some typos (#2978) 2022-07-05 21:49:54 -05:00
Ivan Tham
b612211070 Update tree-sitter-ledger (#2936) 2022-07-05 09:12:28 -05:00
Michael Davis
aacd0c8aa5 Update TSQ queries (#2960)
A few changes to make TSQ highlights better:

* A parsing error has been fixed in the grammar itself
    * Previously tree-sitter-tsq did not parse the variables
      in predicates like `(#set! injection.language "javascript")`
* Theme nodes as `tag`
    * The newly added node to the parser (from the above fix) is
      `variable` which takes over the `variable` capture from nodes
* Highlight known predicates as `function` and unsupported
  predicates as `error`
    * This may help when translating queries from nvim-treesitter.
      For example `#any-of?` is a common one used in nvim-treesitter
      queries but not implemented in Helix or tree-sitter-cli.
* Inject tree-sitter-regex into `#match?` predicates
2022-07-05 20:01:05 +09:00
Matthew Toohey
d78354c537 add language idris (#2971) 2022-07-05 20:00:38 +09:00
Joe
b26e7e2e8f Add live preview to theme picker (#1798)
* Add theme picker with live preview

* Add live theme preview to :theme command

* cargo fmt

* Fix clippy warnings

* Remove picker variant

* Remove unused import

* Cleanup

* Change current_theme to last_theme

* Fix accidental comment flash deletion

* Typo

* Remove theme cache

* Add some comments

* Refactor some theme handling

TIL flatmap on Option is called  and_then

* Remove unnecessary renames

* Constrain last_theme theme preview lifecycle

* Switch to bitflag implementation

* Better handling of last_theme

* Sort theme names

* Better memory juggling

* Missed a branch

* Remove name from theme, switch bitand to &

* cargo fmt

* Update helix-view/src/editor.rs

* Switch boolean to enum

* Remove bitflag impl

* cargo fmt

* Remove un-needed type arg

* cargo fmt
2022-07-05 19:44:16 +09:00
Michael Davis
85411bed83 DAP: Make cwd required in RunTerminalArguments
The spec has `cwd` in `RunInTerminalRequestArguments` as non-optional:
https://microsoft.github.io/debug-adapter-protocol/specification#Reverse_Requests_RunInTerminal
2022-07-05 12:34:03 +02:00
Michael Davis
44f596334a DAP: Skip serializing Options when None
DAP follows the same strict TypeScript interface syntax as LSP
which states:

> The document uses TypeScript interfaces in strict mode to describe
> these. This means for example that a `null` value has to be explicitly
> listed and that a mandatory property must be listed even if a falsify
> value might exist.

So we have to skip serializing any fields that end in `?` instead
of passing `null`.
2022-07-05 12:34:03 +02:00
Jens Getreu
936ed3a226 Add Autumn night theme
Under some light conditions, one prefers a high contrast theme.
2022-07-05 12:33:37 +02:00
Jens Getreu
2e709859c4 Autumn theme: slightly adjust contrast 2022-07-05 12:33:37 +02:00
dependabot[bot]
f3e8b0f34b build(deps): bump smallvec from 1.8.1 to 1.9.0 (#2976)
Bumps [smallvec](https://github.com/servo/rust-smallvec) from 1.8.1 to 1.9.0.
- [Release notes](https://github.com/servo/rust-smallvec/releases)
- [Commits](https://github.com/servo/rust-smallvec/compare/v1.8.1...v1.9.0)

---
updated-dependencies:
- dependency-name: smallvec
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-05 19:31:01 +09:00
dependabot[bot]
f3467399b7 build(deps): bump crossterm from 0.23.0 to 0.24.0 (#2968)
Bumps [crossterm](https://github.com/crossterm-rs/crossterm) from 0.23.0 to 0.24.0.
- [Release notes](https://github.com/crossterm-rs/crossterm/releases)
- [Changelog](https://github.com/crossterm-rs/crossterm/blob/master/CHANGELOG.md)
- [Commits](https://github.com/crossterm-rs/crossterm/compare/0.23...0.24)

---
updated-dependencies:
- dependency-name: crossterm
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-05 19:30:33 +09:00
dependabot[bot]
ba255e3e3e build(deps): bump serde_json from 1.0.81 to 1.0.82 (#2966)
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.81 to 1.0.82.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.81...v1.0.82)

---
updated-dependencies:
- dependency-name: serde_json
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-05 19:25:56 +09:00
dependabot[bot]
1fc8cbeb68 build(deps): bump log from 0.4.14 to 0.4.17 (#2965)
Bumps [log](https://github.com/rust-lang/log) from 0.4.14 to 0.4.17.
- [Release notes](https://github.com/rust-lang/log/releases)
- [Changelog](https://github.com/rust-lang/log/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/log/compare/0.4.14...0.4.17)

---
updated-dependencies:
- dependency-name: log
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-05 19:24:37 +09:00
dependabot[bot]
b98567f248 build(deps): bump which from 4.2.4 to 4.2.5 (#2964)
Bumps [which](https://github.com/harryfei/which-rs) from 4.2.4 to 4.2.5.
- [Release notes](https://github.com/harryfei/which-rs/releases)
- [Commits](https://github.com/harryfei/which-rs/compare/4.2.4...4.2.5)

---
updated-dependencies:
- dependency-name: which
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-05 19:24:07 +09:00
dependabot[bot]
700431d665 build(deps): bump encoding_rs from 0.8.30 to 0.8.31 (#2963)
Bumps [encoding_rs](https://github.com/hsivonen/encoding_rs) from 0.8.30 to 0.8.31.
- [Release notes](https://github.com/hsivonen/encoding_rs/releases)
- [Commits](https://github.com/hsivonen/encoding_rs/compare/v0.8.30...v0.8.31)

---
updated-dependencies:
- dependency-name: encoding_rs
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-05 19:19:27 +09:00
dependabot[bot]
c88d736d5c build(deps): bump once_cell from 1.12.0 to 1.13.0 (#2969)
Bumps [once_cell](https://github.com/matklad/once_cell) from 1.12.0 to 1.13.0.
- [Release notes](https://github.com/matklad/once_cell/releases)
- [Changelog](https://github.com/matklad/once_cell/blob/master/CHANGELOG.md)
- [Commits](https://github.com/matklad/once_cell/compare/v1.12.0...v1.13.0)

---
updated-dependencies:
- dependency-name: once_cell
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-05 11:04:03 +08:00
dependabot[bot]
a679efa8ce build(deps): bump serde from 1.0.136 to 1.0.138 (#2967)
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.136 to 1.0.138.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.136...v1.0.138)

---
updated-dependencies:
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-05 08:20:12 +05:30
Skyler Hawthorne
f392e35439 feat(theme): solarized: add cursorline, ruler, indent guide (#2962) 2022-07-04 18:06:44 -05:00
A-Walrus
2ac1de305e Fix backwards selection duplication widening bug (#2945)
* Fix backwards selection duplication widening bug

* Add integration tests

* Make tests line-ending agnostic

Make tests line-ending agnostic

Use indoc to fix tests

Fix line-ending on test input
2022-07-05 07:51:15 +09:00
川田 恵氏 (Kawada Keishi a.k.a megumish)
244825b9e1 Add runtime xcopy command on powershell in docs (#2958) 2022-07-04 12:32:46 -05:00
0rphee
e58d28a972 Add Haskell roots (#2954) 2022-07-03 22:44:17 -05:00
rsteube
4c30a3609a languages: added elvish (#2948) 2022-07-03 16:19:12 -05:00
ChrHorn
9f43dbc45d Highlight whole row in picker menus (#2939) 2022-07-02 17:29:46 +05:30
Gokul Soumya
6e2aaed5c2 Reuse menu::Item trait in picker (#2814)
* Refactor menu::Item to accomodate external state

Will be useful for storing editor state when reused by pickers.

* Add some type aliases for readability

* Reuse menu::Item trait in picker

This opens the way for merging the menu and picker code in the
future, since a picker is essentially a menu + prompt. More
excitingly, this change will also allow aligning items in the
picker, which would be useful (for example) in the command palette
for aligning the descriptions to the left and the keybinds to
the right in two separate columns.

The item formatting of each picker has been kept as is, even though
there is room for improvement now that we can format the data into
columns, since that is better tackled in a separate PR.

* Rename menu::Item::EditorData to Data

* Call and inline filter_text() in sort_text() completion

* Rename diagnostic picker's Item::Data
2022-07-02 13:21:27 +02:00
nosa
290b3ebbbe Update night_owl for cursorline (#2938) 2022-07-01 14:09:59 -05:00
Michael Jones
1fde77ad9d Sort themes, language & files by score & then name (#2675)
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2022-07-01 11:06:14 -05:00
ramojus
cc3aded185 add statusline mode colors to meliora theme (#2933) 2022-07-01 21:24:33 +09:00
Blaž Hrastnik
a1c1abca2b fix CI 2022-07-01 21:24:10 +09:00
nosa
8a19196ad5 Updated for #2676 , but I took the opportunity to do some other changes. (#2929)
- Misspelling of 'modifiers' for markdown.heading.1 and 2.
- Errors are now just underlined instead of in red.
- Diagnostics are dimmed, as well as whitespace.
- Add constant.builtin.
2022-07-01 19:18:39 +09:00
Blaž Hrastnik
9ae70cc410 Disable tree-sitter python indents, use fallback for now
There's been a lot of complaints about the state of python indentation
and the fallback actually works better until the solution proposed
in https://github.com/helix-editor/helix/issues/763#issuecomment-1137894973=
is implemented.
2022-07-01 19:17:19 +09:00
Michael Jones
d8abd1eaf3 Sort themes, language & files by score & then name (#2675)
* Sort themes by score & then name

Previously the themes were appearing unordered after typing ':theme '.
This sorts them first by fuzzy score and then by name so that they
generally appear in a more ordered fashion in the initial list.

The sort by name does not really pay off when there is a score so an
alternative approach would be to sort by name if there is string to
fuzzy match against and otherwise sort by score.

I've lowercased the names as that avoids lower case & upper case letters
being sorted into separate groups. There might be a preferable approach
to that though.

* Sort language & files by score then name

And change to use sort_unstable_by instead of sort_unstable_by_key as it
allows us to avoid some allocations.

I don't fully understand the flow of the 'filename_impl' function but
this seems to deliver the desired results.

* Remove unnecessary reference

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2022-07-01 18:33:52 +09:00
plexom
f10b6f6ee2 adds --vsplit and --hsplit arguments (#2773)
* adds --vsplit and --hsplit arguments

* moved comment

* fixed lint (third time's a charm)

* changed vsplit and hsplit from two separate bools to type Option<Layout>, and some cleanup
2022-07-01 18:27:32 +09:00
Benjamin Rich
15d96c843a Add new key bindings to view mode (#2803)
* Make view mode more pager-like

Addresses #2721

* Remove view mode bindings for J and K
2022-07-01 18:27:18 +09:00
Sora
edee2f4c34 Fix backwards character deletion on other whitespaces (#2855)
* delete_backwards_char accepts any type of whitespace

* Fix inconsistency, where unicode whitespaces are treated as normal whitespaces

* Changed back to direct whitespace match

* Only accept explicit whitespace / tabs

Co-authored-by: s0LA1337 <dreamer@neoncity.dev>
2022-07-01 18:08:48 +09:00
two-six
444bc24a26 [Theme] Nord Light (#2908)
* add theme

* updated nord_light

* update to colors

* last update to colors
2022-07-01 18:08:27 +09:00
Erasin
051a7f0606 add cursorline to one light theme (#2925) 2022-07-01 18:07:46 +09:00
Jens Getreu
7baa8e837b Add color-modes to Autumn theme (#2928)
Co-authored-by: Jens Getreu <jens.getreu@dlh.lu>
2022-07-01 18:06:16 +09:00
Michael Davis
c5600c9c01 markdown: limit raw block highlight to code fence content 2022-07-01 11:04:23 +02:00
Michael Davis
c8dba2f4c6 erlang: highlight modules in behaviour attributes 2022-07-01 11:04:23 +02:00
Michael Davis
19acbfe02d erlang: highlight records with macro names
You might use a macro like `?MODULE` to name a record:

    -record(?MODULE, {a, b, c}).

With this fix, the record fields correctly get `variable.other.member`
highlights.
2022-07-01 11:04:23 +02:00
Michael Davis
bf1aa8876c git-commit: fix highlight edge cases
* branch message with current branch and diverged branch has been
  added to the parser
* scissors used in verbose commits are marked as a punctuation
  delimiter
    * we could use comment instead since they're visually the
      same but IMO this works better
2022-07-01 11:04:23 +02:00
Michael Davis
a890c4a64d tsq: update parser to fix escaping double quotes
This includes a fix for the new HTML highlights introduced a few
parent commits back:

    ["\"" (attribute_name)] @string

Would get tripped up and the entire line would be highlighted as
a string. Now `\"` is a valid escape.

I'm switching to my fork as the primary repo as the upstream hasn't
been touched in over a year (mostly because stability afaict) but
it has no watchers currently so I'm not hopeful that my PR will
be merged.
2022-07-01 11:04:23 +02:00
Michael Davis
d8f036f0a9 erlang: update parser for fix on remote calls 2022-07-01 11:04:23 +02:00
Michael Davis
199a2460ca make: add injection-regex 2022-07-01 11:04:23 +02:00
Michael Davis
4a0dab8bc2 erlang: fix '#match?' for specs/callbacks 2022-07-01 11:04:23 +02:00
Michael Davis
e4e8a39bf7 replace module captures with namespace
`module` is undocumented and does not exist in other themes. The
equivalent existing scope based on usage (Elixir for example) is
`namespace`.
2022-07-01 11:04:23 +02:00
Michael Davis
016e97314c html: highlight punctuation
* `/>` as in self-closing tags like `<hr/>`
* `=` as in the separator between attribute name and value `<a href="bar">`
2022-07-01 11:04:23 +02:00
Michael Davis
7cf88f2bac edoc: prevent rogue punctuation highlights
Punctuation highlights would show up outside of where they
were valid, for example using parentheses in some text. This
change prevents that by gating the captures to being under
the named nodes in which they are valid.
2022-07-01 11:04:23 +02:00
Michael Davis
78c944ebc3 rust: fix highlight corner-cases
* add punctuation highlights for commas as in function parameters
* remove stray `variable.parameter` highlight
    * I couldn't find any regressions from this and it fixes an
      edge case I ran into (but sadly did not record 😓)
* highlight `fn` as `keyword.function`
    * the theme docs have `fn` as an example so it seems fitting
2022-07-01 11:04:23 +02:00
Michael Davis
beb19fe1bd bash: expand injection-regex to common shells 2022-07-01 11:04:23 +02:00
Michael Davis
ca82cd86e6 markdown: highlight punctuation 2022-07-01 11:04:23 +02:00
Michael Davis
bd527c84e6 erlang: highlight unary '#' as punctuation.bracket
The '#' character may either be interpreted as a map when used
like so:

    %% Example 1
    #{a => b}

Or as an operator which updates an existing map when the left-hand
side is an expression:

    %% Example 2
    MyMap#{a => b}

This commit changes the highlight to `punctuation.bracket` when used
as a character in a literal map (example 1) and keeps the `operator`
highlight when used for updating (example 2).
2022-07-01 11:04:23 +02:00
Michael Davis
d523280e85 erlang: highlight nullary macros as constants 2022-07-01 11:04:23 +02:00
Sora
26501afe13 Update cursorline for tokyonight + tokyonight_storm (#2927)
Co-authored-by: s0LA1337 <dreamer@neoncity.dev>
2022-06-30 17:14:55 -05:00
Skyler Hawthorne
f2768da1f6 add mode colors to solarized (#2926) 2022-07-01 06:52:31 +09:00
Mathspy
d06800f1dd Add mode specific styles (#2676)
* Add mode specific styles

In similar vein to neovim's lualine and similar statusline packages this
allows helix users to style their mode based on which mode it is thus
making each mode more visually distinct at a glance

* Add an example based on rosepine

* Add editor.colors-mode config

* Document statusline mode styles
2022-06-30 18:26:00 +09:00
Falco Hirschenberger
ed89f8897e Add workspace and document diagnostics picker (#2013)
* Add workspace and document diagnostics picker

fixes #1891

* Fix some of @archseer's annotations

* Add From<&Spans> impl for String

* More descriptive parameter names.

* Adding From<Cow<str>> impls for Span and Spans

* Add new keymap entries to docs

* Avoid some clones

* Fix api change

* Update helix-term/src/application.rs

Co-authored-by: Bjorn Ove Hay Andersen <bjrnove@gmail.com>

* Fix a clippy hint

* Sort diagnostics first by URL and then by severity.

* Sort diagnostics first by URL and then by severity.

* Ignore missing lsp severity entries

* Add truncated filepath

* Typo

* Strip cwd from paths and use url-path without schema

* Make tests a doctest

* Better variable names

Co-authored-by: Falco Hirschenberger <falco.hirschenberger@itwm.fraunhofer.de>
Co-authored-by: Bjorn Ove Hay Andersen <bjrnove@gmail.com>
2022-06-30 18:16:18 +09:00
Jens Getreu
94fc41a419 Add cursorline to Autumn theme (#2918)
Co-authored-by: Jens Getreu <jens.getreu@dlh.lu>
2022-06-29 14:14:16 -05:00
Ben Lee-Cohen
15ac1142cf Adding a cursorline for the Nord theme (#2916) 2022-06-29 09:13:49 -05:00
Stuart Hinson
6ac6080969 primary cursorline for Dracula theme (#2915) 2022-06-29 09:08:05 -05:00
Michael Davis
bf1db737d4 nix: update nixCargoIntegration (#2907)
This fixes the aarch64-darwin build - the newer revision uses the
cCompiler override to compile tree-sitter with clang instead of
gcc (which fails).
2022-06-29 17:53:56 +09:00
Seth Bromberger
07e7a13a9e fixes background reset (#2900)
* fixes background reset

* moves creation of default style out of loop

* patches with background_style

* removes commented code
2022-06-28 23:59:10 +09:00
PabloMansanet
030de46e6b Fix recursive macro crash and empty macro lockout (#2902) 2022-06-28 21:30:27 +09:00
dependabot[bot]
ac1d8fa505 build(deps): bump smallvec from 1.8.0 to 1.8.1 (#2901)
Bumps [smallvec](https://github.com/servo/rust-smallvec) from 1.8.0 to 1.8.1.
- [Release notes](https://github.com/servo/rust-smallvec/releases)
- [Commits](https://github.com/servo/rust-smallvec/compare/v1.8.0...v1.8.1)

---
updated-dependencies:
- dependency-name: smallvec
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-28 19:36:38 +09:00
dependabot[bot]
d900b8bb23 build(deps): bump thiserror from 1.0.30 to 1.0.31 (#2899)
Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.30 to 1.0.31.
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/1.0.30...1.0.31)

---
updated-dependencies:
- dependency-name: thiserror
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-28 19:36:28 +09:00
dependabot[bot]
247ebd6689 build(deps): bump indoc from 1.0.3 to 1.0.6 (#2898)
Bumps [indoc](https://github.com/dtolnay/indoc) from 1.0.3 to 1.0.6.
- [Release notes](https://github.com/dtolnay/indoc/releases)
- [Commits](https://github.com/dtolnay/indoc/compare/1.0.3...1.0.6)

---
updated-dependencies:
- dependency-name: indoc
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-28 18:25:17 +09:00
dependabot[bot]
2963fdbed1 build(deps): bump cc from 1.0.72 to 1.0.73 (#2897)
Bumps [cc](https://github.com/alexcrichton/cc-rs) from 1.0.72 to 1.0.73.
- [Release notes](https://github.com/alexcrichton/cc-rs/releases)
- [Commits](https://github.com/alexcrichton/cc-rs/compare/1.0.72...1.0.73)

---
updated-dependencies:
- dependency-name: cc
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-28 18:25:08 +09:00
Michael Davis
64de0b7288 add docs for cursorline scopes (#2904) 2022-06-28 08:55:09 +05:30
Michael Davis
64cf4c859b support Bazel languages (#2903) 2022-06-28 08:48:38 +05:30
dependabot[bot]
6f932375bf build(deps): bump serde_json from 1.0.79 to 1.0.81 (#2896)
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.79 to 1.0.81.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.79...v1.0.81)

---
updated-dependencies:
- dependency-name: serde_json
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-28 07:55:25 +08:00
dependabot[bot]
fd644ccfa2 build(deps): bump tree-sitter from 0.20.4 to 0.20.8 (#2895)
Bumps [tree-sitter](https://github.com/tree-sitter/tree-sitter) from 0.20.4 to 0.20.8.
- [Release notes](https://github.com/tree-sitter/tree-sitter/releases)
- [Commits](https://github.com/tree-sitter/tree-sitter/commits)

---
updated-dependencies:
- dependency-name: tree-sitter
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-28 07:52:27 +08:00
Gokul Soumya
3108a11d35 Refactor handling of mouse events (#2893)
- Simplified match statements by destructuring MouseEvent struct
  at the top and then matching on event.kind.
- Extracted out closures for calculating (1) position and view
  of mouse click and (2) gutter coordinates and view of mouse click.
2022-06-28 01:05:07 +09:00
Gokul Soumya
23ce5f1837 Add cursorline scope for onedark theme (#2892) 2022-06-27 17:36:41 +02:00
ramojus
db2aa57074 update meliora theme (#2890) 2022-06-27 07:49:09 -05:00
lazytanuki
096abdd19b feat: highlight / select symbol under cursor using LSP textDocument/documentHighlight (#2738)
* feat: highlight symbol under cursor using LSP textDocument/documentHighlight

* fix: please clippy

* fix: shorter description and code style
2022-06-27 20:19:56 +09:00
Blaž Hrastnik
fde9e034d4 Only draw cursorline in the currently focused buffer 2022-06-27 17:51:22 +09:00
Blaž Hrastnik
425de09d21 Fix tests again 2022-06-27 17:35:23 +09:00
Blaž Hrastnik
24f03097e3 Remove some more unwraps 2022-06-27 17:27:44 +09:00
Blaž Hrastnik
33d287a9ad Add a default cursorline style for the primary selection 2022-06-27 17:27:24 +09:00
Tobias Menzi
8dc86beabd Implement cursorline (#2170)
* Implement cursorline

* Binary search possible lines
2022-06-27 17:09:34 +09:00
Gokul Soumya
a26943de4e Right align scrollbar with track in completion popup (#2754)
- Align the scollbar to the right edge of the popup rather than at
  a margin of one.
- Add a scrollbar track and a new scope `ui.menu.scroll`.
2022-06-27 16:52:31 +09:00
Ramojus
c113531db9 add meliora theme (#2884) 2022-06-26 23:40:08 -05:00
Kihaya Sugiura
24351c20d4 languages: Fix ruby rakefile and gemfile file type (#2875) 2022-06-26 12:04:53 -05:00
Gokul Soumya
16ccc7ead8 Add single width left margin for completion popup (#2728)
* Add single width left margin for completion popup

* Clear with ui.menu style before rendering menu

When rendering a completion popup, the popup component will clear
the area with ui.popup and then the menu component would draw over
it using a table component. We remove the left edge of the area
before passing it to the table component (so that it will be left
as padding), and the table component uses ui.menu as the style.
If ui.menu and ui.popup are different the left edge of the popup
will look different from the rest of the popup. We avoid this by
clearing the whole area with ui.menu in Menu::render
2022-06-26 17:56:35 +09:00
Amit Beka
ba85779902 book: fix the description of dot repeat (#2878)
Co-authored-by: amitbeka <--->
2022-06-25 15:28:26 -05:00
Triton171
e1b1a5ebc0 Fix edge-case in tree-sitter expand_selection selection command (#2877)
Co-authored-by: Triton171 <triton0171@gmail.com>
2022-06-25 13:12:30 -05:00
two-six
18435899b2 [Theme] Acme (#2876) 2022-06-25 12:09:04 -05:00
Hekno25
33e6df8707 feat: add wgsl_analyzer as wgsl language server (#2872) 2022-06-24 16:21:26 -05:00
Saber Haj Rabiee
3dbad0442f fixes showing the last prompt on empty input (#2870) 2022-06-24 17:14:48 +02:00
Michael Davis
d948ace67b check selection's visible width when copying on mouse click (#2711)
* check selection's visible width when copying on mouse click

Mouse-click-up copies the selection produced by dragging. The event
is ignored if the selection has a width of 1 though so you don't
copy when clicking rather than dragging. The current check copies
text when it has a visible width of 1 but is actually multiple
characters in the rope like a CRLF line-ending. With this change
we check the unicode width of the character(s) in the selection
rather than the range length, so clicking on a CRLF line-ending
does not copy.

* use range.fragment to simplify getting the primary selection width
2022-06-24 22:58:04 +09:00
farwyler
886cff3bcc Redetect indent and line endings after language server replaces documents (#2778)
* redetect indent and line endings after language server replaces document

* removes nested if

* always redetect indent and line endings after format

This reverts commit 764d14f55894dc7213e48022dfa0f91829b8ef59.
2022-06-24 22:56:18 +09:00
Seth Bromberger
c107f4ea49 fixes #2856 by resetting style on diagnostic (#2861) 2022-06-22 20:53:36 +02:00
Gokul Soumya
301065fe4d Fix scrollbar length proportional to total menu items (#2860)
The scrollbar length used to increase with more entries in the menu,
which was counter-intuitive to how scrollbars worked in most
applications. Turns out there was a typo in the floor division
implementation :)
2022-06-23 03:00:12 +09:00
Erin van der Veen
b365f2d614 update tree-sitter-nickel to include ' in ident (#2859)
see https://github.com/nickel-lang/tree-sitter-nickel/pull/9
and  https://github.com/tweag/nickel/pull/737
2022-06-22 20:01:54 +09:00
Yusuf Bera Ertan
8c86cd56cb build(nix): update flake deps, add default.nix file 2022-06-21 17:39:30 -05:00
dependabot[bot]
5b3b6ffc9e build(deps): bump regex from 1.5.4 to 1.5.5 (#2851)
Bumps [regex](https://github.com/rust-lang/regex) from 1.5.4 to 1.5.5.
- [Release notes](https://github.com/rust-lang/regex/releases)
- [Changelog](https://github.com/rust-lang/regex/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/regex/compare/1.5.4...1.5.5)

---
updated-dependencies:
- dependency-name: regex
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-22 03:42:22 +09:00
Blaž Hrastnik
23b5b1e25a Remove a couple more unwraps 2022-06-22 02:26:24 +09:00
Blaž Hrastnik
19dccade7c Merge pull request #2359 from dead10ck/test-harness
Integration testing harness
2022-06-21 18:59:02 +02:00
Termina94
a17626a822 add history suggest to global search (#2717)
Co-authored-by: Dean Revell <revell@gmail.com>
2022-06-22 01:52:25 +09:00
Gokul Soumya
8e8367eea6 Refactor Margin for fine grained control (#2727) 2022-06-22 01:52:08 +09:00
ath3
ce85b9716d Enable shellwords for Windows (with escaping disabled) (#2767) 2022-06-22 01:48:01 +09:00
Gokul Soumya
8b67acf130 Format keys identically in statusline and command palette (#2790)
The command palette previously used + as a delimiter for denoting
a single key in a key sequence, (like C+w). This was at odds with
how the statusline displayed them with pending keys (like <C-w>).
This patch changes the palette formatting to the statusline formatting
2022-06-22 01:46:50 +09:00
Gokul Soumya
8ad0b83e30 Make indent guides configurable 2022-06-21 18:43:25 +02:00
Gokul Soumya
924b4ebb39 Add theme scopes for indent guides 2022-06-21 18:43:25 +02:00
Gokul Soumya
8c4c923e80 Add indent guides support 2022-06-21 18:43:25 +02:00
Blaž Hrastnik
458b89e21d Merge branch 'master' into test-harness 2022-06-21 18:38:21 +02:00
Matthew Toohey
6a3f7f2c39 feat: make move_vertically aware of tabs and wide characters (#2620)
* feat: make `move_vertically` aware of tabs and wide characters

* refactor: replace unnecessary checked_sub with comparison

* refactor: leave pos_at_coords unchanged and introduce separate pos_at_visual_coords

* style: include comment to explain `pos_at_visual_coords` breaking condition

* refactor: use `pos_at_visual_coords` in `text_pos_at_screen_coords`

* feat: make `copy_selection_on_line` aware of wide characters
2022-06-22 01:36:36 +09:00
Mathspy
fa4934cff9 Default rulers color to red (#2669)
* Default rulers color to red

Currently if the theme a user is using doesn't have `ui.virtual.rulers`
set and they set up a ruler it just fails silently making it really hard
to figure out what went wrong. Did they set incorrectly set the ruler?
Are they using an outdated version of Helix that doesn't support rulers?

This happened to me today, I even switched to the default theme with
the assumption that maybe my theme just doesn't have the rulers setup
properly and it still didn't work.

Not sure if this is a good idea or not, feel free to suggest better
alternatives!

* Use builtin Style methods instead of Bevy style defaults

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>

* Only default the style if there's no ui or ui.virtual

* Update themes style from ui.virtual to ui.virtual.whitespace

* Revert ui.virtual change in onelight theme

* Prefer unwrap_or_else

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2022-06-22 01:35:25 +09:00
Michael Davis
9f676dab57 add test textobjects queries for erlang,gleam,go,python,rust 2022-06-21 11:32:03 -05:00
Connor Lay (Clay)
67f6c85792 text-objects: add test capture & elixir queries 2022-06-21 11:32:03 -05:00
A-Walrus
43027d9104 Display highest severity diagnostic in gutter (#2835)
* Display highest severity diagnostic in gutter

* Improve gutter diagnostic performance

Very slight improvement (doesn't really make a difference), iterates over the diagnostics of the line
once instead of twice.

* Add comment justifying unwrap
2022-06-21 08:09:43 +05:30
dependabot[bot]
009f8c4d3b build(deps): bump anyhow from 1.0.57 to 1.0.58 (#2843)
Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.57 to 1.0.58.
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.57...1.0.58)

---
updated-dependencies:
- dependency-name: anyhow
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-21 08:08:45 +05:30
Michael Davis
0ad10ce6f7 rewrite language configuration docs (#2838)
This change moves the configuration tables from the Adding
Languages guide into the overall Languages section. It also
adds more detailed documentation on the `language-server`
configuration key and fixes a typo in the "mylang" example
(the scope was `scope.mylang` instead of `source.mylang`).
2022-06-21 01:15:50 +02:00
Mathis Brossier
8c64c3dfa3 mouse selection now uses character indexing (#2839) 2022-06-20 20:41:34 +02:00
farwyler
cad4e03a00 adds missing tree-sitter-comment injection for js/ts (#2763) 2022-06-20 10:55:51 -05:00
lazytanuki
55f4f69515 fix: do not color health summary when stdout is piped (#2836)
* fix: do not color health summary when stdout is piped

* fix: use crossterm instead of is-terminal
2022-06-20 17:07:32 +02:00
Joe
e2878a6e21 Add noctis bordo theme (#2830) 2022-06-20 09:21:21 -05:00
Skyler Hawthorne
5f7c247430 replace phrase in tests 2022-06-19 00:00:31 -04:00
Skyler Hawthorne
665286c199 factor new Application with file arg to function 2022-06-19 00:00:31 -04:00
Skyler Hawthorne
65bf6836b7 update docs for integration tests 2022-06-19 00:00:31 -04:00
Skyler Hawthorne
086b63ab1b add integration-test cargo alias 2022-06-18 23:57:47 -04:00
Skyler Hawthorne
41bf1d5811 fix(command): write-quit: do not quit if write fails
During write-quit, if the file fails to be written for any reason, helix
will still quit without saving the changes. This fixes this behavior by
introducing fallibility to the asynchronous job queues. This will also
benefit all contexts which may depend on these job queues.

Fixes #1575
2022-06-18 23:57:47 -04:00
Skyler Hawthorne
fac36bc5ea add test for write-quit happy path 2022-06-18 23:57:47 -04:00
Skyler Hawthorne
7c0bca186c rename test helpers 2022-06-18 23:57:47 -04:00
Skyler Hawthorne
526c9be8ca consolidate idle timer logic, make conditional 2022-06-18 23:57:47 -04:00
Skyler Hawthorne
374724f5ac ignore failing write path tests until fixes are merged 2022-06-18 23:57:47 -04:00
Skyler Hawthorne
8d8d389536 rename top level module to satisfy cargo fmt 2022-06-18 23:57:47 -04:00
Skyler Hawthorne
acf931709a use a read only file to ensure write failure 2022-06-18 23:57:47 -04:00
Skyler Hawthorne
ef8fe5a5ce use system's appropriate line ending 2022-06-18 23:57:47 -04:00
Skyler Hawthorne
28e94fb261 need the full languages config for integration tests 2022-06-18 23:57:47 -04:00
Skyler Hawthorne
4e34ee7d2e don't read from stdin for integration tests 2022-06-18 23:57:47 -04:00
Skyler Hawthorne
cb0440be85 use env var for integration test log level 2022-06-18 23:57:47 -04:00
Skyler Hawthorne
652cdda833 use test terminal backend for integration tests 2022-06-18 23:57:47 -04:00
Skyler Hawthorne
ed950fcc56 Add more context; Editor::open doesn't need to own path 2022-06-18 23:57:45 -04:00
Skyler Hawthorne
1533f48934 use Results in integration tests for more error context 2022-06-18 23:54:03 -04:00
Skyler Hawthorne
2fbf833630 add integration feature to github tests 2022-06-18 23:54:03 -04:00
Skyler Hawthorne
2386c81ebc use idle timer instead of fixed timeout 2022-06-18 23:54:03 -04:00
Skyler Hawthorne
40120967e9 tests for buffer-close 2022-06-18 23:54:03 -04:00
Skyler Hawthorne
07fc80aece tests for serialized writes 2022-06-18 23:54:03 -04:00
Skyler Hawthorne
ee705dcb33 use main application event loop
Use the Application's main event loop to allow LSP, file writes, etc
2022-06-18 23:54:03 -04:00
Skyler Hawthorne
36e5809f63 add test for ensuring the initial cursor on a newly opened file 2022-06-18 23:54:03 -04:00
Skyler Hawthorne
267605d147 reorganize tests into groups 2022-06-18 23:54:03 -04:00
Skyler Hawthorne
84bbe6b8f3 refactor helpers, use new test helpers 2022-06-18 23:54:03 -04:00
Skyler Hawthorne
0f3c10a021 Fix initial selection of Document in new view
When a new View of a Document is created, a default cursor of 0, 0 is
created, and it does not get normalized to a single width cursor until
at least one movement of the cursor happens. This appears to have no
practical negative effect that I could find, but it makes tests difficult
to work with, since the initial selection is not what you expect it to be.

This changes the initial selection of a new View to be the width of the
first grapheme in the text.
2022-06-18 23:54:03 -04:00
Skyler Hawthorne
502d3290fb improve test harness
* Use new macro syntax for encoding sequences of keys
* Make convenience helpers for common test pattern
* Use indoc for inline indented raw strings
* Add feature flag for integration testing to disable rendering
2022-06-18 23:54:03 -04:00
Blaž Hrastnik
308cab3e5c Integration testing harness 2022-06-18 23:54:03 -04:00
Blaž Hrastnik
adb6cd5376 Simplify handle_terminal_events signature 2022-06-18 23:54:03 -04:00
Skyler Hawthorne
0623a72599 move config parsing back into main 2022-06-18 23:54:03 -04:00
A-Walrus
ad15e7b5e8 Add "<<=" operator to Rust syntax highlighting (#2805) 2022-06-18 11:44:21 -05:00
Michael Davis
45ce1ebdb6 embed jsonrpc types from jsonrpc-core crate (#2801)
We should not depend on jsonrpc-core anymore:

* The project just announced it's no longer actively maintained[^1],
  preferring their new implementation in `jsonrpsee`.
* The types are too strict: we would benefit from removing some
  `#[serde(deny_unknown_fields)]` annotations to allow language
  servers that disrespect the spec[^2].
* We don't use much of the project. Just the types out of core.
  These are easy to embed directly into the `helix-lsp` crate.

[^1]: https://github.com/paritytech/jsonrpc/pull/674
[^2]: https://github.com/helix-editor/helix/issues/2786
2022-06-18 12:59:57 +09:00
Clay
b13e534b92 HEEx: upgrade version and support new special_attribute node (#2800) 2022-06-17 17:30:28 -05:00
Henry
15807d5f27 simplify some keymap key names follow up tests (#2694) 2022-06-17 09:51:45 -05:00
Grenier Célestin
33ea3eff05 Update theme base16_default (ui.menu) (#2794) 2022-06-17 20:24:18 +09:00
nosa
21d12e1487 Restore section spacing in tutor. (#2791) 2022-06-16 17:28:55 -05:00
Gygaxis Vainhardt
debd2405d9 views -> buffers in write-all (#2788) 2022-06-16 16:09:30 -05:00
Axot
4d604d3b50 Add clojure language support (#2780)
Co-authored-by: Mateusz Ledwoń <mateusz.ledwon@iteo.com>
2022-06-16 11:47:52 -05:00
nosa
3b1866f959 update tutor (#2716)
* update tutor

* Capitalize "command mode ".

* Update runtime/tutor.txt

Editing mistake.

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2022-06-15 15:31:26 -05:00
Bjorn Ove Hay Andersen
794576a5b0 Update auto-pairs and idle-timeout when the config is reloaded (#2736) 2022-06-15 22:59:58 +05:30
Tennix
11dadab371 Add migrate from Vim wiki link (#2781) 2022-06-15 11:04:17 -05:00
Frojdholm
402f285ba5 Improve markdown list rendering (#2687)
* Cleanup old commented code

* Implement line breaks in markdown rendering

* Implement markdown nested, numbered and multiparagraph lists
2022-06-15 13:20:19 +09:00
Roland Kovacs
c2cc2037b5 Better handling of symlinks (#2718)
- Add file-picker.follow-symlinks configuration option (default is true), this
  also controls if filename and directory completers follow symlinks.

- Update FilePicker to set editor error if opening a file fails, instead of
  panicing.

Fix #1548
Fix #2246
2022-06-15 13:17:17 +09:00
Anton Romanov
7983c71752 Introduce storage_class highlight scope (#2731) 2022-06-14 12:35:36 -05:00
Michael Davis
cdeab337cd simplify fallback for selected line-number theming (#2768) 2022-06-14 21:40:38 +05:30
Ryang Sohn
3bd5545577 Add a check to prevent re-selecting same range (#2760) 2022-06-14 08:37:40 -05:00
Kappa
d7bd441675 Cleanup for runtime/tutor.txt (#2590) 2022-06-13 23:12:13 +08:00
Bjorn Ove Hay Andersen
3b2d4031f1 Clarified the text in chapter 3 of the tutor (#2735)
* Clarified the text in chapter 3 of the tutor (#2725)

* Adjusted section 3.1 to better show how C works
2022-06-13 09:00:40 -05:00
Jonas Tepe
a766b32ed1 Expand chapter one recap of tutor
This add the missing variant of entering insert mode
to the chapter 1 recap section.
2022-06-12 14:12:52 -05:00
Ivan
0bc7259672 add prisma tree-sitter and lsp support (#2703)
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2022-06-12 14:08:51 -05:00
Gokul Soumya
e9283b20b4 Add docstring for language_server!() macro (#2750) 2022-06-12 09:53:58 +09:00
Gokul Soumya
0b8a00ac96 Refactor textobject node capture (#2741) 2022-06-12 00:39:21 +09:00
Daniel Hines
9b9c3e5ae2 add rust-analyzer to shell environment (#2739) 2022-06-11 17:23:18 +09:00
Clay
f37ffaa3a1 elixirLS disable dialyzer by default (#2710)
Not all Elixir projects use dialyzer and it can cause the editor
to slow down quite a bit on large projects if the PLT is not built.

See https://github.com/elixir-lsp/elixir-ls#dialyzer-integration=
2022-06-10 10:45:17 +09:00
Danny
567e71fbbc fix spelling of catppuccin theme (#2713) 2022-06-08 23:33:26 +05:30
Frojdholm
e0532771cc Do not add extra line breaks in markdown lists (#2689) 2022-06-08 09:44:07 +09:00
Michael Davis
4a27e2d938 capture rust closures as function textobjects
Closures like

    iter.map(|a| a + 1)

Are sort-of functions, so `]f` or `maf` or `mif` can apply to them
as well as named function definitions.
2022-06-07 20:03:31 +09:00
Michael Davis
f7a3d35752 add textobject queries for gleam 2022-06-07 20:03:31 +09:00
Michael Davis
bcafdf404f add textobject queries for elixir 2022-06-07 20:03:31 +09:00
Michael Davis
7a9147489e add textobject queries for erlang 2022-06-07 20:03:31 +09:00
dependabot[bot]
9f8df05d96 build(deps): bump tokio-stream from 0.1.8 to 0.1.9 (#2690)
Bumps [tokio-stream](https://github.com/tokio-rs/tokio) from 0.1.8 to 0.1.9.
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-stream-0.1.8...tokio-stream-0.1.9)

---
updated-dependencies:
- dependency-name: tokio-stream
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-07 14:51:36 +09:00
dependabot[bot]
5c7d9d6027 build(deps): bump tokio from 1.18.2 to 1.19.2 (#2691)
Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.18.2 to 1.19.2.
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/commits)

---
updated-dependencies:
- dependency-name: tokio
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-07 11:10:00 +05:30
Yusuf Bera Ertan
bb83ea8393 chore(nix): format nix files with alejandra, update deps, minor code refactors (#2683) 2022-06-06 14:24:52 -05:00
farwyler
f0d1c85553 support for openscad (#2680)
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2022-06-06 12:26:56 -05:00
Blaž Hrastnik
26dbdb70fb Refactor push_jump so we're not needlessly fetching doc twice 2022-06-07 00:23:41 +09:00
Blaž Hrastnik
3d9923969a minor: Simplify Document.language_id() 2022-06-07 00:23:41 +09:00
Blaž Hrastnik
b14c258a2c prompt: If submitting empty prompt, use default (last used) 2022-06-07 00:23:40 +09:00
Henry
8351a82c2c simplify some keymap key names (#2677) 2022-06-05 21:22:10 -05:00
Michael Davis
0035c29fc1 Use a minimal binary to fetch grammar sources in release CI (#2557)
This is an optimization for the release CI. The release CI can take
a while since it compiles release builds for all operating systems.
We cut down on duplicate work and overall time by fetching
tree-sitter grammar repositories and then using those repositories
in all later steps. Previously we built all of helix just to run

    helix_loader::grammar::fetch_grammars()

which is wasteful on time. With this change we only build the
helix-loader crate.
2022-06-05 19:53:20 +09:00
Termina94
f1ae496860 Add shell insert commands to typable and config (#2589)
* Add shell insert commands to typable and config

* generate docs

Co-authored-by: Dean Revell <revell@gmail.com>
2022-06-05 19:52:41 +09:00
farwyler
f92a25a856 Passing extra formatting options to LSPs (#2635)
* allows passing extra formatting options to LSPs

- adds optional field 'format' to [[language]] sections in 'languages.toml'

- passes specified options the LSPs via FormattingOptions

* cleaner conversion of formatting properties

* move formatting options inside lsp::Client

* cleans up formatting properties merge
2022-06-05 19:50:57 +09:00
gavynriebau
b2bd87df81 Fix crash due to cycles when replaying macros (#2647)
In certain circumstances it was possible to get into an infinite loop
when replaying macros such as when different macros attempt to replay
each other.

This commit adds changes to track which macros are currently being
replayed and prevent getting into infinite loops.
2022-06-05 19:49:41 +09:00
Michael Davis
1c2aaf3baf ensure :quit and :quit! take no arguments (#2654) 2022-06-05 19:48:16 +09:00
yzwduck
d24ca66dbb Avoid modifying jumplist until jumping to ref (#2670)
When a goto command is cancelled, the jumplist should remain unchanged.

This commit delays saving the current selection to the jumplist until
jumping to a reference.
2022-06-05 19:44:55 +09:00
gavynriebau
026241cf72 Fix panic on close last buffer (#2367) (#2658)
* Fix panic on close last buffer (#2367)

In certain circumstances it was possible to cause a panic when closing
buffers due to some mishandling of view document history.

A change has been made to delete removed documents from the history of
accessed documents for each view. The ensures we don't attempt to jump
to a deleted document by mistake.

* Move remove document code into View function 'remove_document'

* Replace 'view.jumps.remove' call with 'view.remove_document' call
2022-06-05 11:27:41 +09:00
nosa
5b4e0a304b Update selection style of Night Owl (#2668) 2022-06-04 10:40:39 +05:30
nosa
dfd0754394 Update keymap docs for window swapping (#2659) 2022-06-03 07:09:35 -05:00
Michael Davis
fd4858c03d add tree-sitter-jsdoc (#2650) 2022-06-03 10:26:47 +05:30
Michael Davis
42d780b103 add tree-sitter-edoc (#2640)
* add tree-sitter-edoc

* fix escape character capture in markdown queries

* add field negation operator "!" to tsq highlights
2022-06-03 07:41:17 +08:00
Kirawi
4f3d0a7706 append set_line_ending to document history (#2649) 2022-06-02 10:46:53 -05:00
Frojdholm
f7c27b604f Ignore SendErrors when handling grammars (#2641)
When handling grammars, fetching and building is done in a thread
pool.  Results are communicated over channels and the receiving
channel is closed on first error. This causes subsequent sends to
fail causing a mess in stderr. This ignores all SendErrors causing
only the first error to be printed.
2022-06-02 16:54:11 +09:00
Blaž Hrastnik
378f438fb0 fix: lsp: be more defensive about URI conversions 2022-06-02 14:07:19 +09:00
Blaž Hrastnik
6de6a3edbb fix: lsp: be more defensive about URI conversions 2022-06-02 14:07:19 +09:00
Blaž Hrastnik
3d91c99c3e fix: lsp: Sort edits by start range, Omnisharp sends them in reverse 2022-06-02 14:07:19 +09:00
Michael Zeller
99e08f50bd catpuccin ui.popup should be a different color from ui.background (#2644) 2022-06-01 16:11:58 -05:00
Fanda Vacek
8d4c954060 CPON parser supports unsigned int (#2643)
Co-authored-by: Fanda Vacek <fvacek@elektroline.cz>
2022-06-01 15:11:14 -05:00
Ryan Russell
ae12c58f0f Improve Readability (#2639) 2022-06-01 12:01:37 -05:00
Ben Lee-Cohen
fc666db6b9 Solarized Light: Fixing menu colors and adding English translation (#2626) 2022-05-31 10:15:32 -05:00
Andrey Tkachenko
fa2eeccc57 Fix unwrap error when undo after shell_append_output (#2625) 2022-05-31 23:08:16 +09:00
Clay
fc8c488322 Elixir: inject Markdown into docs, remove h sigil HEEx injection (#2619)
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2022-05-30 21:32:14 -05:00
Timothy DeHerrera
eba82250bb feat(lang): Update Nix grammar & improve queries (#2472) 2022-05-30 13:47:18 -05:00
Blaž Hrastnik
370a16d0f0 Update to ropey 1.5 2022-05-30 12:29:07 +09:00
Blaž Hrastnik
5ed6223990 fix: Remove empty scratch buffer from jumplists when removing it
Fixes #1238
2022-05-30 01:22:17 +09:00
Paul Graydon
710c4a84b2 Adjust colors in tokyonight themes (#2606) 2022-05-29 10:56:10 -05:00
Michael Zeller
b43074dad3 illumos linker doesn't currently have -z relro (#2602) 2022-05-29 10:52:48 -05:00
Marcin Puc
cd4622db9b Update from-source install instruction in README (#2603) 2022-05-29 10:52:26 -05:00
Hugo
89c6e8aa94 Remove unnecessary unwrap (#2599)
`strip_prefix` will itself check whether the string starts with the
prefix, so the extra call to `starts_with` was unnecessary.
2022-05-29 11:13:21 +09:00
Blaž Hrastnik
10415a8069 Bump dependencies, allow retain_mut for now 2022-05-29 11:10:49 +09:00
Michael Davis
93e6eac15a mention the C++ compiler in the grammar build failure message (#2597)
Earlier in the builder we enable C++ (`.cpp(true)`) but only mention
the C compiler in the build failure message. Some grammars that have
C++ external scanners can provoke build failures in this step if a
C++ compiler isn't installed, so mentioning it in the error message
should help out debugging.
2022-05-29 11:06:31 +09:00
pancake
7706a4a0d8 Add Vlang tree-sitter in the languages.toml (#2526)
Co-authored-by: pancake <pancake@nopcode.org>
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2022-05-28 14:46:10 -05:00
booklearner
7c107d0d3a Fix link to pop-dark in CHANGELOG.md (#2594) 2022-05-28 13:11:31 -05:00
Blaž Hrastnik
27609f5065 Fix the VERSION file 2022-05-29 01:07:30 +09:00
nitish-17
b31788102e mention the requirement of C++ compiler for building grammar in doc (#2592) 2022-05-28 11:02:47 -05:00
Blaž Hrastnik
a106341fd7 Fix release action 2022-05-28 23:23:08 +09:00
Michael Davis
46f9320709 add 22.05 changelog notes (#2584) 2022-05-28 09:18:15 -05:00
Michael Davis
efae76160d add section on syntax tree motions to the usage docs (#2568) 2022-05-26 10:39:58 +09:00
Ben Lee-Cohen
7160e745f7 Changing Macro color to avoid color confusion
I noticed that in Rust, `println!`being a macro, it matched the color of string literals. This was visually confusing to me, so I checked what the nvim catpuccin theme (https://github.com/catppuccin/nvim) does. While it is pretty different, it does use different colors for strings and all function types: https://share.cleanshot.com/RLG2y1

I don't know if blue or red makes more sense given the other syntax choices, but wanted to propose this change cc @IsotoxalDev
2022-05-25 09:54:20 -05:00
Michael Davis
82da9bd4f2 update Erlang grammar and queries
The update to the grammar itself covers the case where the document
is a single expression without a trailing newline such as "min(A, B)".
A small change to the parser now parses these expressions correctly
which improves the display of the function head in the signature
help popup.

The update to the queries marks 'andalso', 'orelse', 'not', etc. as
`@keyword.operator` which improves the look - it looks odd to see
operators that are words highlighted the same as tokens like '->'
or '=:='.
2022-05-25 21:26:26 +09:00
Michael Davis
45dd54082e update Gleam grammar and queries
With respect to the queries:

The locals scope for functions was not large enough, so a function's
parameter could outlive the function body. To fix it, we just widen
the scope to the `function` node.

See also https://github.com/gleam-lang/tree-sitter-gleam/issues/25

With respect to the parser:

An external scanner has been added that fixes the parsing of strings.
Previously, a comment inside a string would act like a comment rather
than string contents.

See also https://github.com/gleam-lang/tree-sitter-gleam/issues/14#issuecomment-1129263640

A new constructor node has been added as well which makes type
highlighting more fine grained.

See also https://github.com/gleam-lang/tree-sitter-gleam/pull/29
2022-05-25 21:26:26 +09:00
Andrey Tkachenko
10463fe32c Add parameter.around text object query 2022-05-25 21:26:06 +09:00
dependabot[bot]
da29527258 build(deps): bump once_cell from 1.10.0 to 1.12.0
Bumps [once_cell](https://github.com/matklad/once_cell) from 1.10.0 to 1.12.0.
- [Release notes](https://github.com/matklad/once_cell/releases)
- [Changelog](https://github.com/matklad/once_cell/blob/master/CHANGELOG.md)
- [Commits](https://github.com/matklad/once_cell/compare/v1.10.0...v1.12.0)

---
updated-dependencies:
- dependency-name: once_cell
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-25 21:25:47 +09:00
dependabot[bot]
a13ff27023 build(deps): bump regex from 1.5.5 to 1.5.6
Bumps [regex](https://github.com/rust-lang/regex) from 1.5.5 to 1.5.6.
- [Release notes](https://github.com/rust-lang/regex/releases)
- [Changelog](https://github.com/rust-lang/regex/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/regex/compare/1.5.5...1.5.6)

---
updated-dependencies:
- dependency-name: regex
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-25 21:25:34 +09:00
Andrey Tkachenko
67fe16008e Basic verilog support (#2552) 2022-05-24 12:52:32 -05:00
Erasin
386dccc84e Add lua lsp (#2560) 2022-05-24 10:03:53 -05:00
Isotoxal
c429ed660f Add Catppuccin Theme (#2546)
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2022-05-24 09:02:26 -05:00
Blaž Hrastnik
d6865cdca3 nix: bump dependencies 2022-05-24 09:37:17 +09:00
Michael Davis
89c0998aee lower MSRV to 1.57.0
This line uses the Display trait for io::ErrorKind which was
stabilized in Rust 1.60.0. We can set MSRV all the way back to
1.57.0 by replacing it with a pretty-print.

Closes #2460.
2022-05-24 01:05:19 +09:00
Michael Davis
92df5a5425 check MSRV in CI
It's very easy to use new rust features without realizing it since
the CI and local development workflows may use the latest rust version.
We try to keep some backwards compatibility with rust versions to make
packaging easier for some OS-level package-managers like Void Linux's.
See #1881.

This change runs the "Check" step for the pinned version of rust in
the rust-toolchain.toml file as well as the MSRV version in a matrix.
In order to bump the MSRV, we need to edit

    .github/workflows/msrv-rust-toolchain.toml

This commit sets the MSRV as 1.60.0 but a later child commit will
reduce the MSRV back to 1.57.0.

Closes #2482.
2022-05-24 01:05:19 +09:00
Michael Davis
aa87adf54b pin the rust toolchain to 1.61.0
1.61.0 in particular introduced new clippy lints that unexpectedly
failed CI until addressed. The lints are a bit tough to fix since
the toolchain action starts using new rust versions almost immediately
after release, so if you aren't using rustup, you may have a hard
time reproducing the lint results until your package manager updates
rust.

This brings an extra burden that we have to remember to make a
commit/PR to update rust in CI.
2022-05-24 01:05:19 +09:00
Michael Davis
f6531c9db0 inherit rust toolchain channel from rust-toolchain.toml
We've forked actions-rs/toolchain and merged
https://github.com/actions-rs/toolchain/pull/209
so we can take advantage of full support of `rust-toolchain.toml`.
Without that PR, the action fails because the `rustup` version
built into the runners by default is too old. #2528 covers switching
back to the upstream when it includes those changes.
2022-05-24 01:05:19 +09:00
Blaž Hrastnik
35303f749e Replace handwritten CI cache with Swatinem/rust-cache
The cache kept growing as dependencies kept changing and updating.
2022-05-23 13:48:00 +09:00
Jens Getreu
6801b28da0 Highlight active window in Autumn theme (#2531)
Co-authored-by: Jens Getreu <jens.getreu@dlh.lu>
2022-05-22 10:40:27 -05:00
Joel
682bcc3a32 fix: missing quotes around variable.other.member 2022-05-22 18:36:51 +09:00
Joel
0018545263 fix: remove duplicated ui.help in themes
the bottom value is used, so i've removed the top `ui.help` values from all themes

also, the values are not merged, so:

```toml
"ui.help" = { modifiers = ["reversed"] }
"ui.help" = { fg = "white", bg = "black" }
```

is equal to:

```toml
"ui.help" = { fg = "white", bg = "black" }
```
2022-05-22 18:36:51 +09:00
Daniel S Poulin
0c05447d49 Add shrink equivalent of extend_to_line_bounds (#2450)
* Add shrink equivalent of extend_to_line_bounds

* Add a check for being past rope end in end position calc

* Include the EOL character in calculations

* Bind to `A-x` for now

* Document new keybind
2022-05-22 10:33:11 +09:00
Ivan Tham
5bcb31a6df Make Borders u8 2022-05-22 10:26:32 +09:00
Ivan Tham
1837b5e4a6 Refactor Block with Default and bitflags
Specifying empty for bitflags is not recommended, it is now removed and added
Default. For BorderType, it now defaults to plain.
2022-05-22 10:26:32 +09:00
kyrime
bfc4ff4dcf Add theme key for picker separator (#2523)
Co-authored-by: ky <>
2022-05-22 10:24:51 +09:00
Leoi Hung Kin
5c864922d8 Fix panic when reloading a shrunk file (#2506)
* fix panic when reloading a shrunk file

* linting

* use scrolloff
2022-05-22 10:24:32 +09:00
Blaž Hrastnik
8df8ff27c2 cargo xtask docgen 2022-05-22 00:20:45 +09:00
Blaž Hrastnik
d25bae844c Add Scheme support
Skipped scm for now :/ it overlaps with tree-sitter-tsq
2022-05-22 00:01:07 +09:00
Roland Kovacs
6bd8924436 Move Tree nodes on view swap
Instead of moving the Node contents on view swap if they have the same parent
reorder them to keep traversal order otherwise re-parent them.
2022-05-21 08:53:16 -05:00
Roland Kovacs
3f10473d30 Implement view swapping
* add Tree::swap_split_in_direction()
* add swap_view_{left,down,up,right} commands, bound to H,J,K,L
  respectively in the Window menu(s)
* add test for view swapping
2022-05-21 08:53:16 -05:00
Jacob Thompson
e8e252648f Added a default lsp server for Java in languages.toml (#2511)
* Added a default lsp server for Java in languages.toml

* Added a default lsp server for Java in languages.toml cont.

Co-authored-by: Jacob Thompson <a01657923@usu.edu>
2022-05-20 15:17:46 +09:00
Michael Davis
e04bb8b891 address rust 1.61.0 clippy lints (#2514) 2022-05-20 12:16:11 +09:00
Christoph Horn
9be810fd01 add missing ui.menu to themes, fix issues with some themes 2022-05-20 10:32:59 +09:00
Christoph Horn
e7e13dcf06 add ui.menu to default theme 2022-05-20 10:32:59 +09:00
Christoph Horn
82fb217b6a use ui.menu instead of ui.statusline for command completion menu theme 2022-05-20 10:32:59 +09:00
Robert Walter
776686ab24 Separate colors for different diagnostics types (#2437)
* feat(theme): add separate diagnostic colors

This commit adds separate diagnostic highlight colors for the different
types of LSP severities. If the severity type doesn't exist or is
unknown, we use some fallback coloring which was in use before this
commit.

Some initial color options were also added in the theme.toml

Resolves issue #2157

* feat(theme): add docs for new diagnostic options

* feat(theme): adjust defaults & reduce redundancy

- the different colors for different diagnostic severities are now
  disabled in the default theme, instead diagnostics are just generally
  underlined (as prior to the changes of this feature)
- the theme querying is now done once instead of every iteration in the
  loop of processing every diagnostic message
2022-05-20 10:30:28 +09:00
Paul Scott
09f9f70576 Python highlight decorator attribute 2022-05-20 10:28:52 +09:00
Paul Scott
2a2030142f Python highlight keyword argument as parameter 2022-05-20 10:28:52 +09:00
Paul Scott
e680f9644d Python handling highlighting parameters with defaults 2022-05-20 10:28:52 +09:00
Paul Scott
abef250c58 Python highlight improvements: type, parameter etc
* str, list, etc. handled as @function.builtin and @type.builtin
* None and non-conforming type indentifiers as @type in type hints
* class identifiers treated as @type
* @constructor used for constructor definitions and calls rather than
  as a catch-all for type-like things
* Parameters highlighted
* self and cls as @variable.builtin
* improved decorator highlighting as part of @function

Re-ordering of some statements to give more accurate priority.
2022-05-20 10:28:52 +09:00
Zeddicus414
8e8d4ba27f dark_plus theme constructor should be green. 2022-05-20 10:28:52 +09:00
Zeddicus414
a6da99a144 Change python highlights.scm to more fully utilize the themes.
Create type keywords
Allow _CONSTANTS to start with _
Highlight constants before constructors
Move some keywords into @keyword.control
2022-05-20 10:28:52 +09:00
Bob
6462542fc5 support insert register in prompt (#2458)
* support insert register in prompt

* use next_char_handler instead of a flag

* Fix clippy issue

* show autoinfo when inserting register

* Revert "show autoinfo when inserting register"

This reverts commit 5488344de1.

* use completion instead of autoinfo

autoinfo is overlapped when using prompt

* recalculate_completion after inserting register

* Update helix-term/src/ui/prompt.rs

Co-authored-by: Ivan Tham <pickfire@riseup.net>

Co-authored-by: Ivan Tham <pickfire@riseup.net>
2022-05-20 10:27:59 +09:00
Roland Kovacs
8958bf0a92 Implement view transpose (#2461)
Change the layout of existing split view from horizontal to vertical and
vica-versa. It only effects the focused view and its siblings, i.e. not
recursive.

Command is mapped to 't' or 'C-t' under the Window menus.
2022-05-20 10:25:04 +09:00
Andrey Tkachenko
62fd1f6999 Include macro attributes to impls, structs, enums, functions etc. textobjects (#2494) 2022-05-20 10:19:46 +09:00
Alexis Kalabura
301ed9b48f deletion of lines affecting popup scrolling (#2497) 2022-05-20 10:18:19 +09:00
midnightexigent
8493b5fca6 Add tree-sitter ssh client config queries (#2498)
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2022-05-18 14:49:50 -05:00
dependabot[bot]
29121a18b5 build(deps): bump signal-hook from 0.3.13 to 0.3.14 (#2485)
Bumps [signal-hook](https://github.com/vorner/signal-hook) from 0.3.13 to 0.3.14.
- [Release notes](https://github.com/vorner/signal-hook/releases)
- [Changelog](https://github.com/vorner/signal-hook/blob/master/CHANGELOG.md)
- [Commits](https://github.com/vorner/signal-hook/compare/v0.3.13...v0.3.14)

---
updated-dependencies:
- dependency-name: signal-hook
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-17 14:45:43 +09:00
Michael Davis
50dd11985c prevent panic when handling an LSP response with no request (#2475)
A language server may push a response which doesn't belong to any
request. With this change, we discard the response rather than
crashing.

In the case of #2474, the language server sends an error message
with a null request ID which should not ever exist in the
`pending_requests` HashMap.

closes #2474
2022-05-17 14:45:34 +09:00
dependabot[bot]
0258cf45f3 build(deps): bump etcetera from 0.3.2 to 0.4.0 (#2486)
Bumps [etcetera](https://github.com/arzg/etcetera) from 0.3.2 to 0.4.0.
- [Release notes](https://github.com/arzg/etcetera/releases)
- [Commits](https://github.com/arzg/etcetera/commits)

---
updated-dependencies:
- dependency-name: etcetera
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-17 12:32:18 +09:00
Alexis Geoffrey
595213ca74 Change default Hare tab width to 8 (#2480) 2022-05-16 16:48:28 +09:00
Timothy DeHerrera
823eaad1a1 Add Snazzy theme (#2473) 2022-05-14 16:49:06 -05:00
spindlebink
af387e6873 Default to tabs instead of spaces for Odin files (#2464) 2022-05-12 08:23:38 -05:00
Blaž Hrastnik
7b287f636f nix: update flake dependencies 2022-05-11 11:02:40 +09:00
Blaž Hrastnik
7ae6cad52e Don't panic on LSP parsing errors
This made sense initially when the implementation was still new (so we
got user reports more frequently), but a parsing error now generally
signifies a language server isn't properly implementing the spec.
2022-05-11 11:00:55 +09:00
Blaž Hrastnik
8b1a03a178 Add FUNDING.yml 2022-05-11 10:51:20 +09:00
amaihoefner
a5bc69c2b5 feat(commands): add log-open command (#2422) 2022-05-11 10:18:45 +09:00
Ivan Tham
0477d02894 Exclude cursor when doing ctrl-w (#2431)
Currently ctrl-w in insert mode deletes the cursor which results in
unexpected behavior. The patch also reduces the selection to cursor before
performing prev word to remove the behavior of removing unnecessary text
when nothing should be removed.

1. `::#(|)#::` after `ctrl-w` should be `#(|)#::`, previously `#(|)#:`
2. `#(|::)#` after `ctrl-w` should be `#(|::)#`, previously `#(|)#`

Fix #2390
2022-05-11 10:12:27 +09:00
Alexis Kalabura
c80ac84978 Run debug console in windows (#2294) 2022-05-11 10:06:57 +09:00
unrelentingtech
2cb1ea7127 feat(lang): add Meson language support (#2314)
https://mesonbuild.com/Syntax.html
2022-05-11 10:06:37 +09:00
EmmChriss
807cdc60bf configurable lsp request timeout (#2405) 2022-05-11 09:54:35 +09:00
Michael Davis
247ab25bc0 prefer Document::set_selection to inserting selections directly (#2411)
Inserting these with the `HashMap::insert` method evades the call
to `Selection::ensure_invariants`. The effect is that the scratch
buffer (or other buffers opened through these code-paths) can start
with a selection at (0, 0), when a file with equivalent contents ("\n")
would start with (0, 1).

I.e.:

    hx

and

    touch f
    hx f

start with different selections even though they have an equivalent
Rope. With this change they both start with (0, 1).
2022-05-11 09:53:54 +09:00
Michael Davis
e0b5cdfb47 prevent selection collapse when inserting a newline (#2414)
Inserting a newline currently collapses any connected selections when inserting
or appending. It's happening because we're reducing the selections down to
their cursors (`let selection = ..` line) and then computing the new selection
based on the cursor. We're discarding the original head and anchor information
which are necessary to emulate Kakoune's behavior.

In Kakoune, inserting a newline retains the existing selection and _slides_
it (moves head and anchor by the same amount) forward by the newline and
indentation amount. Appending a newline extends the selection to include the
newline and any new indentation.

With the implementation of insert_newline here, we slide by adding the global
and local offsets to both head and anchor. We extend by adding the global
offset to both head and anchor but the local offset only to the head.
2022-05-11 09:53:43 +09:00
dependabot[bot]
40647f03ed build(deps): bump serde_json from 1.0.80 to 1.0.81 (#2447)
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.80 to 1.0.81.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.80...v1.0.81)

---
updated-dependencies:
- dependency-name: serde_json
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-10 07:55:31 +08:00
dependabot[bot]
544a05dabf build(deps): bump tokio from 1.18.1 to 1.18.2 (#2448)
Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.18.1 to 1.18.2.
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.18.1...tokio-1.18.2)

---
updated-dependencies:
- dependency-name: tokio
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-10 07:55:01 +08:00
Yt
ae19aaf1a6 languages: add inc files to php (#2440) 2022-05-09 05:53:03 -05:00
Fanda Vacek
f3164c1174 Monokai pro spectrum theme shows error in yellow on red background (#2433)
Co-authored-by: Fanda Vacek <fvacek@elektroline.cz>
2022-05-08 13:16:29 -05:00
Fanda Vacek
76d55c0d9e Cpon support tree sitter version bumped (#2424)
Co-authored-by: Fanda Vacek <fvacek@elektroline.cz>
2022-05-07 06:47:15 -05:00
ChrHorn
b38c268097 fix Markdown list highlighting (#2401) 2022-05-07 11:26:34 +09:00
Robert Walter
495ba40eaf feat(languages): add odin language (#2399) 2022-05-05 12:09:09 -05:00
Ben Lee-Cohen
2f240b018e Adding the global gitignore to the default (#2410) 2022-05-05 10:58:18 -05:00
Matthew Toohey
a5f4925f53 feat(languages): git-ignore and git-attributes (#2397) 2022-05-05 08:47:28 -05:00
ChrHorn
fc61796895 TOML highlight: use variable.other.member instead of string for quoted keys (#2391) 2022-05-05 16:14:17 +09:00
Pavel Borzenkov
f1a77370cf feat(languages): detect 't' as perl (#2395) 2022-05-04 08:32:05 -05:00
ChrHorn
5ab669f1ac replace constant.number with constant.numeric (#2389) 2022-05-04 14:51:31 +09:00
Ben Lee-Cohen
09a17e4fa3 Making the 'set-option' command help more descriptive. (#2365)
* Making the 'set-option' command help more descriptive.

* Adding the generated docs

* Making the message multi-line

* Replace newline with break in generated docs
2022-05-04 11:17:08 +09:00
Michael Davis
f59b3b91c8 rewrite auto-pairs docs (#2384) 2022-05-04 11:16:34 +09:00
Matthew Toohey
25d128b5b3 feat(languages): detect cjs as javascript (#2387) 2022-05-03 20:55:40 -05:00
Johann Dahm
e529ca1b92 Fix build on aarch64-darwin (#1789)
Co-authored-by: Yusuf Bera Ertan <y.bera003.06@protonmail.com>
2022-05-03 17:32:44 -05:00
Matouš Dzivjak
d2b1add1f4 feat(term): wrap command palette in overlay (#2378)
Looks better and is consistent with the rest, nothing else.
2022-05-03 17:28:41 +09:00
dependabot[bot]
042463a4d1 build(deps): bump serde_json from 1.0.79 to 1.0.80 (#2376)
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.79 to 1.0.80.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.79...v1.0.80)

---
updated-dependencies:
- dependency-name: serde_json
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-03 09:31:55 +09:00
dependabot[bot]
e418fae61b build(deps): bump serde from 1.0.136 to 1.0.137 (#2375)
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.136 to 1.0.137.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.136...v1.0.137)

---
updated-dependencies:
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-03 09:31:34 +09:00
dependabot[bot]
0f1fce9af6 build(deps): bump log from 0.4.16 to 0.4.17 (#2374)
Bumps [log](https://github.com/rust-lang/log) from 0.4.16 to 0.4.17.
- [Release notes](https://github.com/rust-lang/log/releases)
- [Changelog](https://github.com/rust-lang/log/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/log/commits/0.4.17)

---
updated-dependencies:
- dependency-name: log
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-03 09:31:23 +09:00
dependabot[bot]
fc35791af9 build(deps): bump tokio from 1.17.0 to 1.18.1 (#2373)
Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.17.0 to 1.18.1.
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.17.0...tokio-1.18.1)

---
updated-dependencies:
- dependency-name: tokio
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-03 09:31:05 +09:00
dependabot[bot]
feea518300 build(deps): bump thiserror from 1.0.30 to 1.0.31 (#2372)
Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.30 to 1.0.31.
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/1.0.30...1.0.31)

---
updated-dependencies:
- dependency-name: thiserror
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-03 09:30:46 +09:00
Robert Walter
fba198c1e0 Add documentation for hx --health (#2357) 2022-05-02 16:46:25 -05:00
AntonioLucibello
ac2ea800ce Add undo checkpoint command (#2115)
* added undo checkpoint command

* changed add_undo_checkpoint to commit_undo_checkpoint

* mapped commit_undo_checkpoint to Alt-u

* Update default.rs

Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
2022-05-02 23:45:20 +09:00
Kirawi
77ff8d3550 cfg-gate unused functions on macos & windows (#2332) 2022-05-02 23:31:23 +09:00
unrelentingtech
20162a426b feat(commands): make it possible to disable format-on-save via the 'auto-format' option (#2321) 2022-05-02 23:31:07 +09:00
Vince Mutolo
f9baced216 add reflow command (#2128)
* add reflow command

Users need to be able to hard-wrap text for many applications, including
comments in code, git commit messages, plaintext documentation, etc. It
often falls to the user to manually insert line breaks where appropriate
in order to hard-wrap text.

This commit introduces the "reflow" command (both in the TUI and core
library) to automatically hard-wrap selected text to a given number of
characters (defined by Unicode "extended grapheme clusters"). It handles
lines with a repeated prefix, such as comments ("//") and indentation.

* reflow: consider newlines to be word separators

* replace custom reflow impl with textwrap crate

* Sync reflow command docs with book

* reflow: add default max_line_len language setting

Co-authored-by: Vince Mutolo <vince@mutolo.org>
2022-05-02 23:24:22 +09:00
Roland Kovacs
567ddef388 Auto-complete directory members (#1801) (#1907)
Allow tab-completion to continue when there is only a single, unambigous
completion target which is a directory. This allows e.g. nested directories
to be quickly drilled down just by hitting <tab> instead of first selecting
the completion then hitting <enter>.
2022-05-02 23:18:41 +09:00
Ryosuke Hayashi
f85f0b7272 Add run-shell-command for Commands (#1682)
* add run_shell_command

* docgen

* fix command name

Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>

* refactored Info::new

* show 'Command failed' if execution fails

* TypedCommand takes care of error handling and printing the error to the statusline.

* docgen

* use Popup instead of autoinfo

* remove to_string in format!

* Revert chage in info.rs

* Show "Command succeed" when success

* Fix info.rs

Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
2022-05-02 23:15:02 +09:00
Fanda Vacek
1668183590 feat(lang): Cpon lang support (#2355)
Co-authored-by: Fanda Vacek <fvacek@elektroline.cz>
2022-05-01 09:34:46 -05:00
Blaž Hrastnik
ede01b5f1e num_cpus apparently unused in helix-term 2022-05-01 11:40:04 +09:00
Blaž Hrastnik
ade4cbffaa Add a nop clipboard provider for wasm 2022-05-01 11:39:31 +09:00
Blaž Hrastnik
9191af3f8d helix-loader + helix-core now compile for WASM 2022-05-01 11:39:07 +09:00
Blaž Hrastnik
8bb89dafa2 cargo xtask docgen 2022-05-01 11:37:14 +09:00
Blaž Hrastnik
73879052c1 Add Cairo support 2022-05-01 11:24:17 +09:00
unrelentingtech
2c60798b00 feat(ui): add nbsp (non-breaking space) to rendered whitespace (#2322) 2022-04-30 09:48:52 +09:00
Michael Davis
e4c2618099 prevent rendering visible whitespace on trailing cursor (#2331) 2022-04-30 09:48:11 +09:00
unrelentingtech
2687b8fb3b feat(ui): treat slashes as word separators in prompt (#2315)
When fiddling with paths in a :o prompt, one usually would want Ctrl-W to erase a path segment
rather than the whole path. This is how Ctrl-W works in e.g. (neo)vim out of the box.
2022-04-30 09:46:51 +09:00
nosa
0106173375 Add Night Owl Color Theme. (#2330) 2022-04-29 17:27:09 -05:00
unrelentingtech
8e77e3388c feat(lang): add devicetree (Flattened Device Tree Source) (#2329) 2022-04-29 15:08:00 -05:00
unrelentingtech
030e7ab988 fix(docs): cleanup obsolete indents.toml mentions (#2327) 2022-04-29 12:40:59 -05:00
Erasin
668b39d1df change cursor for copy selection (#2323) 2022-04-29 11:11:36 -05:00
Yang Tang
667cdf929f Fix spelling errors in some themes (#2324) 2022-04-29 11:03:46 -05:00
Erin van der Veen
21487d13fd feat(lang): Update nickel to include "rec" keyword (#2320) 2022-04-29 07:34:15 -05:00
Gokul Soumya
22ae1b92a6 Fix tests for surround primitives 2022-04-29 15:51:14 +09:00
Gokul Soumya
76175dbd6d Support m in surround delete and replace 2022-04-29 15:51:14 +09:00
Gokul Soumya
de15d70171 Add m textobject to select closest surround pair 2022-04-29 15:51:14 +09:00
Ivan Tham
c22873c33f Change A-left right to C-left right in insert (#2193)
Currently A-left move one word left and the behavior will be more
consistent for people coming GUI world if the key was changed to control
given that both browsers and editors like vscode uses C-left right by
default to move word rather than alt.
2022-04-29 15:50:01 +09:00
Ivan Tham
ab6a00e196 Make A-hjkl tree-sitter nav A-pion (#2205)
A-hl currently is not very consistent with hl when next object is
selected, since it may go up/down or left/right and this behavior is
confusing such that some people think it should swap the keys with A-jk,
so it is better to use A-pn since that only specifies two direction.

A-jk have the same issue as in it usually moves right and is not
consistent with the behavior of jk so people may think A-hl is better,
maybe A-oi is better here since A-hl will be swapped to A-pn, A-oi can
convey the meaning of in and out, similar to some window manager keys?
2022-04-29 15:49:15 +09:00
nosa
e10cf08516 Extend tutor file (#2133)
* Adds tutorial sections for multiple areas including:
- Changing selections to uppercase / lowercase
- yanking and pasting
- macros
- selecting to chars with t and f

PS: I got kind of carried away and put off commiting for a while,
    will commit to commit more often in the future.

* Changed section titles to all uppercase

* Added recap and section about jumplist

* Added sections for searching in file, joining lines and indenting lines.

* Removed some trailing whitespace

* Evened out the space between sections to all be 5 lines

* Add section on opening lines (o) and recap

* Changed the amount of lines between sections

This is so that - on a 24 line terminal -
only one section is visible at a time and
page up/page down goes straight to the next
section keeping the header at the top.

* Punctuation error

Co-authored-by: Omnikar <omkar.subramaniam@icloud.com>

* Punctuation error

Co-authored-by: Omnikar <omkar.subramaniam@icloud.com>

* Spelling error

Co-authored-by: Omnikar <omkar.subramaniam@icloud.com>

* Remove unnecessary word

Co-authored-by: Omnikar <omkar.subramaniam@icloud.com>

* Reword note about searches

Co-authored-by: Omnikar <omkar.subramaniam@icloud.com>

* Change word

Co-authored-by: Omnikar <omkar.subramaniam@icloud.com>

* Update tutor file

* Made some small changes suggested by Omnikar

* Added better demo for macros.

* Small changes

- Add newlines at the end
- Make "MACROS" section fit into 22 lines
- Correct mistake of saying helix copied to clipboard in "COPYING AND PASTING TEXT"

* Reformatted notes in copying/pasting section to fit in screen

* Add a note about n and N and their difference to Vim.

* Combine f and t commands into one section.

* Removed t/T section which was merged into the f/F section.

* Merge sections on manipulating case into one.

* Gave section's numbers

* Convert 'press' to 'type' in some places

* Added examples of how prompt lines should look.

* Reformatted notes in copy/pasting section.

* More rewording to more comfortably fit sections on screen.

* Grammatical error.

* Missing periods.

* Missing capital + small reformat

* Fix mis-numbered section

* Reworded to use these conventions when referring to inputs:
- "Press" for single keypresses
- "Type" for multiple keypresses / modifiers
- "Use" when referencing two inputs as a pair.

* till not 'til

* Say 'press' instead of 'type' when referring to symbols

* 'outdent' not 'unindent'

* Typo and grammar.

* Replace all 'press's with 'type's (apart from places it would make no sense in).

* Improve examples for joining and indenting lines.

* Section alignment.

Co-authored-by: Omnikar <omkar.subramaniam@icloud.com>
2022-04-29 09:52:11 +08:00
CossonLeo
477b88e99c Wrap current directory picker with overlay widget (#2308) 2022-04-28 22:17:24 +09:00
chunghha
3a398eec56 fix typos (#2304) 2022-04-27 14:21:20 -05:00
Alexis Kalabura
2e46961886 feat(lsp): add toml lsp (#2302) 2022-04-27 13:48:04 -05:00
Gokul Soumya
3626e38e51 Add ui.virtual theme scopes for onedark theme 2022-04-27 13:40:00 -05:00
Matouš Dzivjak
52f5a4228a feat(commands): better handling of buffer-close (#1397)
* feat(commands): better handling of buffer-close

Previously, when closing buffer, you would loose cursor position in other docs.
Also, all splits where the buffer was open would be closed.

This PR changes the behavior, if the view has also other buffer
previously viewed it switches back to the last one instead of the view
being closed. As a side effect, since the views are persisted,
 the cursor history is persisted as well.

Fixes: https://github.com/helix-editor/helix/issues/1186

* Adjust buffer close behavior

* Remove closed documents from jump history

* Fix after rebase
2022-04-28 01:14:46 +09:00
Erasin
a3c0b4db48 Add onelight theme variant (#2287) 2022-04-27 08:09:45 -05:00
meak
1a3d6252b9 feat(lang): add hare language support (#2289)
Co-authored-by: Mehdi Katranji <hello@mek.yt>
2022-04-26 14:55:00 -05:00
Michael Davis
773736b03a Fix paste direction for typed paste commands (#2288) 2022-04-26 23:01:45 +05:30
Tomas Roos
fcd0ca3912 Fix base16_terminal theme using incorrect ansi-color (#2279) 2022-04-26 07:53:02 -05:00
dependabot[bot]
3d3145d511 build(deps): bump anyhow from 1.0.56 to 1.0.57 (#2273)
Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.56 to 1.0.57.
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.56...1.0.57)

---
updated-dependencies:
- dependency-name: anyhow
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-04-26 11:20:58 +08:00
Jens Getreu
8eb15f5283 Autumn theme: improve markup highlighting (#2270)
Co-authored-by: Jens Getreu <jens.getreu@dlh.lu>
2022-04-25 12:39:24 -05:00
Lucy
b65fb0f64a Fix typo (#2264) 2022-04-25 07:26:02 -05:00
matt rice
db47761154 register publish_diagnostics client capability (#2241) 2022-04-25 11:14:46 +09:00
ttys3
a8cb46680d feat(lsp): add vala language support (#2243) 2022-04-24 11:21:07 -05:00
workingj
ea02b46c5d Add Pop-Dark Theme (#2189) 2022-04-24 08:04:47 -05:00
Daniel
15db6031bb Add :get-option command (#2231) 2022-04-24 16:00:18 +05:30
Michael Davis
3f2bd7770e Rename paragraph motion commands from move to goto (#2226)
* fix command name for next/prev paragraph motion

* rename move_next/prev_paragraph to goto_next/prev_paragraph
2022-04-24 10:48:22 +09:00
Lukas
5ca8dfe57c fix(lsp): divide hcl into seperate languages (#2244) 2022-04-23 16:08:12 -05:00
Paul Graydon
6047506ec5 Add tokyonight_storm theme variant (#2240) 2022-04-23 08:56:43 -05:00
Lukas
1c1ba006ae feat(lsp): add yaml lsp (#2234) 2022-04-23 08:38:29 -05:00
Michael Davis
2c7f770aa9 Only merge top-level array when merging languages.toml (#2215)
* Revert "Revert "override nested arrays when merging TOML (#2145)""

This reverts commit 35d2693630.

* flip top-level table merging flag
2022-04-23 17:10:34 +09:00
ttys3
19d042dde6 chore(lsp): check rename capabilities before send rename action (#2203) 2022-04-23 17:09:16 +09:00
Ivan Tham
c1d3d49f3f Fix ctrl-u on insert behavior (#1957)
* Fix ctrl-u on insert behavior

Now should follow vim behavior more
- no longer remove text on cursor
- no longer remove selected text while inserting
- first kill to start non-whitespace, start, previous new line

* Add comment for c-u parts
2022-04-23 17:03:52 +09:00
Kirawi
dd5a7c6191 Replace line endings using set_line_ending command (#1871)
* set_line_ending: now replace line endings

* use ending.len_chars() directly

* account for unicode-lines feaure in line-ending doc
2022-04-23 17:01:08 +09:00
Justin Ma
5c2570582b feat(lang): add nushell language support (#2225)
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2022-04-22 09:37:51 -05:00
Jens Getreu
3c250b7528 Add autumn theme (#2212)
Co-authored-by: Jens Getreu <jens.getreu@dlh.lu>
2022-04-22 08:54:43 -05:00
Michael Davis
6de2e7634f Document ui.virtual.ruler scope in theme docs (#2199)
From the rulers feature (#2060)
2022-04-20 23:34:17 +05:30
ttys3
4144c9d2f2 feat(lang): add go.mod and go.work support (#2197) 2022-04-20 11:16:02 -05:00
ttys3
8d335f63f0 chore(filetype): bash and hcl file type add more common used extensions or files (#2201) 2022-04-20 11:08:57 -05:00
Jappie Klooster
b0bceb5674 Fix nix shell by hardcoding the flakecompat library (#2196) 2022-04-20 09:55:09 -05:00
Erin van der Veen
9616477197 Add Nickel language (#2173) 2022-04-20 09:31:59 -05:00
Emil Fresk
5247d3ae2d dark_plus: Add the borders color from the original theme (#2186) 2022-04-20 08:44:00 -05:00
Blaž Hrastnik
35d2693630 Revert "override nested arrays when merging TOML (#2145)"
Looks like there's some follow-up issues

This reverts commit c8cfd0b1a0.
2022-04-20 17:09:03 +09:00
Michael Davis
1525e3c6c8 theme ui.virtual capture for existing themes 2022-04-20 11:37:23 +09:00
Omnikar
e6b865ed0b allow whitespace to be rendered
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2022-04-20 11:37:23 +09:00
adaliaramon
94eba0e66a Added ability to remap 0 if it is not part of a count (#2174)
* Added ability to remap 0

* Removed duplicated match body
2022-04-20 10:50:13 +09:00
Ivan Tham
2a853cd41d Fix open on multiline selection (#2161)
Select multiple line and open should be based on the whole selection
and not just the line of the cursor, which causes weird behavior like
opening in the middle of the selection which user might not expect.
2022-04-20 10:46:46 +09:00
Thomas
5d5b6bab9b Add rulers option (#2060)
* Add color_column option

* Rename to ruler

Co-authored-by: DeviousStoat <devious@stoat.com>
2022-04-20 10:44:32 +09:00
matan h
02426072cb add table of OS/command for copy/symlink the runtime folder to the config (#2073)
* create table of OS and commands in the readme

* add link to wiki from health check (without color; just simple println)

* move the table from readme to docs and add link from the readme to docs

* drop copy on unix,and apply some style fixes from the conversations

* by mistake, I edit master insted of develop

* remove this file from pr

* Update README.md

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>

* copy table to readme

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2022-04-20 10:44:11 +09:00
Matthew Toohey
e452b97cdc AppImage (#2089)
* Add desktop entry file

Co-authored-by: NNB <n.at@aleeas.com>

* Add placeholder icon for AppImage

* Add AppImage step to release workflow

* Exclude grammar sources from AppImage

Co-authored-by: NNB <n.at@aleeas.com>
2022-04-20 10:43:52 +09:00
Michael Davis
c8cfd0b1a0 override nested arrays when merging TOML (#2145)
We merge the elements of arrays for the top-level array. For
`languages.toml`, this is the array of languages. For any nested
arrays, we simply take the `right` array as-is instead of using
the union of `left` and `right`.

closes #1000
2022-04-20 10:43:09 +09:00
Andrey Tkachenko
3a7bf1c40c Restore document state on completion cancel (#2096) 2022-04-20 10:42:33 +09:00
dependabot[bot]
cc68fa857d build(deps): bump toml from 0.5.8 to 0.5.9 (#2166)
Bumps [toml](https://github.com/alexcrichton/toml-rs) from 0.5.8 to 0.5.9.
- [Release notes](https://github.com/alexcrichton/toml-rs/releases)
- [Commits](https://github.com/alexcrichton/toml-rs/compare/0.5.8...0.5.9)

---
updated-dependencies:
- dependency-name: toml
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-04-19 08:54:20 +09:00
dependabot[bot]
c53ec95708 build(deps): bump fern from 0.6.0 to 0.6.1 (#2165)
Bumps [fern](https://github.com/daboross/fern) from 0.6.0 to 0.6.1.
- [Release notes](https://github.com/daboross/fern/releases)
- [Changelog](https://github.com/daboross/fern/blob/main/CHANGELOG.md)
- [Commits](https://github.com/daboross/fern/compare/fern-0.6.0...fern-0.6.1)

---
updated-dependencies:
- dependency-name: fern
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-04-19 08:54:09 +09:00
Paul Graydon
015a582d44 Add tokyonight theme (#2162) 2022-04-18 21:50:19 +05:30
Michael Davis
4e877de54d Fix Golang textobject queries (#2153)
* log textobject query construction errors

The current behavior is that invalid queries are discarded silently
which makes it difficult to debug invalid textobjects (either invalid
syntax or an update may have come through that changed the valid set
of nodes).

* fix golang textobject query

`method_spec_list` used to be a named node but was removed (I think
for Helix, it was when updated to pull in the support for generics).
Instead of a named node for the list of method specs we have a bunch
of `method_spec` children nodes now. We can match on the set of them
with a `+` wildcard.

Example go for this query:

    type Shape interface {
       area() float64
       perimeter() float64
    }

Which is parsed as:

    (source_file
      (type_declaration
        (type_spec
          name: (type_identifier)
          type: (interface_type
            (method_spec
              name: (field_identifier)
              parameters: (parameter_list)
              result: (type_identifier))
            (method_spec
              name: (field_identifier)
              parameters: (parameter_list)
              result: (type_identifier))))))
2022-04-18 23:14:48 +08:00
Michael Davis
449d1dfdfb prevent panic when receiving malformed LSP PublishDiagnostic (#2160)
Instead of panicing we can discard the malformed diagnostic. This
`.parse()` fails commonly when a non-conformant language server gives
a diagnostic with a location that breaks the spec:

    { "character": 0, "line": -1 }

can currently be returned by ElixirLS and the python LS. Other
messages in this block are discarded but this one feels special enough
to log.
2022-04-18 23:11:28 +08:00
Lucy
4b1fe367fa Remove dim attribute in onedark ui.linenr (#2155) 2022-04-18 15:52:26 +05:30
Ben Lee-Cohen
2bddec02e7 Fixing (in two ways) a small typo (#2156) 2022-04-18 13:12:47 +09:00
Kirawi
c2a40d9d52 Add support for local language configuration (#1249)
* add local configuration

* move config loading to Application::new

* simplify find_root_impl
2022-04-18 12:10:51 +09:00
Danillo Melo
be656c14e3 Ruby TextObjects and more file extensions (#2143) 2022-04-17 19:25:44 -05:00
Michael Davis
ad36a024da Update tree-sitters Erlang and HEEx (#2149) 2022-04-17 23:16:22 +05:30
Terry Brash
c45fb08a93 Add JavaScript control keywords (#2140) 2022-04-17 15:14:55 +09:00
AntonioLucibello
b67e0616dd Add command to extend selection to line above (#2117)
* added command to extend selection to line above

* fixed view not scrolling up when reaching top of the screen

* refactored shared code into separate impl
2022-04-17 12:26:14 +09:00
Robin Jadoul
33b7483db5 Send active diagnostics to LSP when requesting code actions. (#2005)
* Send active diagnostics to LSP when requesting code actions.

This allows for e.g. clangd to properly send the quickfix code actions
corresponding to those diagnostics as options.
The LSP spec v3.16.0 introduced an opaque `data` member that would allow
the server to persist arbitrary data between the diagnostic and the code
actions request, but this is not supported yet by this commit.

* Reuse existing range_to_lsp_range functionality
2022-04-17 12:05:23 +09:00
Thomas
2eca2901f3 Pipe typable command (#1972)
Co-authored-by: DeviousStoat <devious@stoat.com>
2022-04-17 12:03:47 +09:00
Andrey Tkachenko
dc8fef5dd3 Fixes #1991 LSP Auto-import (#2088) 2022-04-16 10:43:54 +09:00
Dr. David A. Kunz
b04c425c63 Make gutters configurable (#1967)
* config option line numbers none

* view tests

* added tests

* doc

* comment

* Make gutters configurable

* docu

* docu

* rm none docu

* order

* order

* precedence

* simpler

* rm todo

* fixed clippy

* order

* double quotes

* only allow diagnostics and line-numbers

* tests

* docu

* format

* rm short variant and more docu

* performance improvements

* typo

* rename
2022-04-16 10:41:25 +09:00
Evan Lecklider
450f348925 Add make file-type "mk" to languages.toml (#2120) 2022-04-15 12:15:17 -05:00
EmmChriss
50df924811 gdscript support (#1985) 2022-04-16 00:35:23 +09:00
nosa
893963df0a Additions to 'themes' section of docs (#2098)
* Added more descriptions to the themes part of the docs

* Add more descriptions to themes section of the docs

* capitalised first letters of descriptions in docs

Co-authored-by: Joe Mckay <jm@pop-os.localdomain>
2022-04-15 09:58:16 +09:00
Jared Ramirez
460e6a857b feat(languages): SQL (#2097) 2022-04-14 13:26:20 -05:00
Blaž Hrastnik
764adbdcf6 fix: prompt: pass through unmapped keys regardless of modifiers
Ctrl + Alt is apparently another common sequence for AltGr:
https://devblogs.microsoft.com/oldnewthing/20040329-00/?p=40003

Fixes #595
Fixes #2080
2022-04-13 15:19:42 +09:00
Michael Davis
4836bb38d3 add tree-sitter-heex
HEEx is a templating engine on top of Elixir's EEx templating
language specific to HTML that is included in Phoenix.LiveView
(though I think the plan is to eventually include it in base
Phoenix). It's a superset of EEx with some additional features
like components and slots.

The injections don't work perfectly because the Elixir grammar is
newline sensitive (the _terminator rule). See
https://github.com/elixir-lang/tree-sitter-elixir/issues/24
for more information.
2022-04-13 14:28:51 +09:00
Michael Davis
9d095e0fdc add tree-sitter-eex
EEx is an templating language for Elixir. Since the incremental
parsing refactor we can used combined injections which allows us
to add EEx support.
2022-04-13 14:28:51 +09:00
Michael Davis
4ac94a5c43 remove error highlighting for tree-sitter-elixir
This will become more important with the HEEx grammar being added.
Error highlighting with the Elixir grammar is a bit jumpy because
in some scenarios, a bit of missing syntax can force tree-sitter to
give up on error recovery and mark the entire tree as an error.
This ends up looking bad when editing. We don't typically highlight
error nodes so I'm inclined to leave it out of the highlights here.
2022-04-13 14:28:51 +09:00
Michael Davis
8c3c90198a update tree-sitter-elixir
The new revision handles a case that I come across often: a stab
clause (i.e. '->') with an empty right hand side:

    Enum.map(xs, fn x ->
    end)

The old version would parse the "end" token as an error.

This is technically valid syntax but more importantly it comes up
very often when editing, and the old revision would flicker between
the keyword highlight and the warning highlight.
2022-04-13 14:28:51 +09:00
scgtrp
740f565c80 Document values for editor.cursor-shape (#2094)
These are hinted at in the example config at the top (except `none`), but really should be listed explicitly near the option itself for clarity.
2022-04-13 13:00:17 +09:00
Ivan Tham
62283fdadb Make textobject select last paragraph (#1992)
* Make textobject select last paragraph

Last paragraph shoud be selected if the cursor was placed on the
whitespace paragraph part and `map` is done, otherwise it would do
nothing useful, but now we select backwards for the last paragraph
which behaves similarly to kakoune, making `map` useful for the last
paragraph with whitespace. Example usecase is to copy and paste last
ledger cli paragraph quickly by `mapyp` to duplicate last entry.

* Fix typo in core textobject

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2022-04-13 10:02:53 +09:00
Roland Kovacs
a0c6c45c1b Fix panic when using set-language on a scratch (#1996)
Skip launching a language server if a document doesn't have a valid URL.
2022-04-13 10:02:14 +09:00
Nirmal Patel
3deb1c9230 Add true or false checkbox in health output table (#1947)
hx --health output table's second and third columns were not showing
symbols like ✔ or ✘ to indicate whether LSP or DAP binaries were found.
This change adds these symbols to improve accessibility.

Fixes #1894

Signed-off-by: Nirmal Patel <npate012@gmail.com>
2022-04-12 17:21:16 +09:00
Benedikt Müller
1fb6144432 Add shell completion (#2022)
* Add shell completion

* Add shell completion to release
2022-04-12 17:10:21 +09:00
Omnikar
660e0e44b2 Add :write! to create nonexistent subdirectories (#1839)
* Make `:write` create nonexistent subdirectories

Prompting as to whether this should take place remains a TODO.

* Move subdirectory creation to new `w!` command
2022-04-12 16:52:54 +09:00
unrelentingtech
d5c0866978 Apply ui.gutter style to empty gutters (#2032)
The unstyled column on the left from the diagnostics_or_breakpoints gutter
looks sad if you want to add a background to all gutters. Let's fix this.
2022-04-12 16:48:30 +09:00
dependabot[bot]
f3dcb4034f build(deps): bump lsp-types from 0.92.1 to 0.93.0 (#2084)
Bumps [lsp-types](https://github.com/gluon-lang/lsp-types) from 0.92.1 to 0.93.0.
- [Release notes](https://github.com/gluon-lang/lsp-types/releases)
- [Changelog](https://github.com/gluon-lang/lsp-types/blob/master/CHANGELOG.md)
- [Commits](https://github.com/gluon-lang/lsp-types/compare/v0.92.1...v0.93.0)

---
updated-dependencies:
- dependency-name: lsp-types
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-04-12 12:12:30 +09:00
dependabot[bot]
6530d452a0 build(deps): bump encoding_rs from 0.8.30 to 0.8.31 (#2083)
Bumps [encoding_rs](https://github.com/hsivonen/encoding_rs) from 0.8.30 to 0.8.31.
- [Release notes](https://github.com/hsivonen/encoding_rs/releases)
- [Commits](https://github.com/hsivonen/encoding_rs/compare/v0.8.30...v0.8.31)

---
updated-dependencies:
- dependency-name: encoding_rs
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-04-12 12:12:03 +09:00
dependabot[bot]
14079bd17b build(deps): bump cachix/install-nix-action from 16 to 17 (#2081)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-04-11 18:34:39 -05:00
dependabot[bot]
f9ddc8a9ac build(deps): bump actions/download-artifact from 2 to 3 (#2082)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-04-11 18:34:29 -05:00
Aral Balkan
7cb6e07ba0 Improve Dracula Theme selections (#2075) (#2077) 2022-04-11 09:21:41 -05:00
Michael Davis
3d79c60a1f Rewrite Language Support docs (#2065) 2022-04-10 23:20:05 +05:30
gavynriebau
562874a720 Add command for picking files from CWD (#1600)
The `file_picker_at_current_directory` command opens the file picker at
the current working directory (CWD). This can be useful when paired with
the built-in `:cd` command which changes the CWD.

It has been mapped to `space F` by default.
2022-04-10 11:30:09 +09:00
Michael Davis
494306ad7a add tree-sitter-embedded-template (erb & ejs) (#2055)
After the incremental parsing rewrite for injections (which was released
in 22.03 https://helix-editor.com/news/release-22-03-highlights/#incremental-injection-parsing-rewrite),
we can now do combined injections which lets us pull in some templating
grammars. The most notable of those is embedded-template - a pretty
straightforward grammar that covers ERB and EJS.

The grammar and highlights queries are shared between the two but they have
different injections.
2022-04-10 08:23:06 +09:00
Michael Davis
78b1600943 Improve documentation on Language Server installation (#2037) 2022-04-09 12:17:32 +05:30
Kurenshe Nurdaulet
0b410b0a16 Add default language server for Vue (#2043) 2022-04-08 21:04:22 -05:00
Evan Relf
7779dbfcb8 docs: Quote TOML keys containing dots (#2040) 2022-04-08 17:21:52 -05:00
Sam Sartor
209ec4468b Add dracula at night theme (#2008) 2022-04-08 15:53:12 -05:00
unrelentingtech
7f461895b0 Add language server command for OCaml (#2035) 2022-04-08 15:02:25 -05:00
Aaron Housh
9caf7c0d5a Add swift language (#2033) 2022-04-08 13:10:37 -05:00
Karl Grasegger
8e12fd5290 PHP roots and languageserver improvements (#2031)
Co-authored-by: Karl Grasegger <karl.grasegger@gebruederheitz.de>
2022-04-08 12:57:46 -05:00
Michael Davis
19ff21eaa2 Remove usage of format ident feature from tests (#2028) 2022-04-08 21:26:50 +05:30
David
61d1684a32 Add default language server for CSS (#2025) 2022-04-08 10:06:54 -05:00
David
22629ca211 Add default language server for JSON (#2024) 2022-04-08 10:06:41 -05:00
David
b5efb9d66c Add default language server for HTML (#2018) 2022-04-08 08:36:10 -05:00
Gaeulbyul
581ac5660f Fix typo (pallete -> palette) (#2020) 2022-04-08 08:35:11 -05:00
Kirawi
2d4f94eb27 [dark_plus] update tag and ui.menu.selected colors (#2014) 2022-04-07 21:08:16 -05:00
Gokul Soumya
420b5b8301 Compute style only once per source highlight event (#1966)
During a single HighlightEvent::Source, the highlight spans do not
change and we can merge them into a single style at the beginning
of the event and use it instead of re-computing it for every grapheme
2022-04-08 09:42:57 +09:00
Matthew Toohey
31c468ab95 add languages r and rmarkdown (#1998)
* add languages `r` and `rmarkdown`

* r: fix highlights

* rmarkdown: add eof in queries

* rmarkdown: update lang-support.md

* r: fix highlight query precedence
2022-04-08 09:30:44 +09:00
tomKPZ
d37369c1e0 Add paragraph textobject to match infobox (#1969) 2022-04-07 09:11:14 +08:00
Michael Davis
b03421a8c0 remove hardcoded '/' from grammar source path (#1986) 2022-04-07 00:32:00 +09:00
Michael Davis
275c05008f fix keymap doc typo for 'delete' in insert-mode (#1990)
closes #1980
see also #1180
2022-04-07 00:31:40 +09:00
Kirawi
b333186721 [dark_plus] update markup colors (#1989) 2022-04-07 00:31:28 +09:00
bootradev
0eb87996a8 add boo_berry theme (#1962) 2022-04-06 01:06:51 +09:00
VuiMuich
eb84d9493c add language ron (#1925) 2022-04-05 07:39:22 -05:00
Danilo Spinella
6b80cb8a77 Fix toggle_comments command on multiple selections (#1882) 2022-04-05 10:01:58 +09:00
Roland Kovacs
d962e06e91 Add runtime language configuration (#1794) (#1866)
* Add runtime language configuration (#1794)

* Add set-language typable command to change the language of current buffer.
* Add completer for available language options.

* Update set-language to refresh language server as well

* Add language id based config lookup on `syntax::Loader`.
* Add `Document::set_language3` to set programming language based on language
  id.
* Update `Editor::refresh_language_server` to try language detection only if
  language is not already set.

* Remove language detection from Editor::refresh_language_server

* Move document language detection to where the scratch buffer is saved.
* Rename Document::set_language3 to Document::set_language_by_language_id.

* Remove unnecessary clone in completers::language
2022-04-05 09:56:14 +09:00
Ivan Tham
6fc6f87260 Fix next paragraph logic over muliple blank lines (#1951)
Fix #1928
2022-04-05 09:43:14 +09:00
Ivan Tham
e7beb32fd7 Add paragraph to last motion (#1956)
Fix #1954
2022-04-05 09:43:04 +09:00
Ivan Tham
d3c8286ea0 Bump crossterm to 0.32.2 (#1955)
Deduplicates mio dependency which results no crate duplication now and
7 lesser crate for cargo to build.
2022-04-05 09:41:28 +09:00
Rose Hudson
f8c83f9885 clear terminal after switching to alternate screen
when using helix over mosh, the screen doesn't get cleared and
characters get left all over the place until they are overwritten. with
this change, the screen gets properly cleared as soon as helix starts
2022-04-04 16:41:11 +09:00
Kirawi
3fc4ea2938 [dark_plus] remove ui.text background (#1950) 2022-04-03 17:59:02 -05:00
Dr. David A. Kunz
9782204f73 Add typed commands buffer-next and buffer-previous (#1940) 2022-04-03 17:56:46 +05:30
Ivan Tham
ec21de0844 Add missing # back to test output 2022-04-03 00:46:53 +09:00
Ivan Tham
8b91ecde40 Rename _para to _paragraph 2022-04-03 00:46:53 +09:00
Gokul Soumya
64c2490f2d Refactor test print to be more readable 2022-04-03 00:46:53 +09:00
Ivan Tham
45b76db506 Change test mark from ^@ to #[|]# 2022-04-03 00:46:53 +09:00
Ivan Tham
8350ee9a0e Add paragraph textobject
Change parameter/argument key from p to a since paragraph only have p
but parameter are also called arguments sometimes and a is not used.
2022-04-03 00:46:53 +09:00
Ivan Tham
e2a6e33b98 Add next paragraph 2022-04-03 00:46:53 +09:00
Ivan Tham
8b02bf2ea8 Add (prev) paragraph motion
Also improved testing facility.

Fix #1580
2022-04-03 00:46:53 +09:00
Lauri Gustafsson
e4561d1dde Add texlab language server for latex (#1922) 2022-04-02 09:00:05 -05:00
Simon H
36d1df71fc Added checkmarks to health.rs output, Resolves #1894 (#1918)
* Added checkmarks to health.rs output

* replaced found/not found text with checkmarks
2022-04-02 17:32:36 +09:00
Michael Davis
ffdc2f1793 separate JSX queries from javascript (#1921)
It looks like a24fb17b2a (and
855e438f55) broke the typescript
highlights because typescript

    ; inherits: javascript

but it doesn't have those named nodes in its grammar.

So instead we can separate out JSX into its own language and copy
over everything from javascript and supplement it with the new
JSX highlights. Luckily there isn't too much duplication, just the
language configuration parts - we can re-use the parser with the
languages.toml `grammar` key and most of the queries with `inherits`.
2022-04-02 10:07:35 +09:00
joezak11
deb7ee6595 Update bash tree sitter (#1917) 2022-04-01 08:48:39 -05:00
jeepee
85c23b31de Avoid unnecessary clone when formatting error (#1903)
Instead of first cloning the query and then allocating again to format
the error, format the error using a reference to the query.
2022-04-01 22:16:51 +09:00
jeepee
8165febe23 Fix start-position of next search (#1904)
The search implementation would start searching at the next grapheme
boundary after the previous selection. In case the next occurence of the
needle is immediately after the current selection, this occurence would
not be found (without wraparound) because the first grapheme is skipped.

The correct approach is to use the ensure_grapheme_boundary functions instead
of using the functions that skip unconditionally to the next grapheme.
2022-04-01 22:16:09 +09:00
antoyo
47fe739757 Jump to the next number on the line before incrementing (#1778)
* Jump to the next number on the line before incrementing

Partially fix #1645

* Refactor to avoid duplicating find_nth_next
2022-04-01 22:14:37 +09:00
Blaž Hrastnik
855e438f55 jsx: Add special highlighting to component names 2022-04-01 17:18:44 +09:00
Blaž Hrastnik
a24fb17b2a Add JSX highlighting queries 2022-04-01 17:14:25 +09:00
Amine Hmida
d0ff2ffd89 Add support for jsx (#1906)
* Add support for javascriptreact language

* Add support for jsx files
2022-04-01 17:08:34 +09:00
جاد
a9635659f7 Reintroduce win32yank as a clipboard provider on Linux for WSL2 + Windows 10 (#1912)
* feat(clipboard): reintroduce win32yank for wsl2 linux

* refactor(clipboard): adjust win32yank position to not interrupt wayland/x11

Co-authored-by: jiqb <gthbji@ml1.net>
2022-04-01 11:35:47 +09:00
Triton171
6bb2298391 Fix an issue that caused an empty indentation query to be used instead of using the fallback method of copying the indentation from the current line. (#1908)
Co-authored-by: Triton171 <triton0171@gmail.com>
2022-04-01 11:27:06 +09:00
Blaž Hrastnik
8adf0c1b3a lsp: Implement support for workspace_folders (currently just one)
Refs #1898
2022-04-01 11:20:41 +09:00
Blaž Hrastnik
236c6b7707 fix: copy_selections was broken with selections (not cursors) 2022-04-01 10:11:44 +09:00
Marcin Puc
924462edda Add install instructions for Void Linux (#1911) 2022-03-31 14:55:55 -05:00
Blaž Hrastnik
84e799f0e4 fix: Some LSPs still want rootPath, so provide it
Refs #1898
2022-03-31 17:45:51 +09:00
Rohan Jain
5d61631507 Resolve conflicts between prompt/picker bindings (#1792)
Currently, the picker's re-using a few bindings which are also present
in the prompt. This causes some editing behaviours to not function on
the picker.

**Ctrl + k** and **Ctrl + j**
This should kill till the end of the line on prompt, but is overridden
by the picker for scrolling. Since there are redundancies (`Ctrl + p`,
`Ctrl + n`), we can remove it from picker.

**Ctrl + f** and **Ctrl + b**
This are used by the prompt for back/forward movement. We could modify
it to be Ctrl + d and Ctrl + u, to match the `vim` behaviour.
2022-03-31 16:51:11 +09:00
Michael Davis
ef91b6500c set VERSION file to dev (#1883)
* set VERSION file to dev

* bump to 22.05-dev
2022-03-31 16:31:38 +09:00
Blaž Hrastnik
d15c875214 Add a TODO for the future 2022-03-31 15:59:09 +09:00
Blaž Hrastnik
ab7885e934 fix: copy_selection needs to account for to() being exclusive
Fixes #1367
Fixes #1590
2022-03-31 15:59:09 +09:00
Max
4eed4c26e9 Use fromTOML on Nix >= 2.6.0 (#1892) 2022-03-30 11:28:05 -05:00
Triton171
58758fee61 Indentation rework (#1562)
* WIP: Rework indentation system

* Add ComplexNode for context-aware indentation (including a proof of concept for assignment statements in rust)

* Add switch statements to Go indents.toml (fixes the second half of issue #1523)
Remove commented-out code

* Migrate all existing indentation queries.
Add more options to ComplexNode and use them to improve C/C++ indentation.

* Add comments & replace Option<Vec<_>> with Vec<_>

* Add more detailed documentation for tree-sitter indentation

* Improve code style in indent.rs

* Use tree-sitter queries for indentation instead of TOML config.
Migrate existing indent queries.

* Add documentation for the new indent queries.
Change xtask docgen to look for indents.scm instead of indents.toml

* Improve code style in indent.rs.
Fix an issue with the rust indent query.

* Move indentation test sources to separate files.
Add `#not-kind-eq?`, `#same-line?` and `#not-same-line` custom predicates.
Improve the rust and c indent queries.

* Fix indent test.
Improve rust indent queries.

* Move indentation tests to integration test folder.

* Improve code style in indent.rs.
Reuse tree-sitter cursors for indentation queries.

* Migrate HCL indent query

* Replace custom loading in indent tests with a designated languages.toml

* Update indent query file name for --health command.

* Fix single-space formatting in indent queries.

* Add explanation for unwrapping.

Co-authored-by: Triton171 <triton0171@gmail.com>
2022-03-31 00:08:07 +09:00
Blaž Hrastnik
c18de0e8f0 fix: Don't rely on FormattingOptions::default()
Refs #1884
2022-03-30 15:19:21 +09:00
Nirmal Patel
8702aaaefc Handle BrokenPipe when piping hx --health through head (#1876)
Co-authored-by: Gokul Soumya <gokulps15@gmail.com>
2022-03-30 10:39:25 +05:30
Michael Davis
7cd6050235 add tree-sitter-gleam 2022-03-30 13:24:53 +09:00
Michael Davis
1819478940 update tree-sitter-elixir
news:

- tree-sitter-elixir now powers Elixir syntax highlighting on github.com
- GitHub now supports code-navigation for Elixir repos via
  tree-sitter-elixir

changes:

- modules now use the `@module` highlight, which was added upstream to
  tree-sitter
    - it seems appropriate to use `@namespace` to follow helix convention
- added nullary range operator (e.g. `Enum.to_list(..) == []`), a new syntax
  for elixir 1.14
- a fix for stab clause nodes mis-highlighting when the right hand side of
  the stab clause contained multiple simple expressions
2022-03-30 13:24:53 +09:00
Michael Davis
e2a50711d5 update tree-sitter-erlang
changes:

- typed fields within records which do not declare a default
  value are now correctly highlighted as record fields
- the EEP49 'maybe' form is now parsed
- fixes for highlights for 'begin' and 'after' tokens
2022-03-30 13:24:53 +09:00
Marcin Puc
f2dd3d4469 Avoid using the format ident Rust feature (#1881) 2022-03-30 09:08:30 +09:00
Michael Davis
c8082a1133 update screenshot (#1879) 2022-03-30 00:16:57 +09:00
Michael Davis
d4e45fd479 changelog notes for 22.03 (#1830) 2022-03-29 22:15:00 +09:00
Blaž Hrastnik
6c276d7868 Revert "Resize is not necessary inside SIGCONT, handled by render()"
Fixes #1877

This reverts commit 85264a861a.
2022-03-29 22:08:19 +09:00
Michael Davis
838cfcc7cd publish a source tarball with version and grammars (#1875)
* publish a source tarball with version and grammars

* include_str! the release version from a VERSION file

* remove setting of .version file from tag

don't need this anymore since the file is checked into source
2022-03-29 14:34:19 +09:00
dependabot[bot]
6e7c287371 build(deps): bump log from 0.4.14 to 0.4.16 (#1874)
Bumps [log](https://github.com/rust-lang/log) from 0.4.14 to 0.4.16.
- [Release notes](https://github.com/rust-lang/log/releases)
- [Changelog](https://github.com/rust-lang/log/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/log/commits)

---
updated-dependencies:
- dependency-name: log
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-03-29 09:07:17 +09:00
dependabot[bot]
3af0a7f3cb build(deps): bump smartstring from 1.0.0 to 1.0.1 (#1873)
Bumps [smartstring](https://github.com/bodil/smartstring) from 1.0.0 to 1.0.1.
- [Release notes](https://github.com/bodil/smartstring/releases)
- [Changelog](https://github.com/bodil/smartstring/blob/master/CHANGELOG.md)
- [Commits](https://github.com/bodil/smartstring/compare/v1.0.0...v1.0.1)

---
updated-dependencies:
- dependency-name: smartstring
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-03-29 09:07:07 +09:00
Max
b63b37d5a0 grammars.nix: use github type for fetchTree where possible (#1872) 2022-03-28 16:50:18 -05:00
Blaž Hrastnik
511f37c736 clipboard: fix import on macOS 2022-03-28 11:08:38 +09:00
Blaž Hrastnik
33510d60f4 cargo fmt 2022-03-28 11:05:26 +09:00
Blaž Hrastnik
a516f5881b Address clippy lint 2022-03-28 11:03:42 +09:00
Blaž Hrastnik
8611c5b84e Refactor clipboard to make it easier to feature gate std::process 2022-03-28 11:02:56 +09:00
Blaž Hrastnik
4940db3e2d Make truncate_start a builder method instead 2022-03-28 11:02:49 +09:00
Blaž Hrastnik
20cf75dfa1 Strip some more params 2022-03-28 11:02:39 +09:00
Blaž Hrastnik
1849ad1fde Clean up global search 2022-03-28 11:02:32 +09:00
Blaž Hrastnik
92bb312f0f Make line a private property 2022-03-28 11:02:26 +09:00
Blaž Hrastnik
96a4eb8483 Remove more push_layer calls 2022-03-28 11:02:21 +09:00
Blaž Hrastnik
5c162ef995 Make regex_prompt directly call cx.push_layer 2022-03-28 11:02:13 +09:00
Blaž Hrastnik
83b3272166 This doesn't need to be mut 2022-03-28 11:02:07 +09:00
Blaž Hrastnik
9a6ee88e66 Split off dap event handlers into helix-view to allow reuse 2022-03-28 11:01:59 +09:00
Blaž Hrastnik
85264a861a Resize is not necessary inside SIGCONT, handled by render() 2022-03-28 11:01:53 +09:00
Gokul Soumya
7b3a3d562c Move top level lsp config to editor.lsp (#1868)
* Move top level lsp config to editor.lsp

This is mainly done to accomodate the new lsp.signature-help config
option that will be introduced in https://github.com/helix-editor/helix/pull/1755
which will have to be accessed by commands. The top level config
struct is split and moved to different places, making the relocation
necessary

* Revert rebase slipup
2022-03-28 10:11:52 +09:00
Joe
bee05dd32a Add refresh-config and open-config command (#1803)
* Add refresh-config and open-config command

* clippy

* Use dynamic dispatch for editor config

* Refactor Result::Ok to Ok

* Remove unused import

* cargo fmt

* Modify config error handling

* cargo xtask docgen

* impl display for ConfigLoadError

* cargo fmt

* Put keymaps behind dyn access, refactor config.load()

* Update command names

* Update helix-term/src/application.rs

Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>

* Switch to unbounded_channel

* Remove --edit-config command

* Update configuration docs

* Revert "Put keymaps behind dyn access", too hard

This reverts commit 06bad8cf49.

* Add refresh for keys

* Refactor default_keymaps, fix config default, add test

* swap -> store, remove unneeded clone

* cargo fmt

* Rename default_keymaps to default

Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
2022-03-25 18:05:20 +09:00
Narazaki Shuji
309f2c2c8e Revise the color for ui.cursor.match (#1862)
- bogster.toml
 - solarized_dark.toml
 - solarized_light.toml
 - spacebones_light.toml
2022-03-25 15:57:25 +09:00
Jared Ramirez
22ba668fad Fix Rescript hightlights query (#1863) 2022-03-23 14:03:58 -05:00
Blaž Hrastnik
919ac7ba15 Handle RPC returning an invalid call 2022-03-23 16:16:19 +09:00
Slin Lee
3e78b8fdad Add syntax highlighting for Solidity (#1854) 2022-03-22 11:38:49 -05:00
Slin Lee
79477ec6e7 Fix typo in query parsing error message (#1856) 2022-03-22 16:22:57 +05:30
Slin Lee
3c79bf5117 Add LSP support for Solidity (#1848)
* Add LSP support for Solidity

This requires a recent version of Solidity 0.8.11+

* Add Solidity to docs

* Update the docs
2022-03-22 11:22:34 +09:00
dependabot[bot]
5d7fa57754 build(deps): bump lsp-types from 0.92.0 to 0.92.1 (#1852)
Bumps [lsp-types](https://github.com/gluon-lang/lsp-types) from 0.92.0 to 0.92.1.
- [Release notes](https://github.com/gluon-lang/lsp-types/releases)
- [Changelog](https://github.com/gluon-lang/lsp-types/blob/master/CHANGELOG.md)
- [Commits](https://github.com/gluon-lang/lsp-types/compare/v0.92.0...v0.92.1)

---
updated-dependencies:
- dependency-name: lsp-types
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-03-22 11:14:43 +09:00
dependabot[bot]
1de99cf46a build(deps): bump which from 4.2.4 to 4.2.5 (#1851)
Bumps [which](https://github.com/harryfei/which-rs) from 4.2.4 to 4.2.5.
- [Release notes](https://github.com/harryfei/which-rs/releases)
- [Commits](https://github.com/harryfei/which-rs/compare/4.2.4...4.2.5)

---
updated-dependencies:
- dependency-name: which
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-03-22 11:14:35 +09:00
dependabot[bot]
585347aca0 build(deps): bump actions/cache from 2.1.7 to 3 (#1850)
Bumps [actions/cache](https://github.com/actions/cache) from 2.1.7 to 3.
- [Release notes](https://github.com/actions/cache/releases)
- [Commits](https://github.com/actions/cache/compare/v2.1.7...v3)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-03-22 11:14:14 +09:00
zetashift
7eb013c6fb Initial basic Org markup support thanks to tree-sitter-org (#1845) 2022-03-20 17:14:30 -05:00
Blaž Hrastnik
a7ee9f74f7 No need for KeymapResult anymore since we can query .sticky() 2022-03-20 16:03:14 +09:00
Blaž Hrastnik
7909d6f05e keymap: Store pending/sticky on the root level 2022-03-20 16:03:13 +09:00
Michael Davis
cfd992b151 update tree-sitter-git-commit (#1838)
changes:

- any text following a (scissors) is now contained in one (message)
    - this vastly improves performance on large verbose commits:
      no more slowness on huge commits
2022-03-19 14:43:13 +09:00
Ivan Tham
533cca7195 Improve bug report template (#1826) 2022-03-18 14:06:56 +09:00
Michael Davis
cb7b674f87 cleanup changelog markup (#1829) 2022-03-18 11:53:47 +09:00
Blaž Hrastnik
0b9620108d ropey 1.4.1 fixes the issue 2022-03-17 12:03:15 +09:00
Blaž Hrastnik
2376fc875e Temporarily turn on unicode-lines
Ropey's non-unicode lines impl has some bugs still
2022-03-17 10:53:50 +09:00
Blaž Hrastnik
16e2b2e36b ropey 1.4.0 is out! 2022-03-17 09:29:47 +09:00
Blaž Hrastnik
f67e1ee172 Put esoteric line endings behind a feature flag 2022-03-17 09:29:47 +09:00
Blaž Hrastnik
b4a282fd36 Configure ropey to only use CR/CRLF line breaks by default
Fixes #1643
2022-03-17 09:29:47 +09:00
Blaž Hrastnik
59f05088b9 Optimize rendering by using Ropey::byte_slice
This avoids costly conversions via byte_to_char (which are then
reversed back into bytes internally in Ropey).

Reduces time spent in slice/byte_to_char from ~24% to ~5%.
2022-03-17 09:29:47 +09:00
Michael Davis
c6bd105484 fix enum definition for use-grammars selections (#1818)
See https://github.com/helix-editor/helix/discussions/1817

It looks like we need the enums to have the `only`/`except` fields in order
to deserialize correctly.
2022-03-16 18:26:22 +09:00
Blaž Hrastnik
20a132e36f Update dependencies (crossterm 0.23.1)
Fixes #1654
2022-03-16 10:40:07 +09:00
Gokul Soumya
2b0835b295 Refactor :set to parse by deserializing values (#1799)
* Refactor :set to parse by deserializing values

* Implement serialize for idle_timeout config
2022-03-15 17:04:22 +09:00
ChrHorn
0902ede7b1 simplify Julia config (#1811)
* simplify Julia config

* remove trailing whitespace
2022-03-15 10:41:36 +09:00
dependabot[bot]
9400d74307 build(deps): bump tree-sitter from 0.20.5 to 0.20.6 (#1813)
Bumps [tree-sitter](https://github.com/tree-sitter/tree-sitter) from 0.20.5 to 0.20.6.
- [Release notes](https://github.com/tree-sitter/tree-sitter/releases)
- [Commits](https://github.com/tree-sitter/tree-sitter/compare/v0.20.5...v0.20.6)

---
updated-dependencies:
- dependency-name: tree-sitter
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-03-15 09:16:14 +09:00
dependabot[bot]
be2b452a39 build(deps): bump regex from 1.5.4 to 1.5.5 (#1812)
Bumps [regex](https://github.com/rust-lang/regex) from 1.5.4 to 1.5.5.
- [Release notes](https://github.com/rust-lang/regex/releases)
- [Changelog](https://github.com/rust-lang/regex/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/regex/compare/1.5.4...1.5.5)

---
updated-dependencies:
- dependency-name: regex
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-03-15 09:16:04 +09:00
Joe
c0dbd6dc3f Add horizontal and vertical split scratch buffers (#1763)
Make subcommand name more descriptive

Fix vsplit completer

Run cargo xtask docgen
2022-03-14 11:47:52 +09:00
Gokul Soumya
85492e587c Deploy docs for master separately (#1783)
* Deploy docs for master separately

* Output docs for every tagged release

* Update .github/workflows/gh-pages.yml

Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
2022-03-14 11:46:40 +09:00
Rohan Jain
1ac576f2b3 Handle panic on move within empty picker (#1786)
When the picker results output is empty, movement actions result in a panic:
```
thread 'main' panicked at 'attempt to calculate the remainder with a divisor of zero', helix-term/src/ui/picker.rs:420:31
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
```

This could be a no-op instead when the matches length is zero.
2022-03-14 11:46:23 +09:00
Ivan Tham
29d6a5a9b6 Perform extend line on every selection (#1804)
Currently `x` only affect the current selection, but this will make it
affect every selection so `x` can be more useful with multi-cursors.
2022-03-14 11:45:45 +09:00
Ivan Tham
3d76fa0b81 Match in visual use head not anchor (#1805)
Currently match is finding the match based on the anchor rather than the
head (cursor) so this behavior is rather unexpected when user is doing
a match but a different item was matched instead when the selection is
more than one character.
2022-03-14 11:45:22 +09:00
Michael Davis
43fc073cb3 ci: configure restore-keys for caches (#1806)
`restore-keys` is a configuration option for the actions/cache action
which specifies fallback behavior. The [docs][docs] say it best:

> When a cache miss occurs, the action searches for alternate keys
> called `restore-keys`.
>
> If you provide `restore-keys`, the `cache` action sequentially
> searches for any caches that match the list of `restore-keys`.
> ... If there are no exact matches, the action searches for partial
> matches of the restore keys. When the action finds a partial match,
> the most recent cache is restored to the `path` directory.

So this improves caching when there's a miss. For example if I edit
`.github/workflows/languages.toml`, the current behavior is that the
cache for downloaded grammars will miss and all of them will need to
be fetched again. With `restore-keys`, we use the latest published
cache as 'good enough', we'll fetch whatever grammars changed, and
then at the end we publish a new cache under the new hash.

[docs]: https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#example-using-the-cache-action
2022-03-14 11:44:51 +09:00
Blaž Hrastnik
c94c0d9f1c minor: occurance -> occurrence 2022-03-14 11:43:52 +09:00
Blaž Hrastnik
610ce93600 fix #1808 2022-03-14 11:34:21 +09:00
Narazaki Shuji
05161aa85e Fix: insert_register (#1751)
- set register name correctly
 - use autoinfo to display register contents
 - call `paste` with `Paste::Cursor`
2022-03-13 17:23:55 +09:00
Daniel S Poulin
e8cc7ace75 Update keymap documentation in the book (#1745)
* Add missing key bindings to keymap docs

* Add a note about readline bindings in insert mode

* Rewrite section on selection extend mode

We seem to have settled on this model, so no reason to say in the
docs that this is experimental. I also don't think we have any
movements that don't obey extend mode left.

* Fix table formatting

* Fix missing command for command palette binding

* Fix missed capitalization of descriptions in keymap docs

* Be consistent with multiple bindings in keymap docs

* Fix differently marked up commands in keymap docs

* Make special key capitalization consistent

Co-authored-by: Michael Davis <michael.davis@nfiindustries.com>

* Fix extra space in docs

Co-authored-by: Michael Davis <michael.davis@nfiindustries.com>

* A few more capitalizations of special keys in keymap docs

* Move a selection manipulation key map to the appropriate section in docs

* Move minor mode entry bindings to the minor modes section of keymap docs

* Add note about default register used in search commands in keymap docs

* Fix formatting of rebased addition

* Remove note about potential removal of select mode

It's been decided since to keep it

Co-authored-by: Michael Davis <michael.davis@nfiindustries.com>
2022-03-13 17:12:13 +09:00
Philipp Mildenberger
6fdf5d0920 C# highlighting improvements (#1795) 2022-03-12 12:06:56 -06:00
nibon7
43997f1936 Use ^ and $ to match the beginning and end of a line when searching (#1790)
Fixes #1737

Signed-off-by: nibon7 <nibon7@163.com>
2022-03-12 16:05:50 +09:00
Michael Davis
61828ea519 use 'cargo test --workspace' in CI (#1793)
79caa7b72b setup helix-term as the
default workspace member (which I believe is done to avoid building
xtask on every compile). This changes the behavior of 'cargo test'
though so that it only runs helix-term tests by default. To run all
tests, we switch to 'cargo test --workspace'.
2022-03-12 16:04:52 +09:00
Aaron Housh
0712eb3e3b Add csharp lsp support (#1788)
* add csharp lsp support

* remove hostPID

* update docs
2022-03-12 09:19:31 +09:00
Rohan Jain
cf8f59ddd0 theme: Use distinct colors for match pair and cursor for gruvbox (#1791) 2022-03-11 17:49:21 +05:30
Michael Davis
98851d1594 remove stray 'println!' from grammar building function (#1785) 2022-03-11 12:28:34 +09:00
Michael Davis
37fed4de80 fix '--grammar' flag in help text (#1784) 2022-03-10 22:33:51 +09:00
Blaž Hrastnik
5eb9a0167f Remove remaining helix-syntax leftovers 2022-03-10 17:46:29 +09:00
Michael Davis
94203a97e5 update revision for tree-sitter-rescript
Looks like this was rebased a few hours ago and now the 789a171
revision no longer exists.
2022-03-10 17:31:57 +09:00
Michael Davis
e01c53551d flake: use builtins.fetchTree to shallow-clone grammar repos
Here we perform a shallow fetch using builtins.fetchTree. In order
to make this work, we need to specify the `ref' for any repository
that doesn't have `master' as its default branch (I'm not sure why
this limitation exists since we don't need this when performing
the shallow fetch in `--grammar build')

This `ref' field is ignored by helix, so I have left it undocumented
for now, but I could be open to documenting it.
2022-03-10 17:31:57 +09:00
Michael Davis
7044d7d804 rename '--fetch/build-grammars' flags into '--grammar fetch/build'
The old flags were a bit long. --grammar is also aliased to -g to make
it even easier.
2022-03-10 17:31:57 +09:00
Michael Davis
37520f46ae fetch and build grammars with nix in flake
This commit replaces the out-of-date builder in the flake which relied
on submodules for fetching and the compiler for building. Now we
disable fetching and building explicitly with the environment variable
and then use builtins.fetchGit and a derivation mostly derived from
upstream to compile the grammars.

Anecdotally, this is still quite slow as builtins.fetchGit does not
seem to do shallow clones. I'm not sure I see a way around it though
without recording sha256s, which seems cumbersome.
2022-03-10 17:31:57 +09:00
Michael Davis
b157c5a8a4 fetch and compile tree-sitter grammars in helix-term build
This restores much of the behavior that existed before this PR:
helix will build the grammars when compiling. The difference is that
now fetching is also done during the build phase and is done much
more quickly - both shallow and in parallel.
2022-03-10 17:31:57 +09:00
Michael Davis
6fcab90d16 only fetch git-sourced grammars
This is a bit of a micro-optimization: in the current setup we waste
a thread in the pool for a local grammar only to println! a message
saying we're skipping fetching because it's a local grammar.
2022-03-10 17:31:57 +09:00
Skyler Hawthorne
a229f405cc shallow clone 2022-03-10 17:31:57 +09:00
Skyler Hawthorne
31b7596f09 fix context in error 2022-03-10 17:31:57 +09:00
Michael Davis
4fc991fdec migrate grammar fetching/building code into helix-loader crate
This is a rather large refactor that moves most of the code for
loading, fetching, and building grammars into a new helix-loader
module. This works well with the [[grammars]] syntax for
languages.toml defined earlier: we only have to depend on the types
for GrammarConfiguration in helix-loader and can leave all the
[[language]] entries for helix-core.
2022-03-10 17:31:57 +09:00
Michael Davis
08ee949dcb add 'use-grammars' to languages.toml
The vision with 'use-grammars' is to allow the long-requested feature
of being able to declare your own set of grammars that you would like.
A simple schema with only/except grammar names controls the list
of grammars that is fetched and built. It does not (yet) control which
grammars may be loaded at runtime if they already exist.
2022-03-10 17:31:57 +09:00
Michael Davis
db3470d973 ensure rust grammar is available in CI 2022-03-10 17:31:57 +09:00
Michael Davis
8081e9f052 replace all submodule documentation with flags documentation 2022-03-10 17:31:57 +09:00
Michael Davis
00b2d616eb implement build_grammars and fetch_grammars
build_grammars adapts the functionality that previously came from
helix-syntax to be used at runtime from the command line flags.

fetch_grammars wraps command-line git to perform the same actions
previously done in the scripts in #1560.
2022-03-10 17:31:57 +09:00
Michael Davis
8330f6af20 add --fetch-grammars and --build-grammars CLI flags 2022-03-10 17:31:57 +09:00
Michael Davis
c1f677ff75 rename tree_sitter_library in LanguageConfig to 'grammar'
This is not strictly speaking necessary. tree_sitter_library was used by
just one grammar: llvm-mir-yaml, which uses the yaml grammar. This will
make the language more consistent, though. Each language can explicitly
say that they use Some(grammar), defaulting when None to the grammar that
has a grammar_id matching the language's language_id.
2022-03-10 17:31:57 +09:00
Michael Davis
eeb3f8e963 migrate helix-syntax crate into helix-core and helix-term
helix-syntax mostly existed for the sake of the build task which
checks and compiles the submodules. Since we won't be relying on
that process anymore, it doesn't end up making much sense to have
a very thin crate just for some functions that we could port to
helix-core.

The remaining build-related code is moved to helix-term which will
be able to provide grammar builds through the --build-grammars CLI
flag.
2022-03-10 17:31:57 +09:00
Michael Davis
c1f90a127b add tree-sitter sources to languages.toml
Here we add syntax to the languages.toml languge

    [[grammar]]
    name = "<name>"
    source = { .. }

Which can be used to specify a tree-sitter grammar separately of
the language that defines it, and we make this distinction for
two reasons:

* In later commits, we will separate this code from helix-core
  and bring it to a new helix-loader crate. Using separate schemas
  for language and grammar configurations allows for a nice divide
  between the types needed to be declared in helix-loader and in
  helix-core/syntax

* Two different languages may use the same grammar. This is currently
  the case with llvm-mir-yaml and yaml. We could accomplish a config
  that works for this with just `[[languages]]`, but it gets a bit
  dicey with languages depending on one another. If you enable
  llvm-mir-yaml and disable yaml, does helix still need to fetch and
  build tree-sitter-yaml? It could be a matter of interpretation.
2022-03-10 17:31:57 +09:00
Michael Davis
fbb98300df remove all submodules
The submodules system is being replaced with a command-line flag

    hx --fetch-grammars

Which shallow-clones grammar repositories at the given revision and

    hx --build-grammars

For building grammars separate of the initial compilation of helix.

Why remove submodules?

* Cloning helix in general takes a long time because of the submodules,
  especially when the submodules are not fetched as shallow
* Packaging is consistently painful no matter the package-manager
* It is quite difficult to devise a scheme where users can declare
  a desired set of grammars and implement it with submodules

This commit fully removes the existing tree-sitter submodules from
the tree (as well as the .gitmodules file which is no longer used).
2022-03-10 17:31:57 +09:00
Joe
8d7a25b4d4 Add --edit-config flag to directly open config.toml (#1771)
Co-authored-by: Gokul Soumya <gokulps15@gmail.com>
2022-03-10 00:04:12 +05:30
Daniel S Poulin
3f603b27f1 Update architecture.md (#1750)
* Update architecture.md

Adds some more details on how views work.

* Add additional architecture discussion from matrix, written by @sudormrfbin
2022-03-09 11:19:03 +09:00
Emil Fresk
bfa533fe78 Fix bug in LSP when creating a file in a folder that does not exist (#1775) 2022-03-09 00:21:19 +05:30
Gokul Soumya
194b09fbc1 Add --health command for troubleshooting (#1669)
* Move runtime file location definitions to core

* Add basic --health command

* Add language specific --health

* Show summary for all langs with bare --health

* Use TsFeature from xtask for --health

* cargo fmt

Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
2022-03-08 14:25:46 +09:00
Michael Davis
f31e85aca4 use latest nix-cargo-integration which depends on dream2nix (#1758)
https://github.com/nix-community/dream2nix is a fairly new and
cool-looking project for adapting upstream package manager outputs
(lockfiles mostly it would seem) for nix.

This should improve the ability to cross-compile. As a more concrete
measure of improvement, `nix flake check' now succeeds 🎉
2022-03-08 14:14:00 +09:00
Daniel S Poulin
24352b2729 Add arrow key mappings for tree-sitter parent/child/sibling nav (#1724)
* Add arrow key mappings for tree-sitter parent/child/sibling nav

This helps my use case, where I use a non-qwerty layout with a
programmable mechanical keyboard, and use a layer switching key (think
fn) to send left down up right from the traditional hjkl positions.

* Add new bindings to docs
2022-03-08 14:02:03 +09:00
Gokul Soumya
bde0307c87 Allow highlighting additional spans in md renderer 2022-03-08 13:59:38 +09:00
Gokul Soumya
970a111aa3 Extract markdown code block highlighting function 2022-03-08 13:59:38 +09:00
Blaž Hrastnik
5a60989efe Bump dependencies 2022-03-08 10:33:40 +09:00
dependabot[bot]
9a04064373 build(deps): bump tree-sitter from 0.20.4 to 0.20.5 (#1770)
Bumps [tree-sitter](https://github.com/tree-sitter/tree-sitter) from 0.20.4 to 0.20.5.
- [Release notes](https://github.com/tree-sitter/tree-sitter/releases)
- [Commits](https://github.com/tree-sitter/tree-sitter/compare/v0.20.4...v0.20.5)

---
updated-dependencies:
- dependency-name: tree-sitter
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-03-08 08:55:50 +08:00
dependabot[bot]
b67686d318 build(deps): bump once_cell from 1.9.0 to 1.10.0 (#1768)
Bumps [once_cell](https://github.com/matklad/once_cell) from 1.9.0 to 1.10.0.
- [Release notes](https://github.com/matklad/once_cell/releases)
- [Changelog](https://github.com/matklad/once_cell/blob/master/CHANGELOG.md)
- [Commits](https://github.com/matklad/once_cell/compare/v1.9.0...v1.10.0)

---
updated-dependencies:
- dependency-name: once_cell
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-03-08 08:55:23 +08:00
dependabot[bot]
0d0165b76e build(deps): bump actions/checkout from 2 to 3 (#1767)
Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 3.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v2...v3)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-03-08 09:12:37 +09:00
dependabot[bot]
1493ff7657 build(deps): bump actions/upload-artifact from 2.3.1 to 3 (#1766)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 2.3.1 to 3.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v2.3.1...v3)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-03-08 09:12:22 +09:00
Gokul Soumya
b0aaf08995 Change parameter object keybind from p to a (#1708)
This is largely to avoid a collision with the soon
to be merged paragraph object which takes up the p key.
2022-03-07 16:46:14 +09:00
Blaž Hrastnik
79caa7b72b Add helix-term as default-members 2022-03-07 14:41:28 +09:00
Blaž Hrastnik
19247ff0ec Split out typable commands into a separate file 2022-03-07 14:41:28 +09:00
Daniel S Poulin
9bfb0caf1b Add comment textobject for surround selection and navigation (#1605) 2022-03-06 10:54:24 +05:30
chunghha
7633c5acd3 chore(theme): apply renamed infobox theme scopes for rose_pine themes (#1754) 2022-03-05 22:52:19 +05:30
Michael Davis
f1e90ac2e3 update helix-syntax revision in flake.nix (#1747)
closes #1746

The queries for Go were updated in ddbf03613d.
The old ref was before this commit, so running helix from the flake

    nix flake run github:helix-editor/helix/d62ad8b595a4f901b9c5dba1bb6e8f70ece395bf -- path/to/file.go

will crash because the old grammar's query analysis will fail (because `iota`
was not yet a named node).

This commit updates the version of the grammars that we pull down when building
the flake so that the queries match the grammars. We'll have to do an update like
this whenever a grammar is bumped in a breaking way (which happens fairly often
in tree-sitter) until #1659 comes along and the version of the grammar becomes
tied to the version declared in source.
2022-03-05 10:10:41 +09:00
Blaž Hrastnik
d62ad8b595 fix: text_pos_at_screen_coords tests 2022-03-04 11:23:05 +09:00
Blaž Hrastnik
fd02d1bf89 Fix tab rendering to use dynamic tab width
Each tab is just wide enough to round to the nearest tab stop.

Refs #1243
2022-03-04 11:01:33 +09:00
Blaž Hrastnik
5f386fa355 Remove TODO.md
The file predates open-sourcing and we managed to implement most
of it by now. The remaining features have tracking issues.

Fixes #1155
2022-03-04 09:36:34 +09:00
Blaž Hrastnik
5d14f56fa9 Reuse visual_coords_at_pos function in view 2022-03-04 09:36:31 +09:00
Gokul Soumya
74a9dd51ff Fallback to broader scope if theme scope not found (#1714) 2022-03-04 09:35:21 +09:00
Gokul Soumya
c484b08923 Rename infobox theme scopes (#1741)
This makes it play nicely with https://github.com/helix-editor/helix/pull/1714
2022-03-04 09:31:51 +09:00
Blaž Hrastnik
0062af6a19 minor: Remove some outdated comments 2022-03-03 17:18:26 +09:00
Blaž Hrastnik
737282d0e9 Extract a common function for paste_before/_after 2022-03-03 17:06:14 +09:00
Blaž Hrastnik
376d99a51d core: transaction: Resolve some TODOs 2022-03-03 17:04:25 +09:00
Blaž Hrastnik
adf97e088e Simplify get_clipboard_provider by defining one per host 2022-03-03 16:52:41 +09:00
Blaž Hrastnik
68bad148a5 Extract idle timeout code into ui/editor.rs 2022-03-03 16:52:41 +09:00
Blaž Hrastnik
78fba8683b Picker performance improvements 2022-03-03 16:52:41 +09:00
Erin Kim
0ff3e3ea38 Add inputs.nixpkgs.follows to rust-overlay in flake.nix (#1729)
* add `inputs.nixpkgs.follows` to `rust-overlay`

* Update flake.lock
2022-03-03 10:45:45 +09:00
Blaž Hrastnik
c0b86afdc8 Refactor align_selection by simplifying the calculation 2022-03-03 10:44:57 +09:00
Bob Qi
1c1aee74b4 refactor align_selection using kakoune logic 2022-03-03 10:44:57 +09:00
Gokul Soumya
5c810e5e52 Fix bug with auto replacing components in compositor (#1711)
* Fix bug with auto replacing components in compositor

This was last known to be working with 5995568c at the
time of commit, but now doesn't work with latest rust
stable.

The issue probably stems from using
std::any::type_name() for finding a component in the
compositor, for which the docs explicitly warn against
considering it as a unique identifier for types.

`replace_or_push()` takes a boxed `Component` and
passes it to `find_id()` which compares this with a
bare Component. `type_name()` returns `Box<T>` for
the former and `T` for latter and we have a false
negative. This has been solved by using a generics
instead of trait objects to pass in a `T: Component`
and then use it for comparison.

I'm not exactly sure how this worked fine at the
time of commit of 5995568c; maybe the internal
implementation of `type_name()` changed to properly
indicate indirection with Box.

* Do not compare by type name in compositor find_id
2022-03-03 10:14:50 +09:00
Blaž Hrastnik
86b1236b46 Fix cachix.yml definition 2022-03-02 11:18:29 +09:00
Michael Davis
227e0108e9 add workflow for pushing nix flake artifacts to Cachix (#1721)
* add workflow for pushing nix flake artifacts to Cachix

* add docs on using the cachix cache from nix

* remove submodule clone from cachix workflow

* remove flake check
2022-03-02 11:12:50 +09:00
Michael Daffin
a76e94848a Add terraform lsp support (#1726)
Using terraform-ls and enables auto-formate support. Also adds tfvars as an extra filetype.
2022-03-01 20:59:03 +09:00
Philipp Mildenberger
49c5bc5934 Add jumplist support for the search (closes #1625) (#1718) 2022-03-01 20:57:57 +09:00
Mateusz S. Szczygieł
14e2ced440 Make repeat operator work with completion edits (#1640)
* add basic completion replay

* use transaction as the last completion

* completion replay only on trigger position

* cache changes in CompletionAction

Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
2022-03-01 10:45:29 +09:00
Gokul Soumya
e83cdf3fd3 Ensure non empty grouped nodes in textobject queries 2022-03-01 10:32:50 +09:00
Gokul Soumya
e6c36e82cf Allow capturing multiple nodes in textobject queries
Treesitter captures can contain multiple nodes like so:

```
(line_comment)+ @comment
```

This would match each line in a comment as a separate
`@comment` capture when what we actually want is the
whole set of contiguous `line_comment` nodes to be
captured under the `@comment` capture. This commit enables
this behaviour.
2022-03-01 10:32:50 +09:00
Daniel S Poulin
78d37fd332 Implement bulk buffer closing commands (#1677)
* Implement buffer-close-all

* Implement buffer-close-others

* Refactor all buffer close variants to use shared logic

* Fix clippy lint

* Docgen for new commands

* Shorten error message for attempting to close buffers that don't exist

* Refactor shared buffer methods to pass only editor, not whole compositor

* Switch signature of bulk buffer closing to use slice of DocumentIds

Addresses feedback that accepting an IntoIterator implementor is too
much for an internal. Also possibly saves some moving?
2022-03-01 10:31:24 +09:00
Ludwig Stecher
59c691d2db Highlight matching text in file picker suggestions (#1635)
* Highlight matching text in file picker suggestions

* Remove cache, specialize highlighting code

* Fix outdated comments
2022-03-01 10:30:02 +09:00
Daniel S Poulin
b13d44156c Show infobox to hint textobjects with mi and ma (#1686)
* Show infobox to hint textobjects with `mi` and `ma`

* Add note to infobox than any pair of characters will work too

The wording could probably be a little more clear, but I wanted to
keep it short but still accurate.

* Don't allocate a vec for the static help text

* Fix bug where `mi<esc>` would swallow next input and persist infobox

* Better help text for arbitrary pair matching in textobject selection

* Add way to add fake pending key data below status, use with `mi`/`ma`

This is a bit hacky as it makes use of global state which will end
up managed in multiple places, but has precedent in the way autoinfo
works. There should probably be a bigger refactor to handle this
kind of state better.

* Return early on anything other than `mi` and `ma` for autoinfo

* Remove "ascii" from help text with `mi` and `ma`

* Update helix-term/src/ui/editor.rs

Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
2022-03-01 10:29:22 +09:00
Daniel S Poulin
bdbf423876 Minor cleanup of file picker file gathering logic (#1683)
* Refactor file picker filetype filter logic to remove panic, make clearer

An unwrap was unneccesarily present due to a prior contribution of mine
which was before I had any understanding of error handling in Rust. I've
also swapped a match for an if let, as was originally suggested in the
original pull request adding filetype filtering, but was merged before I
could address.

* Add some comments to the file picker code for clarity

* Switch to expect instead of ignoring type def error
2022-03-01 10:16:25 +09:00
Philipp Mildenberger
7bb1db3ab5 Bring configuration documentation up to date (missing editor.search section) (#1719) 2022-03-01 10:06:14 +09:00
dependabot[bot]
0846822371 build(deps): bump smartstring from 0.2.10 to 1.0.0 (#1722)
Bumps [smartstring](https://github.com/bodil/smartstring) from 0.2.10 to 1.0.0.
- [Release notes](https://github.com/bodil/smartstring/releases)
- [Changelog](https://github.com/bodil/smartstring/blob/master/CHANGELOG.md)
- [Commits](https://github.com/bodil/smartstring/compare/v0.2.10...v1.0.0)

---
updated-dependencies:
- dependency-name: smartstring
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-03-01 09:38:44 +09:00
Triton171
f044059a2a Implement LSP workspace/configuration and workspace/didChangeConfiguration (#1684)
* Implement LSP `workspace/configuration` request

* Implement LSP `workspace/didChangeConfiguration` notification.

* Simplify retrieval of LSP configuration

* Implement suggestions from PR discussion

Co-authored-by: Triton171 <triton0171@gmail.com>
2022-02-28 17:57:22 +09:00
Gokul Soumya
c15996aff5 Show surround delete and replace errors in editor (#1709)
* Refactor surround commands to use early returns

* Show surround delete and replace errors in editor
2022-02-28 17:56:39 +09:00
chunghha
f9ad1cafdc chore(theme): fix "ui.selection" for rose_pine themes (#1716) 2022-02-28 17:56:03 +09:00
Michael Davis
39f7ba36e0 ignore Enter keypress when menu has no selection (#1704)
* ignore Enter keypress when menu has no selection

supersedes #1622

Builds on the work in #1285. I want to allow Enter to create a newline
when there is no selection in the autocomplete menu.

This occurs somewhat often when using LSP autocomplete in Elixir which
uses `do/end` blocks (and I set the autocomplete menu delay to 0 which
exacerbates the problem):

```elixir
defmodule MyModule do
  def do_foo(x) do
    x
  end
  def other_function(y) do|
end
```

Here the cursor is `|` in insert mode. The LSP suggests `do_foo` but I
want to create a newline. Hitting Enter currently closes the menu,
so I end up having to hit Enter twice when the module contains any
local with a `do` prefix, which can be inconsistent. With this change,
we ignore the Enter keypress to end up creating the newline in this case.

* pop compositor layer when ignoring Enter keypress

* move closing function out of consumed event result closure

* explicitly label close_fn as an 'Option<Callback>'
2022-02-27 16:20:21 +09:00
Gregory Oakes
c1251aecc7 Fix duplicate "ui.help" key. (#1713) 2022-02-27 15:39:44 +09:00
Blaž Hrastnik
6a6a9ab2b3 fix: theme: bogster: Only primary selection had a cursor style 2022-02-25 18:04:43 +09:00
Blaž Hrastnik
78a6f77e99 Work around a nix-direnv issue
https://github.com/nix-community/nix-direnv/issues/109
2022-02-25 18:01:47 +09:00
Blaž Hrastnik
66637be700 Add an optimised release profile 2022-02-25 18:01:41 +09:00
Gokul Soumya
8e07e1b898 Alert if LSP is inactive when command is invoked (#1703) 2022-02-25 17:53:10 +09:00
Matouš Dzivjak
951fd1c80e fix(commands): don't indent empty lines (#1653)
* fix(commands): don't indent empty lines

Fixes: https://github.com/helix-editor/helix/issues/1642

* Apply suggestions

* Update helix-term/src/commands.rs

* Update helix-term/src/commands.rs

Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
2022-02-25 17:49:02 +09:00
Michael Daffin
93ec42d06e Add support for HCL language (#1705)
Queries based on the neovims ones: https://github.com/nvim-treesitter/nvim-treesitter/tree/master/queries/hcl and modified for helix support.
2022-02-25 17:48:20 +09:00
Skyler Hawthorne
a494f47a5d Configurable auto pairs (#1624)
* impl auto pairs config

Implements configuration for which pairs of tokens get auto completed.

In order to help with this, the logic for when *not* to auto complete
has been generalized from a specific hardcoded list of characters to
simply testing if the next/prev char is alphanumeric.

It is possible to configure a global list of pairs as well as at the
language level. The language config will take precedence over the
global config.

* rename AutoPair -> Pair

* clean up insert_char command

* remove Rc

* remove some explicit cloning with another impl

* fix lint

* review comments

* global auto-pairs = false takes precedence over language settings

* make clippy happy

* print out editor config on startup

* move auto pairs accessor into Document

* rearrange auto pair doc comment

* use pattern in Froms
2022-02-25 17:36:54 +09:00
Blaž Hrastnik
b935fac957 Fix 1.60 lints 2022-02-25 13:06:11 +09:00
Blaž Hrastnik
9712bbb23b Use which to resolve lsp/dap binaries
This resolves the following issue: https://github.com/helix-editor/helix/discussions/962#discussioncomment-1580046
2022-02-24 11:38:40 +09:00
chunghha
4526216139 chore(theme): update markup styles for rose_pine themes (#1706) 2022-02-24 09:08:20 +08:00
Michael Daffin
f83843ceba Add kotlin language (#1689)
* Add kotlin language

Queries taken from https://github.com/nvim-treesitter/nvim-treesitter/blob/master/queries/kotlin seem to work well enough for my needs though I don't use kotlin heavily.

* Update lang-support doc

* Updates the kotlin highlight query to use helixs scopes

* Updates the queries from PR feedback

* Adds 'shallow = true' to gitmodules

* Removes kotlin locals.scm

* Remove blank line

Co-authored-by: Ivan Tham <pickfire@riseup.net>

Co-authored-by: Ivan Tham <pickfire@riseup.net>
2022-02-23 23:25:44 +09:00
Bram
40eb1268c7 Close some popups automatically (#1285)
* Add Event::Used to use event callback without consuming

* Close popup if contents ignored event

* collect event results before executing callbacks

* don't add new result variant, use Ignored(..) instead

* break in match cases

* Make auto_close configurable

* fix merge

* auto close hover popups

* fix formatting
2022-02-23 12:46:12 +09:00
Arjun P
e1a92fd399 Readme: fix typo (#1695) 2022-02-22 21:31:19 +09:00
dependabot[bot]
806cc1c3b1 build(deps): bump tokio from 1.16.1 to 1.17.0 (#1691)
Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.16.1 to 1.17.0.
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.16.1...tokio-1.17.0)

---
updated-dependencies:
- dependency-name: tokio
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-22 12:29:19 +09:00
dependabot[bot]
dd549e1729 build(deps): bump cc from 1.0.72 to 1.0.73 (#1693)
Bumps [cc](https://github.com/alexcrichton/cc-rs) from 1.0.72 to 1.0.73.
- [Release notes](https://github.com/alexcrichton/cc-rs/releases)
- [Commits](https://github.com/alexcrichton/cc-rs/compare/1.0.72...1.0.73)

---
updated-dependencies:
- dependency-name: cc
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-22 10:01:28 +09:00
dependabot[bot]
77b1a4a768 build(deps): bump smartstring from 0.2.9 to 0.2.10 (#1692)
Bumps [smartstring](https://github.com/bodil/smartstring) from 0.2.9 to 0.2.10.
- [Release notes](https://github.com/bodil/smartstring/releases)
- [Changelog](https://github.com/bodil/smartstring/blob/master/CHANGELOG.md)
- [Commits](https://github.com/bodil/smartstring/compare/v0.2.9...v0.2.10)

---
updated-dependencies:
- dependency-name: smartstring
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-22 10:01:14 +09:00
dependabot[bot]
7d2a77e53c build(deps): bump anyhow from 1.0.53 to 1.0.55 (#1690)
Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.53 to 1.0.55.
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.53...1.0.55)

---
updated-dependencies:
- dependency-name: anyhow
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-22 10:00:33 +09:00
Blaž Hrastnik
24f86017a6 fix: ui: Markdown popups stopped taking vertical padding into account
Fix #1688
2022-02-21 23:24:03 +09:00
Alex
865881ba19 update markup styles for everforest theme (#1687) 2022-02-21 17:37:02 +09:00
Blaž Hrastnik
1ca6ba03ca Simplify some code 2022-02-21 16:47:14 +09:00
Alex
d5ba0b5162 Allow separate styles for markup headings (#1618)
* update markdown highlighting to use separate heading themes

* remove markdown theme scopes in ui
2022-02-21 16:45:48 +09:00
Daniel S Poulin
700058f433 Always ignore the .git directory in file picker (#1604)
Some users (including myself) want to turn off filtering of files
prefixed with `.`, as they are often useful to edit. For example, `.env`
files, configuration for linters `.eslint.json` and the like.
2022-02-20 15:47:43 +09:00
Blaž Hrastnik
c7b326be04 ui: prompt: Render aliases + border on the doc 2022-02-20 14:55:16 +09:00
Blaž Hrastnik
2af04325d8 fix: Allow multi-line prompt documentation 2022-02-20 14:44:44 +09:00
Blaž Hrastnik
a449156702 Extract a lsp position helper 2022-02-18 14:37:59 +09:00
Blaž Hrastnik
5af9136aec Extract some duplication in lsp goto_ calls 2022-02-18 14:37:59 +09:00
Blaž Hrastnik
1cd710fe01 Extract jump_to_location 2022-02-18 14:37:59 +09:00
Blaž Hrastnik
4e845409b6 Extract a common "language server or return" macro 2022-02-18 14:37:59 +09:00
Blaž Hrastnik
c06155ace4 Extract a helper function for lsp::Location 2022-02-18 14:37:59 +09:00
Blaž Hrastnik
504d5ce8bd Move most LSP specific commmands to commands::lsp 2022-02-18 14:37:59 +09:00
Blaž Hrastnik
7b1d682fe5 dap: fix runInTerminal with lldb-vscode 2022-02-18 14:37:59 +09:00
Blaž Hrastnik
4e1b3b12f3 Refactor symbol picker to share code 2022-02-18 13:50:06 +09:00
Michael Davis
a8cf0c6b90 filter git revision on git command success exit code (#1674)
The unwrap (or '.ok()' rather) triggers for some errors but not
negative status codes. In the case where helix is being packaged
in an empty git repository, the existing mechanism will fail because

    git init
    git rev-parse HEAD

gives a negative exit code and prints to stderr

    stderr: "fatal: ambiguous argument 'HEAD': unknown revision or path not in the working tree....

with a stdout of "HEAD\n" (too short to slice with [..8]).
2022-02-18 13:05:12 +09:00
tomKPZ
368064e316 Fix bug when launching hx file.rs:10 (#1676) 2022-02-18 12:13:02 +09:00
Matouš Dzivjak
afec54485a feat(commands): command palette (#1400)
* feat(commands): command palette

Add new command to display command pallete that can be used
to discover and execute available commands.

Fixes: https://github.com/helix-editor/helix/issues/559

* Make picker take the whole context, not just editor

* Bind command pallete

* Typable commands also in the palette

* Show key bindings for commands

* Fix tests, small refactor

* Refactor keymap mapping, fix typo

* Ignore sequence key bindings for now

* Apply suggestions

* Fix lint issues in tests

* Fix after rebase

Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
2022-02-17 14:03:11 +09:00
Blaž Hrastnik
24f90ba8d8 Manually recalculate initial completion where it matters 2022-02-17 14:02:42 +09:00
Blaž Hrastnik
af21e2a5b4 Pass through Editor instead of Context 2022-02-17 14:02:42 +09:00
Cole Helbling
e023a78919 WIP: show all buffers that couldn't be closed 2022-02-17 14:02:42 +09:00
Cole Helbling
6118486eb2 helix-term: implement buffer completer
In order to implement this completer, the completion function needs to
be able to access the compositor's context (to allow it to get the
list of buffers currently open in the context's editor).
2022-02-17 14:02:42 +09:00
Cole Helbling
a1207fd768 helix-term/commands: display buffer id in picker 2022-02-17 14:02:42 +09:00
Blaž Hrastnik
d11b652139 Allow static strings in set_status/set_error so API is nicer 2022-02-15 16:45:28 +09:00
Blaž Hrastnik
fd0e4b1159 dap: Reduce amount of block_on uses 2022-02-15 16:30:23 +09:00
David Crespo
a629343476 Fix hover menu item text color in base16 themes (#1668)
* fix hover menu item text in base16 dark

* same ix for base16_default_light and base16_terminal
2022-02-15 14:21:52 +09:00
Gokul Soumya
ab2a0f325b Add object.movement for tree-sitter navigation 2022-02-15 14:04:46 +09:00
Gokul Soumya
989407f190 Add docs for tree-sitter based navigation 2022-02-15 14:04:46 +09:00
Gokul Soumya
966fbc5984 Add tree-sitter based function, class navigation 2022-02-15 14:04:46 +09:00
Blaž Hrastnik
1422449537 .. 2022-02-15 11:37:33 +09:00
Blaž Hrastnik
eeb9b39857 Fix build on master 2022-02-15 10:33:55 +09:00
Ludwig Stecher
4429993842 Add PageUp, PageDown, Ctrl-u, Ctrl-d, Home, End keyboard shortcuts to file picker (#1612)
* Add `PageUp`, `PageDown`, `Ctrl-u`, `Ctrl-d`, `Home`, `End` keyboard shortcuts to file picker

* Refactor file picker paging logic

* change key mapping

* Add overlay component

* Use closure instead of margin to calculate size

* Don't wrap file picker in `Overlay` automatically
2022-02-15 10:24:03 +09:00
Kirawi
23907a063c use PathBuf::to_string_lossy() instead of to_str() (#1655) 2022-02-15 10:22:55 +09:00
Michael Davis
3a83a764e3 add tree-sitter-erlang (#1657) 2022-02-15 10:14:02 +09:00
Blaž Hrastnik
8a7aec6414 fix: nix flake build 2022-02-15 10:12:37 +09:00
dependabot[bot]
225484c26c build(deps): bump serde_json from 1.0.78 to 1.0.79 (#1667)
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.78 to 1.0.79.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.78...v1.0.79)

---
updated-dependencies:
- dependency-name: serde_json
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-15 10:08:39 +09:00
Gokul Soumya
4c424d5ee4 Refactor language config loading (#1658) 2022-02-15 01:41:53 +09:00
CossonLeo
e267dc834a Makefile indent must be '\t' (#1661) 2022-02-14 18:03:18 +09:00
Gokul Soumya
59acee308d Add new dap commands to docs (#1660) 2022-02-14 11:32:22 +09:00
Blaž Hrastnik
97d4b2b5fe Mark DAP as experimental 2022-02-13 18:32:57 +09:00
Blaž Hrastnik
bd549d8a20 Merge remote-tracking branch 'origin/master' into debug 2022-02-13 18:31:51 +09:00
Cydiater
7083b98a38 postpone clone after found (#1656) 2022-02-13 13:53:35 +09:00
Maximilian Schoenenberg
a19a6ca01e Added docs for ensure_selections_forward (#1651) 2022-02-11 20:25:59 +05:30
Blaž Hrastnik
1bcb624ae6 Instant is more suitable than SystemTime for spinners 2022-02-10 11:12:47 +09:00
Blaž Hrastnik
f88c077f99 Replace tendril with smartstring
Slightly smaller API surface, less dependencies.
2022-02-10 11:12:47 +09:00
Matouš Dzivjak
fdb9a1677b feat(editor): add config for search wrap_around (#1516)
* feat(editor): add config for search wrap_around

Fixes: https://github.com/helix-editor/helix/issues/1489

* Move search settings into separate config

* Disable linter
2022-02-10 11:04:40 +09:00
Gokul Soumya
59b5bf3178 Refactor document methods 2022-02-10 10:56:08 +09:00
Gokul Soumya
fa83426011 Handle newlines in register infobox 2022-02-10 10:52:06 +09:00
Gokul Soumya
bf773db451 Show infobox with register contents 2022-02-10 10:52:06 +09:00
Gokul Soumya
5995568c1d Prevent multiple code action popups 2022-02-08 16:44:39 +09:00
Gokul Soumya
547c3ecd0c Preselect first item in code action popup menu 2022-02-08 16:44:39 +09:00
Gokul Soumya
e90276df0b Replace if let with early return 2022-02-08 16:44:39 +09:00
Gokul Soumya
f0cd02d5ef Update keybind docs for treesitter, view mode (#1628) 2022-02-08 13:45:40 +09:00
dependabot[bot]
828d39e736 build(deps): bump lsp-types from 0.91.1 to 0.92.0 (#1631)
Bumps [lsp-types](https://github.com/gluon-lang/lsp-types) from 0.91.1 to 0.92.0.
- [Release notes](https://github.com/gluon-lang/lsp-types/releases)
- [Changelog](https://github.com/gluon-lang/lsp-types/blob/master/CHANGELOG.md)
- [Commits](https://github.com/gluon-lang/lsp-types/compare/v0.91.1...v0.92.0)

---
updated-dependencies:
- dependency-name: lsp-types
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-08 07:51:11 +08:00
dependabot[bot]
718d4ab0f0 build(deps): bump unicode-segmentation from 1.8.0 to 1.9.0 (#1632)
Bumps [unicode-segmentation](https://github.com/unicode-rs/unicode-segmentation) from 1.8.0 to 1.9.0.
- [Release notes](https://github.com/unicode-rs/unicode-segmentation/releases)
- [Commits](https://github.com/unicode-rs/unicode-segmentation/commits)

---
updated-dependencies:
- dependency-name: unicode-segmentation
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-08 07:50:29 +08:00
Blaž Hrastnik
23553bd37c Update dependencies (crossterm 0.23, tree-sitter 0.20.4)
Fixes #677
2022-02-07 10:47:57 +09:00
Blaž Hrastnik
ad62e1e129 fix: Revert Block widget change that broke autoinfo background 2022-02-07 10:30:03 +09:00
Blaž Hrastnik
e7f5ec5561 fix: There is no such thing as markup.normal, use ui.text 2022-02-07 10:30:03 +09:00
Jared Ramirez
f5b95beef6 feat(languages): rescript (#1616)
* Add rescript language support

* cargo xtask docgen

* Add textobjects & file line ending

* Fix text objects & rerun docgen

* Fix textobjects queries
2022-02-06 14:24:01 +09:00
Ivan Tham
6c11708fb3 Fix incorrect last modified behavior (#1621)
Looks like it checked the wrong doc id when setting last modified doc.
2022-02-06 14:23:12 +09:00
Blaž Hrastnik
6ea477ab60 Don't use block_on in jobs.finish(), we can .await 2022-02-05 15:05:19 +09:00
Blaž Hrastnik
d3221b03a2 fix: Only parse git revision, don't use the tag for version
If building from source and the source is contained in a larger
repository, we'd contain the wrong version. It's also easy to
accidentally have a newer tag that would change the version.
2022-02-03 01:19:44 +09:00
Daniel S Poulin
d6b6ad879e epocsquadron/add tree sitter twig (#1602)
* Add tree-sitter-twig grammer and highlights

The gammar itself is quite basic, but is much better than nothing
for working with real files consisting mostly of html.

* Docgen for newly added grammar
2022-02-01 12:35:07 +09:00
dependabot[bot]
983a53bfb4 build(deps): bump tokio from 1.15.0 to 1.16.1 (#1610)
Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.15.0 to 1.16.1.
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.15.0...tokio-1.16.1)

---
updated-dependencies:
- dependency-name: tokio
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-01 12:24:41 +09:00
dependabot[bot]
d090369404 build(deps): bump serde from 1.0.135 to 1.0.136 (#1608)
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.135 to 1.0.136.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.135...v1.0.136)

---
updated-dependencies:
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-01 12:24:32 +09:00
dependabot[bot]
05aeeaca0b build(deps): bump unicode-general-category from 0.4.0 to 0.5.1 (#1609)
Bumps [unicode-general-category](https://github.com/yeslogic/unicode-general-category) from 0.4.0 to 0.5.1.
- [Release notes](https://github.com/yeslogic/unicode-general-category/releases)
- [Commits](https://github.com/yeslogic/unicode-general-category/compare/0.4.0...0.5.1)

---
updated-dependencies:
- dependency-name: unicode-general-category
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-01 12:24:23 +09:00
Blaž Hrastnik
36b975c4ce ui: menu: Don't allocate scrollbar space if options fit 2022-02-01 01:25:59 +09:00
Blaž Hrastnik
f10a06f4de ui: Only render menu scrollbar if it doesn't fit 2022-01-31 16:04:58 +09:00
Blaž Hrastnik
094a0aa3f9 Render code actions as a menu, allow adding padding to popup 2022-01-31 16:04:58 +09:00
Blaž Hrastnik
f7f55143a1 Improve code action picker by displaying it inline 2022-01-31 16:04:58 +09:00
chunghha
4c996f43df chore(theme): fix rose_pine/rose_pine_dawn themes' popup bg color (#1606) 2022-01-31 16:03:44 +09:00
Blaž Hrastnik
62561e9d23 Stop collecting highlight_iter events then turning back into iter 2022-01-30 22:38:44 +09:00
Blaž Hrastnik
5aead46f4b Remove some unnecessary clippy tags 2022-01-30 22:38:44 +09:00
Blaž Hrastnik
2a7ae963e1 Automatically commit changes to history if not in insert mode
Fixes #1500
2022-01-30 22:38:44 +09:00
Daniel S Poulin
e2833b5853 Add textobjects queries for php (#1601)
* Add textobjects queries for php

* Missing EOL fix

* Update generated docs after adding textobjects to php
2022-01-30 11:04:36 +09:00
Andrew Neth
333c2949c2 feat(helix-view): dynamic line numbers (#1522)
* feat(helix-view): dynamic line numbers

* docs: describe editor.line-number in more detail

* Make dynamic numbers the default behavior of `relative`
2022-01-26 00:18:01 +09:00
Blaž Hrastnik
48a0c80652 Run clippy on all targets (including tests) 2022-01-25 16:37:03 +09:00
Michael Davis
7bce91556a add tree-sitter-iex (#1576)
* add tree-sitter-iex

* run docgen task

* fix url for iex submodule
2022-01-25 15:50:34 +09:00
dependabot[bot]
ed03be1450 build(deps): bump which from 4.2.2 to 4.2.4 (#1577)
Bumps [which](https://github.com/harryfei/which-rs) from 4.2.2 to 4.2.4.
- [Release notes](https://github.com/harryfei/which-rs/releases)
- [Commits](https://github.com/harryfei/which-rs/compare/4.2.2...4.2.4)

---
updated-dependencies:
- dependency-name: which
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-25 09:59:16 +09:00
dependabot[bot]
5c007c2248 build(deps): bump clipboard-win from 4.3.0 to 4.4.1 (#1578)
Bumps [clipboard-win](https://github.com/DoumanAsh/clipboard-win) from 4.3.0 to 4.4.1.
- [Release notes](https://github.com/DoumanAsh/clipboard-win/releases)
- [Commits](https://github.com/DoumanAsh/clipboard-win/commits)

---
updated-dependencies:
- dependency-name: clipboard-win
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-25 09:42:14 +09:00
Eric Crosson
0ad7561135 Enable tree-sitter for .zshenv and zsh files (#1574)
This commit builds on #1460, #1571, and others, adding the .zshenv
file and all files with the zsh extension to the file-types using
bash syntax-highlighting.
2022-01-24 23:25:19 +08:00
VuiMuich
1bcff796e5 [theme] Serika light and dark (#1566)
* add theme `serika` in light and dark variant

* add `markup.*`s
2022-01-24 23:16:05 +08:00
chunghha
a4fffaed9f Enable tree-sitter for .bash_profile (#1571) 2022-01-24 08:12:46 +05:30
CossonLeo
d49e5323f9 Use markup scopes for the Markdown component (#1363) 2022-01-24 10:41:25 +09:00
Benjamin
4044c70eb2 Fix picker won't scroll down when it hits the bottom #1544 (#1567) 2022-01-23 23:06:28 +09:00
Ivan Tham
759b850859 Allow specifying file start position (#445)
Like helix-term/src/commands.rs:3426:15
2022-01-23 16:54:03 +09:00
Blaž Hrastnik
7d510429c5 Enable tree-sitter for .zshrc and .bashrc
Closes #1460
2022-01-23 16:39:18 +09:00
Omnikar
f064894e57 Fix Clippy lints in tests (#1563)
Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
2022-01-23 16:37:23 +09:00
Blaž Hrastnik
e2d2f19fd0 Merge pull request #1154 from sudormrfbin/cursor-shape-new
Change cursor shape on mode change
2022-01-23 16:35:22 +09:00
Kyra
a8e69e12f4 Add haskell-language-server-wrapper --lsp to default languages.toml (#1556)
After the changes to upgrade and reenable tree-sitter-haskell #1417
for the purpose of enabling Haskell syntax highlighting #1384, we
might as well take the final step.
2022-01-23 16:22:31 +09:00
Blaž Hrastnik
4080341977 cargo fmt + clippy lint 2022-01-23 16:15:27 +09:00
Blaž Hrastnik
7c9ebd05b8 Remove some TODOs 2022-01-23 16:10:36 +09:00
Blaž Hrastnik
80e920ba36 Update dependencies (includes tree-sitter 0.20.3) 2022-01-23 16:06:05 +09:00
Blaž Hrastnik
ac81b47a41 Don't calculate symbol width twice
This is potentially costly so we should avoid calling width()
2022-01-23 16:04:26 +09:00
Blaž Hrastnik
66a8612351 cleanup 2022-01-23 16:04:26 +09:00
Blaž Hrastnik
2302869836 fix: ensure_grapheme_boundary_next_byte needs to index at valid char 2022-01-23 16:04:26 +09:00
Blaž Hrastnik
add3be8528 Slicing micro-optimization 2022-01-23 16:04:26 +09:00
Blaž Hrastnik
df0d58e9f7 Set flags necessary for cargo-flamegraph 2022-01-23 16:04:12 +09:00
Blaž Hrastnik
11c3ba9350 Speed up ensure_next_boundary during render
This code:

    let start = ensure_grapheme_boundary_next(text, text.byte_to_char(start));
    let end = ensure_grapheme_boundary_next(text, text.byte_to_char(end));

Would convert byte to char index, but then internally immediately convert back
to byte index, operate on it, then convert it to char index.

This change reduces the amount of time spent in ensure_grapheme_boundary from
29% to 2%.
2022-01-23 16:04:12 +09:00
Blaž Hrastnik
9d41113ae0 Make Layer::parse take &mut tree_sitter::Parser 2022-01-23 16:04:12 +09:00
Blaž Hrastnik
e22dbf102f Use filter_map rather than flat_map 2022-01-23 16:04:12 +09:00
Blaž Hrastnik
2f4a9fea03 Set byte range on cursor again 2022-01-23 16:04:12 +09:00
Blaž Hrastnik
24314bd844 Only call scopes.load() once 2022-01-23 16:04:12 +09:00
Blaž Hrastnik
4b0205f690 Resolve some outdated comments 2022-01-23 16:04:12 +09:00
Blaž Hrastnik
9508684031 fix: Skip modifying the root layer range, it always covers 0..max 2022-01-23 16:04:12 +09:00
Blaž Hrastnik
7315f6f3e4 Update range markers so we can determine which layers can be reused 2022-01-23 16:04:12 +09:00
Blaž Hrastnik
8a53e34e66 Try to reuse an existing layer based on layer.ranges 2022-01-23 16:04:07 +09:00
Blaž Hrastnik
72eb2ce1f1 Ignore layers without highlight captures, avoid cloning ranges 2022-01-23 16:00:24 +09:00
Blaž Hrastnik
5135fa37eb Reuse the source slice between layers 2022-01-23 16:00:24 +09:00
Blaž Hrastnik
53d881f172 Store theme scopes on the loader, this way theme isn't passed around 2022-01-23 16:00:24 +09:00
Blaž Hrastnik
6728e44490 syntax: Split parsing and highlighting 2022-01-23 16:00:24 +09:00
NNB
83bde1004d Add markup support (#1525)
* Add markup support for all Base16 themes

* Fix rose_pine `markup.link.text` attribute misname

* Add basic default markup support for all themes

* Fix cursor change color on Base16 terminal and default

* Remove old markup monokai_pro support and fix Onedark `markup.link.text` attribute misname

* Remove old markup dracula support
2022-01-23 11:18:50 +09:00
Daniel Flanagan
b8cafee9f5 docs: Fix typo in book (#1537)
* docs: Fix typo in book

* Update book/src/usage.md

Co-authored-by: Eric Crosson <EricCrosson@users.noreply.github.com>

Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
Co-authored-by: Eric Crosson <EricCrosson@users.noreply.github.com>
2022-01-23 00:34:19 +09:00
Rohan Jain
1c747674b6 Add tag to gruvbox theme (#1555)
Missed in the commit 943fca332e.
2022-01-23 00:33:43 +09:00
Sebastian Zivota
5c1a06d28e dracula theme: add markup support (#1554) 2022-01-23 00:32:41 +09:00
Jared Ramirez
0b55b21f30 feat(languages): GraphQL (#1515)
* Add Graphql language support

* Fix docs gen

* Add JS Graphql injection query

* Updates based on PR feedback

Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
2022-01-21 23:16:40 +09:00
Michael Davis
f453f8724d change show_subtree command into ':tree-sitter-subtree' typable command (#1524)
* add default keymap for show_subtree command

* remove space+t keymap

* add a typable command ':show-subtree'

* generate documentation for ':show-subtree'

* remove non-typable show_subtree command

* ':show-subtree'->':tree-sitter-subtree'
2022-01-21 23:15:35 +09:00
WindSoilder
4563832318 add markup support for monokai pro themes (#1553) 2022-01-21 22:03:01 +09:00
Michael Davis
392dfa0841 add select_next_sibling and select_prev_sibling commands (#1495)
* add select_next_sibling and select_prev_sibling commands

* refactor objects to use higher order functions

* address clippy feedback

* move selection cloning into commands

* add default keybindings under left/right brackets

* use [+t,]+t for selecting sibling syntax nodes

* setup Alt-{j,k,h,l} default keymaps for syntax selection commands

* reduce boilerplate of select_next/prev_sibling in commands

* import tree-sitter Node type in commands
2022-01-21 00:52:33 +09:00
Mathis Brossier
fd7080498e tree sitter comments injections (#1527)
* tree sitter comments injections

* trailing newlines & julia fix

* Update runtime/queries/julia/injections.scm

Co-authored-by: Michael Davis <michael.davis@nfiindustries.com>

Co-authored-by: Michael Davis <michael.davis@nfiindustries.com>
2022-01-21 00:50:06 +09:00
Jared Ramirez
b2c8aa1ee7 feat(languages): Elm (#1514)
* Add Elm language support

* Fix docs gen

* Updates based on PR feedback
2022-01-21 00:47:23 +09:00
Ivan Tham
440d4ae9df Add terminal emulator to bug report (#1535) 2022-01-18 21:39:02 +05:30
dependabot[bot]
22b728d1eb build(deps): bump libloading from 0.7.2 to 0.7.3 (#1530)
Bumps [libloading](https://github.com/nagisa/rust_libloading) from 0.7.2 to 0.7.3.
- [Release notes](https://github.com/nagisa/rust_libloading/releases)
- [Commits](https://github.com/nagisa/rust_libloading/commits/0.7.3)

---
updated-dependencies:
- dependency-name: libloading
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-18 09:42:48 +08:00
dependabot[bot]
89eb22525b build(deps): bump serde_json from 1.0.74 to 1.0.75 (#1531)
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.74 to 1.0.75.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.74...v1.0.75)

---
updated-dependencies:
- dependency-name: serde_json
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-18 09:42:27 +08:00
dependabot[bot]
ed45d380eb build(deps): bump smallvec from 1.7.0 to 1.8.0 (#1532)
Bumps [smallvec](https://github.com/servo/rust-smallvec) from 1.7.0 to 1.8.0.
- [Release notes](https://github.com/servo/rust-smallvec/releases)
- [Commits](https://github.com/servo/rust-smallvec/compare/v1.7.0...v1.8.0)

---
updated-dependencies:
- dependency-name: smallvec
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-18 09:42:07 +08:00
Skyler Hawthorne
96d4ca5f73 Dependabot/cargo/pulldown cmark 0.9.1 (#1533)
* build(deps): bump pulldown-cmark from 0.8.0 to 0.9.1

Bumps [pulldown-cmark](https://github.com/raphlinus/pulldown-cmark) from 0.8.0 to 0.9.1.
- [Release notes](https://github.com/raphlinus/pulldown-cmark/releases)
- [Commits](https://github.com/raphlinus/pulldown-cmark/compare/v0.8.0...v0.9.1)

---
updated-dependencies:
- dependency-name: pulldown-cmark
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* cmark 0.9 fixes

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-18 09:41:44 +08:00
Skyler Hawthorne
56a9ce5d83 fix(auto_pairs): fix auto pairs with crlf (#1470)
Auto pairs were resulting in incorrect ranges in the resulting when the
line terminators are CRLF (i.e. Windows). It turns out this is because
when we were checking if the selection was a single-width cursor, it
incorrectly assumed that this would be a single char. This is not the
case, as a cursor can cover a multi-code point grapheme. Therefore,
we must instead explicitly work with and check graphemes to determine
if the cursor should move or extend the selection.

Fixes #1436
2022-01-18 00:39:12 +09:00
Anders Christiansen Sørby
8ea5742b08 feat(languages): Lean experimental tree-sitter-lean (#1422)
* Add experimental tree-sitter-lean

* Run docgen

* Copy over the queries from lean.nvim

* Update .gitmodules

Co-authored-by: Ivan Tham <pickfire@riseup.net>

* Update lean highlights and run docgen

* Update runtime/queries/lean/injections.scm

Co-authored-by: Michael Davis <michael.davis@nfiindustries.com>

* Lean: Move variable matcher to bottom

* Update runtime/queries/lean/locals.scm

Co-authored-by: Michael Davis <michael.davis@nfiindustries.com>

Co-authored-by: Ivan Tham <pickfire@riseup.net>
Co-authored-by: Michael Davis <michael.davis@nfiindustries.com>
2022-01-17 23:05:17 +09:00
Blaž Hrastnik
e7eab95b94 Update to rust 1.58, fix a bunch of optional lints 2022-01-16 14:19:48 +09:00
Mathis Brossier
f5b0821860 Fix panics when resizing (#1408)
* Change buffer.get & buffer.get_mut to return Option, Implement Trait Index & IndexMut to panic

* Prevent FilePicker from drawing outside buffer (rust panics)

* apply suggestion

* add function in_bounds to avoid useless calculations

Co-authored-by: mathis <mathis.brossier@universite-paris-saclay.fr>
2022-01-16 10:55:28 +09:00
Stuart Hinson
9da0abaa5d Add modified background to dracula popup (#1434) 2022-01-16 10:42:00 +09:00
WindSoilder
22297d0b40 Add alt-backspace, alt-<, alt->, ctrl-j to insert mode (#1441)
* add alt-backspace keymap to delete word backward

* add more useful keymap

* map to correct command

* add C-j to insert_newline
2022-01-16 10:41:21 +09:00
Matouš Dzivjak
38ca8daa09 fix(commands): run fmt for all documents being closed (#1444)
When writing all documents, fmt wouldn't be run.
Run fmt in close all implementation so that all documents
are formatted if necessary.

Fixes: https://github.com/helix-editor/helix/issues/1442
2022-01-16 10:39:49 +09:00
Rohan Jain
62c78c061c Add markup. scopes in gruvbox themes (#1518)
As recommended by @archseer in https://github.com/helix-editor/helix/pull/1509#issuecomment-1013583069
2022-01-16 10:32:29 +09:00
Michael Davis
64d3e7b705 add show_subtree command for viewing tree-sitter subtree in Popup (#1453)
* add show_subtree command for viewing tree-sitter subtree in Popup

* remove '.slice(..)' from show_subtree command

* name docs and subtree Popups 'hover'
2022-01-16 10:26:09 +09:00
Daniel S Poulin
dd1f64d4dc Update tree-sitter-php to latest upstream (#1521)
Brings in PHP 8.1 features, like enums, union types and the like.
2022-01-16 10:11:47 +09:00
Kirawi
a7b0cc730c Re-enable haskell in languages.toml (#1520) 2022-01-16 10:11:31 +09:00
Kevin Sjöberg
3a34036310 Use the correct language ID for JavaScript & TypeScript (#1466)
* Use correct language ID for JavaScript/TypeScript

* Add missing slash

* Only calculate fallback when needed
2022-01-15 15:23:06 +09:00
Rohan Jain
97e6f2a38f Add gruvbox-light theme (#1509)
Similar to `gruvbox`, add the light version as well.
2022-01-14 22:33:22 +08:00
voroskoi
6bfd001b48 Update zig tree-sitter (#1501)
use latest upstream version
move comptime from @keyword.function to @keyword.directive
use AssignOp
enhance indents
2022-01-14 22:29:24 +08:00
Matouš Dzivjak
ac6b2de0fd feat(languages): enable css tree-sitter for scss files (#1507)
The grammer works fine for scss files to and it is better than no hihglighting at all
2022-01-14 16:25:44 +05:30
Alexis Mousset
f80da7b4de Add pom.xml as maven root directory marker (#1496) 2022-01-14 15:37:59 +09:00
Mathis Brossier
85cf2648a2 buffer picker allow hsplit / vsplit (#1502) 2022-01-14 15:32:24 +09:00
Jared Ramirez
a2fad4fcb0 Fix Nix flake (#1455) 2022-01-13 09:40:07 +09:00
NexiNov
f77dbc7c83 Minor(book): Add G in normal mode (#1482) 2022-01-12 23:43:03 +08:00
Kirawi
8d273a5613 remove outdated note (#1485) 2022-01-12 13:11:00 +09:00
Blaž Hrastnik
ddbf03613d Update tree-sitter-go with generics support 2022-01-11 19:10:02 +09:00
dependabot[bot]
afc602d306 build(deps): bump clipboard-win from 4.2.2 to 4.3.0 (#1476)
Bumps [clipboard-win](https://github.com/DoumanAsh/clipboard-win) from 4.2.2 to 4.3.0.
- [Release notes](https://github.com/DoumanAsh/clipboard-win/releases)
- [Commits](https://github.com/DoumanAsh/clipboard-win/commits)

---
updated-dependencies:
- dependency-name: clipboard-win
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-11 07:41:18 +08:00
dependabot[bot]
1a34a3ce57 build(deps): bump signal-hook-tokio from 0.3.0 to 0.3.1 (#1477)
Bumps [signal-hook-tokio](https://github.com/vorner/signal-hook) from 0.3.0 to 0.3.1.
- [Release notes](https://github.com/vorner/signal-hook/releases)
- [Changelog](https://github.com/vorner/signal-hook/blob/master/CHANGELOG.md)
- [Commits](https://github.com/vorner/signal-hook/compare/v0.3.0...v0.3.1)

---
updated-dependencies:
- dependency-name: signal-hook-tokio
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-11 07:40:59 +08:00
Michael Davis
e0a99ae51a add tree-sitter-git-config (#1426)
* add tree-sitter-git-config

* add todo comment for improving filetype check
2022-01-09 22:10:20 +08:00
Gokul Soumya
b3b4e78585 Merge branch 'master' into cursor-shape-new 2022-01-09 10:38:58 +05:30
Cottser
97e12f5c5a docs: editor.filepicker -> editor.file-picker (#1465) 2022-01-09 11:45:54 +09:00
Benoît Cortier
05e5520ec0 Put some tests behind #[cfg(test)] (#1459)
It was missing in a few places.
2022-01-09 00:32:50 +09:00
Michael Davis
939261fc07 expand_selection to current node with no children (#1454) 2022-01-09 00:31:05 +09:00
Eric Crosson
5b45bdd80f docs: document @keyword.control.exception scope
As identified in [this GitHub comment](https://github.com/helix-editor/helix/pull/1433#discussion_r777786140)
2022-01-09 00:30:22 +09:00
Eric Crosson
1c6bc6d455 feat: add tree-sitter-make
This commit adds syntax highlighting for GNU Make[^1] makefiles
via tree-sitter-make[^2].

[^1]: https://www.gnu.org/software/make/
[^2]: https://github.com/alemuller/tree-sitter-make
2022-01-09 00:30:22 +09:00
Owen Shepherd
c238f20e1d Add fixity keywords to haskell's highlights.scm 2022-01-09 00:28:56 +09:00
Owen Shepherd
9eacbc1887 Upgrade haskell queries 2022-01-09 00:28:56 +09:00
Owen Shepherd
41ee45ce54 Upgrade and reenable tree-sitter-haskell 2022-01-09 00:28:56 +09:00
Michael Davis
b799b0d50e capture markdown link text as markup.link.text (#1456) 2022-01-09 00:27:50 +09:00
Kevin Sjöberg
5e22694865 Add default language server for JavaScript (#1457)
* Add default language server for JavaScript

* Update lang support documentation
2022-01-09 00:27:10 +09:00
CJ van den Berg
1af8dd9912 Rework beginning of themes chapter
The specifics of configuring themes has caused some confusion. Hopefully this will clarify things a little.
2022-01-07 16:04:34 -05:00
Michael Davis
a8fd33ac01 add tree-sitter-regex (#1362)
* add tree-sitter-regex

* adapt regex highlights from upstream

* inject regex into elixir sigil_r/2 and sigil_R/2

* generate lang-support docs

* capture interesting nodes in character-ranges

* make $.character_class captures more consistent

* fix fallthrough behavior for character classes

* capture pattern characters as 'string'

* use latest tree-sitter-regex

* set elixir regex injections as combined

* add link to upstream queries

* inject regex in rust into 'Regex::new' raw string literals
2022-01-06 23:00:00 +08:00
Gokul Soumya
449624965b Merge branch 'master' into cursor-shape-new 2022-01-06 11:32:03 +05:30
Matouš Dzivjak
2e02a1d6bc feat(commands): shrink_selection (#1340)
* feat(commands): shrink_selection

Add `shrink_selection` command that can be used to shrink
previously expanded selection.

To make `shrink_selection` work it was necessary to add
selection history to the Document since we want to shrink
the selection towards the syntax tree node that was initially
selected.

Selection history is cleared any time the user changes
selection other way than by `expand_selection`. This ensures
that we don't get some funky edge cases when user calls
`shrink_selection`.

Related: https://github.com/helix-editor/helix/discussions/1328

* Refactor shrink_selection, move history to view

* Remove useless comment

* Add default key mapping for extend&shrink selection

* Rework contains_selection method

* Shrink selection without expand selects first child
2022-01-06 11:12:02 +09:00
Philipp Mildenberger
66afbc9fff Fix null and boolean constants in tree-sitter-nix highlights queries (#1428) 2022-01-06 11:04:55 +09:00
Blaž Hrastnik
3e4f81547c fix: Use std::path::MAIN_SEPARATOR to determine completion
Refs #1439
2022-01-06 11:03:54 +09:00
Stuart Hinson
b18bda928f fix slash in search selector status message (#1449) 2022-01-06 10:39:19 +09:00
Blaž Hrastnik
7767703979 fix: Only use shellwords parsing on unix platforms 2022-01-05 11:01:30 +09:00
Blaž Hrastnik
bed9aced5f Revert "Convert Windows style path separator in completers to Unix style (#1389)"
This reverts commit 49444f9c05.
2022-01-05 10:58:12 +09:00
Blaž Hrastnik
bd0d20a2b3 minor: Fix previous version's header 2022-01-04 19:25:59 +09:00
Blaž Hrastnik
1bcae78f06 minor: Fix some changelog links 2022-01-04 18:58:26 +09:00
Blaž Hrastnik
efaac6c5d3 Release 0.6 2022-01-04 18:54:37 +09:00
Blaž Hrastnik
c8794b30ee Update changelog 2022-01-04 18:54:37 +09:00
Sebastian Neubauer
5b1a628e81 Add textobjects and indents to c and cpp (#1293)
Indentation of single line statements doesn't work, i.e.

  for (;;)<hit enter>
leads to
  for(;;)
  <cursor here>

Only blocks with curly braces are indented.
2022-01-04 10:53:04 +09:00
Sebastian Neubauer
641255ccc8 Add llvm-mir highlighting (#1398)
* Add injection regex for more languages

To support embedding them in other languages like markdown.

* Add llvm-mir highlighting

LLVM Machine IR is dumped as yaml files that can embed LLVM IR and
Machine IR.

To support this, add a llvm-mir-yaml language that uses the yaml
parser, but uses different injections to highlight IR and MIR.

* Update submodule with fixed multiline comments

Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
2022-01-04 10:52:34 +09:00
dumrich
7c9d3682db Fix grammatical error (#1427)
it's to its (possessive)
2022-01-04 10:45:31 +09:00
dependabot[bot]
4d59f66b76 build(deps): bump tree-sitter from 0.20.1 to 0.20.2 (#1429)
Bumps [tree-sitter](https://github.com/tree-sitter/tree-sitter) from 0.20.1 to 0.20.2.
- [Release notes](https://github.com/tree-sitter/tree-sitter/releases)
- [Commits](https://github.com/tree-sitter/tree-sitter/compare/v0.20.1...v0.20.2)

---
updated-dependencies:
- dependency-name: tree-sitter
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-04 10:44:48 +09:00
dependabot[bot]
96935eb28d build(deps): bump serde_json from 1.0.73 to 1.0.74 (#1430)
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.73 to 1.0.74.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.73...v1.0.74)

---
updated-dependencies:
- dependency-name: serde_json
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-04 10:44:15 +09:00
dependabot[bot]
78967779bd build(deps): bump ropey from 1.3.1 to 1.3.2 (#1431)
Bumps [ropey](https://github.com/cessen/ropey) from 1.3.1 to 1.3.2.
- [Release notes](https://github.com/cessen/ropey/releases)
- [Changelog](https://github.com/cessen/ropey/blob/master/CHANGELOG.md)
- [Commits](https://github.com/cessen/ropey/compare/v1.3.1...v1.3.2)

---
updated-dependencies:
- dependency-name: ropey
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-04 10:44:10 +09:00
dependabot[bot]
61fe1dc9e8 build(deps): bump serde from 1.0.132 to 1.0.133 (#1432)
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.132 to 1.0.133.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.132...v1.0.133)

---
updated-dependencies:
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-04 10:44:03 +09:00
Mathis Brossier
dbaed0ba83 scroll: change only main selection, only when needed (#1420)
Co-authored-by: mathis <mathis.brossier@universite-paris-saclay.fr>
2022-01-03 11:50:53 +09:00
WindSoilder
609f7363a1 Add everforest_light, change everforest_dark string color (#1412) 2022-01-03 11:32:47 +09:00
Omnikar
ed97ecceb8 Add :cquit! command and prevent :cquit from ignoring unsaved changes (#1414)
* Add `:cquit!` command and prevent `:cquit` from ignoring unsaved changes

* `cargo xtask docgen`
2022-01-03 11:31:24 +09:00
Kirawi
ea095ca5fb Optimize lsp_pos_to_pos (#1423)
lines().count() is slow compared to len_lines()
2022-01-03 11:26:17 +09:00
Triton171
4da050b4bb Add basic indentation for languages without treesitter-based indentation rules (always use the indent of the current line for a new line). (#1341)
Fix several bugs in the treesitter indentation calculation.

Co-authored-by: Triton171 <triton0171@gmail.com>
2022-01-03 11:03:57 +09:00
Sebastian Neubauer
8f2af71340 Add LLVM TableGen highlighting (#1409)
Add a tree-sitter grammar and highlights for TableGen files.
TableGen and its grammar are described here:
https://llvm.org/docs/TableGen/index.html

Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
2022-01-03 10:57:55 +09:00
Kirawi
93a948d889 switch redundant current! usage to doc! (#1416) 2022-01-03 10:46:57 +09:00
Martin Junghanns
aaa42e1a69 Underline diagnostics in bogster theme (#1399) 2022-01-02 13:45:22 +09:00
Flakebi
0dab6c8c17 Fix markdown code-block highlighting
Markdown code blocks should be highlighted as a single block, so set
injection.include-children.
2022-01-01 17:36:12 +08:00
Alexis Mousset
8a019b423f Detect workspace root using language markers (#1370)
* Detect workspace root using language markers

* Avoid allocating root_markers

* Update helix-core/src/lib.rs

Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>

* Update helix-core/src/lib.rs

Co-authored-by: Kirawi <67773714+kirawi@users.noreply.github.com>

Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
Co-authored-by: Kirawi <67773714+kirawi@users.noreply.github.com>
2021-12-31 17:06:54 +09:00
Michael Davis
8fda87af2b add tree-sitter-git-rebase (#1402)
* add submodule on tree-sitter-rebase, add to languages

* add basic highlights query

* inject bash in execute statements

* update tree-sitter-rebase

* tree-sitter-rebase->tree-sitter-git-rebase

* get injection working with tree-sitter-git-commit

* set scope under source.gitrebase

* unset include-children on commit message injections

* Revert "unset include-children on commit message injections"

This reverts commit 2ecee155ea.

* fix generated language docs

* use rebase_command scopes from tree-sitter-git-commit
2021-12-31 06:58:47 +08:00
Blaž Hrastnik
a066f59dc8 Don't just filter commands by fuzzy match, also order the matches 2021-12-30 15:20:22 +09:00
Michael Davis
bcf3808e97 Add tree-sitter-git-diff (#1373)
* add submodule on tree-sitter-git-diff

* add git-diff highlights

* inject git-diff into git-commit

* update tree-sitter-git-commit with fix for bad diff case

* add git-diff to language support docs

* include-children in diff injections

This ensures that children nodes of $.message are included in the
injection, such as $.user or issue/pr numbers. Without this change,
diffs containing '#' or '@' characters can trip up the injection and
be parsed separately.

See https://github.com/helix-editor/helix/pull/1373#issuecomment-1001215629

* set diff language's scope as source.diff
2021-12-30 00:31:23 +09:00
ath3
49444f9c05 Convert Windows style path separator in completers to Unix style (#1389) 2021-12-30 00:30:20 +09:00
Sebastian Neubauer
8c29b76bcc Improve llvm highlighting and queries (#1388)
* Improve llvm highlighting and queries

The llvm tree-sitter parser was updated to support scopes and more
accurate highlighting.

* Group highlight expressions better
2021-12-29 18:30:44 +09:00
WindSoilder
f1ed042c84 Fix: when goto normal mode, only want to remove indentation if the line is blank with no text following (#1349)
* when opened new line contains other characters after current position, don't dedent

* abstract checking logic
2021-12-29 18:21:20 +09:00
Stuart Hinson
34db33e1dc Use a fuzzy matcher for commands (#1386)
* Use a fuzzy matcher for commands

* Take Clippy up on its suggestion

* Rescope FUZZY_MATCHER
2021-12-29 18:18:17 +09:00
Matouš Dzivjak
bd2ab5be43 feat(commands): ensure_selections_forward (#1393)
* feat(commands): ensure_selections_forward

Add command that ensures that selections are in forward direction.

Fixes: https://github.com/helix-editor/helix/issues/1332

* Add keybinding for ensure_selections_forward

Add `A-:` keybinding for the ensure_selections_forward command.

* Re-use range.flip for flip_selections command
2021-12-29 18:17:46 +09:00
dependabot[bot]
dc1faa35cb build(deps): bump anyhow from 1.0.51 to 1.0.52 (#1392)
Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.51 to 1.0.52.
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.51...1.0.52)

---
updated-dependencies:
- dependency-name: anyhow
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-28 09:35:17 +09:00
dependabot[bot]
1d2009e4f0 build(deps): bump chardetng from 0.1.15 to 0.1.17 (#1390)
Bumps [chardetng](https://github.com/hsivonen/chardetng) from 0.1.15 to 0.1.17.
- [Release notes](https://github.com/hsivonen/chardetng/releases)
- [Commits](https://github.com/hsivonen/chardetng/compare/v0.1.15...v0.1.17)

---
updated-dependencies:
- dependency-name: chardetng
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-28 09:35:08 +09:00
Omnikar
5b69e9b466 Fix indentation (#1387) 2021-12-28 08:03:14 +09:00
Matouš Dzivjak
a4641a8613 feat(commands): sort command (#1288)
* feat(commands): sort/rsort  command

Add basic implementation of sort command.

* Sort by selections instead, implement reverse sort

* Generate docs

* Rename sort! to rsort
2021-12-27 13:11:06 +09:00
Stuart Hinson
7001665342 Add ruby indents (#1372)
* Add ruby indents

* Include ruby in generated docs
2021-12-27 13:07:09 +09:00
Omnikar
8340d73545 Extract macro parsing to helix-view and add unit tests 2021-12-27 10:13:18 +09:00
Omnikar
2d4bc0aec7 Change how macros separate keypresses
* Keypresses are no longer separated by spaces
* Single-character keypresses are serialized as-is
* Multi-character keypresses are delimited by `<>`
2021-12-27 10:13:18 +09:00
Ivan Tham
ee3eb4057a Update macro display as [q] in message 2021-12-27 10:13:18 +09:00
Ivan Tham
b9cb3930e2 Mark macros as experimental in docs
Given that currently macro does not integrate well with registers and
the internal representation of macros is expected to be changed.
2021-12-27 10:13:18 +09:00
Ivan Tham
9a32617b30 Rename play macro to replay macro
Macro needs to be defined first before playing so replay is more accurate.
Also, replay have the same length as record which makes it looks nice.
2021-12-27 10:13:18 +09:00
Ivan Tham
5326a05117 Improve macro error handling 2021-12-27 10:13:18 +09:00
Ivan Tham
c7a59e24e6 Switch macro Q and q 2021-12-27 10:13:18 +09:00
Tamo
a306a1052a Update settings at runtime (#798)
* feat: Update settings at runtime

fix the clippy warning

* update the documentation

* use to_value instead of to_vec+from_value

* drop the equal

* remove an useless comment

* apply suggestion
2021-12-26 10:04:33 +09:00
Michael Davis
6af0d51dc5 highlight rebase-commands as markup.raw 2021-12-26 00:12:49 +09:00
Michael Davis
c3fb86cbaa tree-sitter-gitcommit->tree-sitter-git-commit 2021-12-26 00:12:49 +09:00
Michael Davis
28c9afdd0e add commented-out diff and rebase injection queries 2021-12-26 00:12:49 +09:00
Michael Davis
c1f4c0e67a add new scopes to themes docs 2021-12-26 00:12:49 +09:00
Michael Davis
3b800025af add diff.{plus,minus,delta} to themes 2021-12-26 00:12:49 +09:00
Michael Davis
78f93239b5 add gitcommit highlights 2021-12-26 00:12:49 +09:00
Michael Davis
fd31662b70 add gitcommit grammar and language configuration 2021-12-26 00:12:49 +09:00
Matouš Dzivjak
4b0b1a5657 feat(ui): file encoding in statusline (#1355)
* feat(ui): file encoding in statusline

Display file encoding in statusline if the encoding
isn't UTF-8.

* Re-export encoding_rs from core

From there it can be imported by other mods
that rely on it.
2021-12-26 00:10:46 +09:00
Sebastian Neubauer
ec878e4011 Add textobjects and indents to cmake (#1307) 2021-12-26 00:10:19 +09:00
Gabriel Berto
5d7b5db8ab Resolve completion item (#1315)
Co-authored-by: Gabriel Berto <gabriel.berto@pottencial.com.br>
2021-12-25 19:00:57 +09:00
Matouš Dzivjak
0e7d757869 feat(lsp): configurable diagnostic severity (#1325)
* feat(lsp): configurable diagnostic severity

Allow severity of diagnostic messages to be configured.
E.g. allow turning of Hint level diagnostics.

Fixes: https://github.com/helix-editor/helix/issues/1007

* Use language_config() method

* Add documentation for diagnostic_severity

* Use unreachable for unknown severity level

* fix: documentation for diagnostic_severity config
2021-12-25 14:32:43 +09:00
BB
60f3225c7f Truncate the start of file paths in the StatusLine (#1351)
* Truncate the start of file paths in the StatusLine

* cargo fmt

Co-authored-by: Bódi Balázs <97936@4ig.hu>
2021-12-25 14:24:29 +09:00
chunghha
8aa0b8eacf chore: update rose pine themes to support markup (#1353) 2021-12-25 14:20:20 +09:00
Laurențiu Nicola
13d804418f Enable Rust proc macro support (#1350) 2021-12-24 23:56:13 +09:00
Gokul Soumya
b2f8f2ba77 Update onedark theme to use new scopes (#1297) 2021-12-24 11:18:04 +09:00
Stuart Hinson
02f24e1214 Fix match brackets comment (#1346) 2021-12-24 07:27:31 +05:30
Stuart Hinson
bb684a2b42 Typo fix in ocaml indents.toml (#1342) 2021-12-24 10:05:29 +09:00
Gokul Soumya
c0bbadcaaf Manually draw all block cursors 2021-12-23 11:56:52 +05:30
Gokul Soumya
a8618cf111 Add precise rust queries for use, mod, as (#1339)
- Differentiates between `as` keyword as a binary type cast
  operator and import renamer.
- `mod` and `use` are now under `@keyword.control.import`,
  but `mod` is a `@keyword` if used as `mod name;`.
2021-12-23 12:10:24 +09:00
Dylan Richardson
34766e242a languages: add .dockerfile extension (#1330)
Many folks use `.dockerfile` as an extension for dockerfiles in addition to plain `Dockerfile`. This change associates both file extensions with dockerfile syntax highlighting
2021-12-22 09:45:02 +09:00
Midnight Exigent
dba22c60ed Support dockerfiles (#1303)
* allow language.config (in languages.toml) to be passed in as a toml object

* Change config field for languages from json string to toml object

* remove indents on languages.toml config

* fix: remove patch version from serde_json import in helix-core

* Use same tree-sitter-zig as upstream/master

* fix(completion_popup): Fixes #1256

* Update helix-term/src/ui/completion.rs

* feat(languages): Add support for `Dockerfile`s

* docs(cargo-xtask-docgen):

* improvement(langs-dockerfile): Add `injection-regex` to `languages.toml` for
`Dockerfile`

* improvement(langs-dockerfile): Add injections.scm

* Update .gitmodules

Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
2021-12-21 18:22:15 +09:00
Matouš Dzivjak
75a8b789d2 LSP code action commands (#1304)
* feat(lsp): codeAction commands

* Don't block on command call

* Fix lifetime of command execution

* Fix lint issues
2021-12-21 18:21:45 +09:00
WindSoilder
600ce70cf6 Improve dedent behavior (#1232)
* tmp add code for dedent

* finish normal_mode with dedent behavior

* use function pointer

* rebase from origin

* check dedent condition inside normal_mode implementation

* using if let...

* fix check

* using char_is_whitespace instead of ch.is_whitespace

* fix clippy

* abstract restore_indent function
2021-12-21 18:17:55 +09:00
Skyler Hawthorne
5b4540fc2d Auto pairs selection (#1254)
* use auto pairs with selections

Previously, the auto pairs code was converting the user selection into
its cursor form, and setting the transaction's selection to that cursor.
This has the effect of destroying the user's selection if they type a
pair character that gets auto completed.

This fixes the code to work with the user's selection, inserting auto
pairs where appropriate, but either keeping or extending the user's
selection.

* use movement::Direction instead of bool

* assume 0-width cursor is forward
2021-12-21 18:17:33 +09:00
Ivan Tham
1c082cb4ef Add README for helix-syntax (#1312) 2021-12-21 12:38:32 +09:00
Gokul Soumya
176fbe760a docs: Add note about tree-sitter query precedence (#1314) 2021-12-21 11:03:44 +09:00
Sebastian Neubauer
205dc8776b Add fish highlighting (#1308)
The highlights were copied and modified from
https://github.com/nvim-treesitter/nvim-treesitter/blob/master/queries/fish/highlights.scm
2021-12-21 11:02:53 +09:00
dependabot[bot]
f16651b590 build(deps): bump serde from 1.0.131 to 1.0.132 (#1323)
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.131 to 1.0.132.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.131...v1.0.132)

---
updated-dependencies:
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-21 08:49:10 +09:00
dependabot[bot]
5dfdc95f6f build(deps): bump once_cell from 1.8.0 to 1.9.0 (#1322)
Bumps [once_cell](https://github.com/matklad/once_cell) from 1.8.0 to 1.9.0.
- [Release notes](https://github.com/matklad/once_cell/releases)
- [Changelog](https://github.com/matklad/once_cell/blob/master/CHANGELOG.md)
- [Commits](https://github.com/matklad/once_cell/compare/v1.8.0...v1.9.0)

---
updated-dependencies:
- dependency-name: once_cell
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-21 08:48:53 +09:00
dependabot[bot]
e02c0d1573 build(deps): bump signal-hook from 0.3.12 to 0.3.13 (#1318)
Bumps [signal-hook](https://github.com/vorner/signal-hook) from 0.3.12 to 0.3.13.
- [Release notes](https://github.com/vorner/signal-hook/releases)
- [Changelog](https://github.com/vorner/signal-hook/blob/master/CHANGELOG.md)
- [Commits](https://github.com/vorner/signal-hook/compare/v0.3.12...v0.3.13)

---
updated-dependencies:
- dependency-name: signal-hook
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-21 08:48:33 +09:00
dependabot[bot]
692ed7500f build(deps): bump actions/upload-artifact from 2.3.0 to 2.3.1 (#1316)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 2.3.0 to 2.3.1.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v2.3.0...v2.3.1)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-21 08:48:13 +09:00
dependabot[bot]
73f97fbb96 build(deps): bump futures-executor from 0.3.18 to 0.3.19 (#1317)
Bumps [futures-executor](https://github.com/rust-lang/futures-rs) from 0.3.18 to 0.3.19.
- [Release notes](https://github.com/rust-lang/futures-rs/releases)
- [Changelog](https://github.com/rust-lang/futures-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/futures-rs/compare/0.3.18...0.3.19)

---
updated-dependencies:
- dependency-name: futures-executor
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-21 08:47:56 +09:00
dependabot[bot]
25691061a2 build(deps): bump futures-util from 0.3.18 to 0.3.19 (#1319)
Bumps [futures-util](https://github.com/rust-lang/futures-rs) from 0.3.18 to 0.3.19.
- [Release notes](https://github.com/rust-lang/futures-rs/releases)
- [Changelog](https://github.com/rust-lang/futures-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/futures-rs/compare/0.3.18...0.3.19)

---
updated-dependencies:
- dependency-name: futures-util
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-21 08:47:39 +09:00
dependabot[bot]
65b7acea75 build(deps): bump num_cpus from 1.13.0 to 1.13.1 (#1320)
Bumps [num_cpus](https://github.com/seanmonstar/num_cpus) from 1.13.0 to 1.13.1.
- [Release notes](https://github.com/seanmonstar/num_cpus/releases)
- [Changelog](https://github.com/seanmonstar/num_cpus/blob/master/CHANGELOG.md)
- [Commits](https://github.com/seanmonstar/num_cpus/compare/v1.13.0...v1.13.1)

---
updated-dependencies:
- dependency-name: num_cpus
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-21 08:46:59 +09:00
dependabot[bot]
614e0e0026 build(deps): bump tokio from 1.14.0 to 1.15.0 (#1321)
Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.14.0 to 1.15.0.
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.14.0...tokio-1.15.0)

---
updated-dependencies:
- dependency-name: tokio
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-21 08:46:43 +09:00
Sebastian Zivota
7438db66ae Add dracula theme (#1258)
* Add dracula theme

* remove unused colors

* correctly name constant.character.escape

* Change cursors and selections

* add some missing ui scopes

* sorting
2021-12-20 22:37:47 +09:00
Gokul Soumya
f1c634326b Improve rust syntax highlighting (#1295)
- Highlight fragment specifiers (expr, tt, in macro
  definitions) with @type.
- Highlight attributes as macros
2021-12-20 11:47:40 +09:00
Sebastian Neubauer
23091c9d29 Highlight comments in c, cpp, cmake and llvm (#1309)
Also, reuse the c injections in glsl
2021-12-20 11:42:23 +09:00
Michael Davis
e72786df8e Add tree-sitter-comment (#1300)
* Add tree-sitter-comment

Fix #1164

* fix precedence in tree-sitter-comment highlights

connects https://github.com/helix-editor/helix/pull/1170

* set injection-regex for comment language

* remove comment filetype

* fix comment injections for neovim-style injections tags

* add comment injections for elixir

* remove f.comment

* fix spacing in .gitmodules

* run 'cargo xtask docgen'

Co-authored-by: Ivan Tham <pickfire@riseup.net>
2021-12-19 23:56:56 +09:00
Gokul Soumya
7c01d92653 Add link and quote queries for markdown
- Rename markup.underline.link to markup.link.url
- Add markup.link.label
- Add markup.quote

(The constructor theme scope was missing from the
docs, so unrelated to this commit).
2021-12-19 15:23:39 +09:00
Blaž Hrastnik
8208d22601 nix: Update flake.lock 2021-12-19 13:46:00 +09:00
Gokul Soumya
d52eda5d1b Improve yaml syntax highlighting highlighting (#1294) 2021-12-19 10:20:52 +09:00
Sebastian Neubauer
6d183b2154 Fix tree-sitter-llvm submodule (#1298)
Fix the path to the submodule and init the submodule.
2021-12-19 09:46:47 +09:00
Ivan Tham
f174d27d0d Change text for gg to explain <n>gg (#1287) 2021-12-18 20:28:17 +05:30
Kirawi
02fc52f6d5 Apply recent nightly suggestions (#1286)
array iterators are now implicit
2021-12-18 14:57:49 +09:00
Blaž Hrastnik
a66833590c cargo xtask docgen 2021-12-18 13:42:41 +09:00
Luke Jones
edf3c70c30 Add dart lsp config and queries (#1250)
* Add language: dart

The setup requires that dart be in the users path, such as:
```
export PATH="$HOME/Android/flutter/bin/cache/dart-sdk/bin/:$PATH"
```

Refactor the dart highlights

* lang: dart: add indents and locals

* lang: dart: corrections to local scope

Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
2021-12-18 13:41:32 +09:00
Oliver Hechtl
0683f0a20a Add scala syntax highlights (#1278)
* add partial scala syntax highlights

* ran cargo xtask docgen

* updated tree-sitter-scala, fixed highlights

* fix comments

* move identifier to the end of the highlights

* add indents
2021-12-18 13:40:34 +09:00
Gokul Soumya
d4fb1d0633 Merge branch 'master' into cursor-shape-new 2021-12-18 08:33:15 +05:30
Gokul Soumya
016640f4fb Remove ui.cursor.primary and hashmap lookups 2021-12-18 08:26:11 +05:30
Chetan Vardhan
3ef115d420 Add instructions for Fedora Linux (#1270)
* Add instructions for Fedora Linux

* Update README.md

* Update install.md
2021-12-17 23:46:32 +09:00
Blaž Hrastnik
5d91335d6b Fix more highlight scopes 2021-12-17 17:04:59 +09:00
Blaž Hrastnik
9c484e88cf highlights: @include -> @keyword.control.import 2021-12-17 17:04:59 +09:00
Blaž Hrastnik
78b6155292 Partly fix julia's locals.scm 2021-12-17 17:04:59 +09:00
ath3
a8060c06d1 Add indents.toml to perl (#1280) 2021-12-17 09:56:07 +09:00
WindSoilder
0c447151cf In README, add example for windows config directory (#1273)
* better doc for windows user

* fix doc
2021-12-16 10:48:49 +09:00
Blaž Hrastnik
ac4b72fcc8 Add injections query for markdown 2021-12-15 18:03:02 +09:00
Blaž Hrastnik
40969ad452 Partly fix latex highlights and add markup scope docs 2021-12-15 17:46:40 +09:00
Blaž Hrastnik
9bfb701c94 Update lang-support.md 2021-12-15 17:38:03 +09:00
Blaž Hrastnik
49e0678741 Add markdown grammar
Fixes #215
2021-12-15 00:50:11 +09:00
Omnikar
6da2174e14 Allow paste commands to take a count (#1261)
* Allow paste commands to take a count

* Call `.repeat` within iterator methods

* Implement counts for paste-replace
2021-12-14 17:49:29 +09:00
Blaž Hrastnik
4527d63a65 fix: rust: disable unresolved-proc-macro
Since we disabled proc macro expansion, disable the related info
level lint:

https://users.rust-lang.org/t/how-to-disable-rust-analyzer-proc-macro-warnings-in-neovim/53150/3
2021-12-14 13:58:26 +09:00
Midnight Exigent
e188926138 Fix panic when scrolling through completion popup (#1260)
* fix(completion_popup): Fixes #1256

* Update helix-term/src/ui/completion.rs

Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
2021-12-14 10:14:23 +09:00
dependabot[bot]
10ad25b95b build(deps): bump actions/upload-artifact from 2.2.4 to 2.3.0 (#1263)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 2.2.4 to 2.3.0.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v2.2.4...v2.3.0)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-14 09:34:11 +09:00
dependabot[bot]
5404a3f01b build(deps): bump serde from 1.0.130 to 1.0.131 (#1264)
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.130 to 1.0.131.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.130...v1.0.131)

---
updated-dependencies:
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-14 09:33:43 +09:00
dependabot[bot]
3820258c57 build(deps): bump serde_json from 1.0.72 to 1.0.73 (#1265)
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.72 to 1.0.73.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.72...v1.0.73)

---
updated-dependencies:
- dependency-name: serde_json
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-14 09:33:30 +09:00
dependabot[bot]
b711687e19 build(deps): bump encoding_rs from 0.8.29 to 0.8.30 (#1266)
Bumps [encoding_rs](https://github.com/hsivonen/encoding_rs) from 0.8.29 to 0.8.30.
- [Release notes](https://github.com/hsivonen/encoding_rs/releases)
- [Commits](https://github.com/hsivonen/encoding_rs/compare/v0.8.29...v0.8.30)

---
updated-dependencies:
- dependency-name: encoding_rs
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-14 09:26:07 +09:00
dependabot[bot]
ca0c5fb08c build(deps): bump signal-hook from 0.3.10 to 0.3.12 (#1267)
Bumps [signal-hook](https://github.com/vorner/signal-hook) from 0.3.10 to 0.3.12.
- [Release notes](https://github.com/vorner/signal-hook/releases)
- [Changelog](https://github.com/vorner/signal-hook/blob/master/CHANGELOG.md)
- [Commits](https://github.com/vorner/signal-hook/compare/v0.3.10...v0.3.12)

---
updated-dependencies:
- dependency-name: signal-hook
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-14 09:25:31 +09:00
Skyler Hawthorne
94535fa013 Add auto pairs for same-char pairs (#1219)
* Add auto pairs for same-char pairs

* Add unit tests for all existing functionality
* Add auto pairs for same-char pairs (quotes, etc). Account for
  apostrophe in prose by requiring both sides of the cursor to be
  non-pair chars or whitespace. This also incidentally will work for
  avoiding a double single quote in lifetime annotations, at least until
  <> is added
* Slight factor of moving the cursor transform of the selection to
  inside the hooks. This will enable doing auto pairing with selections,
  and fixing the bug where auto pairs destroy the selection.

Fixes #1014
2021-12-14 00:58:58 +09:00
Blaž Hrastnik
730d3be201 Add ui.gutter to theme all gutters (i.e. set bg) 2021-12-14 00:52:15 +09:00
NNB
c7ace15fd4 Add ui.gutter theming 2021-12-14 00:48:45 +09:00
Omnikar
cce34feb4e Assume true color support on Windows 2021-12-14 00:48:45 +09:00
Omnikar
42e6d96a75 Use base16_tty as 16-color default, fix theme name 2021-12-14 00:48:45 +09:00
NNB
d9727868dd change to .unwrap_or_default() and fix ui.window and ui.statusline 2021-12-14 00:48:45 +09:00
NNB
3080be8268 Fix error color, add tty theme 2021-12-14 00:48:45 +09:00
NNB
a9a9d498e8 Update theme.rs 2021-12-14 00:47:30 +09:00
NNB
cff5344a13 Rename base16_theme.toml to base16_terminal.toml 2021-12-14 00:47:30 +09:00
Omnikar
98ce2a301d Load alt default theme if true color is not supported
* Move `runtime/themes/base16_default_terminal.toml` to
  `base16_theme.toml` alongside `theme.toml`
* Use `terminfo` crate to detect whether the terminal supports true
  color and, if the user has no theme configured and their terminal does
  not support true color, load the alt default theme instead of the
  normal default.

Remove `terminfo` dependency, use `COLORTERM` env instead

Prevent user from switching to an unsupported theme

Add `true-color-override` option

If the terminal is wrongly detected to not support true color,
`true-color-override = true` will override the detection.

Rename `true-color-override` to `true-color`
2021-12-14 00:47:18 +09:00
NNB
43d17c482c Fix Base16 Dark, add Base16 Light and Terminal
Improve accuracy with line number and cursor color
2021-12-14 00:47:02 +09:00
Blaž Hrastnik
7ad8eaaef0 wip 2021-12-14 00:41:51 +09:00
Blaž Hrastnik
b25d453f64 minor: Shorten goto file(s) descriptions 2021-12-13 14:36:53 +09:00
Omnikar
e91d357fae Macros (#1234)
* Macros WIP

`helix_term::compositor::Callback` changed to take a `&mut Context` as
a parameter for use by `play_macro`

* Default to `@` register for macros

* Import `KeyEvent`

* Special-case shift-tab -> backtab in `KeyEvent` conversion

* Move key recording to the compositor

* Add comment

* Add persistent display of macro recording status

When macro recording is active, the pending keys display will be shifted
3 characters left, and the register being recorded to will be displayed
between brackets — e.g., `[@]` — right of the pending keys display.

* Fix/add documentation
2021-12-12 21:16:48 +09:00
ath3
3156577fbf Open files with spaces in filename, allow opening multiple files (#1231) 2021-12-12 21:13:33 +09:00
Blaž Hrastnik
3307f44ce2 ui: popup: Don't allow scrolling past the end of content 2021-12-10 19:23:58 +09:00
Omnikar
b66d3d3d9d Add save_selection command (#1247) 2021-12-10 11:46:24 +09:00
Omnikar
44681c5057 Add default-run = "hx" to helix-term/Cargo.toml (#1244)
Following the addition of `xtask`, `cargo run` has multiple possible
targets, necessitating the usage of `cargo run --bin hx` to run Helix
during development. This allows `cargo run` to be used to run `hx`.
2021-12-10 11:04:31 +09:00
Blaž Hrastnik
df3b88387b dap: Improve variables UI 2021-12-09 11:28:53 +09:00
Blaž Hrastnik
dac317e620 TODO 2021-12-09 10:55:32 +09:00
Blaž Hrastnik
60c86eff89 dap: Simplify a few more statements that could use the debugger macro 2021-12-09 10:55:32 +09:00
Oskar Nehlin
a1e64815cb Update book to include typable command remapping (#1240)
* Update book to include typable command remapping

* Add additional example
2021-12-09 00:26:33 +09:00
Kirawi
29c053e84e Only use a single documentation popup (#1241) 2021-12-08 16:11:18 +09:00
Gokul Soumya
d08bdfa838 Use same name used in config files for langs in docs 2021-12-08 10:23:50 +09:00
Gokul Soumya
70c989e122 Add github action to lint unmerged docs 2021-12-08 10:23:50 +09:00
Gokul Soumya
a78b789406 Auto generate docs for language support 2021-12-08 10:23:50 +09:00
Gokul Soumya
71292f9f11 docs: Auto generate command list 2021-12-08 10:23:50 +09:00
Skyler Hawthorne
9bdbafa075 Fix solarized selection colors (#1236)
* do not select a foreground color in selections, as this eliminates
  syntax coloring
* select lighter color for selections
* Make non-primary cursor cyan instead of green
2021-12-08 10:22:55 +09:00
Blaž Hrastnik
d8351d35ab dap: Extract a macro that fetches a debugger or returns 2021-12-08 00:59:11 +09:00
Blaž Hrastnik
e98993d609 dap: Fix an off-by-one error when jumping 2021-12-08 00:22:48 +09:00
Omnikar
178cd5ecfc Add note to keymap.md regarding format_selections (#1230) 2021-12-07 01:44:50 +09:00
WindSoilder
93e276cd9d Make kill_to_line_end behave like emacs (#1235) 2021-12-07 01:44:04 +09:00
Blaž Hrastnik
35ac815409 Fix compilation
nix-direnv issues still mess with my shell..
2021-12-06 12:50:28 +09:00
Blaž Hrastnik
a2b22ec152 Use binary_search when looking up diagnostics
They're sorted by range so they should also be sorted by line
2021-12-06 12:48:25 +09:00
Blaž Hrastnik
cab09093dd fix: Normalize backtab into shift-tab
Fixes #1150
2021-12-06 12:25:19 +09:00
Blaž Hrastnik
bf8437d098 clippy lint 2021-12-06 09:36:02 +09:00
Blaž Hrastnik
dc8df7ba21 Make thread_picker non-blocking 2021-12-06 09:35:59 +09:00
Blaž Hrastnik
2b4de41bf0 dap: Reply to RunInTerminal 2021-12-06 09:32:21 +09:00
Blaž Hrastnik
d5d1a9b1ae Apply suggestions from code review
Co-authored-by: Gokul Soumya <gokulps15@gmail.com>
2021-12-06 09:32:11 +09:00
Jason Rodney Hansen
461cd20563 Small change 2021-12-05 16:22:58 +08:00
Jason Rodney Hansen
539c27e3f5 Remove Clone derive 2021-12-05 16:22:58 +08:00
Jason Rodney Hansen
0b7911d921 Remove FormatError 2021-12-05 16:22:58 +08:00
Jason Rodney Hansen
31ed91dc2e Don't increment for overlapping changes 2021-12-05 16:22:58 +08:00
Jason Rodney Hansen
584a31cd90 Used checked_add for years and months 2021-12-05 16:22:58 +08:00
Jason Rodney Hansen
c74cd48f38 Cleanup 2021-12-05 16:22:58 +08:00
Jason Rodney Hansen
febee2dc0c No need to clone format 2021-12-05 16:22:58 +08:00
Jason Rodney Hansen
37e484ee38 Add support for time and more date formats 2021-12-05 16:22:58 +08:00
Jason Rodney Hansen
c9641fcced Add Increment trait 2021-12-05 16:22:58 +08:00
Jason Rodney Hansen
2a0c685a78 Remove dependency on gregorian crate 2021-12-05 16:22:58 +08:00
Jason Rodney Hansen
64afd54654 Cleanup 2021-12-05 16:22:58 +08:00
Jason Rodney Hansen
cc04fabe40 Formatting 2021-12-05 16:22:58 +08:00
Jason Rodney Hansen
57a8e79940 No default features for gregorian 2021-12-05 16:22:58 +08:00
Jason Rodney Hansen
95cfeed2fa Add support for incrementing year and month 2021-12-05 16:22:58 +08:00
Jason Rodney Hansen
c1f6167e37 Add support for dates for increment/decrement 2021-12-05 16:22:58 +08:00
ath3
11a2f9ac31 Assert in release mode too on duplicate keys (#1228) 2021-12-05 13:04:10 +09:00
Oskar Nehlin
a06871a689 feat: Make it possible to keybind TypableCommands (#1169)
* Make TypableCommands mappable

* Fix pr comments

* Update PartialEq implementation
2021-12-04 20:17:18 +05:30
ath3
70c62530ee Support env flags in shebang (#1224) 2021-12-04 00:13:24 +09:00
chunghha
038a6ce22c rose_pine_dawn.toml colorscheme (#1226)
* adds: rose_pine_dawn.toml colorscheme

* chore: define ui.statusline.inactive colors of rose_pine
2021-12-03 23:14:03 +09:00
WindSoilder
cf40e61b0a add more monokai pro filter themes (#1220) 2021-12-03 23:13:21 +09:00
Blaž Hrastnik
5545f8ebb5 dap: Add RunInTerminal reverse request, support replying to requests 2021-12-03 16:09:28 +09:00
Blaž Hrastnik
bcf70d8e67 dap: All of these calls don't need &mut 2021-12-03 13:29:46 +09:00
Blaž Hrastnik
43fbb6d965 Make dap_start non-blocking 2021-12-03 13:27:00 +09:00
Blaž Hrastnik
371c84f70b cargo fmt 2021-12-03 12:51:55 +09:00
Blaž Hrastnik
34f46e7502 Bump rust to 1.57, fix new lint failures 2021-12-03 12:48:07 +09:00
Blaž Hrastnik
032aaffa15 dap: Split call/request in the same way LSP does 2021-12-03 12:41:07 +09:00
Blaž Hrastnik
2dbf966293 dap: Start working on runInTerminal support 2021-12-03 11:59:44 +09:00
Blaž Hrastnik
0d73a4d23a dap: console = internalConsole is actually not a lldb-vscode param 2021-12-03 10:18:23 +09:00
Blaž Hrastnik
d31bef7fea lsp: Don't panic if init fails
We correctly filter out the language server inside Document to ignore it
if the capabilities are missing, so this way it'll simply ignore the
errored out LSP rather than panicking.
2021-12-03 10:05:27 +09:00
Blaž Hrastnik
01f7a312d0 Address new lint on 1.57 2021-12-03 10:02:44 +09:00
Blaž Hrastnik
a45df12699 nix: Update to lld 13, drop flake-compat (was unused) 2021-12-03 10:02:07 +09:00
Blaž Hrastnik
119dee2980 fix: Correctly detect empty transactions
Fixes #1221
2021-12-02 23:49:54 +09:00
WindSoilder
27ffc79c44 Add monokai pro theme (#1206)
* add monokai_pro theme

* add monokai_pro theme

* claim the inspired theme and original author

* make diagnostic underlined
2021-12-02 13:51:27 +09:00
Ivan Tham
e2b428cc2d Add last modified file (gm) (#1093) 2021-12-02 13:46:57 +09:00
Bob
418b833d2b fix goto_window index crash (#1207) 2021-12-02 13:42:34 +09:00
Blaž Hrastnik
d14ca05d6b Simplify some cases that use return None to use ? 2021-12-02 10:31:19 +09:00
Blaž Hrastnik
de5e5863aa dap: Use cursor_line over cursor + char_to_line 2021-12-02 10:24:17 +09:00
Blaž Hrastnik
54f8e5c9c3 dap: Fix an off-by-one and move the function over to commands/dap 2021-12-02 10:22:17 +09:00
Blaž Hrastnik
573cb39926 dap: Remove some unwraps 2021-12-02 10:20:19 +09:00
Blaž Hrastnik
ffc89e483b Mark some more TODOs as resolved 2021-12-01 19:28:29 +09:00
Blaž Hrastnik
dfd499f5a9 dap: Highlight line of current stack frame 2021-12-01 19:23:42 +09:00
Blaž Hrastnik
c955eaa6cd Revert "Improve dedent behavior, make kill_to_line_end behave like emacs (#1173)"
1. pressing o on a line with no indentation will open a new line as
   expected, but esc will then delete the line altogether

2. the kill_line behavior happens after insert mode changes are already
   commited to history, and the change isn't commited. pressing u after
   this will break highlighting & undo history

This reverts commit c08d2fae58.
2021-12-01 13:40:54 +09:00
Blaž Hrastnik
662ecf0cd4 Annotate Theme::highlight with #[inline] 2021-12-01 13:13:50 +09:00
Blaž Hrastnik
259678585c ui: Optimize tree-sitter style lookups
Tree sitter returns an index referring to the position of the scope in
the scopes array. We can use that same index to avoid a hashmap lookup
and instead store the styles in an array.

This currently stores the styles in both a map and an array because the
UI still uses hashmap lookups, but it's a reasonable tradeoff.
2021-12-01 13:08:20 +09:00
Blaž Hrastnik
7bbf4c5b06 ui: Only calculate span styling when it's actually in bounds 2021-12-01 12:57:57 +09:00
Blaž Hrastnik
d562e13e1f minor: Use anchor::ensure in some cases 2021-12-01 12:57:22 +09:00
Blaž Hrastnik
b4fd3148e3 These TODOs have been resolved 2021-12-01 12:56:41 +09:00
George Rodrigues
3e15aead4a Fix typo on docs (#1201) 2021-12-01 09:11:25 +09:00
Blaž Hrastnik
96ae5897a1 Remove another parameter from render_view 2021-12-01 01:08:52 +09:00
Blaž Hrastnik
84e939ef58 Provide a single gutter component that does breakpoint || diagnostic 2021-12-01 00:24:45 +09:00
Blaž Hrastnik
d906911417 dap: Prevent crashes on files with no name or breakpoints 2021-11-30 17:59:30 +09:00
Blaž Hrastnik
30ac5869df dap: Extract diagnostics gutter into gutters.rs 2021-11-30 17:56:00 +09:00
Blaž Hrastnik
8ffafb826f dap: Rewrite breakpoints so that there's a single set maintained 2021-11-30 17:56:00 +09:00
Blaž Hrastnik
3633f85b38 Pass editor into render_view & gutter, reducing the number of params 2021-11-30 16:47:46 +09:00
WindSoilder
c08d2fae58 Improve dedent behavior, make kill_to_line_end behave like emacs (#1173)
* restore indent when press esc right after open a new line

* add comment for restore_indent

* fix, and make kill to line end behaves like emacs

* update comment

* fix comment

* adjust cancel restore_indent situation

* check esc logic in mode transaction

* improve comment

* add more check for dedent

* update comment

* use matches to check for last_cmd

* no need to introduct CommandFun type
2021-11-30 16:40:38 +09:00
Blaž Hrastnik
9ed930b233 Merge remote-tracking branch 'origin/master' into debug 2021-11-30 13:06:30 +09:00
dependabot[bot]
94296229e7 build(deps): bump futures-executor from 0.3.17 to 0.3.18
Bumps [futures-executor](https://github.com/rust-lang/futures-rs) from 0.3.17 to 0.3.18.
- [Release notes](https://github.com/rust-lang/futures-rs/releases)
- [Changelog](https://github.com/rust-lang/futures-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/futures-rs/compare/0.3.17...0.3.18)

---
updated-dependencies:
- dependency-name: futures-executor
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-30 09:08:37 +09:00
dependabot[bot]
5313d0f04e build(deps): bump anyhow from 1.0.48 to 1.0.51
Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.48 to 1.0.51.
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.48...1.0.51)

---
updated-dependencies:
- dependency-name: anyhow
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-30 08:48:36 +09:00
dependabot[bot]
fcd39adcaa build(deps): bump futures-util from 0.3.17 to 0.3.18
Bumps [futures-util](https://github.com/rust-lang/futures-rs) from 0.3.17 to 0.3.18.
- [Release notes](https://github.com/rust-lang/futures-rs/releases)
- [Changelog](https://github.com/rust-lang/futures-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/futures-rs/compare/0.3.17...0.3.18)

---
updated-dependencies:
- dependency-name: futures-util
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-30 08:47:25 +09:00
dependabot[bot]
987c4ad97f build(deps): bump serde_json from 1.0.71 to 1.0.72
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.71 to 1.0.72.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.71...v1.0.72)

---
updated-dependencies:
- dependency-name: serde_json
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-30 08:47:17 +09:00
dependabot[bot]
82889d7c41 build(deps): bump actions/cache from 2.1.6 to 2.1.7
Bumps [actions/cache](https://github.com/actions/cache) from 2.1.6 to 2.1.7.
- [Release notes](https://github.com/actions/cache/releases)
- [Commits](https://github.com/actions/cache/compare/v2.1.6...v2.1.7)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-30 08:47:10 +09:00
Corey Powell
0dd2303f64 Merge pull request #1184 from nichobi/patch-1
Remove defunct helix-bin AUR link
2021-11-29 08:51:46 -05:00
Nicholas Boyd Isacsson
6204c38556 Remove defunct helix-bin AUR link 2021-11-29 13:07:32 +01:00
Gokul Soumya
058796c18e Change default cursors to block for all modes 2021-11-29 11:09:04 +05:30
Blaž Hrastnik
225e8ccf31 Extract gutters into helix-view 2021-11-29 11:00:28 +09:00
Blaž Hrastnik
27c1a84f05 Reuse a text buffer for each gutter line 2021-11-29 11:00:28 +09:00
Blaž Hrastnik
ba45db84d4 Tie the GutterFn lifetime to the doc so we can avoid cloning data 2021-11-29 11:00:28 +09:00
Blaž Hrastnik
c71c9f69e2 TODO 2021-11-29 11:00:28 +09:00
Blaž Hrastnik
30171416cb Gutter functions 2021-11-29 11:00:28 +09:00
Bob
42fde95223 Accept count for goto_window (#1033)
* accept count for goto_window

also fix view is not fullfilled issue

* fix fulfilled mispell

* Update helix-term/src/commands.rs

Co-authored-by: Ivan Tham <pickfire@riseup.net>

* Update helix-term/src/commands.rs

Co-authored-by: Ivan Tham <pickfire@riseup.net>

* fix merge issue

* revert line computation logic

Co-authored-by: Ivan Tham <pickfire@riseup.net>
2021-11-29 10:58:21 +09:00
Bob
4f9390a435 gf as goto_file (#1102)
* goto_file

* support goto_file under current cursor

* add C-w f/F

* sync space w with window mode

* Update helix-term/src/commands.rs

Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
2021-11-29 10:53:29 +09:00
Kirawi
6f1a7b1220 Add llvm grammar (#1167) 2021-11-29 10:38:17 +09:00
Gokul Soumya
dc53e65b9e Fix surround cursor position calculation (#1183)
Fixes #1077. This was caused by the assumption that a block
cursor is represented as zero width internally and simply
rendered to be a single width selection, where as in reality
a block cursor is an actual single width selection in form and
function.

Behavioural changes:

1. Surround selection no longer works when cursor is _on_ a
    surround character that has matching pairs (like `'`
    or `"`). This was the intended behaviour from the start
    but worked till now because of the cursor position
    calculation mismatch.
2021-11-29 10:33:53 +09:00
ath3
1d773bcefb Implement black hole register (#1165) 2021-11-28 10:21:40 +09:00
RustyStriker
103b5125e4 Detect filetype on :write (#1141)
fixes #1136

* removed a log::info

* removed temp.rs

* cargo clippy no longer complains

* new get_lang_server function

* get_lang_server is now launch_language_server

* launch_lang_server will now close the previous one

* better code readability

* remove resfresh_ls(and a wrong comment)
2021-11-28 10:19:54 +09:00
ath3
3b2b7341a5 Fix next char delete key documentation for prompt (#1180) 2021-11-28 10:18:25 +09:00
Kirawi
4ec20eaeff Add language support for WGSL (#1166) 2021-11-27 07:49:40 +05:30
Blaž Hrastnik
6e62c3de47 Simplify some code in editor.rs 2021-11-26 18:26:22 +09:00
Gokul Soumya
17473b51d3 Use serde attribute to rename to lowercase 2021-11-25 22:35:07 +05:30
Ivan Tham
67bf4250ca Optimize space for DocumentId with NonZeroUsize (#1097)
Now Option<DocumentId> uses one byte rather than two
2021-11-25 11:07:23 +09:00
Thanabodee Charoenpiriyakij
e8f800a141 Do not crash when run goto command without line number (#1160)
* Do not crash when run goto command without line number

Report an error when running goto command without entering a
line number.

Fixes #1159

* Use is_empty() instead check len zero
2021-11-25 11:02:51 +09:00
Thanabodee Charoenpiriyakij
95f392b18d Fix bug report template use wrong hx version (#1158) 2021-11-24 20:58:25 +05:30
shenlebantongying
1eecd9a2ac Add language: racket (#1143) 2021-11-24 22:47:12 +09:00
ath3
72f606ee19 Implement no-yank delete/change (#1099) 2021-11-24 16:46:40 +09:00
Gokul Soumya
7961355ba1 Change cursor shape on mode change
Fixes #323. Due to terminal limitations we can only
change the shape of the primary cursor.
2021-11-24 12:26:49 +05:30
Martin Junghanns
57c14d4a93 Add :<line> and :goto <line> commands (#1128)
* Add typable `goto` command

* Support `:<line-number>` on prompt

* Rename function according to convention

* Directly call into goto_line_number function
2021-11-24 15:26:55 +09:00
Bob
21143e8d22 Align selections via & (#1101)
* align lines

* remove log statement

* use selections to align

* fix a clippy issue

* only accept 1,2,3 as user count

* Update helix-term/src/commands.rs

Co-authored-by: Ivan Tham <pickfire@riseup.net>

* return if user count is not correct

* add doc

Co-authored-by: Ivan Tham <pickfire@riseup.net>
2021-11-23 23:08:05 +09:00
dependabot[bot]
f24e5a3c41 build(deps): bump tokio from 1.13.1 to 1.14.0 (#1146)
Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.13.1 to 1.14.0.
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.13.1...tokio-1.14.0)

---
updated-dependencies:
- dependency-name: tokio
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-23 10:07:59 +09:00
dependabot[bot]
2cc19bd8e4 build(deps): bump serde_json from 1.0.70 to 1.0.71 (#1147)
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.70 to 1.0.71.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.70...v1.0.71)

---
updated-dependencies:
- dependency-name: serde_json
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-23 09:56:58 +09:00
dependabot[bot]
a2f301ee4f build(deps): bump anyhow from 1.0.46 to 1.0.48 (#1144)
Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.46 to 1.0.48.
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.46...1.0.48)

---
updated-dependencies:
- dependency-name: anyhow
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-23 09:56:35 +09:00
dependabot[bot]
8fec8c0791 build(deps): bump tree-sitter from 0.20.0 to 0.20.1 (#1145)
Bumps [tree-sitter](https://github.com/tree-sitter/tree-sitter) from 0.20.0 to 0.20.1.
- [Release notes](https://github.com/tree-sitter/tree-sitter/releases)
- [Commits](https://github.com/tree-sitter/tree-sitter/compare/v0.20.0...v0.20.1)

---
updated-dependencies:
- dependency-name: tree-sitter
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-23 09:55:20 +09:00
NexiNov
4238a843f7 Add link to Keymap page in book. (#1137) 2021-11-22 20:14:42 +05:30
Blaž Hrastnik
72576822f3 dap: Replace breakpoint when changed event comes through 2021-11-22 16:30:56 +09:00
Blaž Hrastnik
85b4410703 dap: Toggle breakpoints without changing selection, fix offset calc 2021-11-22 16:30:35 +09:00
Blaž Hrastnik
177b6fcdc9 cargo fmt 2021-11-22 12:10:37 +09:00
Blaž Hrastnik
28fd704bce ui: Since diagnostics are sorted, we can use binary search 2021-11-22 11:26:16 +09:00
Blaž Hrastnik
b55ca8fdb8 dap: Always edit breakpoints on the correct document 2021-11-22 11:22:08 +09:00
Blaž Hrastnik
0eadeab8c7 dap: Remove the prompt line parameter, use insert_str instead 2021-11-22 11:14:10 +09:00
Blaž Hrastnik
5f329a22c4 dap: Modify breakpoints in place with no cloning 2021-11-22 11:09:09 +09:00
Blaž Hrastnik
3b3c396ca4 nix: Update to lld 13, drop flake-compat (was unused) 2021-11-22 10:32:35 +09:00
NNB
1724930765 Fix "good first issue" link (#1140) 2021-11-22 07:16:26 +09:00
Blaž Hrastnik
05d3ad4a0e dap: Remove an excess clone on enable_exceptions 2021-11-22 00:02:58 +09:00
Blaž Hrastnik
d1854d8e6a Merge remote-tracking branch 'origin/master' into debug 2021-11-21 20:06:45 +09:00
Dan Nases Sha
6a4d9693ba File picker config (#988)
* squashed WIP commits

* hide_gitignore working with config

* pass reference to new config parameter of file_picker()

* update config option name to match name on walk builder

* add comments to config and documentation of option to book

* add git_ignore option to WalkBuilder within prompt in commands.rs

* WIP: add FilePickerConfig struct

* WIP: cleanup

* WIP: add more options including max_depth

* WIP: changed defaults to match ignore crate defaults

* WIP: change WalkBuilder in global_search() to use config options

* WIP: removed follow_links, changed max_depth to follow config setting

* WIP: update book with file-picker inline table notation

* update documentation for file-picker config in book

* adjusted to [editor.file-picker] in book configuration.md

* adjust comments in editor.rs to be doc comments, cleanup

* adjust comments

* adjust book
2021-11-20 23:23:36 +09:00
Skyler Hawthorne
05c6cb1d0b Solarized theme: fix popup colors, adjust menu (#1124)
* fix popup colors, adjust menu

* fix hardcoded horizontal rule color
2021-11-20 23:17:38 +09:00
Martin Junghanns
a3a3b0b517 Jump to end char of surrounding pair from any cursor pos (#1121)
* Jump to end char of surrounding pair from any cursor pos

* Separate bracket matching into exact and fuzzy search

* Add constants for bracket chars

* Abort early if char under cursor is not a bracket

* Simplify bracket char validation

* Refactor node search and unify find methods

* Remove bracket constants
2021-11-20 23:17:25 +09:00
Koen Van der Auwera
b95c9470de Add spacebones light theme (#1131)
* Add spacebones light theme

* Fix error background
2021-11-20 07:22:06 +05:30
Kirawi
ed76cdf238 revert log truncation (#895) (#1130) 2021-11-19 13:26:39 +09:00
Blaž Hrastnik
2b7c086653 fix: Expand tilde first, then deal with relative paths
Otherwise the ~ gets treated as a relative path.

Fixes #1107
2021-11-19 12:09:17 +09:00
Martin Junghanns
f2b4ff23ba Document scrolling for hover command in keymap.md (#1117)
* Document scrolling for hover command in keymap.md

* Move popup keys to a dedicated section
2021-11-19 11:58:22 +09:00
WindSoilder
5959356a24 Implement indent-aware delete (#1120)
* delete character backward can make undent behavior

* improve to handle mixed indentation
2021-11-19 00:19:40 +09:00
Ivan Tham
bd56dde6e2 Ensure cursor in view after pipe (#1123)
Fix #1024
2021-11-18 18:46:27 +09:00
Blaž Hrastnik
e9dc658de4 Remove unused imports 2021-11-18 18:41:44 +09:00
Blaž Hrastnik
9dcccb45bb ui: Stop hardcoding markdown doc colors 2021-11-18 18:40:27 +09:00
Blaž Hrastnik
27ceeb83bb Simplify view/doc macros 2021-11-18 14:13:42 +09:00
Blaž Hrastnik
fa4c59df46 Simplify compositor.find 2021-11-18 11:09:04 +09:00
ath3
90fd09f2cc Fix selection remove doc comment (#1122) 2021-11-18 09:49:56 +09:00
WindSoilder
1132b7088a improve nord status bar line 2021-11-16 22:06:21 +08:00
Blaž Hrastnik
8db6fffe90 ui: Increase diagnostics sideline width to 100 max and wrap if needed 2021-11-16 15:02:48 +09:00
Skyler Hawthorne
335ed7fa69 Improve Solarzed Dark theme (#1105)
Adjusts the Solarized Dark theme to be modeled more closely after
vim's incarnation. Also adjust the Solarized Light theme to match.
2021-11-16 12:34:25 +09:00
dependabot[bot]
f1d3d97004 build(deps): bump libloading from 0.7.1 to 0.7.2 (#1113)
Bumps [libloading](https://github.com/nagisa/rust_libloading) from 0.7.1 to 0.7.2.
- [Release notes](https://github.com/nagisa/rust_libloading/releases)
- [Commits](https://github.com/nagisa/rust_libloading/commits)

---
updated-dependencies:
- dependency-name: libloading
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-16 11:22:01 +09:00
dependabot[bot]
39479949fc build(deps): bump serde_json from 1.0.69 to 1.0.70 (#1112)
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.69 to 1.0.70.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.69...v1.0.70)

---
updated-dependencies:
- dependency-name: serde_json
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-16 11:21:32 +09:00
dependabot[bot]
bc31d998de build(deps): bump cc from 1.0.71 to 1.0.72 (#1111)
Bumps [cc](https://github.com/alexcrichton/cc-rs) from 1.0.71 to 1.0.72.
- [Release notes](https://github.com/alexcrichton/cc-rs/releases)
- [Commits](https://github.com/alexcrichton/cc-rs/compare/1.0.71...1.0.72)

---
updated-dependencies:
- dependency-name: cc
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-16 11:21:20 +09:00
dependabot[bot]
411f522e5d build(deps): bump arc-swap from 1.4.0 to 1.5.0 (#1110)
Bumps [arc-swap](https://github.com/vorner/arc-swap) from 1.4.0 to 1.5.0.
- [Release notes](https://github.com/vorner/arc-swap/releases)
- [Changelog](https://github.com/vorner/arc-swap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/vorner/arc-swap/compare/v1.4.0...v1.5.0)

---
updated-dependencies:
- dependency-name: arc-swap
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-16 11:21:14 +09:00
dependabot[bot]
7e4418468a build(deps): bump tokio from 1.13.0 to 1.13.1 (#1109)
Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.13.0 to 1.13.1.
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.13.0...tokio-1.13.1)

---
updated-dependencies:
- dependency-name: tokio
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-16 11:21:02 +09:00
Cole Helbling
225e7904ec helix-view/editor: use SCRATCH_BUFFER_NAME const (#1104) 2021-11-16 01:46:39 +09:00
NexiNov
c95cb2be28 Remove extra instance of delete_word_backword in book (#1103) 2021-11-16 01:46:27 +09:00
Blaž Hrastnik
dd98727bad fix: editor.close now takes only a single parameter 2021-11-16 00:37:30 +09:00
Jason Hansen
6cb35d28a8 Add command to inc/dec number under cursor (#1027)
* Add command to inc/dec number under cursor

With the cursor over a number in normal mode, Ctrl + A will increment the
number and Ctrl + X will decrement the number. It works with binary, octal,
decimal, and hexidecimal numbers. Here are some examples.

0b01110100
0o1734
-24234
0x1F245

If the number isn't over a number it will try to find a number after the
cursor on the same line.

* Move several functions to helix-core

* Change to work based on word under selection

* It no longer finds the next number if the cursor isn't already over
  a number.
* It only matches numbers that are part of words with other characters
  like "foo123bar".
* It now works with multiple selections.

* Add some unit tests

* Fix for clippy

* Simplify some things

* Keep previous selection after incrementing

* Use short word instead of long word

This change requires us to manually handle minus sign.

* Don't pad decimal numbers if no leading zeros

* Handle numbers with `_` separators

* Refactor and add tests

* Move most of the code into core
* Add tests for the incremented output

* Use correct range

* Formatting

* Rename increment functions

* Make docs more specific

* This is easier to read

* This is clearer

* Type can be inferred
2021-11-16 00:32:58 +09:00
Bob
46d9ae2b62 Readline style insert mode (#1039)
* readline style insert mode

* update keymap.md

* don't save change history in insert mode

* Revert "don't save change history in insert mode"

This reverts commit cb47f946d7.

* don't affect register and history in insert mode

* add insert_register

* don't call exit_select_mode in insert mode

* avoid set_selection

* avoid duplicated current!
2021-11-16 00:31:20 +09:00
Cole Helbling
c638b6b60e helix-term/commands: implement buffer-close (bc, bclose) (#1035)
* helix-view/view: impl method to remove document from jumps

* helix-view/editor: impl close_document

* helix-view/editor: remove close_buffer argument from `close`

According to archseer, this was never implemented or used properly. Now
that we have a proper "buffer close" function, we can get rid of this.

* helix-term/commands: implement buffer-close (bc, bclose)

This behaves the same as Kakoune's `delete-buffer` / `db` command:

* With 3 files opened by the user with `:o ab`, `:o cd`, and `:o ef`:
  * `buffer-close` once closes `ef` and switches to `cd`
  * `buffer-close` again closes `cd` and switches to `ab`
  * `buffer-close` again closes `ab` and switches to a scratch buffer
* With 3 files opened from the command line with `hx -- ab cd ef`:
  * `buffer-close` once closes `ab` and switches to `cd`
  * `buffer-close` again closes `cd` and switches to `ef`
  * `buffer-close` again closes `ef` and switches to a scratch buffer
* With 1 file opened (`ab`):
  * `buffer-close` once closes `ab` and switches to a scratch buffer
  * `buffer-close` again closes the scratch buffer and switches to a new
    scratch buffer

* helix-term/commands: implement buffer-close! (bclose!, bc!)

Namely, if you have a document open in multiple splits, all the splits
will  be closed at the same time, leaving only splits without that
document focused (or a scratch buffer if they were all focused on that
buffer).

* helix-view/tree: reset focus if Tree is empty
2021-11-16 00:30:45 +09:00
Blaž Hrastnik
cccc1949eb Enable thin LTO
It compiles about half a second slower for me, so it seems fine to use
by default.
2021-11-15 14:38:03 +09:00
Cole Helbling
87e61a0894 helix-term/commands: implement cquit (#1096)
This allows you to exit helix with an exit code, e.g. `:cq 2`.
2021-11-15 13:06:12 +09:00
Blaž Hrastnik
f5e070e808 minor: Remove leftover log line 2021-11-15 10:33:14 +09:00
Blaž Hrastnik
e128a8702e Implement MarkedString rendering
Solves typescript and python documentation rendering
2021-11-15 10:30:05 +09:00
Kirawi
8f7ada12ac Solarized dark theme (#999)
* init

* wip

* wip
2021-11-15 09:29:39 +09:00
Ivan Tham
b7c3877e94 Add movement shortcut for history (#1088)
alt-u and alt-U
2021-11-15 00:16:47 +09:00
ath3
6fa76d9fe7 Add trim_selections command (#1092) 2021-11-15 00:16:20 +09:00
Ebbe Steenhoudt
edc976b6bb Added workspace_symbol_picker (#1041)
* Added workspace_symbol_picker

* Moved truncation of the symbol pickers to the end.

* Fixed typo
2021-11-15 00:12:56 +09:00
Blaž Hrastnik
1817b7f581 minor: Import Range too 2021-11-15 00:12:14 +09:00
ath3
35c974c9c4 Implement "Goto last modification" command (#1067) 2021-11-15 00:11:53 +09:00
Gygaxis Vainhardt
0949a0de7f Add commit hash to version info, if present (#957)
* Add commit hash to version info, if present

* Rename GIT_HASH to indicate that it includes version, fix linter error

* Add whitespace after use statement

Co-authored-by: Ivan Tham <pickfire@riseup.net>

Co-authored-by: Ivan Tham <pickfire@riseup.net>
2021-11-15 00:09:02 +09:00
Cole Helbling
b74912ea78 helix-term/editor: display scratch buffer name in status bar 2021-11-14 12:33:17 +05:30
Cole Helbling
b824e091a9 helix-term/commands: move SCRATCH_BUFFER_NAME to helix-view/document (#1091)
This way, the name is accessible everywhere `Document` and related types
are.
2021-11-13 13:15:41 +09:00
Omnikar
6d4409c00f Make prompts consistent (#1080) 2021-11-13 01:34:49 +09:00
Blaž Hrastnik
d3def16584 fix: shift-tab mappings broken after efc2b4c7 2021-11-12 16:21:03 +09:00
Gokul Soumya
fa0cb010e1 docs: Mark more keybinds that require LSP and treesitter (#1081) 2021-11-12 10:35:32 +09:00
NexiNov
187197afb1 Add arrow keys to view mode (#987)
* Add arrow keys to view mode

* Drop C-up and C-down

* Update docs for #987

* Format correctly

* Drop other keymaps

* Correct keymap.md

* Add arrow keys to view mode

Drop C-up and C-down

Update docs for #987

Format correctly

Drop other keymaps

Correct keymap.md

Rebase

Co-authored-by: Rust & Python <nexinov@localhost.gud-o15>
Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
2021-11-12 09:48:37 +09:00
Omnikar
bf95a9ed04 Add remove_selections command (#1065)
* Add `remove_selections` command

* Document `remove_selections`

* Update helix-term/src/keymap.rs

Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
2021-11-12 09:34:08 +09:00
Ivan Tham
9d591427be Fix earlier/later missing changeset update (#1069)
Fix #1059
2021-11-11 22:32:44 +09:00
Omnikar
d131a9dd0e Allow keys to be mapped to sequences of commands (#589)
* Allow keys to be mapped to sequences of commands

* Handle `Sequence` at the start of `Keymap::get`

* Use `"[Multiple commands]"` as command sequence doc

* Add command sequence example to `remapping.md`
2021-11-11 13:44:50 +09:00
Cole Helbling
bf70cfd050 helix-term/command: make scratch buffer name consistent (#1071) 2021-11-11 12:22:15 +09:00
Omnikar
ebc14d9d20 Add m textobject for pair under cursor (#961) 2021-11-11 11:33:31 +09:00
Bob
4d22454386 add wonly -- window only (#1057)
* add wonly

* Update book/src/keymap.md

Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>

* add `wonly` to space w mode too

* remove the TODO

Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
2021-11-11 11:32:23 +09:00
ath3
c7cb7527be Fix moving with arrow keys in prompt (#1070) 2021-11-11 11:08:19 +09:00
Mateusz S. Szczygieł
e0540fbcc4 Add json indents.toml file (#1055)
* add glsl language support

* glsl: use indents.toml file

* add json indents.toml
2021-11-11 01:01:19 +09:00
Gokul Soumya
efc2b4c77b Refactor keyevent handling using key, ctrl macros (#1058)
Adds ctrl! and alt! macros (which existed before the big keymap
refactor) and uses them in event handling of Components. Note
that this converts crossterm's KeyEvent to our own KeyEvent on
each invocation of handle_event in Components.
2021-11-11 00:58:46 +09:00
Gokul Soumya
e863e3b62d Ensure that identical keymaps stay in sync (#1056)
Space mode and view mode are duplicated on two different
keybinds, and they tend to get out of sync by contributers
forgetting to update both of them. This commit adds a test
that explicitly checks that they are identical. Prevents
issues like #1050.
2021-11-11 00:58:35 +09:00
Gokul Soumya
f9e9efb3ec Check for duplicate keys in default keymap 2021-11-11 00:58:25 +09:00
Gokul Soumya
80036b8bd3 Change page keybinds in view mode
b which was assigned to page_up conflicts with
align to bottom, so this commit replaces page up,
down, etc keybinds to use normal mode keybinds
(C-f, C-b, etc) in view mode too.
2021-11-11 00:58:25 +09:00
Omnikar
5654909135 Update space w window mode (#1050) 2021-11-10 11:04:03 +09:00
Jason Hansen
cf831b1a65 Allow piping from stdin into a buffer on startup (#996)
* Allow piping from stdin into a buffer on startup

* Refactor

* Don't allow piping into new buffer on macOS

* Update helix-term/src/application.rs

Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>

* Update helix-term/src/application.rs

Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>

* Fix

Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
2021-11-10 10:53:14 +09:00
CossonLeo
68224232af buffer picker add is_modifier flag (#1020) 2021-11-10 10:52:39 +09:00
Gokul Soumya
92d23430c0 Cleanup keymap doc book page (#1042)
- Clearly mark keybinds that require LSP
- Fix incorrect rendering of Prompt section due to missing newline
2021-11-10 10:47:07 +09:00
Ivan Tham
97893cca64 Restore screen position when abort search (#1047) 2021-11-10 10:46:55 +09:00
Bob
7c9f620236 add <C-h>, <C-u>, <C-d>, Delete in prompt mode (#1034) 2021-11-09 14:43:50 +09:00
CossonLeo
490919df4f Add rename_symbol to book/ (#1031)
* rename_symbol book

* Update book/src/keymap.md

Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>

Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
2021-11-09 11:12:11 +09:00
CossonLeo
a69caff450 search_impl will only align cursor center when it isn't in view (#959) 2021-11-09 11:11:45 +09:00
CossonLeo
f96be0fcbc add solarized_light theme (#1010)
* add solarized_light theme

* solarized_light add constant.numeric
2021-11-09 11:08:08 +09:00
Omnikar
a424ef4e20 Use default languages.toml if user's is invalid (#994) 2021-11-09 11:07:54 +09:00
dependabot[bot]
eb68cd3767 build(deps): bump serde_json from 1.0.68 to 1.0.69 (#1030)
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.68 to 1.0.69.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.68...v1.0.69)

---
updated-dependencies:
- dependency-name: serde_json
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-09 11:04:44 +09:00
dependabot[bot]
81015266d9 build(deps): bump anyhow from 1.0.44 to 1.0.46 (#1029)
Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.44 to 1.0.46.
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.44...1.0.46)

---
updated-dependencies:
- dependency-name: anyhow
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-09 11:04:38 +09:00
Blaž Hrastnik
e18198aeb2 Revert "fix(core): stop merging array toml config values (#1004)"
It breaks languages.toml merging

This reverts commit 4304b52ff8.
2021-11-09 10:58:23 +09:00
Blaž Hrastnik
f804ed3192 Make shebangs optional, they don't make sense outside of scripts 2021-11-09 10:57:08 +09:00
Curiosidad-Racional
41fc326325 Fix panicked missing field shebangs (#1025)
Fix the error:
```
thread 'main' panicked at 'Could not parse merged (built-in + user) languages.toml: Error { inner: ErrorInner { kind: Custom, line: None, col: 0, at: None, message: "missing field `shebangs`", key: ["language"] } }', helix-term/src/application.rs:87:14
```
2021-11-09 10:49:43 +09:00
Mateusz S. Szczygieł
3f0345ff58 glsl support (#993)
* add glsl language support

* glsl: use indents.toml file
2021-11-09 00:48:00 +09:00
Blaž Hrastnik
549cdee561 Refactor shebang detection to reuse the loaded buffer 2021-11-09 00:30:34 +09:00
ath3
77dbbc73f9 Detect filetype from shebang line (#1001) 2021-11-09 00:19:44 +09:00
CossonLeo
29e6849413 Add LSP rename_symbol (space-r) (#1011)
improve apply_workspace_edit
2021-11-09 00:17:54 +09:00
LollipopFt
bf4c70e027 added Down keymapping. (#1019) 2021-11-09 00:14:03 +09:00
ath3
30744646cb Perl support (#978) 2021-11-08 10:05:12 +09:00
Blaž Hrastnik
cdc2107bca fix: #896 broke some of the default highlights 2021-11-08 10:03:53 +09:00
Blaž Hrastnik
82ff5b0ab6 Specify capacity on toggle_line_comments 2021-11-08 10:03:21 +09:00
Blaž Hrastnik
8b85903116 wip 2021-11-08 10:03:08 +09:00
jgart
4010b327e2 Adds mint language server (#974) 2021-11-08 10:01:55 +09:00
Daniel S Poulin
1e793c2bbf Adds single and double quotes to matching pairs (#995)
This enables `mm` to work on quote characters as well as highlighting of
matching quote when on it.
2021-11-08 09:57:26 +09:00
Omnikar
a252ecd8c8 Add WORD textobject (#991)
* Add WORD textobject

* Document WORD textobject
2021-11-08 09:54:39 +09:00
Gokul Soumya
e0e227d172 Touch up docs for adding new language (#1002) 2021-11-08 09:52:51 +09:00
Carter Snook
4304b52ff8 fix(core): stop merging array toml config values (#1004) 2021-11-08 09:50:03 +09:00
Blaž Hrastnik
09f5796537 dap: Simplify get_breakpoint_at_current_line 2021-11-07 22:03:55 +09:00
Blaž Hrastnik
c39d9f44a0 dap: Simplify debug_parameter_prompt 2021-11-07 21:58:06 +09:00
Blaž Hrastnik
3042ff3e5a dap: Clean up dap_start_impl, no need to clone arg keys 2021-11-07 21:47:44 +09:00
Blaž Hrastnik
9963a5614d dap: Minor simplifications 2021-11-07 21:37:00 +09:00
Blaž Hrastnik
65868081fc dap: Simplify launch & start
There's no need to re-detect language config, just use the one available
on the document.
2021-11-07 21:26:03 +09:00
Blaž Hrastnik
4f2a01cc09 dap: Error implements Display so we can format with {} 2021-11-07 21:20:58 +09:00
Blaž Hrastnik
2bd8a9b39d dap: Consistently rename type as ty 2021-11-07 21:18:53 +09:00
Blaž Hrastnik
31b431bfdd dap: Remove Deref for DebuggerCapabilities
Looks like a mistake
2021-11-07 21:17:09 +09:00
Blaž Hrastnik
9dd17c46a2 dap: Avoid cloning old_breakpoints if we are immediately replacing them 2021-11-07 18:58:47 +09:00
Blaž Hrastnik
757babb1b4 dap: Avoid cloning *entire* stack frames when picking a thread 2021-11-07 18:56:09 +09:00
Blaž Hrastnik
5803de2067 dap: Simplify more calls 2021-11-07 18:51:29 +09:00
Blaž Hrastnik
155c608237 dap: Drop examples 2021-11-07 18:38:27 +09:00
Blaž Hrastnik
9baddc825d dap: Get rid of excessive cloning 2021-11-07 18:38:04 +09:00
Blaž Hrastnik
fd9b826f2c dap: Inline empty completer 2021-11-07 18:15:17 +09:00
Blaž Hrastnik
5938ab1bf1 dap: Fully extract template parameter prompts 2021-11-07 18:13:37 +09:00
Blaž Hrastnik
3b8d5102ac Make picker take the whole context, not just editor 2021-11-07 18:03:04 +09:00
Blaž Hrastnik
64bb1f7563 dap: Extract out variable rendering
Will improve on the UI later
2021-11-07 17:55:01 +09:00
Blaž Hrastnik
29fe504398 book: Mention git submodule sync too 2021-11-07 10:33:05 +09:00
ammkrn
acced82be6 feat(book/src/languages.md) (#979)
* feat(book/src/languages.md)

Add a section in the book about language-specific settings and the languages.toml file.

* Update book/src/languages.md

Co-authored-by: Gokul Soumya <gokulps15@gmail.com>

* feat(book/src/guides/adding_languages.md)

Add book section on adding a new language to the compile-time/root languages.toml file.

* Update book/src/guides/adding_languages.md

Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>

* Update book/src/guides/adding_languages.md

Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>

* refactor(revise book/src/languages.md)

Change the book page on language settings to match suggestions by archseer and mention both toml files.

Co-authored-by: Gokul Soumya <gokulps15@gmail.com>
Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
2021-11-07 10:31:12 +09:00
Omnikar
ed23057ff8 Launch with defaults upon invalid config/theme (#982)
* Launch with defaults upon invalid config/theme

* Startup message if there is a problematic config
* Statusline error if trying to switch to an invalid theme

* Use serde `deny_unknown_fields` for config
2021-11-07 00:57:14 +09:00
Blaž Hrastnik
e2a23ac0b5 If there is no live debugger, treat breakpoints as unverified 2021-11-07 00:48:34 +09:00
Blaž Hrastnik
2e1aa5f15b Fix compilation 2021-11-07 00:32:28 +09:00
Blaž Hrastnik
a5ea61433c dap: Bump helix-core 2021-11-07 00:29:43 +09:00
Blaž Hrastnik
09d8c139af dap: Enable sticky mode for the submode 2021-11-07 00:29:12 +09:00
Blaž Hrastnik
14a3502cf1 dap: Move template selection into a picker
It's time to move all these components out of ui/editor.rs
2021-11-07 00:28:57 +09:00
Blaž Hrastnik
f2b709a3c3 Merge branch 'master' into debug 2021-11-07 00:28:19 +09:00
Blaž Hrastnik
f979bdc442 Specify capacity on toggle_line_comments 2021-11-06 23:57:42 +09:00
Blaž Hrastnik
2c1313c064 Specify vector capacity on surround_add 2021-11-06 23:52:49 +09:00
Blaž Hrastnik
1a1685acf7 Simplify current!(..).1 into doc!() 2021-11-06 23:52:26 +09:00
Blaž Hrastnik
e80708eba7 Make sure document diagnostics are sorted 2021-11-06 18:58:58 +09:00
Blaž Hrastnik
0f4cd73000 Simplify goto_*_diagnostic commands 2021-11-06 18:58:58 +09:00
Blaž Hrastnik
f659e1178a minor: view!(..).doc is slightly more efficient than current!(..).1.id() 2021-11-06 17:54:04 +09:00
Blaž Hrastnik
4c1321b3b6 minor: Extend search was decclared twice in the keymap 2021-11-06 17:49:18 +09:00
Blaž Hrastnik
b81a554424 Retain range direction on search
Co-authored-by: CossonLeo <20379044+cossonleo@users.noreply.github.com>
2021-11-06 17:41:30 +09:00
Blaž Hrastnik
6431b26a6a Implement Selection::replace to replace a single range
Fixes #985

Co-authored-by: Daniel S Poulin <crimsonmage+github@gmail.com>
2021-11-06 17:37:45 +09:00
Gygaxis Vainhardt
911b9b3276 Add reverse search functionality (#958)
* Add reverse search functionality

* Change keybindings for extend to be in select mode, incorporate Movement and Direction enums

* Fix accidental revert of #948 in rebase

* Add reverse search to docs, clean up mismatched whitespace

* Reverse search optimization

* More optimization via github feedback
2021-11-06 17:33:30 +09:00
Omnikar
cfc8285867 Allow infoboxes to be disabled (#972)
* Allow infoboxes to be disabled

* Document `infoboxes` default value

* Rename `infoboxes` to `auto_info`

* Document `auto-info`

* Fix incomplete rename
2021-11-05 11:25:08 +09:00
Omnikar
51b4d35dce Inform when reaching undo/redo bounds (#981)
* Inform when reaching undo/redo bounds

* `Already at oldest change` when undo fails
* `Already at newest change` when redo fails

* Add missing `the`
2021-11-05 10:20:06 +09:00
ath3
aa4d0b4646 Fix crash on changing from empty scratch buffer to itself (#975) 2021-11-04 17:57:04 +09:00
Blaž Hrastnik
7b65a6d687 Rewrite goto_buffer 2021-11-04 14:03:03 +09:00
ath3
78c68fae91 Implement "Goto next buffer / Goto previous buffer" commands 2021-11-04 14:03:03 +09:00
Blaž Hrastnik
e2560f427e Replace documents SlotMap with BTreeMap 2021-11-04 13:43:45 +09:00
CossonLeo
39584cbccd Add c-s to pick word under doc cursor to prompt line & search completion (#831)
* Add prompt shourtcut to book
Add completions to search
Add c-s to pick word under doc cursor to prompt line

* limit 20 last items of search completion, update book

* Update book/src/keymap.md

Co-authored-by: Ivan Tham <pickfire@riseup.net>

* limit search completions 200

Co-authored-by: Ivan Tham <pickfire@riseup.net>
2021-11-04 12:26:01 +09:00
diegodox
70d21a903f Prevent preview binary or large file (#939)
* Prevent preview binary or large file (#847)

* fix wrong method name

* fix add use trait

* update lock file

* rename MAX_PREVIEW_SIZE from MAX_BYTE_PREVIEW

* read small bytes to determine cotent type

* [WIP] add preview struct to represent calcurated preveiw

* Refactor content type detection

- Remove unwraps
- Reuse a single read buffer to avoid 1kb reallocations between previews

* Refactor preview rendering so we don't construct docs when not necessary

* Replace unwarap whit Preview::NotFound

* Use index access to hide unwrap

Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>

* fix Get and unwarp equivalent to referce of Index acess

* better preview implementation

* Rename Preview enum and vairant

Co-authored-by: Gokul Soumya <gokulps15@gmail.com>

* fixup! Rename Preview enum and vairant

* simplify long match

* Center text, add docs, fix formatting, refactor

Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
Co-authored-by: Gokul Soumya <gokulps15@gmail.com>
2021-11-04 12:24:52 +09:00
Omnikar
5b5d1b9dff Truncate the starts of file paths instead of the ends in picker (#951)
* Truncate the starts of file paths in picker

* Simplify the truncate implementation

* Break loop at appropriate point

* Fix alignment and ellipsis presence

* Remove extraneous usage of `x_offset`

Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
2021-11-04 12:24:05 +09:00
Omnikar
e39cfa40df Hide keys bound to no_op from infobox (#971) 2021-11-04 09:50:38 +09:00
Gokul Soumya
253bd6b3a8 Add better description for copy_selection command (#969) 2021-11-03 22:22:41 +09:00
Ivan Tham
3eb829e233 Ensure coords in screen depends on char width (#885)
The issue affected files with lots of tabs at the start as well.

Fix #840
2021-11-03 12:02:29 +09:00
Kirawi
ee889aaa85 Updated tree-sitter query scopes (#896)
* updated theme scopes

variable.property -> variable.field
property -> variable.field

* updated theme scopes

* update book and themes

updated book and themes to reflect scope changes

* wip

* update more queries

* update dark_plus.toml
2021-11-03 12:00:52 +09:00
Triton171
7a0c4322ea Simplify BTreeSet construction
Co-authored-by: Ivan Tham <pickfire@riseup.net>
2021-11-03 11:56:55 +09:00
Daniel Ebert
eb8745db09 Implement key ordering for info box 2021-11-03 11:56:55 +09:00
Carter Snook
e505bf2b48 chore(doc): use faq for finding helix log file (#963) 2021-11-03 09:57:18 +09:00
Daniel Poulin
9e247bf6ee Add indents definition based on the one from nvim-treesitter 2021-11-02 17:53:24 +09:00
Daniel Poulin
924b7d3b19 Adjust PHP indentation defaults to 4 spaces
In the PHP community, 4 spaces is widely considered the default, as
it is recommended by the PSR-2 and PSR-12 standards, as well as popular
derivative standards like those for Laravel and Symphony.
2021-11-02 17:53:24 +09:00
CossonLeo
1720b98760 only remove primary index when search next without extend (#948) 2021-11-02 13:32:57 +09:00
dependabot[bot]
44ff597841 build(deps): bump tokio-stream from 0.1.7 to 0.1.8 (#953)
Bumps [tokio-stream](https://github.com/tokio-rs/tokio) from 0.1.7 to 0.1.8.
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-stream-0.1.7...tokio-stream-0.1.8)

---
updated-dependencies:
- dependency-name: tokio-stream
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-02 09:34:39 +09:00
dependabot[bot]
0c381adcb1 build(deps): bump lsp-types from 0.91.0 to 0.91.1 (#954)
Bumps [lsp-types](https://github.com/gluon-lang/lsp-types) from 0.91.0 to 0.91.1.
- [Release notes](https://github.com/gluon-lang/lsp-types/releases)
- [Changelog](https://github.com/gluon-lang/lsp-types/blob/master/CHANGELOG.md)
- [Commits](https://github.com/gluon-lang/lsp-types/compare/v0.91.0...v0.91.1)

---
updated-dependencies:
- dependency-name: lsp-types
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-02 09:15:25 +09:00
dependabot[bot]
a13af476c1 build(deps): bump tokio from 1.12.0 to 1.13.0 (#955)
Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.12.0 to 1.13.0.
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.12.0...tokio-1.13.0)

---
updated-dependencies:
- dependency-name: tokio
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-02 09:15:05 +09:00
Omnikar
2f8ad7f890 If switching away from an empty scratch buffer, remove it (#935)
* If switching away from an empty scratch buffer, remove it

* Move `view.jumps.push` call into `else` clause

* Refactor
2021-10-31 09:42:49 +09:00
kabirz
592fba1100 add cmake-language-server as cmake language server 2021-10-30 13:17:30 +05:30
Gokul Soumya
ea452bec80 Update onedark theme (#936)
- Use named color palette
- Remove blue highlight for variables (too much noise)
- Add purple highlight for control statements (if, match, etc)
2021-10-30 14:17:51 +09:00
Gygaxis Vainhardt
f140a2a00e Add arrow-key bindings for window switching (#933) 2021-10-30 10:48:00 +09:00
Blaž Hrastnik
e5de103728 Extract a clear_completion method 2021-10-29 16:48:41 +09:00
Za Wilcox
68697cb332 Move 'Note' from incorrect location (#921) 2021-10-29 14:11:42 +09:00
Houkime
a1c7e55e3b update cpp queries (#930)
Co-authored-by: Houkime <>
2021-10-29 14:11:19 +09:00
Ivan Tham
49f6c2623f Bump lsp-types to 0.91.0 (#932) 2021-10-29 12:00:18 +09:00
Kirawi
cec0cfdaec Uncomment mapping LSP diagnostics through changes (#925) 2021-10-29 10:11:30 +09:00
Ivan Tham
bc6a34d97e Make match work with extend and multi cursors (#920) 2021-10-29 10:08:53 +09:00
Ivan Tham
21d535565b Support extend for multiple goto (#909)
gg, ge, [n]gg
2021-10-29 10:07:07 +09:00
cossonleo
befecc8a9a select smaller range on some case 2021-10-29 10:04:12 +09:00
cossonleo
f1d339919f add expand_selection to last_motion 2021-10-29 10:04:12 +09:00
Omnikar
45fadf6151 Add hyperlinks to fix cargo doc warn (#931) 2021-10-29 09:55:15 +09:00
ath3
58b8100751 Mention CMake support in changelog (#926) 2021-10-28 21:23:13 +09:00
Blaž Hrastnik
c02534d261 changelog: Add links to all pull requests 2021-10-28 16:57:44 +09:00
Blaž Hrastnik
8af6d713cd Fix the release date 2021-10-28 16:49:13 +09:00
Dmitry Sharshakov
cde57dae35 lldb: add gdbserver connection template
Can be better customized in a personal languages.toml for perfect fit
2021-10-24 17:34:24 +03:00
Dmitry Sharshakov
6aa9838ea6 dap: support arrays as arguments 2021-10-24 17:24:18 +03:00
Blaž Hrastnik
d6e8a44d85 dap: Fix examples 2021-10-17 14:12:03 +09:00
Blaž Hrastnik
bda05ec4bf Use a newtype for ThreadId 2021-10-17 14:06:52 +09:00
Blaž Hrastnik
83a8167402 Invert core -> dap dependency 2021-10-17 13:58:11 +09:00
Blaž Hrastnik
ea59f77a6b Port over parsing improvements from the LSP
We need to terminate if we ever read 0 bytes which indicates closed
stream.
2021-10-17 13:54:47 +09:00
Blaž Hrastnik
0a6b60085a Merge branch 'master' into debug 2021-10-17 13:51:56 +09:00
Dmitry Sharshakov
bc0084d071 fix command descriptions 2021-10-09 16:06:32 +03:00
Dmitry Sharshakov
48cb81eff1 Merge branch 'master' into debug 2021-10-09 16:03:46 +03:00
Dmitry Sharshakov
814dcfa8d2 fix lints 2021-09-26 21:54:36 +03:00
Dmitry Sharshakov
d943a51e3e editor: add Node.js debugger 2021-09-26 21:36:06 +03:00
Dmitry Sharshakov
0e51e5fbaf editor: support setExceptionBreakpoints 2021-09-26 10:24:58 +03:00
Dmitry Sharshakov
bf53aff27d Merge branch 'master' into debug 2021-09-25 23:14:59 +03:00
Dmitry Sharshakov
413e477dc2 lldb: use stdio transport by default 2021-09-06 13:49:31 +03:00
Dmitry Sharshakov
507a1f8dd6 Get breakpoint reports from debugger 2021-09-06 08:47:54 +03:00
Dmitry Sharshakov
c9cd06e904 Fetch stack traces for all threads when debugger sets all_thread_stopped flag 2021-09-05 16:09:38 +03:00
Dmitry Sharshakov
bdd636d8ee Clean up import 2021-09-05 15:21:39 +03:00
Dmitry Sharshakov
9b8c5bdade Remove redundant fetching of stack traces 2021-09-05 15:19:52 +03:00
Dmitry Sharshakov
0add0c5639 Make conditional logpoints underlined 2021-09-05 15:12:13 +03:00
Dmitry Sharshakov
2d35b7b99c Normalize line in picker preview to avoid crash 2021-09-05 14:31:16 +03:00
Dmitry Sharshakov
b6c58ea23e Support thread previews 2021-09-05 13:39:27 +03:00
Dmitry Sharshakov
bb26c589b4 Keybinding for editing log 2021-09-05 08:52:30 +03:00
Dmitry Sharshakov
0e1e4edc5e different display for conditional logpoints 2021-09-05 08:51:33 +03:00
Dmitry Sharshakov
8a609047c3 Mouse command for editing logpoint 2021-09-05 08:50:03 +03:00
Dmitry Sharshakov
7bdead5b4b Drop old commands
TODO: edit logpoints with a keybinding and mouse
2021-09-05 08:20:21 +03:00
Dmitry Sharshakov
3b0ec750ff Support editing breakpoint condition with right click 2021-09-05 08:14:17 +03:00
Dmitry Sharshakov
1befbd076c Add command for editing breakpoint condition 2021-09-04 22:57:58 +03:00
Dmitry Sharshakov
e36fc57fff refactor breakpoint edit 2021-09-04 22:18:42 +03:00
Dmitry Sharshakov
698583c241 Support setting breakpoints with mouse 2021-09-04 21:14:24 +03:00
Dmitry Sharshakov
df0ea6674a examples: ensure target stopped by waiting for enter from user 2021-09-04 19:36:36 +03:00
Dmitry Sharshakov
430c80ff2a Fix crash when trying to select (view) threads when debuggee is running 2021-09-04 10:28:11 +03:00
Dmitry Sharshakov
c6186ce600 jump to selected stack frame 2021-09-04 10:24:00 +03:00
Dmitry Sharshakov
cb31d20b46 mark thread as running when resumed 2021-09-04 10:22:29 +03:00
Dmitry Sharshakov
9a1916ebfd show thread states in thread picker 2021-09-04 10:14:04 +03:00
Dmitry Sharshakov
00cccdc62a Don't show thread picker for single-threaded targets 2021-09-04 09:19:19 +03:00
Dmitry Sharshakov
9939dbf119 Fix clippy warnings 2021-09-04 09:08:52 +03:00
Dmitry Sharshakov
cf7237d0b9 compat: make thread IDs signed
Delve needs it
2021-09-03 23:11:06 +03:00
Blaž Hrastnik
c63ad60c31 dap: Allow switching between stack frames 2021-09-03 17:25:11 +09:00
Blaž Hrastnik
7b61c63ece Handle stderr 2021-09-03 13:26:30 +09:00
Blaž Hrastnik
b997d2cdeb dap: Allow setting breakpoints before starting the adapter 2021-09-03 13:26:30 +09:00
Blaž Hrastnik
289303a30d dap: small TODO 2021-09-03 11:48:55 +09:00
Blaž Hrastnik
42f9718f55 dap: Extract thread_picker, make pause explicitly select a thread 2021-09-03 11:43:11 +09:00
Blaž Hrastnik
27c1b3f98b dap: Extract a thread_states map 2021-09-03 11:30:25 +09:00
Blaž Hrastnik
5b920c53f0 Refactor resume_application state handling 2021-09-03 11:11:22 +09:00
Blaž Hrastnik
4c410eef87 Merge remote-tracking branch 'origin/master' into debug 2021-09-03 11:03:34 +09:00
Dmitry Sharshakov
9c64650a26 force update of stack trace when stopped 2021-09-02 22:51:41 +03:00
Dmitry Sharshakov
2c89107349 Fix crash when stack trace not loaded
Still doesn't address the issue though
2021-09-02 19:58:03 +03:00
Dmitry Sharshakov
e0180a4b88 find main thread automatically if thread stopped is not known 2021-09-02 11:08:24 +03:00
Dmitry Sharshakov
5b20f6020a Merge remote-tracking branch 'origin/master' into debug
Contains type fix on helix-term/src/ui/editor.rs:752:13
2021-08-31 21:29:11 +03:00
Dmitry Sharshakov
6265e196b7 compat: change lldb to lldb-vscode
This should be preferred ID, although now lldb-vscode works with any
2021-08-30 16:09:41 +03:00
Blaž Hrastnik
0b0b1d850a dap: Stop comparing file paths per line number 2021-08-30 11:22:26 +09:00
Blaž Hrastnik
2c7b75475f dap: refactor frame handling 2021-08-30 11:07:59 +09:00
Blaž Hrastnik
986828e75c dap: Remap keys, match current thread behavior from dap-mode, switch-thread 2021-08-29 23:32:46 +09:00
Blaž Hrastnik
03b2d81406 dap: better yet, use Selection::single.. 2021-08-29 23:03:27 +09:00
Blaž Hrastnik
4d24a43651 dap: use smallvec! macro 2021-08-29 23:02:46 +09:00
Blaž Hrastnik
81f51c13fa dap: continued: THis check is already done before the match statement 2021-08-29 23:01:18 +09:00
Blaž Hrastnik
51328a4966 dap: extract dap_pos_to_pos 2021-08-29 22:59:29 +09:00
Blaž Hrastnik
d6ccc150c7 Extract dap commands into a separate file 2021-08-29 22:43:08 +09:00
Blaž Hrastnik
ee2ba744a2 Rename dap_in/_out to dap_step_in/_out 2021-08-29 22:37:21 +09:00
Blaž Hrastnik
2a7e38a2b4 helix-core doesn't need to import serde_json 2021-08-29 22:33:42 +09:00
Dmitry Sharshakov
db7f693550 More advanced completions 2021-08-29 14:55:42 +03:00
Dmitry Sharshakov
b42631942b Defaults in completions, better schema 2021-08-29 14:51:47 +03:00
Dmitry Sharshakov
f53d8411cb Add extra annotations to completions 2021-08-29 14:06:36 +03:00
Dmitry Sharshakov
98fda6b8f0 better completion 2021-08-29 13:16:57 +03:00
Dmitry Sharshakov
9d2f2a9e32 Support multiple arguments for debug configs 2021-08-29 13:06:22 +03:00
Dmitry Sharshakov
2d42766a71 wip: refactor parameters in UI start 2021-08-29 10:23:36 +03:00
Dmitry Sharshakov
af657ef2ec Fix lints 2021-08-28 19:15:13 +03:00
Dmitry Sharshakov
94901b8677 Customized completion for template parameters 2021-08-28 19:11:19 +03:00
Dmitry Sharshakov
ef155e62ef Add filename autocomplete to template args 2021-08-28 15:36:16 +03:00
Dmitry Sharshakov
e315394631 Merge remote-tracking branch 'origin/master' into debug 2021-08-28 14:59:26 +03:00
Dmitry Sharshakov
8df6739759 New way of starting debug sessions 2021-08-28 14:23:54 +03:00
Dmitry Sharshakov
5e4da09be2 Don't let picker be too narrow 2021-08-28 13:55:52 +03:00
Dmitry Sharshakov
890b51b568 Paginated variables 2021-08-28 10:13:19 +03:00
Dmitry Sharshakov
3b87fce0ce Print errors occurred in debug commands 2021-08-25 21:01:15 +03:00
Dmitry Sharshakov
2ad2838a27 Fix tests 2021-08-25 19:36:49 +03:00
Dmitry Sharshakov
c7759a5aa0 Merge remote-tracking branch 'origin/master' into debug 2021-08-25 19:22:01 +03:00
Dmitry Sharshakov
4ee66b8766 Support remote debug adapter 2021-08-25 19:14:47 +03:00
Dmitry Sharshakov
ba96f5d296 Format Cargo.toml 2021-08-25 08:40:53 +03:00
Dmitry Sharshakov
326293cb57 only show variables' names and types 2021-08-25 08:33:46 +03:00
Dmitry Sharshakov
2c3e2b979b Workaround for debugging Go tests 2021-08-24 21:28:51 +03:00
Dmitry Sharshakov
8cc6d68160 Autocomplete files for debug command 2021-08-24 20:38:49 +03:00
Dmitry Sharshakov
235a84d989 Remove shortcut for starting debug 2021-08-24 20:32:38 +03:00
Dmitry Sharshakov
299da5a35b Support attach request 2021-08-24 20:27:54 +03:00
Dmitry Sharshakov
b001008a69 Support templates in debug configurations 2021-08-24 20:04:14 +03:00
Dmitry Sharshakov
31212e133d Rename functions 2021-08-24 16:48:38 +03:00
Dmitry Sharshakov
1041a5bb07 Support launching configs by name 2021-08-24 12:21:00 +03:00
Dmitry Sharshakov
0e779381a8 Format 2021-08-24 12:01:58 +03:00
Dmitry Sharshakov
774ab6f8b6 Add new format configs for Rust and C/C++ 2021-08-24 12:01:05 +03:00
Dmitry Sharshakov
c463142e5e Create new debugger config format 2021-08-24 11:56:18 +03:00
Dmitry Sharshakov
34c6094604 refactor 2021-08-24 11:32:44 +03:00
Dmitry Sharshakov
2158366b24 Enable variable types in DAP config
We have this feature
2021-08-24 10:51:52 +03:00
Dmitry Sharshakov
fdad7d67aa Check capabilities for breakpoint config 2021-08-24 10:48:47 +03:00
Dmitry Sharshakov
c4085b4e88 Use saturating_sub for lenght 2021-08-24 08:54:32 +03:00
Dmitry Sharshakov
5d3c69d565 Support logpoints
Tested with Node (Delve and LLDB do not support logpoints)
2021-08-24 08:47:20 +03:00
Dmitry Sharshakov
ec599a1eac Do not panic if entered unknown code via stack trace
e.g. Rust std library
2021-08-23 21:25:58 +03:00
Dmitry Sharshakov
3a5e044c89 languages: support debug for Rust with LLDB 2021-08-23 21:11:45 +03:00
Dmitry Sharshakov
b3469df5bf add lldb for c++ 2021-08-23 20:52:16 +03:00
Dmitry Sharshakov
c09b15197b fix freeze with lldb terminated event 2021-08-23 20:38:17 +03:00
Dmitry Sharshakov
09c994a97a editor: drop telemetry output messages 2021-08-23 20:22:55 +03:00
Dmitry Sharshakov
b5b79e3656 types: make some fields optional as in spec 2021-08-23 20:22:21 +03:00
Dmitry Sharshakov
e529f4eb21 add lldb debugger for C 2021-08-23 18:12:28 +03:00
Dmitry Sharshakov
56d00fa7f4 Fix tests 2021-08-23 18:00:30 +03:00
Dmitry Sharshakov
802ef20dbc chore: bump helix-dap version to 0.4.1 2021-08-23 17:27:39 +03:00
Dmitry Sharshakov
b6b99b2487 config: minor fixes 2021-08-23 17:26:12 +03:00
Dmitry Sharshakov
839d210573 Enable stdio transport via config 2021-08-23 17:18:03 +03:00
Dmitry Sharshakov
f55a012fb7 editor: add debug session config 2021-08-23 16:56:41 +03:00
Dmitry Sharshakov
c5b210df59 Add debug-adapter field to languages.toml 2021-08-23 16:48:06 +03:00
Dmitry Sharshakov
dabec2d799 Fix line endings 2021-08-22 15:59:42 +03:00
Dmitry Sharshakov
b78f70e602 show breakpoint condition in diagnostics 2021-08-22 15:52:05 +03:00
Dmitry Sharshakov
53ee57f84a clippy 2021-08-22 15:16:59 +03:00
Dmitry Sharshakov
f247858055 Support conditional breakpoints 2021-08-22 15:06:27 +03:00
Dmitry Sharshakov
3197c2536e Add eval command 2021-08-22 14:44:16 +03:00
Dmitry Sharshakov
838f69929d Simplify variables display 2021-08-22 12:49:18 +03:00
Dmitry Sharshakov
060a422c7e fix crash when pausing 2021-08-22 12:26:36 +03:00
Dmitry Sharshakov
74102bfc6d examples: fix build 2021-08-22 12:13:43 +03:00
Dmitry Sharshakov
d0b0c9b2ef editor: select a range if stack pointer has an end 2021-08-22 12:06:43 +03:00
Dmitry Sharshakov
132198323c editor: go to pos where stack pointer is located 2021-08-22 11:56:22 +03:00
Dmitry Sharshakov
be9dc5802a editor: mark target as running when continued 2021-08-22 11:21:02 +03:00
Dmitry Sharshakov
d93cd2a261 editor: support stepIn, stepOut, next and pause commands 2021-08-22 11:16:11 +03:00
Dmitry Sharshakov
dfc70a12f3 dap: support stepIn, stepOut, next and pause commands 2021-08-22 11:02:54 +03:00
Blaž Hrastnik
28658836ee Add more event types, simplify event decoding 2021-08-22 16:05:12 +09:00
Dmitry Sharshakov
2aee5f02d0 Style 2021-08-22 09:52:37 +03:00
Dmitry Sharshakov
7233ab2deb Merge branch 'debug' of https://github.com/sh7dm/helix into debug 2021-08-22 09:47:22 +03:00
Blaž Hrastnik
a964cbae65 Extract handle_debugger_message, we should avoid bloating tokio::select! 2021-08-22 15:36:07 +09:00
Dmitry Sharshakov
91f2c60b36 Jump to stack pointer when stopped 2021-08-22 09:28:50 +03:00
Dmitry Sharshakov
89ad54a2e5 Add variable type to output 2021-08-22 08:31:01 +03:00
Dmitry Sharshakov
cc66475592 Add commands for variable introspection 2021-08-22 08:25:38 +03:00
Dmitry Sharshakov
95ba4ff5bd Hide stack pointer when continued 2021-08-21 21:00:18 +03:00
Dmitry Sharshakov
f3e47bfee4 Disable continuing when running 2021-08-21 20:55:45 +03:00
Dmitry Sharshakov
5230a2b669 Continue command in keymap 2021-08-21 20:44:14 +03:00
Dmitry Sharshakov
66c035fa99 Continue command 2021-08-21 20:42:13 +03:00
Dmitry Sharshakov
6709b4242f Drop and terminate debugger 2021-08-21 20:38:03 +03:00
Dmitry Sharshakov
26dee49dc9 Add command to detach debugger 2021-08-21 20:33:56 +03:00
Dmitry Sharshakov
462c8a6ec8 Show debugger output in the statusline 2021-08-21 20:29:01 +03:00
Dmitry Sharshakov
afeaba1113 add rx dispatcher to examples 2021-08-21 20:19:11 +03:00
Dmitry Sharshakov
5a06263b78 report status when target started or stopped 2021-08-21 20:08:37 +03:00
Dmitry Sharshakov
bcab93c94e Update editor window when stopped 2021-08-21 17:26:51 +03:00
Dmitry Sharshakov
a938f5a87a refactor: handle DAP events in editor main loop 2021-08-21 17:21:35 +03:00
Dmitry Sharshakov
3fc501c99f Correctly display 1-based breakpoints 2021-08-21 15:17:25 +03:00
Dmitry Sharshakov
7087558918 Don't leave debugged programs running 2021-08-21 15:14:29 +03:00
Dmitry Sharshakov
56bddb12f8 Highlight line number of stack pointer 2021-08-21 14:58:05 +03:00
Dmitry Sharshakov
5f5b383979 Fix clippy warnings 2021-08-21 14:35:53 +03:00
Dmitry Sharshakov
6458edecfd Add stack pointer display when stopped 2021-08-21 14:15:29 +03:00
Dmitry Sharshakov
738e8a4dd3 Unify init and launch commands 2021-08-20 19:11:37 +03:00
Dmitry Sharshakov
9e22842d51 move debug command to keybinding 2021-08-20 19:06:52 +03:00
Dmitry Sharshakov
e2c74d26e0 Add command to run debug target 2021-08-20 18:18:35 +03:00
Dmitry Sharshakov
c4970c617e make CI green 2021-08-20 16:48:59 +03:00
Blaž Hrastnik
a54b09e3fe dap: Split out launch from init 2021-08-20 14:06:55 +09:00
Blaž Hrastnik
94a1951d40 Work towards a breakpoint UI 2021-08-20 13:51:38 +09:00
Blaž Hrastnik
8759dc7e33 Add Default to some structs 2021-08-20 13:48:33 +09:00
Blaž Hrastnik
86102a651f wip 2021-08-20 13:48:33 +09:00
Blaž Hrastnik
2094ff1aaf Silence TCP client messages on stdout, log them in the future 2021-08-20 13:48:33 +09:00
Blaž Hrastnik
d39baa3b4e Start integrating into the editor's event loop 2021-08-20 13:48:32 +09:00
Blaž Hrastnik
0300dbdeb3 Avoid cloning a request on send 2021-08-20 13:43:54 +09:00
Blaž Hrastnik
54dc2f8107 Fix example compilation 2021-08-20 13:43:54 +09:00
Blaž Hrastnik
8fbda0abaf fix: Used the wrong type for variables 2021-08-20 13:43:54 +09:00
Blaž Hrastnik
184abdc510 dap: Significantly simplify code using the Request trait 2021-08-20 13:43:54 +09:00
Blaž Hrastnik
3a9e1c305b Refactor types, add a Request trait 2021-08-20 13:43:54 +09:00
Blaž Hrastnik
2d1ae2e44b dap: Split types off into types.rs 2021-08-20 13:43:54 +09:00
Blaž Hrastnik
6225401e84 A request always needs to have a response, per spec (the body can be empty) 2021-08-20 13:43:54 +09:00
Blaž Hrastnik
3f62799656 Get cargo check to pass in the subcrate 2021-08-20 13:43:54 +09:00
Dmitry Sharshakov
b9797a7dd2 client: support tcp_process transport 2021-08-20 13:43:54 +09:00
Dmitry Sharshakov
6c0f7eafc3 examples: continue handling output events 2021-08-20 13:43:54 +09:00
Dmitry Sharshakov
279db98d3c refactor: use tagged enum for handling DAP payloads 2021-08-20 13:43:54 +09:00
Dmitry Sharshakov
36fb8d1b1a examples: make examples identical 2021-08-20 13:43:54 +09:00
Dmitry Sharshakov
f92fb966c0 working lldb example 2021-08-20 13:43:54 +09:00
Dmitry Sharshakov
ae32159247 Revert "compat: don't wait for launch and attach response"
This reverts commit 766e3380622e2c7ddf5051ed672b78ece8d99f1f.

Not required for lldb-vscode
2021-08-20 13:43:54 +09:00
Dmitry Sharshakov
4f2b8fb05a dap-dlv: rename from dap-go 2021-08-20 13:43:54 +09:00
Dmitry Sharshakov
2a6210806b dap-lldb: adjust breakpoint position 2021-08-20 13:43:54 +09:00
Dmitry Sharshakov
f5b1655eab format 2021-08-20 13:43:54 +09:00
Dmitry Sharshakov
e7f543fe66 format 2021-08-20 13:43:54 +09:00
Dmitry Sharshakov
eb0605c13d dap: create C example 2021-08-20 13:43:54 +09:00
Dmitry Sharshakov
809990a3a4 format 2021-08-20 13:43:54 +09:00
Dmitry Sharshakov
d4c215b35d compat: don't wait for launch and attach response
I could not get one from codelldb
2021-08-20 13:43:54 +09:00
Dmitry Sharshakov
e388079a0b compat: add all possible debugger caps 2021-08-20 13:43:54 +09:00
Dmitry Sharshakov
43c9eba037 compat: remove missing caps
Only report present features now
2021-08-20 13:43:54 +09:00
Dmitry Sharshakov
c5492788a2 compat: remove seq from Response and Event 2021-08-20 13:43:54 +09:00
Dmitry Sharshakov
cc650c7f4f types: capitalize ID in names
Part of LLDB integration
2021-08-20 13:43:54 +09:00
Dmitry Sharshakov
b3be6b269a dap-basic: parse stop event 2021-08-20 13:43:54 +09:00
Dmitry Sharshakov
0777948fc0 dap-basic: better output formatting 2021-08-20 13:43:54 +09:00
Dmitry Sharshakov
09390be6a5 dap-basic: handle output events 2021-08-20 13:43:54 +09:00
Dmitry Sharshakov
c72475bc30 client: handle events multiple times 2021-08-20 13:43:54 +09:00
Dmitry Sharshakov
d6de5408b7 dispatch events in client 2021-08-20 13:43:54 +09:00
Dmitry Sharshakov
59d6b92e5b refactor response processing 2021-08-20 13:43:54 +09:00
Dmitry Sharshakov
9678df1c62 refactor server message handling 2021-08-20 13:43:54 +09:00
Dmitry Sharshakov
541f7a0514 Add attach command 2021-08-20 13:43:54 +09:00
Dmitry Sharshakov
aac586b546 types: simplify working with client's launch args 2021-08-20 13:43:54 +09:00
Dmitry Sharshakov
6bb653f820 dap: move launch request argumets outside of client 2021-08-20 13:43:54 +09:00
Dmitry Sharshakov
3d64cf8356 fix: move adapter_id out of DAP client 2021-08-20 13:43:54 +09:00
Dmitry Sharshakov
fabee03983 dap: support TCP clients 2021-08-20 13:43:54 +09:00
Dmitry Sharshakov
26a55dcefd dap: make transport IO-agnostic 2021-08-20 13:43:54 +09:00
Dmitry Sharshakov
e11b67b0db dap: add missing fields to structs 2021-08-20 13:43:54 +09:00
Dmitry Sharshakov
0fa127b105 dap: support getting scopes and variables 2021-08-20 13:43:54 +09:00
Dmitry Sharshakov
7d2d4ed4a8 dap: implement threads request 2021-08-20 13:43:54 +09:00
Dmitry Sharshakov
5f3e806341 dap-basic: pretty-print results 2021-08-20 13:43:54 +09:00
Dmitry Sharshakov
5fd0a2ddda format 2021-08-20 13:43:54 +09:00
Dmitry Sharshakov
fd709bc56d dap: logging using fern 2021-08-20 13:43:54 +09:00
Dmitry Sharshakov
0f6e81b85b Initial debug adapter protocol implementation 2021-08-20 13:43:54 +09:00
729 changed files with 61805 additions and 12362 deletions

3
.cargo/config.toml Normal file
View File

@@ -0,0 +1,3 @@
[alias]
xtask = "run --package xtask --"
integration-test = "test --features integration --workspace --test integration"

1
.envrc
View File

@@ -3,3 +3,4 @@ watch_file flake.lock
# try to use flakes, if it fails use normal nix (ie. shell.nix)
use flake || use nix
eval "$shellHook"

11
.gitattributes vendored Normal file
View File

@@ -0,0 +1,11 @@
# Auto detect text files and perform normalization
* text=auto
*.rs text diff=rust
*.toml text diff=toml
*.scm text diff=scheme
*.md text diff=markdown
book/theme/highlight.js linguist-vendored
Cargo.lock text

1
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1 @@
open_collective: helix-editor

View File

@@ -1,28 +0,0 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: C-bug
assignees: ''
---
<!-- Your issue may already be reported!
Please search on the issue tracker before creating one. -->
### Reproduction steps
<!-- Ideally provide a key sequence and/or asciinema.org recording. -->
### Environment
- Platform: <!-- macOS / Windows / Linux -->
- Helix version: <!-- 'hx -v' if using a release, 'git describe' if building from master -->
<details><summary>~/.cache/helix/helix.log</summary>
```
please provide a copy of `~/.cache/helix/helix.log` here if possible, you may need to redact some of the lines
```
</details>

67
.github/ISSUE_TEMPLATE/bug_report.yaml vendored Normal file
View File

@@ -0,0 +1,67 @@
name: Bug Report
description: Create a report to help us improve
labels: C-bug
body:
- type: markdown
attributes:
value: Thank you for filing a bug report! 🐛
- type: textarea
id: problem
attributes:
label: Summary
description: >
Please provide a short summary of the bug, along with any information
you feel relevant to replicate the bug.
validations:
required: true
- type: textarea
id: reproduction-steps
attributes:
label: Reproduction Steps
value: |
<!-- Ideally provide a key sequence and/or asciinema.org recording. -->
I tried this:
1. `hx`
I expected this to happen:
Instead, this happened:
- type: textarea
id: helix-log
attributes:
label: Helix log
description: See `hx -h` for log file path
value: |
<details><summary>~/.cache/helix/helix.log</summary>
```
please provide a copy of `~/.cache/helix/helix.log` here if possible, you may need to redact some of the lines
```
</details>
- type: input
id: platform
attributes:
label: Platform
placeholder: Linux / macOS / Windows
validations:
required: true
- type: input
id: terminal-emulator
attributes:
label: Terminal Emulator
placeholder: wezterm 20220101-133340-7edc5b5a
validations:
required: true
- type: input
id: helix-version
attributes:
label: Helix Version
description: >
Helix version (`hx -V` if using a release, `git describe` if building
from master)
placeholder: "helix 0.6.0 (c0dbd6dc)"
validations:
required: true

13
.github/ISSUE_TEMPLATE/enhancement.md vendored Normal file
View File

@@ -0,0 +1,13 @@
---
name: Enhancement
about: Suggest an improvement
title: ''
labels: C-enhancement
assignees: ''
---
<!--
Your enhancement may already be reported!
Please search on the issue tracker before creating a new issue.
If this is an idea for a feature, please open an "Idea" Discussion instead.
-->

View File

@@ -1,13 +0,0 @@
---
name: Feature request
about: Suggest a new feature or improvement
title: ''
labels: C-enhancement
assignees: ''
---
<!-- Your feature may already be reported!
Please search on the issue tracker before creating one. -->
#### Describe your feature request

View File

@@ -11,129 +11,129 @@ jobs:
check:
name: Check
runs-on: ubuntu-latest
strategy:
matrix:
rust: [stable, msrv]
steps:
- name: Checkout sources
uses: actions/checkout@v2
with:
submodules: true
uses: actions/checkout@v3
- name: Use MSRV rust toolchain
if: matrix.rust == 'msrv'
run: cp .github/workflows/msrv-rust-toolchain.toml rust-toolchain.toml
- name: Install stable toolchain
uses: actions-rs/toolchain@v1
uses: helix-editor/rust-toolchain@v1
with:
profile: minimal
toolchain: stable
override: true
- name: Cache cargo registry
uses: actions/cache@v2.1.6
with:
path: ~/.cargo/registry
key: ${{ runner.os }}-v2-cargo-registry-${{ hashFiles('**/Cargo.lock') }}
- name: Cache cargo index
uses: actions/cache@v2.1.6
with:
path: ~/.cargo/git
key: ${{ runner.os }}-v2-cargo-index-${{ hashFiles('**/Cargo.lock') }}
- name: Cache cargo target dir
uses: actions/cache@v2.1.6
with:
path: target
key: ${{ runner.os }}-v2-cargo-build-target-${{ hashFiles('**/Cargo.lock') }}
- uses: Swatinem/rust-cache@v2
- name: Run cargo check
uses: actions-rs/cargo@v1
with:
command: check
run: cargo check
test:
name: Test Suite
runs-on: ${{ matrix.os }}
env:
RUST_BACKTRACE: 1
HELIX_LOG_LEVEL: info
steps:
- name: Checkout sources
uses: actions/checkout@v2
with:
submodules: true
uses: actions/checkout@v3
- name: Install stable toolchain
uses: actions-rs/toolchain@v1
uses: helix-editor/rust-toolchain@v1
with:
profile: minimal
toolchain: ${{ matrix.rust }}
override: true
- name: Cache cargo registry
uses: actions/cache@v2.1.6
with:
path: ~/.cargo/registry
key: ${{ runner.os }}-v2-cargo-registry-${{ hashFiles('**/Cargo.lock') }}
- uses: Swatinem/rust-cache@v2
- name: Cache cargo index
uses: actions/cache@v2.1.6
- name: Cache test tree-sitter grammar
uses: actions/cache@v3
with:
path: ~/.cargo/git
key: ${{ runner.os }}-v2-cargo-index-${{ hashFiles('**/Cargo.lock') }}
- name: Cache cargo target dir
uses: actions/cache@v2.1.6
with:
path: target
key: ${{ runner.os }}-v2-cargo-build-target-${{ hashFiles('**/Cargo.lock') }}
path: runtime/grammars
key: ${{ runner.os }}-stable-v${{ env.CACHE_VERSION }}-tree-sitter-grammars-${{ hashFiles('languages.toml') }}
restore-keys: ${{ runner.os }}-stable-v${{ env.CACHE_VERSION }}-tree-sitter-grammars-
- name: Run cargo test
uses: actions-rs/cargo@v1
with:
command: test
run: cargo test --workspace
- name: Run cargo integration-test
run: cargo integration-test
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
rust: [stable]
lints:
name: Lints
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v2
with:
submodules: true
uses: actions/checkout@v3
- name: Install stable toolchain
uses: actions-rs/toolchain@v1
uses: helix-editor/rust-toolchain@v1
with:
profile: minimal
toolchain: stable
override: true
components: rustfmt, clippy
- name: Cache cargo registry
uses: actions/cache@v2.1.6
with:
path: ~/.cargo/registry
key: ${{ runner.os }}-v2-cargo-registry-${{ hashFiles('**/Cargo.lock') }}
- name: Cache cargo index
uses: actions/cache@v2.1.6
with:
path: ~/.cargo/git
key: ${{ runner.os }}-v2-cargo-index-${{ hashFiles('**/Cargo.lock') }}
- name: Cache cargo target dir
uses: actions/cache@v2.1.6
with:
path: target
key: ${{ runner.os }}-v2-cargo-build-target-${{ hashFiles('**/Cargo.lock') }}
- uses: Swatinem/rust-cache@v2
- name: Run cargo fmt
uses: actions-rs/cargo@v1
with:
command: fmt
args: --all -- --check
run: cargo fmt --all --check
- name: Run cargo clippy
uses: actions-rs/cargo@v1
run: cargo clippy --workspace --all-targets -- -D warnings
- name: Run cargo doc
run: cargo doc --no-deps --workspace --document-private-items
env:
RUSTDOCFLAGS: -D warnings
docs:
name: Docs
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v3
- name: Install stable toolchain
uses: helix-editor/rust-toolchain@v1
with:
command: clippy
args: -- -D warnings
profile: minimal
override: true
- uses: Swatinem/rust-cache@v2
- name: Generate docs
run: cargo xtask docgen
- name: Check uncommitted documentation changes
run: |
git diff
git diff-files --quiet \
|| (echo "Run 'cargo xtask docgen', commit the changes and push again" \
&& exit 1)
queries:
name: Tree-sitter queries
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v3
- name: Install stable toolchain
uses: helix-editor/rust-toolchain@v1
with:
profile: minimal
override: true
- uses: Swatinem/rust-cache@v2
- name: Generate docs
run: cargo xtask query-check

26
.github/workflows/cachix.yml vendored Normal file
View File

@@ -0,0 +1,26 @@
# Publish the Nix flake outputs to Cachix
name: Cachix
on:
push:
branches:
- master
jobs:
publish:
name: Publish Flake
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v3
- name: Install nix
uses: cachix/install-nix-action@v18
- name: Authenticate with Cachix
uses: cachix/cachix-action@v12
with:
name: helix
authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
- name: Build nix flake
run: nix build -L

View File

@@ -4,12 +4,14 @@ on:
push:
branches:
- master
tags:
- '*'
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Setup mdBook
uses: peaceiris/actions-mdbook@v1
@@ -18,10 +20,22 @@ jobs:
# mdbook-version: '0.4.8'
- run: mdbook build book
- name: Set output directory
run: |
OUTDIR=$(basename ${{ github.ref }})
echo "OUTDIR=$OUTDIR" >> $GITHUB_ENV
- name: Deploy
uses: peaceiris/actions-gh-pages@v3
if: github.ref == 'refs/heads/master'
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./book/book
destination_dir: ./${{ env.OUTDIR }}
- name: Deploy stable
uses: peaceiris/actions-gh-pages@v3
if: startswith(github.ref, 'refs/tags/')
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./book/book

26
.github/workflows/languages.toml vendored Normal file
View File

@@ -0,0 +1,26 @@
# This languages.toml is used for testing in CI.
[[language]]
name = "rust"
scope = "source.rust"
injection-regex = "rust"
file-types = ["rs"]
comment-token = "//"
roots = ["Cargo.toml", "Cargo.lock"]
indent = { tab-width = 4, unit = " " }
[[grammar]]
name = "rust"
source = { git = "https://github.com/tree-sitter/tree-sitter-rust", rev = "0431a2c60828731f27491ee9fdefe25e250ce9c9" }
[[language]]
name = "nix"
scope = "source.nix"
injection-regex = "nix"
file-types = ["nix"]
shebangs = []
roots = []
comment-token = "#"
# A grammar entry is not necessary for this language - it is only used for
# testing TOML merging behavior.

View File

@@ -0,0 +1,3 @@
[toolchain]
channel = "1.61.0"
components = ["rustfmt", "rust-src"]

View File

@@ -1,21 +1,57 @@
name: Release
on:
# schedule:
# - cron: '0 0 * * *' # midnight UTC
push:
tags:
- 'v[0-9]+.[0-9]+.[0-9]+'
## - release
- '[0-9]+.[0-9]+'
- '[0-9]+.[0-9]+.[0-9]+'
branches:
- 'patch/ci-release-*'
pull_request:
paths:
- '.github/workflows/release.yml'
env:
# Preview mode: Publishes the build output as a CI artifact instead of creating
# a release, allowing for manual inspection of the output. This mode is
# activated if the CI run was triggered by events other than pushed tags, or
# if the repository is a fork.
preview: ${{ !startsWith(github.ref, 'refs/tags/') || github.repository != 'helix-editor/helix' }}
jobs:
fetch-grammars:
name: Fetch Grammars
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v3
- name: Install stable toolchain
uses: helix-editor/rust-toolchain@v1
with:
profile: minimal
override: true
- uses: Swatinem/rust-cache@v2
- name: Fetch tree-sitter grammars
run: cargo run --package=helix-loader --bin=hx-loader
- name: Bundle grammars
run: tar cJf grammars.tar.xz -C runtime/grammars/sources .
- uses: actions/upload-artifact@v3
with:
name: grammars
path: grammars.tar.xz
dist:
name: Dist
needs: [fetch-grammars]
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false # don't fail other jobs if one fails
matrix:
build: [x86_64-linux, aarch64-linux, x86_64-macos, x86_64-windows] #, x86_64-win-gnu, win32-msvc
build: [x86_64-linux, x86_64-macos, x86_64-windows] #, x86_64-win-gnu, win32-msvc
include:
- build: x86_64-linux
os: ubuntu-20.04
@@ -27,6 +63,11 @@ jobs:
rust: stable
target: aarch64-unknown-linux-gnu
cross: true
- build: riscv64-linux
os: ubuntu-20.04
rust: stable
target: riscv64gc-unknown-linux-gnu
cross: true
- build: x86_64-macos
os: macos-latest
rust: stable
@@ -37,10 +78,12 @@ jobs:
rust: stable
target: x86_64-pc-windows-msvc
cross: false
# - build: aarch64-macos
# os: macos-latest
# rust: stable
# target: aarch64-apple-darwin
- build: aarch64-macos
os: macos-latest
rust: stable
target: aarch64-apple-darwin
cross: false
skip_tests: true # x86_64 host can't run aarch64 code
# - build: x86_64-win-gnu
# os: windows-2019
# rust: stable-x86_64-gnu
@@ -52,9 +95,16 @@ jobs:
steps:
- name: Checkout sources
uses: actions/checkout@v2
with:
submodules: true
uses: actions/checkout@v3
- name: Download grammars
uses: actions/download-artifact@v3
- name: Move grammars under runtime
if: "!startsWith(matrix.os, 'windows')"
run: |
mkdir -p runtime/grammars/sources
tar xJf grammars/grammars.tar.xz -C runtime/grammars/sources
- name: Install ${{ matrix.rust }} toolchain
uses: actions-rs/toolchain@v1
@@ -64,12 +114,29 @@ jobs:
target: ${{ matrix.target }}
override: true
# Install a pre-release version of Cross
# TODO: We need to pre-install Cross because we need cross-rs/cross#591 to
# get a newer C++ compiler toolchain. Remove this step when Cross
# 0.3.0, which includes cross-rs/cross#591, is released.
- name: Install Cross
if: "matrix.cross"
run: cargo install cross --git https://github.com/cross-rs/cross.git --rev 47df5c76e7cba682823a0b6aa6d95c17b31ba63a
- name: Run cargo test
uses: actions-rs/cargo@v1
if: "!matrix.skip_tests"
with:
use-cross: ${{ matrix.cross }}
command: test
args: --release --locked --target ${{ matrix.target }}
args: --release --locked --target ${{ matrix.target }} --workspace
- name: Set profile.release.strip = true
shell: bash
run: |
cat >> .cargo/config.toml <<EOF
[profile.release]
strip = true
EOF
- name: Build release binary
uses: actions-rs/cargo@v1
@@ -78,31 +145,65 @@ jobs:
command: build
args: --release --locked --target ${{ matrix.target }}
- name: Strip release binary (linux and macos)
if: matrix.build == 'x86_64-linux' || matrix.build == 'x86_64-macos'
run: strip "target/${{ matrix.target }}/release/hx"
- name: Strip release binary (arm)
if: matrix.build == 'aarch64-linux'
- name: Build AppImage
shell: bash
if: matrix.build == 'aarch64-linux' || matrix.build == 'x86_64-linux'
run: |
docker run --rm -v \
"$PWD/target:/target:Z" \
rustembedded/cross:${{ matrix.target }} \
aarch64-linux-gnu-strip \
/target/${{ matrix.target }}/release/hx
mkdir dist
name=dev
if [[ $GITHUB_REF == refs/tags/* ]]; then
name=${GITHUB_REF:10}
fi
build="${{ matrix.build }}"
export VERSION="$name"
export ARCH=${build%-linux}
export APP=helix
export OUTPUT="helix-$VERSION-$ARCH.AppImage"
export UPDATE_INFORMATION="gh-releases-zsync|$GITHUB_REPOSITORY_OWNER|helix|latest|$APP-*-$ARCH.AppImage.zsync"
mkdir -p "$APP.AppDir"/usr/{bin,lib/helix}
cp "target/${{ matrix.target }}/release/hx" "$APP.AppDir/usr/bin/hx"
rm -rf runtime/grammars/sources
cp -r runtime "$APP.AppDir/usr/lib/helix/runtime"
cat << 'EOF' > "$APP.AppDir/AppRun"
#!/bin/sh
APPDIR="$(dirname "$(readlink -f "${0}")")"
HELIX_RUNTIME="$APPDIR/usr/lib/helix/runtime" exec "$APPDIR/usr/bin/hx" "$@"
EOF
chmod 755 "$APP.AppDir/AppRun"
curl -Lo linuxdeploy-x86_64.AppImage \
https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage
chmod +x linuxdeploy-x86_64.AppImage
./linuxdeploy-x86_64.AppImage \
--appdir "$APP.AppDir" -d contrib/Helix.desktop \
-i contrib/helix.png --output appimage
mv "$APP-$VERSION-$ARCH.AppImage" \
"$APP-$VERSION-$ARCH.AppImage.zsync" dist
- name: Build archive
shell: bash
run: |
mkdir dist
mkdir -p dist
if [ "${{ matrix.os }}" = "windows-2019" ]; then
cp "target/${{ matrix.target }}/release/hx.exe" "dist/"
else
cp "target/${{ matrix.target }}/release/hx" "dist/"
fi
if [ -d runtime/grammars/sources ]; then
rm -rf runtime/grammars/sources
fi
cp -r runtime dist
- uses: actions/upload-artifact@v2.2.4
- uses: actions/upload-artifact@v3
with:
name: bins-${{ matrix.build }}
path: dist
@@ -113,33 +214,22 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v2
with:
submodules: false
uses: actions/checkout@v3
- uses: actions/download-artifact@v2
# with:
# path: dist
# - run: ls -al ./dist
- run: ls -al bins-*
- name: Calculate tag name
run: |
name=dev
if [[ $GITHUB_REF == refs/tags/v* ]]; then
name=${GITHUB_REF:10}
fi
echo ::set-output name=val::$name
echo TAG=$name >> $GITHUB_ENV
id: tagname
- uses: actions/download-artifact@v3
- name: Build archive
shell: bash
run: |
set -ex
rm -rf tmp
mkdir tmp
source="$(pwd)"
mkdir -p runtime/grammars/sources
tar xJf grammars/grammars.tar.xz -C runtime/grammars/sources
rm -rf grammars
cd "$(mktemp -d)"
mv $source/bins-* .
mkdir dist
for dir in bins-* ; do
@@ -147,25 +237,42 @@ jobs:
if [[ $platform =~ "windows" ]]; then
exe=".exe"
fi
pkgname=helix-$TAG-$platform
mkdir tmp/$pkgname
cp LICENSE README.md tmp/$pkgname
mv bins-$platform/runtime tmp/$pkgname/
mv bins-$platform/hx$exe tmp/$pkgname
chmod +x tmp/$pkgname/hx$exe
pkgname=helix-$GITHUB_REF_NAME-$platform
mkdir $pkgname
cp $source/LICENSE $source/README.md $pkgname
mkdir $pkgname/contrib
cp -r $source/contrib/completion $pkgname/contrib
mv bins-$platform/runtime $pkgname/
mv bins-$platform/hx$exe $pkgname
chmod +x $pkgname/hx$exe
if [[ "$platform" = "aarch64-linux" || "$platform" = "x86_64-linux" ]]; then
mv bins-$platform/helix-*.AppImage* dist/
fi
if [ "$exe" = "" ]; then
tar cJf dist/$pkgname.tar.xz -C tmp $pkgname
tar cJf dist/$pkgname.tar.xz $pkgname
else
(cd tmp && 7z a -r ../dist/$pkgname.zip $pkgname)
7z a -r dist/$pkgname.zip $pkgname
fi
done
tar cJf dist/helix-$GITHUB_REF_NAME-source.tar.xz -C $source .
mv dist $source/
- name: Upload binaries to release
uses: svenstaro/upload-release-action@v2
if: env.preview == 'false'
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: dist/*
file_glob: true
tag: ${{ steps.tagname.outputs.val }}
tag: ${{ github.ref_name }}
overwrite: true
- name: Upload binaries as artifact
uses: actions/upload-artifact@v3
if: env.preview == 'true'
with:
name: release
path: dist/*

1
.gitignore vendored
View File

@@ -1,6 +1,5 @@
target
.direnv
helix-term/rustfmt.toml
helix-syntax/languages/
result
runtime/grammars

136
.gitmodules vendored
View File

@@ -1,136 +0,0 @@
[submodule "helix-syntax/languages/tree-sitter-cpp"]
path = helix-syntax/languages/tree-sitter-cpp
url = https://github.com/tree-sitter/tree-sitter-cpp
shallow = true
[submodule "helix-syntax/languages/tree-sitter-javascript"]
path = helix-syntax/languages/tree-sitter-javascript
url = https://github.com/tree-sitter/tree-sitter-javascript
shallow = true
[submodule "helix-syntax/languages/tree-sitter-julia"]
path = helix-syntax/languages/tree-sitter-julia
url = https://github.com/tree-sitter/tree-sitter-julia
shallow = true
[submodule "helix-syntax/languages/tree-sitter-python"]
path = helix-syntax/languages/tree-sitter-python
url = https://github.com/tree-sitter/tree-sitter-python
shallow = true
[submodule "helix-syntax/languages/tree-sitter-typescript"]
path = helix-syntax/languages/tree-sitter-typescript
url = https://github.com/tree-sitter/tree-sitter-typescript
shallow = true
[submodule "helix-syntax/languages/tree-sitter-agda"]
path = helix-syntax/languages/tree-sitter-agda
url = https://github.com/tree-sitter/tree-sitter-agda
shallow = true
[submodule "helix-syntax/languages/tree-sitter-go"]
path = helix-syntax/languages/tree-sitter-go
url = https://github.com/tree-sitter/tree-sitter-go
shallow = true
[submodule "helix-syntax/languages/tree-sitter-ruby"]
path = helix-syntax/languages/tree-sitter-ruby
url = https://github.com/tree-sitter/tree-sitter-ruby
shallow = true
[submodule "helix-syntax/languages/tree-sitter-java"]
path = helix-syntax/languages/tree-sitter-java
url = https://github.com/tree-sitter/tree-sitter-java
shallow = true
[submodule "helix-syntax/languages/tree-sitter-php"]
path = helix-syntax/languages/tree-sitter-php
url = https://github.com/tree-sitter/tree-sitter-php
shallow = true
[submodule "helix-syntax/languages/tree-sitter-html"]
path = helix-syntax/languages/tree-sitter-html
url = https://github.com/tree-sitter/tree-sitter-html
shallow = true
[submodule "helix-syntax/languages/tree-sitter-scala"]
path = helix-syntax/languages/tree-sitter-scala
url = https://github.com/tree-sitter/tree-sitter-scala
shallow = true
[submodule "helix-syntax/languages/tree-sitter-bash"]
path = helix-syntax/languages/tree-sitter-bash
url = https://github.com/tree-sitter/tree-sitter-bash
shallow = true
[submodule "helix-syntax/languages/tree-sitter-rust"]
path = helix-syntax/languages/tree-sitter-rust
url = https://github.com/tree-sitter/tree-sitter-rust
shallow = true
[submodule "helix-syntax/languages/tree-sitter-json"]
path = helix-syntax/languages/tree-sitter-json
url = https://github.com/tree-sitter/tree-sitter-json
shallow = true
[submodule "helix-syntax/languages/tree-sitter-css"]
path = helix-syntax/languages/tree-sitter-css
url = https://github.com/tree-sitter/tree-sitter-css
shallow = true
[submodule "helix-syntax/languages/tree-sitter-c-sharp"]
path = helix-syntax/languages/tree-sitter-c-sharp
url = https://github.com/tree-sitter/tree-sitter-c-sharp
shallow = true
[submodule "helix-syntax/languages/tree-sitter-c"]
path = helix-syntax/languages/tree-sitter-c
url = https://github.com/tree-sitter/tree-sitter-c
shallow = true
[submodule "helix-syntax/languages/tree-sitter-haskell"]
path = helix-syntax/languages/tree-sitter-haskell
url = https://github.com/tree-sitter/tree-sitter-haskell
shallow = true
[submodule "helix-syntax/languages/tree-sitter-swift"]
path = helix-syntax/languages/tree-sitter-swift
url = https://github.com/tree-sitter/tree-sitter-swift
shallow = true
[submodule "helix-syntax/languages/tree-sitter-toml"]
path = helix-syntax/languages/tree-sitter-toml
url = https://github.com/ikatyang/tree-sitter-toml
shallow = true
[submodule "helix-syntax/languages/tree-sitter-elixir"]
path = helix-syntax/languages/tree-sitter-elixir
url = https://github.com/elixir-lang/tree-sitter-elixir
shallow = true
[submodule "helix-syntax/languages/tree-sitter-nix"]
path = helix-syntax/languages/tree-sitter-nix
url = https://github.com/cstrahan/tree-sitter-nix
shallow = true
[submodule "helix-syntax/languages/tree-sitter-latex"]
path = helix-syntax/languages/tree-sitter-latex
url = https://github.com/latex-lsp/tree-sitter-latex
shallow = true
[submodule "helix-syntax/languages/tree-sitter-ledger"]
path = helix-syntax/languages/tree-sitter-ledger
url = https://github.com/cbarrete/tree-sitter-ledger
shallow = true
[submodule "helix-syntax/languages/tree-sitter-protobuf"]
path = helix-syntax/languages/tree-sitter-protobuf
url = https://github.com/yusdacra/tree-sitter-protobuf.git
shallow = true
[submodule "helix-syntax/languages/tree-sitter-ocaml"]
path = helix-syntax/languages/tree-sitter-ocaml
url = https://github.com/tree-sitter/tree-sitter-ocaml
shallow = true
[submodule "helix-syntax/languages/tree-sitter-lua"]
path = helix-syntax/languages/tree-sitter-lua
url = https://github.com/nvim-treesitter/tree-sitter-lua
shallow = true
[submodule "helix-syntax/languages/tree-sitter-yaml"]
path = helix-syntax/languages/tree-sitter-yaml
url = https://github.com/ikatyang/tree-sitter-yaml
shallow = true
[submodule "helix-syntax/languages/tree-sitter-zig"]
path = helix-syntax/languages/tree-sitter-zig
url = https://github.com/maxxnino/tree-sitter-zig
shallow = true
[submodule "helix-syntax/languages/tree-sitter-svelte"]
path = helix-syntax/languages/tree-sitter-svelte
url = https://github.com/Himujjal/tree-sitter-svelte
shallow = true
[submodule "helix-syntax/languages/tree-sitter-vue"]
path = helix-syntax/languages/tree-sitter-vue
url = https://github.com/ikatyang/tree-sitter-vue
shallow = true
[submodule "helix-syntax/languages/tree-sitter-tsq"]
path = helix-syntax/languages/tree-sitter-tsq
url = https://github.com/tree-sitter/tree-sitter-tsq
shallow = true
[submodule "helix-syntax/languages/tree-sitter-cmake"]
path = helix-syntax/languages/tree-sitter-cmake
url = https://github.com/uyha/tree-sitter-cmake
shallow = true

5
.ignore Normal file
View File

@@ -0,0 +1,5 @@
# Things that we don't want ripgrep to search that we do want in git
# https://github.com/BurntSushi/ripgrep/blob/master/GUIDE.md#automatic-filtering
# Minified JS vendored from mdbook
book/theme/highlight.js

File diff suppressed because it is too large Load Diff

1833
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -4,13 +4,24 @@ members = [
"helix-view",
"helix-term",
"helix-tui",
"helix-syntax",
"helix-lsp",
"helix-dap",
"helix-loader",
"helix-vcs",
"xtask",
]
# Build helix-syntax in release mode to make the code path faster in development.
# [profile.dev.package."helix-syntax"]
# opt-level = 3
default-members = [
"helix-term"
]
[profile.dev]
split-debuginfo = "unpacked"
[profile.release]
lto = "thin"
# debug = true
[profile.opt]
inherits = "release"
lto = "fat"
codegen-units = 1
# strip = "debuginfo" # TODO: or strip = true
opt-level = 3

126
README.md
View File

@@ -1,14 +1,27 @@
# Helix
<div align="center">
<h1>
<picture>
<source media="(prefers-color-scheme: dark)" srcset="logo_dark.svg">
<source media="(prefers-color-scheme: light)" srcset="logo_light.svg">
<img alt="Helix" height="128" src="logo_light.svg">
</picture>
</h1>
[![Build status](https://github.com/helix-editor/helix/actions/workflows/build.yml/badge.svg)](https://github.com/helix-editor/helix/actions)
[![GitHub Release](https://img.shields.io/github/v/release/helix-editor/helix)](https://github.com/helix-editor/helix/releases/latest)
[![Documentation](https://shields.io/badge/-documentation-452859)](https://docs.helix-editor.com/)
[![GitHub contributors](https://img.shields.io/github/contributors/helix-editor/helix)](https://github.com/helix-editor/helix/graphs/contributors)
[![Matrix Space](https://img.shields.io/matrix/helix-community:matrix.org)](https://matrix.to/#/#helix-community:matrix.org)
</div>
![Screenshot](./screenshot.png)
A kakoune / neovim inspired editor, written in Rust.
A Kakoune / Neovim inspired editor, written in Rust.
The editing model is very heavily based on kakoune; during development I found
myself agreeing with most of kakoune's design decisions.
The editing model is very heavily based on Kakoune; during development I found
myself agreeing with most of Kakoune's design decisions.
For more information, see the [website](https://helix-editor.com) or
[documentation](https://docs.helix-editor.com/).
@@ -25,27 +38,58 @@ All shortcuts/keymaps can be found [in the documentation on the website](https:/
- Smart, incremental syntax highlighting and code editing via tree-sitter
It's a terminal-based editor first, but I'd like to explore a custom renderer
(similar to emacs) in wgpu or skulpin.
(similar to Emacs) in wgpu or skulpin.
Note: Only certain languages have indentation definitions at the moment. Check
`runtime/queries/<lang>/` for `indents.scm`.
# Installation
Note: Only certain languages have indentation definitions at the moment. Check
`runtime/queries/<lang>/` for `indents.toml`.
Packages are available for various distributions (see [Installation docs](https://docs.helix-editor.com/install.html)).
We provide packaging for various distributions, but here's a quick method to
build from source.
If you would like to build from source:
```
git clone --recurse-submodules --shallow-submodules -j8 https://github.com/helix-editor/helix
```shell
git clone https://github.com/helix-editor/helix
cd helix
cargo install --path helix-term
```
This will install the `hx` binary to `$HOME/.cargo/bin`.
This will install the `hx` binary to `$HOME/.cargo/bin` and build tree-sitter grammars in `./runtime/grammars`.
Helix also needs its runtime files so make sure to copy/symlink the `runtime/` directory into the
config directory (for example `~/.config/helix/runtime` on Linux/macOS). This location can be overriden
via the `HELIX_RUNTIME` environment variable.
Helix needs its runtime files so make sure to copy/symlink the `runtime/` directory into the
config directory (for example `~/.config/helix/runtime` on Linux/macOS, or `%AppData%/helix/runtime` on Windows).
| OS | Command |
| -------------------- | ------------------------------------------------ |
| Windows (Cmd) | `xcopy /e /i runtime %AppData%\helix\runtime` |
| Windows (PowerShell) | `xcopy /e /i runtime $Env:AppData\helix\runtime` |
| Linux / macOS | `ln -s $PWD/runtime ~/.config/helix/runtime` |
Starting with Windows Vista you can also create symbolic links on Windows. Note that this requires
elevated privileges - i.e. PowerShell or Cmd must be run as administrator.
**PowerShell:**
```powershell
New-Item -ItemType SymbolicLink -Target "runtime" -Path "$Env:AppData\helix\runtime"
```
**Cmd:**
```cmd
cd %appdata%\helix
mklink /D runtime "<helix-repo>\runtime"
```
The runtime location can be overridden via the `HELIX_RUNTIME` environment variable.
> NOTE: if `HELIX_RUNTIME` is set prior to calling `cargo install --path helix-term`,
> tree-sitter grammars will be built in `$HELIX_RUNTIME/grammars`.
If you plan on keeping the repo locally, an alternative to copying/symlinking
runtime files is to set `HELIX_RUNTIME=/path/to/helix/runtime`
(`HELIX_RUNTIME=$PWD/runtime` if you're in the helix repo directory).
Packages already solve this for you by wrapping the `hx` binary with a wrapper
that sets the variable to the install dir.
@@ -53,36 +97,50 @@ that sets the variable to the install dir.
> NOTE: running via cargo also doesn't require setting explicit `HELIX_RUNTIME` path, it will automatically
> detect the `runtime` directory in the project root.
If you want to customize your `languages.toml` config,
tree-sitter grammars may be manually fetched and built with `hx --grammar fetch` and `hx --grammar build`.
In order to use LSP features like auto-complete, you will need to
[install the appropriate Language Server](https://github.com/helix-editor/helix/wiki/How-to-install-the-default-language-servers)
for a language.
[![Packaging status](https://repology.org/badge/vertical-allrepos/helix.svg)](https://repology.org/project/helix/versions)
## MacOS
Helix can be installed on MacOS through homebrew via:
## Adding Helix to your desktop environment
If installing from source, to use Helix in desktop environments that supports [XDG desktop menu](https://specifications.freedesktop.org/menu-spec/menu-spec-latest.html), including Gnome and KDE, copy the provided `.desktop` file to the correct folder:
```bash
cp contrib/Helix.desktop ~/.local/share/applications
```
To use another terminal than the default, you will need to modify the `.desktop` file. For example, to use `kitty`:
```bash
sed -i "s|Exec=hx %F|Exec=kitty hx %F|g" ~/.local/share/applications/Helix.desktop
sed -i "s|Terminal=true|Terminal=false|g" ~/.local/share/applications/Helix.desktop
```
Please note: there is no icon for Helix yet, so the system default will be used.
## macOS
Helix can be installed on macOS through homebrew:
```
brew tap helix-editor/helix
brew install helix
```
# Contributing
Contributors are very welcome! **No contribution is too small and all contributions are valued.**
Some suggestions to get started:
- You can look at the [good first issue](https://github.com/helix-editor/helix/labels/E-easy) label on the issue tracker.
- Help with packaging on various distributions needed!
- To use print debugging to the `~/.cache/helix/helix.log` file, you must:
* Print using `log::info!`, `warn!`, or `error!`. (`log::info!("helix!")`)
* Pass the appropriate verbosity level option for the desired log level. (`hx -v <file>` for info, more `v`s for higher severity inclusive)
- If your preferred language is missing, integrating a tree-sitter grammar for
it and defining syntax highlight queries for it is straight forward and
doesn't require much knowledge of the internals.
We provide an [architecture.md](./docs/architecture.md) that should give you
a good overview of the internals.
Contributing guidelines can be found [here](./docs/CONTRIBUTING.md).
# Getting help
Your question might already be answered on the [FAQ](https://github.com/helix-editor/helix/wiki/FAQ).
Discuss the project on the community [Matrix Space](https://matrix.to/#/#helix-community:matrix.org) (make sure to join `#helix-editor:matrix.org` if you're on a client that doesn't support Matrix Spaces yet).
# Credits
Thanks to [@JakeHL](https://github.com/JakeHL) for designing the logo!

32
TODO.md
View File

@@ -1,32 +0,0 @@
- tree sitter:
- markdown
- regex
- kotlin
- clojure
- erlang
- [ ] completion isIncomplete support
1
- [ ] respect view fullscreen flag
- [ ] Implement marks (superset of Selection/Range)
- [ ] = for auto indent line/selection
- [ ] :x for closing buffers
- [ ] lsp: signature help
2
- [ ] macro recording
- [ ] extend selection (treesitter select parent node) (replaces viw, vi(, va( etc )
- [ ] selection align
- [ ] store some state between restarts: file positions, prompt history
- [ ] highlight matched characters in picker
3
- [ ] diff mode with highlighting?
- [ ] snippet support (tab to jump between marks)
- [ ] gamelisp/wasm scripting
X
- [ ] rendering via skulpin/skia or raw wgpu

1
VERSION Normal file
View File

@@ -0,0 +1 @@
22.12

50
base16_theme.toml Normal file
View File

@@ -0,0 +1,50 @@
# Author: NNB <nnbnh@protonmail.com>
"ui.menu" = { fg = "black", bg = "white" }
"ui.menu.selected" = { modifiers = ["reversed"] }
"ui.linenr" = { fg = "gray", bg = "black" }
"ui.popup" = { modifiers = ["reversed"] }
"ui.linenr.selected" = { fg = "white", bg = "black", modifiers = ["bold"] }
"ui.selection" = { fg = "black", bg = "blue" }
"ui.selection.primary" = { fg = "white", bg = "blue" }
"comment" = { fg = "gray" }
"ui.statusline" = { fg = "black", bg = "white" }
"ui.statusline.inactive" = { fg = "gray", bg = "white" }
"ui.cursor" = { fg = "white", modifiers = ["reversed"] }
"variable" = "red"
"constant.numeric" = "yellow"
"constant" = "yellow"
"attributes" = "yellow"
"type" = "yellow"
"ui.cursor.match" = { fg = "yellow", modifiers = ["underlined"] }
"string" = "green"
"variable.other.member" = "green"
"constant.character.escape" = "cyan"
"function" = "blue"
"constructor" = "blue"
"special" = "blue"
"keyword" = "magenta"
"label" = "magenta"
"namespace" = "magenta"
"ui.help" = { fg = "white", bg = "black" }
"markup.heading" = "blue"
"markup.list" = "red"
"markup.bold" = { fg = "yellow", modifiers = ["bold"] }
"markup.italic" = { fg = "magenta", modifiers = ["italic"] }
"markup.link.url" = { fg = "yellow", modifiers = ["underlined"] }
"markup.link.text" = "red"
"markup.quote" = "cyan"
"markup.raw" = "green"
"diff.plus" = "green"
"diff.delta" = "yellow"
"diff.minus" = "red"
"diagnostic" = { modifiers = ["underlined"] }
"ui.gutter" = { bg = "black" }
"info" = "blue"
"hint" = "gray"
"debug" = "gray"
"warning" = "yellow"
"error" = "red"

View File

@@ -9,3 +9,4 @@ edit-url-template = "https://github.com/helix-editor/helix/tree/master/book/{pat
cname = "docs.helix-editor.com"
default-theme = "colibri"
preferred-dark-theme = "colibri"
git-repository-url = "https://github.com/helix-editor/helix"

View File

@@ -1,12 +1,18 @@
# Summary
[Helix](./title-page.md)
- [Installation](./install.md)
- [Usage](./usage.md)
- [Keymap](./keymap.md)
- [Commands](./commands.md)
- [Language Support](./lang-support.md)
- [Migrating from Vim](./from-vim.md)
- [Configuration](./configuration.md)
- [Themes](./themes.md)
- [Keymap](./keymap.md)
- [Key Remapping](./remapping.md)
- [Hooks](./hooks.md)
- [Languages](./languages.md)
- [Guides](./guides/README.md)
- [Adding Languages](./guides/adding_languages.md)
- [Adding Textobject Queries](./guides/textobject.md)
- [Adding Indent Queries](./guides/indent.md)

5
book/src/commands.md Normal file
View File

@@ -0,0 +1,5 @@
# Commands
Command mode can be activated by pressing `:`, similar to Vim. Built-in commands:
{{#include ./generated/typable-cmd.md}}

View File

@@ -5,28 +5,253 @@ To override global configuration parameters, create a `config.toml` file located
* Linux and Mac: `~/.config/helix/config.toml`
* Windows: `%AppData%\helix\config.toml`
> Hint: You can easily open the config file by typing `:config-open` within Helix normal mode.
Example config:
```toml
theme = "onedark"
[editor]
line-number = "relative"
mouse = false
[editor.cursor-shape]
insert = "bar"
normal = "block"
select = "underline"
[editor.file-picker]
hidden = false
```
You may also specify a file to use for configuration with the `-c` or
`--config` CLI argument: `hx -c path/to/custom-config.toml`.
It is also possible to trigger configuration file reloading by sending the `USR1`
signal to the helix process, e.g. via `pkill -USR1 hx`. This is only supported
on unix operating systems.
## Editor
`[editor]` section of the config.
### `[editor]` Section
| Key | Description | Default |
|--|--|---------|
| `scrolloff` | Number of lines of padding around the edge of the screen when scrolling. | `3` |
| `scrolloff` | Number of lines of padding around the edge of the screen when scrolling. | `5` |
| `mouse` | Enable mouse mode. | `true` |
| `middle-click-paste` | Middle click paste support. | `true` |
| `scroll-lines` | Number of lines to scroll per scroll wheel step. | `3` |
| `shell` | Shell to use when running external commands. | Unix: `["sh", "-c"]`<br/>Windows: `["cmd", "/C"]` |
| `line-number` | Line number display (`absolute`, `relative`) | `absolute` |
| `smart-case` | Enable smart case regex searching (case insensitive unless pattern contains upper case characters) | `true` |
| `auto-pairs` | Enable automatic insertion of pairs to parenthese, brackets, etc. | `true` |
| `line-number` | Line number display: `absolute` simply shows each line's number, while `relative` shows the distance from the current line. When unfocused or in insert mode, `relative` will still show absolute line numbers. | `absolute` |
| `cursorline` | Highlight all lines with a cursor. | `false` |
| `cursorcolumn` | Highlight all columns with a cursor. | `false` |
| `gutters` | Gutters to display: Available are `diagnostics` and `diff` and `line-numbers` and `spacer`, note that `diagnostics` also includes other features like breakpoints, 1-width padding will be inserted if gutters is non-empty | `["diagnostics", "spacer", "line-numbers", "spacer", "diff"]` |
| `auto-completion` | Enable automatic pop up of auto-completion. | `true` |
| `auto-format` | Enable automatic formatting on save. | `true` |
| `auto-save` | Enable automatic saving on focus moving away from Helix. Requires [focus event support](https://github.com/helix-editor/helix/wiki/Terminal-Support) from your terminal. | `false` |
| `idle-timeout` | Time in milliseconds since last keypress before idle timers trigger. Used for autocompletion, set to 0 for instant. | `400` |
| `completion-trigger-len` | The min-length of word under cursor to trigger autocompletion | `2` |
| `auto-info` | Whether to display infoboxes | `true` |
| `true-color` | Set to `true` to override automatic detection of terminal truecolor support in the event of a false negative. | `false` |
| `rulers` | List of column positions at which to display the rulers. Can be overridden by language specific `rulers` in `languages.toml` file. | `[]` |
| `bufferline` | Renders a line at the top of the editor displaying open buffers. Can be `always`, `never` or `multiple` (only shown if more than one buffer is in use) | `never` |
| `color-modes` | Whether to color the mode indicator with different colors depending on the mode itself | `false` |
## LSP
### `[editor.statusline]` Section
Allows configuring the statusline at the bottom of the editor.
The configuration distinguishes between three areas of the status line:
`[ ... ... LEFT ... ... | ... ... ... ... CENTER ... ... ... ... | ... ... RIGHT ... ... ]`
Statusline elements can be defined as follows:
To display all language server messages in the status line add the following to your `config.toml`:
```toml
[lsp]
display-messages = true
[editor.statusline]
left = ["mode", "spinner"]
center = ["file-name"]
right = ["diagnostics", "selections", "position", "file-encoding", "file-line-ending", "file-type"]
separator = "│"
mode.normal = "NORMAL"
mode.insert = "INSERT"
mode.select = "SELECT"
```
The `[editor.statusline]` key takes the following sub-keys:
| Key | Description | Default |
| --- | --- | --- |
| `left` | A list of elements aligned to the left of the statusline | `["mode", "spinner", "file-name"]` |
| `center` | A list of elements aligned to the middle of the statusline | `[]` |
| `right` | A list of elements aligned to the right of the statusline | `["diagnostics", "selections", "position", "file-encoding"]` |
| `separator` | The character used to separate elements in the statusline | `"│"` |
| `mode.normal` | The text shown in the `mode` element for normal mode | `"NOR"` |
| `mode.insert` | The text shown in the `mode` element for insert mode | `"INS"` |
| `mode.select` | The text shown in the `mode` element for select mode | `"SEL"` |
The following statusline elements can be configured:
| Key | Description |
| ------ | ----------- |
| `mode` | The current editor mode (`mode.normal`/`mode.insert`/`mode.select`) |
| `spinner` | A progress spinner indicating LSP activity |
| `file-name` | The path/name of the opened file |
| `file-encoding` | The encoding of the opened file if it differs from UTF-8 |
| `file-line-ending` | The file line endings (CRLF or LF) |
| `total-line-numbers` | The total line numbers of the opened file |
| `file-type` | The type of the opened file |
| `diagnostics` | The number of warnings and/or errors |
| `workspace-diagnostics` | The number of warnings and/or errors on workspace |
| `selections` | The number of active selections |
| `primary-selection-length` | The number of characters currently in primary selection |
| `position` | The cursor position |
| `position-percentage` | The cursor position as a percentage of the total number of lines |
| `separator` | The string defined in `editor.statusline.separator` (defaults to `"│"`) |
| `spacer` | Inserts a space between elements (multiple/contiguous spacers may be specified) |
### `[editor.lsp]` Section
| Key | Description | Default |
| --- | ----------- | ------- |
| `display-messages` | Display LSP progress messages below statusline[^1] | `false` |
| `auto-signature-help` | Enable automatic popup of signature help (parameter hints) | `true` |
| `display-signature-help-docs` | Display docs under signature help popup | `true` |
[^1]: By default, a progress spinner is shown in the statusline beside the file path.
### `[editor.cursor-shape]` Section
Defines the shape of cursor in each mode. Note that due to limitations
of the terminal environment, only the primary cursor can change shape.
Valid values for these options are `block`, `bar`, `underline`, or `hidden`.
| Key | Description | Default |
| --- | ----------- | ------- |
| `normal` | Cursor shape in [normal mode][normal mode] | `block` |
| `insert` | Cursor shape in [insert mode][insert mode] | `block` |
| `select` | Cursor shape in [select mode][select mode] | `block` |
[normal mode]: ./keymap.md#normal-mode
[insert mode]: ./keymap.md#insert-mode
[select mode]: ./keymap.md#select--extend-mode
### `[editor.file-picker]` Section
Sets options for file picker and global search. All but the last key listed in
the default file-picker configuration below are IgnoreOptions: whether hidden
files and files listed within ignore files are ignored by (not visible in) the
helix file picker and global search. There is also one other key, `max-depth`
available, which is not defined by default.
All git related options are only enabled in a git repository.
| Key | Description | Default |
|--|--|---------|
|`hidden` | Enables ignoring hidden files. | true
|`parents` | Enables reading ignore files from parent directories. | true
|`ignore` | Enables reading `.ignore` files. | true
|`git-ignore` | Enables reading `.gitignore` files. | true
|`git-global` | Enables reading global .gitignore, whose path is specified in git's config: `core.excludefile` option. | true
|`git-exclude` | Enables reading `.git/info/exclude` files. | true
|`max-depth` | Set with an integer value for maximum depth to recurse. | Defaults to `None`.
### `[editor.auto-pairs]` Section
Enables automatic insertion of pairs to parentheses, brackets, etc. Can be a
simple boolean value, or a specific mapping of pairs of single characters.
To disable auto-pairs altogether, set `auto-pairs` to `false`:
```toml
[editor]
auto-pairs = false # defaults to `true`
```
The default pairs are <code>(){}[]''""``</code>, but these can be customized by
setting `auto-pairs` to a TOML table:
```toml
[editor.auto-pairs]
'(' = ')'
'{' = '}'
'[' = ']'
'"' = '"'
'`' = '`'
'<' = '>'
```
Additionally, this setting can be used in a language config. Unless
the editor setting is `false`, this will override the editor config in
documents with this language.
Example `languages.toml` that adds <> and removes ''
```toml
[[language]]
name = "rust"
[language.auto-pairs]
'(' = ')'
'{' = '}'
'[' = ']'
'"' = '"'
'`' = '`'
'<' = '>'
```
### `[editor.search]` Section
Search specific options.
| Key | Description | Default |
|--|--|---------|
| `smart-case` | Enable smart case regex searching (case insensitive unless pattern contains upper case characters) | `true` |
| `wrap-around`| Whether the search should wrap after depleting the matches | `true` |
### `[editor.whitespace]` Section
Options for rendering whitespace with visible characters. Use `:set whitespace.render all` to temporarily enable visible whitespace.
| Key | Description | Default |
|-----|-------------|---------|
| `render` | Whether to render whitespace. May either be `"all"` or `"none"`, or a table with sub-keys `space`, `tab`, and `newline`. | `"none"` |
| `characters` | Literal characters to use when rendering whitespace. Sub-keys may be any of `tab`, `space`, `nbsp`, `newline` or `tabpad` | See example below |
Example
```toml
[editor.whitespace]
render = "all"
# or control each character
[editor.whitespace.render]
space = "all"
tab = "all"
newline = "none"
[editor.whitespace.characters]
space = "·"
nbsp = "⍽"
tab = "→"
newline = "⏎"
tabpad = "·" # Tabs will look like "→···" (depending on tab width)
```
### `[editor.indent-guides]` Section
Options for rendering vertical indent guides.
| Key | Description | Default |
| --- | --- | --- |
| `render` | Whether to render indent guides. | `false` |
| `character` | Literal character to use for rendering the indent guide | `│` |
| `skip-levels` | Number of indent levels to skip | `0` |
Example:
```toml
[editor.indent-guides]
render = true
character = "╎" # Some characters that work well: "▏", "┆", "┊", "⸽"
skip-levels = 1
```

View File

@@ -1,12 +1,12 @@
# Migrating from Vim
Helix's editing model is strongly inspired from vim and kakoune, and a notable
difference from vim (and the most striking similarity to kakoune) is that Helix
Helix's editing model is strongly inspired from Vim and Kakoune, and a notable
difference from Vim (and the most striking similarity to Kakoune) is that Helix
follows the `selection → action` model. This means that the whatever you are
going to act on (a word, a paragraph, a line, etc) is selected first and the
action itself (delete, change, yank, etc) comes second. A cursor is simply a
single width selection.
See also Kakoune's [Migrating from Vim](https://github.com/mawww/kakoune/wiki/Migrating-from-Vim).
See also Kakoune's [Migrating from Vim](https://github.com/mawww/kakoune/wiki/Migrating-from-Vim) and Helix's [Migrating from Vim](https://github.com/helix-editor/helix/wiki/Migrating-from-Vim).
> TODO: Mention texobjects, surround, registers
> TODO: Mention textobjects, surround, registers

View File

@@ -0,0 +1,139 @@
| Language | Syntax Highlighting | Treesitter Textobjects | Auto Indent | Default LSP |
| --- | --- | --- | --- | --- |
| astro | ✓ | | | |
| awk | ✓ | ✓ | | `awk-language-server` |
| bash | ✓ | | | `bash-language-server` |
| bass | ✓ | | | `bass` |
| beancount | ✓ | | | |
| bibtex | ✓ | | | `texlab` |
| bicep | ✓ | | | `bicep-langserver` |
| c | ✓ | ✓ | ✓ | `clangd` |
| c-sharp | ✓ | ✓ | | `OmniSharp` |
| cairo | ✓ | | | |
| clojure | ✓ | | | `clojure-lsp` |
| cmake | ✓ | ✓ | ✓ | `cmake-language-server` |
| comment | ✓ | | | |
| common-lisp | ✓ | | | `cl-lsp` |
| cpon | ✓ | | ✓ | |
| cpp | ✓ | ✓ | ✓ | `clangd` |
| css | ✓ | | | `vscode-css-language-server` |
| cue | ✓ | | | `cuelsp` |
| d | ✓ | ✓ | ✓ | `serve-d` |
| dart | ✓ | | ✓ | `dart` |
| devicetree | ✓ | | | |
| diff | ✓ | | | |
| dockerfile | ✓ | | | `docker-langserver` |
| dot | ✓ | | | `dot-language-server` |
| edoc | ✓ | | | |
| eex | ✓ | | | |
| ejs | ✓ | | | |
| elixir | ✓ | ✓ | ✓ | `elixir-ls` |
| elm | ✓ | | | `elm-language-server` |
| elvish | ✓ | | | `elvish` |
| env | ✓ | | | |
| erb | ✓ | | | |
| erlang | ✓ | ✓ | | `erlang_ls` |
| esdl | ✓ | | | |
| fish | ✓ | ✓ | ✓ | |
| fortran | ✓ | | ✓ | `fortls` |
| gdscript | ✓ | ✓ | | |
| git-attributes | ✓ | | | |
| git-commit | ✓ | | | |
| git-config | ✓ | | | |
| git-ignore | ✓ | | | |
| git-rebase | ✓ | | | |
| gleam | ✓ | ✓ | | `gleam` |
| glsl | ✓ | ✓ | ✓ | |
| go | ✓ | ✓ | ✓ | `gopls` |
| godot-resource | ✓ | | | |
| gomod | ✓ | | | `gopls` |
| gotmpl | ✓ | | | `gopls` |
| gowork | ✓ | | | `gopls` |
| graphql | ✓ | | | |
| hare | ✓ | | | |
| haskell | ✓ | ✓ | | `haskell-language-server-wrapper` |
| hcl | ✓ | | ✓ | `terraform-ls` |
| heex | ✓ | ✓ | | `elixir-ls` |
| html | ✓ | | | `vscode-html-language-server` |
| idris | | | | `idris2-lsp` |
| iex | ✓ | | | |
| ini | ✓ | | | |
| java | ✓ | ✓ | | `jdtls` |
| javascript | ✓ | ✓ | ✓ | `typescript-language-server` |
| jsdoc | ✓ | | | |
| json | ✓ | | ✓ | `vscode-json-language-server` |
| jsonnet | ✓ | | | `jsonnet-language-server` |
| jsx | ✓ | ✓ | ✓ | `typescript-language-server` |
| julia | ✓ | | | `julia` |
| kdl | ✓ | | | |
| kotlin | ✓ | | | `kotlin-language-server` |
| latex | ✓ | ✓ | | `texlab` |
| lean | ✓ | | | `lean` |
| ledger | ✓ | | | |
| llvm | ✓ | ✓ | ✓ | |
| llvm-mir | ✓ | ✓ | ✓ | |
| llvm-mir-yaml | ✓ | | ✓ | |
| lua | ✓ | ✓ | ✓ | `lua-language-server` |
| make | ✓ | | | |
| markdown | ✓ | | | `marksman` |
| markdown.inline | ✓ | | | |
| meson | ✓ | | ✓ | |
| mint | | | | `mint` |
| nickel | ✓ | | ✓ | `nls` |
| nix | ✓ | | | `nil` |
| nu | ✓ | | | |
| ocaml | ✓ | | ✓ | `ocamllsp` |
| ocaml-interface | ✓ | | | `ocamllsp` |
| odin | ✓ | | | `ols` |
| openscad | ✓ | | | `openscad-lsp` |
| org | ✓ | | | |
| pascal | ✓ | ✓ | | `pasls` |
| perl | ✓ | ✓ | ✓ | |
| php | ✓ | ✓ | ✓ | `intelephense` |
| prisma | ✓ | | | `prisma-language-server` |
| prolog | | | | `swipl` |
| protobuf | ✓ | | ✓ | |
| purescript | ✓ | | | `purescript-language-server` |
| python | ✓ | ✓ | ✓ | `pylsp` |
| qml | ✓ | | ✓ | `qmlls` |
| r | ✓ | | | `R` |
| racket | ✓ | | | `racket` |
| regex | ✓ | | | |
| rescript | ✓ | ✓ | | `rescript-language-server` |
| rmarkdown | ✓ | | ✓ | `R` |
| ron | ✓ | | ✓ | |
| ruby | ✓ | ✓ | ✓ | `solargraph` |
| rust | ✓ | ✓ | ✓ | `rust-analyzer` |
| scala | ✓ | | ✓ | `metals` |
| scheme | ✓ | | | |
| scss | ✓ | | | `vscode-css-language-server` |
| slint | ✓ | | ✓ | `slint-lsp` |
| sml | ✓ | | | |
| solidity | ✓ | | | `solc` |
| sql | ✓ | | | |
| sshclientconfig | ✓ | | | |
| starlark | ✓ | ✓ | | |
| svelte | ✓ | | | `svelteserver` |
| swift | ✓ | | | `sourcekit-lsp` |
| tablegen | ✓ | ✓ | ✓ | |
| task | ✓ | | | |
| tfvars | | | | `terraform-ls` |
| toml | ✓ | | | `taplo` |
| tsq | ✓ | | | |
| tsx | ✓ | ✓ | ✓ | `typescript-language-server` |
| twig | ✓ | | | |
| typescript | ✓ | ✓ | ✓ | `typescript-language-server` |
| ungrammar | ✓ | | | |
| v | ✓ | | | `vls` |
| vala | ✓ | | | `vala-language-server` |
| verilog | ✓ | ✓ | | `svlangserver` |
| vhs | ✓ | | | |
| vue | ✓ | | | `vls` |
| wast | ✓ | | | |
| wat | ✓ | | | |
| wgsl | ✓ | | | `wgsl_analyzer` |
| wit | ✓ | | ✓ | |
| xit | ✓ | | | |
| xml | ✓ | | ✓ | |
| yaml | ✓ | | ✓ | `yaml-language-server` |
| zig | ✓ | ✓ | ✓ | `zls` |

View File

@@ -0,0 +1,76 @@
| Name | Description |
| --- | --- |
| `:quit`, `:q` | Close the current view. |
| `:quit!`, `:q!` | Force close the current view, ignoring unsaved changes. |
| `:open`, `:o` | Open a file from disk into the current view. |
| `:buffer-close`, `:bc`, `:bclose` | Close the current buffer. |
| `:buffer-close!`, `:bc!`, `:bclose!` | Close the current buffer forcefully, ignoring unsaved changes. |
| `:buffer-close-others`, `:bco`, `:bcloseother` | Close all buffers but the currently focused one. |
| `:buffer-close-others!`, `:bco!`, `:bcloseother!` | Force close all buffers but the currently focused one. |
| `:buffer-close-all`, `:bca`, `:bcloseall` | Close all buffers without quitting. |
| `:buffer-close-all!`, `:bca!`, `:bcloseall!` | Force close all buffers ignoring unsaved changes without quitting. |
| `:buffer-next`, `:bn`, `:bnext` | Goto next buffer. |
| `:buffer-previous`, `:bp`, `:bprev` | Goto previous buffer. |
| `:write`, `:w` | Write changes to disk. Accepts an optional path (:write some/path.txt) |
| `:write!`, `:w!` | Force write changes to disk creating necessary subdirectories. Accepts an optional path (:write some/path.txt) |
| `:new`, `:n` | Create a new scratch buffer. |
| `:format`, `:fmt` | Format the file using the LSP formatter. |
| `:indent-style` | Set the indentation style for editing. ('t' for tabs or 1-8 for number of spaces.) |
| `:line-ending` | Set the document's default line ending. Options: crlf, lf. |
| `:earlier`, `:ear` | Jump back to an earlier point in edit history. Accepts a number of steps or a time span. |
| `:later`, `:lat` | Jump to a later point in edit history. Accepts a number of steps or a time span. |
| `:write-quit`, `:wq`, `:x` | Write changes to disk and close the current view. Accepts an optional path (:wq some/path.txt) |
| `:write-quit!`, `:wq!`, `:x!` | Write changes to disk and close the current view forcefully. Accepts an optional path (:wq! some/path.txt) |
| `:write-all`, `:wa` | Write changes from all buffers to disk. |
| `:write-quit-all`, `:wqa`, `:xa` | Write changes from all buffers to disk and close all views. |
| `:write-quit-all!`, `:wqa!`, `:xa!` | Write changes from all buffers to disk and close all views forcefully (ignoring unsaved changes). |
| `:quit-all`, `:qa` | Close all views. |
| `:quit-all!`, `:qa!` | Force close all views ignoring unsaved changes. |
| `:cquit`, `:cq` | Quit with exit code (default 1). Accepts an optional integer exit code (:cq 2). |
| `:cquit!`, `:cq!` | Force quit with exit code (default 1) ignoring unsaved changes. Accepts an optional integer exit code (:cq! 2). |
| `:theme` | Change the editor theme (show current theme if no name specified). |
| `:clipboard-yank` | Yank main selection into system clipboard. |
| `:clipboard-yank-join` | Yank joined selections into system clipboard. A separator can be provided as first argument. Default value is newline. |
| `:primary-clipboard-yank` | Yank main selection into system primary clipboard. |
| `:primary-clipboard-yank-join` | Yank joined selections into system primary clipboard. A separator can be provided as first argument. Default value is newline. |
| `:clipboard-paste-after` | Paste system clipboard after selections. |
| `:clipboard-paste-before` | Paste system clipboard before selections. |
| `:clipboard-paste-replace` | Replace selections with content of system clipboard. |
| `:primary-clipboard-paste-after` | Paste primary clipboard after selections. |
| `:primary-clipboard-paste-before` | Paste primary clipboard before selections. |
| `:primary-clipboard-paste-replace` | Replace selections with content of system primary clipboard. |
| `:show-clipboard-provider` | Show clipboard provider name in status bar. |
| `:change-current-directory`, `:cd` | Change the current working directory. |
| `:show-directory`, `:pwd` | Show the current working directory. |
| `:encoding` | Set encoding. Based on `https://encoding.spec.whatwg.org`. |
| `:reload` | Discard changes and reload from the source file. |
| `:reload-all` | Discard changes and reload all documents from the source files. |
| `:update` | Write changes only if the file has been modified. |
| `:lsp-workspace-command` | Open workspace command picker |
| `:lsp-restart` | Restarts the Language Server that is in use by the current doc |
| `:tree-sitter-scopes` | Display tree sitter scopes, primarily for theming and development. |
| `:debug-start`, `:dbg` | Start a debug session from a given template with given parameters. |
| `:debug-remote`, `:dbg-tcp` | Connect to a debug adapter by TCP address and start a debugging session from a given template with given parameters. |
| `:debug-eval` | Evaluate expression in current debug context. |
| `:vsplit`, `:vs` | Open the file in a vertical split. |
| `:vsplit-new`, `:vnew` | Open a scratch buffer in a vertical split. |
| `:hsplit`, `:hs`, `:sp` | Open the file in a horizontal split. |
| `:hsplit-new`, `:hnew` | Open a scratch buffer in a horizontal split. |
| `:tutor` | Open the tutorial. |
| `:goto`, `:g` | Goto line number. |
| `:set-language`, `:lang` | Set the language of current buffer. |
| `:set-option`, `:set` | Set a config option at runtime.<br>For example to disable smart case search, use `:set search.smart-case false`. |
| `:get-option`, `:get` | Get the current value of a config option. |
| `:sort` | Sort ranges in selection. |
| `:rsort` | Sort ranges in selection in reverse order. |
| `:reflow` | Hard-wrap the current selection of lines to a given width. |
| `:tree-sitter-subtree`, `:ts-subtree` | Display tree sitter subtree under cursor, primarily for debugging queries. |
| `:config-reload` | Refresh user config. |
| `:config-open` | Open the user config.toml file. |
| `:log-open` | Open the helix log file. |
| `:insert-output` | Run shell command, inserting output before each selection. |
| `:append-output` | Run shell command, appending output after each selection. |
| `:pipe` | Pipe each selection to the shell command. |
| `:pipe-to` | Pipe each selection to the shell command, ignoring output. |
| `:run-shell-command`, `:sh` | Run a shell command |
| `:help`, `:h` | Open documentation for a command or keybind. |

View File

@@ -1,4 +1,4 @@
# Guides
This section contains guides for adding new language server configurations,
tree-sitter grammers, textobject queries, etc.
tree-sitter grammars, textobject queries, etc.

View File

@@ -0,0 +1,45 @@
# Adding languages
## Language configuration
To add a new language, you need to add a `[[language]]` entry to the
`languages.toml` (see the [language configuration section]).
When adding a new language or Language Server configuration for an existing
language, run `cargo xtask docgen` to add the new configuration to the
[Language Support][lang-support] docs before creating a pull request.
When adding a Language Server configuration, be sure to update the
[Language Server Wiki][install-lsp-wiki] with installation notes.
## Grammar configuration
If a tree-sitter grammar is available for the language, add a new `[[grammar]]`
entry to `languages.toml`.
You may use the `source.path` key rather than `source.git` with an absolute path
to a locally available grammar for testing, but switch to `source.git` before
submitting a pull request.
## Queries
For a language to have syntax-highlighting and indentation among
other things, you have to add queries. Add a directory for your
language with the path `runtime/queries/<name>/`. The tree-sitter
[website](https://tree-sitter.github.io/tree-sitter/syntax-highlighting#queries)
gives more info on how to write queries.
> NOTE: When evaluating queries, the first matching query takes
precedence, which is different from other editors like Neovim where
the last matching query supersedes the ones before it. See
[this issue][neovim-query-precedence] for an example.
## Common Issues
- If you get errors when running after switching branches, you may have to update the tree-sitter grammars. Run `hx --grammar fetch` to fetch the grammars and `hx --grammar build` to build any out-of-date grammars.
- If a parser is segfaulting or you want to remove the parser, make sure to remove the compiled parser in `runtime/grammar/<name>.so`
[language configuration section]: ../languages.md
[neovim-query-precedence]: https://github.com/helix-editor/helix/pull/1170#issuecomment-997294090
[install-lsp-wiki]: https://github.com/helix-editor/helix/wiki/How-to-install-the-default-language-servers
[lang-support]: ../lang-support.md

93
book/src/guides/indent.md Normal file
View File

@@ -0,0 +1,93 @@
# Adding Indent Queries
Helix uses tree-sitter to correctly indent new lines. This requires
a tree-sitter grammar and an `indent.scm` query file placed in
`runtime/queries/{language}/indents.scm`. The indentation for a line
is calculated by traversing the syntax tree from the lowest node at the
beginning of the new line. Each of these nodes contributes to the total
indent when it is captured by the query (in what way depends on the name
of the capture).
Note that it matters where these added indents begin. For example,
multiple indent level increases that start on the same line only increase
the total indent level by 1.
## Scopes
Added indents don't always apply to the whole node. For example, in most
cases when a node should be indented, we actually only want everything
except for its first line to be indented. For this, there are several
scopes (more scopes may be added in the future if required):
- `all`:
This scope applies to the whole captured node. This is only different from
`tail` when the captured node is the first node on its line.
- `tail`:
This scope applies to everything except for the first line of the
captured node.
Every capture type has a default scope which should do the right thing
in most situations. When a different scope is required, this can be
changed by using a `#set!` declaration anywhere in the pattern:
```scm
(assignment_expression
right: (_) @indent
(#set! "scope" "all"))
```
## Capture Types
- `@indent` (default scope `tail`):
Increase the indent level by 1. Multiple occurrences in the same line
don't stack. If there is at least one `@indent` and one `@outdent`
capture on the same line, the indent level isn't changed at all.
- `@outdent` (default scope `all`):
Decrease the indent level by 1. The same rules as for `@indent` apply.
- `@extend`:
Extend the range of this node to the end of the line and to lines that
are indented more than the line that this node starts on. This is useful
for languages like Python, where for the purpose of indentation some nodes
(like functions or classes) should also contain indented lines that follow them.
- `@extend.prevent-once`:
Prevents the first extension of an ancestor of this node. For example, in Python
a return expression always ends the block that it is in. Note that this only stops the
extension of the next `@extend` capture. If multiple ancestors are captured,
only the extension of the innermost one is prevented. All other ancestors are unaffected
(regardless of whether the innermost ancestor would actually have been extended).
## Predicates
In some cases, an S-expression cannot express exactly what pattern should be matched.
For that, tree-sitter allows for predicates to appear anywhere within a pattern,
similar to how `#set!` declarations work:
```scm
(some_kind
(child_kind) @indent
(#predicate? arg1 arg2 ...)
)
```
The number of arguments depends on the predicate that's used.
Each argument is either a capture (`@name`) or a string (`"some string"`).
The following predicates are supported by tree-sitter:
- `#eq?`/`#not-eq?`:
The first argument (a capture) must/must not be equal to the second argument
(a capture or a string).
- `#match?`/`#not-match?`:
The first argument (a capture) must/must not match the regex given in the
second argument (a string).
Additionally, we support some custom predicates for indent queries:
- `#not-kind-eq?`:
The kind of the first argument (a capture) must not be equal to the second
argument (a string).
- `#same-line?`/`#not-same-line?`:
The captures given by the 2 arguments must/must not start on the same line.

View File

@@ -5,7 +5,7 @@ require an accompanying tree-sitter grammar and a `textobjects.scm` query file
to work properly. Tree-sitter allows us to query the source code syntax tree
and capture specific parts of it. The queries are written in a lisp dialect.
More information on how to write queries can be found in the [official tree-sitter
documentation](tree-sitter-queries).
documentation][tree-sitter-queries].
Query files should be placed in `runtime/queries/{language}/textobjects.scm`
when contributing. Note that to test the query files locally you should put
@@ -20,11 +20,30 @@ The following [captures][tree-sitter-captures] are recognized:
| `function.around` |
| `class.inside` |
| `class.around` |
| `test.inside` |
| `test.around` |
| `parameter.inside` |
| `comment.inside` |
| `comment.around` |
[Example query files][textobject-examples] can be found in the helix GitHub repository.
## Queries for Textobject Based Navigation
[Tree-sitter based navigation][textobjects-nav] is done using captures in the
following order:
- `object.movement`
- `object.around`
- `object.inside`
For example if a `function.around` capture has been already defined for a language
in it's `textobjects.scm` file, function navigation should also work automatically.
`function.movement` should be defined only if the node captured by `function.around`
doesn't make sense in a navigation context.
[textobjects]: ../usage.md#textobjects
[textobjects-nav]: ../usage.md#tree-sitter-textobject-based-navigation
[tree-sitter-queries]: https://tree-sitter.github.io/tree-sitter/using-parsers#query-syntax
[tree-sitter-captures]: https://tree-sitter.github.io/tree-sitter/using-parsers#capturing-nodes
[textobject-examples]: https://github.com/search?q=repo%3Ahelix-editor%2Fhelix+filename%3Atextobjects.scm&type=Code&ref=advsearch&l=&l=

View File

@@ -1 +0,0 @@
# Hooks

View File

@@ -6,10 +6,9 @@ We provide pre-built binaries on the [GitHub Releases page](https://github.com/h
## OSX
A Homebrew tap is available:
Helix is available in homebrew-core:
```
brew tap helix-editor/helix
brew install helix
```
@@ -19,26 +18,150 @@ brew install helix
A [flake](https://nixos.wiki/wiki/Flakes) containing the package is available in
the project root. The flake can also be used to spin up a reproducible development
shell for working on Helix.
shell for working on Helix with `nix develop`.
Flake outputs are cached for each push to master using
[Cachix](https://www.cachix.org/). The flake is configured to
automatically make use of this cache assuming the user accepts
the new settings on first use.
If you are using a version of Nix without flakes enabled you can
[install Cachix cli](https://docs.cachix.org/installation); `cachix use helix` will
configure Nix to use cached outputs when possible.
### Arch Linux
Releases are available in the `community` repository.
Packages are also 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
A [helix-git](https://aur.archlinux.org/packages/helix-git/) package is also available on the AUR, which builds the master branch.
### Fedora Linux
You can install the COPR package for Helix via
```
sudo dnf copr enable varlad/helix
sudo dnf install helix
```
### Void Linux
```
sudo xbps-install helix
```
## Windows
Helix can be installed using [Scoop](https://scoop.sh/), [Chocolatey](https://chocolatey.org/)
or [MSYS2](https://msys2.org/).
**Scoop:**
```
scoop install helix
```
**Chocolatey:**
```
choco install helix
```
**MSYS2:**
```
pacman -S mingw-w64-i686-helix
```
or
```
pacman -S mingw-w64-x86_64-helix
```
or
```
pacman -S mingw-w64-ucrt-x86_64-helix
```
## Build from source
```
git clone --recurse-submodules --shallow-submodules -j8 https://github.com/helix-editor/helix
git clone https://github.com/helix-editor/helix
cd helix
cargo install --path helix-term
```
This will install the `hx` binary to `$HOME/.cargo/bin`.
This will install the `hx` binary to `$HOME/.cargo/bin` and build tree-sitter grammars in `./runtime/grammars`.
Helix also needs it's runtime files so make sure to copy/symlink the `runtime/` directory into the
config directory (for example `~/.config/helix/runtime` on Linux/macOS). This location can be overriden
Helix also needs its runtime files so make sure to copy/symlink the `runtime/` directory into the
config directory (for example `~/.config/helix/runtime` on Linux/macOS). This location can be overridden
via the `HELIX_RUNTIME` environment variable.
| OS | Command |
| -------------------- | ------------------------------------------------ |
| Windows (Cmd) | `xcopy /e /i runtime %AppData%\helix\runtime` |
| Windows (PowerShell) | `xcopy /e /i runtime $Env:AppData\helix\runtime` |
| Linux / macOS | `ln -s $PWD/runtime ~/.config/helix/runtime` |
Starting with Windows Vista you can also create symbolic links on Windows. Note that this requires
elevated privileges - i.e. PowerShell or Cmd must be run as administrator.
**PowerShell:**
```powershell
New-Item -ItemType SymbolicLink -Target "runtime" -Path "$Env:AppData\helix\runtime"
```
**Cmd:**
```cmd
cd %appdata%\helix
mklink /D runtime "<helix-repo>\runtime"
```
The runtime location can be overridden via the `HELIX_RUNTIME` environment variable.
> NOTE: if `HELIX_RUNTIME` is set prior to calling `cargo install --path helix-term`,
> tree-sitter grammars will be built in `$HELIX_RUNTIME/grammars`.
If you plan on keeping the repo locally, an alternative to copying/symlinking
runtime files is to set `HELIX_RUNTIME=/path/to/helix/runtime`
(`HELIX_RUNTIME=$PWD/runtime` if you're in the helix repo directory).
To use Helix in desktop environments that supports [XDG desktop menu](https://specifications.freedesktop.org/menu-spec/menu-spec-latest.html), including Gnome and KDE, copy the provided `.desktop` file to the correct folder:
```bash
cp contrib/Helix.desktop ~/.local/share/applications
```
To use another terminal than the default, you will need to modify the `.desktop` file. For example, to use `kitty`:
```bash
sed -i "s|Exec=hx %F|Exec=kitty hx %F|g" ~/.local/share/applications/Helix.desktop
sed -i "s|Terminal=true|Terminal=false|g" ~/.local/share/applications/Helix.desktop
```
Please note: there is no icon for Helix yet, so the system default will be used.
## Finishing up the installation
To make sure everything is set up as expected you should finally run the helix healthcheck via
```
hx --health
```
For more information on the information displayed in the health check results refer to [Healthcheck](https://github.com/helix-editor/helix/wiki/Healthcheck).
### Building tree-sitter grammars
Tree-sitter grammars must be fetched and compiled if not pre-packaged.
Fetch grammars with `hx --grammar fetch` (requires `git`) and compile them
with `hx --grammar build` (requires a C++ compiler).
### Installing language servers
Language servers can optionally be installed if you want their features (auto-complete, diagnostics etc.).
Follow the [instructions on the wiki page](https://github.com/helix-editor/helix/wiki/How-to-install-the-default-language-servers) to add your language servers of choice.

View File

@@ -1,176 +1,231 @@
# Keymap
- [Normal mode](#normal-mode)
- [Movement](#movement)
- [Changes](#changes)
- [Shell](#shell)
- [Selection manipulation](#selection-manipulation)
- [Search](#search)
- [Minor modes](#minor-modes)
- [View mode](#view-mode)
- [Goto mode](#goto-mode)
- [Match mode](#match-mode)
- [Window mode](#window-mode)
- [Space mode](#space-mode)
- [Popup](#popup)
- [Unimpaired](#unimpaired)
- [Insert Mode](#insert-mode)
- [Select / extend mode](#select--extend-mode)
- [Picker](#picker)
- [Prompt](#prompt)
> 💡 Mappings marked (**LSP**) require an active language server for the file.
> 💡 Mappings marked (**TS**) require a tree-sitter grammar for the filetype.
## Normal mode
### Movement
> NOTE: Unlike vim, `f`, `F`, `t` and `T` are not confined to the current line.
> NOTE: Unlike Vim, `f`, `F`, `t` and `T` are not confined to the current line.
| Key | Description | Command |
| ----- | ----------- | ------- |
| `h`/`Left` | Move left | `move_char_left` |
| `j`/`Down` | Move down | `move_line_down` |
| `k`/`Up` | Move up | `move_line_up` |
| `l`/`Right` | Move right | `move_char_right` |
| `w` | Move next word start | `move_next_word_start` |
| `b` | Move previous word start | `move_prev_word_start` |
| `e` | Move next word end | `move_next_word_end` |
| `W` | Move next WORD start | `move_next_long_word_start` |
| `B` | Move previous WORD start | `move_prev_long_word_start` |
| `E` | Move next WORD end | `move_next_long_word_end` |
| `t` | Find 'till next char | `find_till_char` |
| `f` | Find next char | `find_next_char` |
| `T` | Find 'till previous char | `till_prev_char` |
| `F` | Find previous char | `find_prev_char` |
| `Alt-.` | Repeat last motion (`f`, `t` or `m`) | `repeat_last_motion` |
| `Home` | Move to the start of the line | `goto_line_start` |
| `End` | Move to the end of the line | `goto_line_end` |
| `PageUp` | Move page up | `page_up` |
| `PageDown` | Move page down | `page_down` |
| `Ctrl-u` | Move half page up | `half_page_up` |
| `Ctrl-d` | Move half page down | `half_page_down` |
| `Ctrl-i` | Jump forward on the jumplist | `jump_forward` |
| `Ctrl-o` | Jump backward on the jumplist | `jump_backward` |
| `v` | Enter [select (extend) mode](#select--extend-mode) | `select_mode` |
| `g` | Enter [goto mode](#goto-mode) | N/A |
| `m` | Enter [match mode](#match-mode) | N/A |
| `:` | Enter command mode | `command_mode` |
| `z` | Enter [view mode](#view-mode) | N/A |
| `Z` | Enter sticky [view mode](#view-mode) | N/A |
| `Ctrl-w` | Enter [window mode](#window-mode) | N/A |
| `Space` | Enter [space mode](#space-mode) | N/A |
| Key | Description | Command |
| ----- | ----------- | ------- |
| `h`, `Left` | Move left | `move_char_left` |
| `j`, `Down` | Move down | `move_line_down` |
| `k`, `Up` | Move up | `move_line_up` |
| `l`, `Right` | Move right | `move_char_right` |
| `w` | Move next word start | `move_next_word_start` |
| `b` | Move previous word start | `move_prev_word_start` |
| `e` | Move next word end | `move_next_word_end` |
| `W` | Move next WORD start | `move_next_long_word_start` |
| `B` | Move previous WORD start | `move_prev_long_word_start` |
| `E` | Move next WORD end | `move_next_long_word_end` |
| `t` | Find 'till next char | `find_till_char` |
| `f` | Find next char | `find_next_char` |
| `T` | Find 'till previous char | `till_prev_char` |
| `F` | Find previous char | `find_prev_char` |
| `G` | Go to line number `<n>` | `goto_line` |
| `Alt-.` | Repeat last motion (`f`, `t` or `m`) | `repeat_last_motion` |
| `Home` | Move to the start of the line | `goto_line_start` |
| `End` | Move to the end of the line | `goto_line_end` |
| `Ctrl-b`, `PageUp` | Move page up | `page_up` |
| `Ctrl-f`, `PageDown` | Move page down | `page_down` |
| `Ctrl-u` | Move half page up | `half_page_up` |
| `Ctrl-d` | Move half page down | `half_page_down` |
| `Ctrl-i` | Jump forward on the jumplist | `jump_forward` |
| `Ctrl-o` | Jump backward on the jumplist | `jump_backward` |
| `Ctrl-s` | Save the current selection to the jumplist | `save_selection` |
### Changes
| Key | Description | Command |
| ----- | ----------- | ------- |
| `r` | Replace with a character | `replace` |
| `R` | Replace with yanked text | `replace_with_yanked` |
| `~` | Switch case of the selected text | `switch_case` |
| `` ` `` | Set the selected text to lower case | `switch_to_lowercase` |
| `` Alt-` `` | Set the selected text to upper case | `switch_to_uppercase` |
| `i` | Insert before selection | `insert_mode` |
| `a` | Insert after selection (append) | `append_mode` |
| `I` | Insert at the start of the line | `prepend_to_line` |
| `A` | Insert at the end of the line | `append_to_line` |
| `o` | Open new line below selection | `open_below` |
| `O` | Open new line above selection | `open_above` |
| `.` | Repeat last change | N/A |
| `u` | Undo change | `undo` |
| `U` | Redo change | `redo` |
| `y` | Yank selection | `yank` |
| `p` | Paste after selection | `paste_after` |
| `P` | Paste before selection | `paste_before` |
| `"` `<reg>` | Select a register to yank to or paste from | `select_register` |
| `>` | Indent selection | `indent` |
| `<` | Unindent selection | `unindent` |
| `=` | Format selection | `format_selections` |
| `d` | Delete selection | `delete_selection` |
| `c` | Change selection (delete and enter insert mode) | `change_selection` |
| Key | Description | Command |
| ----- | ----------- | ------- |
| `r` | Replace with a character | `replace` |
| `R` | Replace with yanked text | `replace_with_yanked` |
| `~` | Switch case of the selected text | `switch_case` |
| `` ` `` | Set the selected text to lower case | `switch_to_lowercase` |
| `` Alt-` `` | Set the selected text to upper case | `switch_to_uppercase` |
| `i` | Insert before selection | `insert_mode` |
| `a` | Insert after selection (append) | `append_mode` |
| `I` | Insert at the start of the line | `insert_at_line_start` |
| `A` | Insert at the end of the line | `insert_at_line_end` |
| `o` | Open new line below selection | `open_below` |
| `O` | Open new line above selection | `open_above` |
| `.` | Repeat last insert | N/A |
| `u` | Undo change | `undo` |
| `U` | Redo change | `redo` |
| `Alt-u` | Move backward in history | `earlier` |
| `Alt-U` | Move forward in history | `later` |
| `y` | Yank selection | `yank` |
| `p` | Paste after selection | `paste_after` |
| `P` | Paste before selection | `paste_before` |
| `"` `<reg>` | Select a register to yank to or paste from | `select_register` |
| `>` | Indent selection | `indent` |
| `<` | Unindent selection | `unindent` |
| `=` | Format selection (currently nonfunctional/disabled) (**LSP**) | `format_selections` |
| `d` | Delete selection | `delete_selection` |
| `Alt-d` | Delete selection, without yanking | `delete_selection_noyank` |
| `c` | Change selection (delete and enter insert mode) | `change_selection` |
| `Alt-c` | Change selection (delete and enter insert mode, without yanking) | `change_selection_noyank` |
| `Ctrl-a` | Increment object (number) under cursor | `increment` |
| `Ctrl-x` | Decrement object (number) under cursor | `decrement` |
| `Q` | Start/stop macro recording to the selected register (experimental) | `record_macro` |
| `q` | Play back a recorded macro from the selected register (experimental) | `replay_macro` |
#### Shell
| Key | Description | Command |
| ------ | ----------- | ------- |
| <code>&#124;</code> | Pipe each selection through shell command, replacing with output | `shell_pipe` |
| <code>A-&#124;</code> | Pipe each selection into shell command, ignoring output | `shell_pipe_to` |
| `!` | Run shell command, inserting output before each selection | `shell_insert_output` |
| `A-!` | Run shell command, appending output after each selection | `shell_append_output` |
| Key | Description | Command |
| ------ | ----------- | ------- |
| <code>&#124;</code> | Pipe each selection through shell command, replacing with output | `shell_pipe` |
| <code>Alt-&#124;</code> | Pipe each selection into shell command, ignoring output | `shell_pipe_to` |
| `!` | Run shell command, inserting output before each selection | `shell_insert_output` |
| `Alt-!` | Run shell command, appending output after each selection | `shell_append_output` |
| `$` | Pipe each selection into shell command, keep selections where command returned 0 | `shell_keep_pipe` |
### Selection manipulation
| Key | Description | Command |
| ----- | ----------- | ------- |
| `s` | Select all regex matches inside selections | `select_regex` |
| `S` | Split selection into subselections on regex matches | `split_selection` |
| `Alt-s` | Split selection on newlines | `split_selection_on_newline` |
| `;` | Collapse selection onto a single cursor | `collapse_selection` |
| `Alt-;` | Flip selection cursor and anchor | `flip_selections` |
| `,` | Keep only the primary selection | `keep_primary_selection` |
| `Alt-,` | Remove the primary selection | `remove_primary_selection` |
| `C` | Copy selection onto the next line | `copy_selection_on_next_line` |
| `Alt-C` | Copy selection onto the previous line | `copy_selection_on_prev_line` |
| `(` | Rotate main selection backward | `rotate_selections_backward` |
| `)` | Rotate main selection forward | `rotate_selections_forward` |
| `Alt-(` | Rotate selection contents backward | `rotate_selection_contents_backward` |
| `Alt-)` | Rotate selection contents forward | `rotate_selection_contents_forward` |
| `%` | Select entire file | `select_all` |
| `x` | Select current line, if already selected, extend to next line | `extend_line` |
| `X` | Extend selection to line bounds (line-wise selection) | `extend_to_line_bounds` |
| | Expand selection to parent syntax node TODO: pick a key | `expand_selection` |
| `J` | Join lines inside selection | `join_selections` |
| `K` | Keep selections matching the regex | `keep_selections` |
| `$` | Pipe each selection into shell command, keep selections where command returned 0 | `shell_keep_pipe` |
| `Ctrl-c` | Comment/uncomment the selections | `toggle_comments` |
| Key | Description | Command |
| ----- | ----------- | ------- |
| `s` | Select all regex matches inside selections | `select_regex` |
| `S` | Split selection into subselections on regex matches | `split_selection` |
| `Alt-s` | Split selection on newlines | `split_selection_on_newline` |
| `&` | Align selection in columns | `align_selections` |
| `_` | Trim whitespace from the selection | `trim_selections` |
| `;` | Collapse selection onto a single cursor | `collapse_selection` |
| `Alt-;` | Flip selection cursor and anchor | `flip_selections` |
| `Alt-:` | Ensures the selection is in forward direction | `ensure_selections_forward` |
| `,` | Keep only the primary selection | `keep_primary_selection` |
| `Alt-,` | Remove the primary selection | `remove_primary_selection` |
| `C` | Copy selection onto the next line (Add cursor below) | `copy_selection_on_next_line` |
| `Alt-C` | Copy selection onto the previous line (Add cursor above) | `copy_selection_on_prev_line` |
| `(` | Rotate main selection backward | `rotate_selections_backward` |
| `)` | Rotate main selection forward | `rotate_selections_forward` |
| `Alt-(` | Rotate selection contents backward | `rotate_selection_contents_backward` |
| `Alt-)` | Rotate selection contents forward | `rotate_selection_contents_forward` |
| `%` | Select entire file | `select_all` |
| `x` | Select current line, if already selected, extend to next line | `extend_line_below` |
| `X` | Extend selection to line bounds (line-wise selection) | `extend_to_line_bounds` |
| `Alt-x` | Shrink selection to line bounds (line-wise selection) | `shrink_to_line_bounds` |
| `J` | Join lines inside selection | `join_selections` |
| `Alt-J` | Join lines inside selection and select space | `join_selections_space` |
| `K` | Keep selections matching the regex | `keep_selections` |
| `Alt-K` | Remove selections matching the regex | `remove_selections` |
| `Ctrl-c` | Comment/uncomment the selections | `toggle_comments` |
| `Alt-o`, `Alt-up` | Expand selection to parent syntax node (**TS**) | `expand_selection` |
| `Alt-i`, `Alt-down` | Shrink syntax tree object selection (**TS**) | `shrink_selection` |
| `Alt-p`, `Alt-left` | Select previous sibling node in syntax tree (**TS**) | `select_prev_sibling` |
| `Alt-n`, `Alt-right` | Select next sibling node in syntax tree (**TS**) | `select_next_sibling` |
### Search
> TODO: The search implementation isn't ideal yet -- we don't support searching in reverse.
Search commands all operate on the `/` register by default. Use `"<char>` to operate on a different one.
| Key | Description | Command |
| ----- | ----------- | ------- |
| `/` | Search for regex pattern | `search` |
| `?` | Search for previous pattern | `rsearch` |
| `n` | Select next search match | `search_next` |
| `N` | Add next search match to selection | `extend_search_next` |
| `N` | Select previous search match | `search_prev` |
| `*` | Use current selection as the search pattern | `search_selection` |
### Minor modes
These sub-modes are accessible from normal mode and typically switch back to normal mode after a command.
| Key | Description | Command |
| ----- | ----------- | ------- |
| `v` | Enter [select (extend) mode](#select--extend-mode) | `select_mode` |
| `g` | Enter [goto mode](#goto-mode) | N/A |
| `m` | Enter [match mode](#match-mode) | N/A |
| `:` | Enter command mode | `command_mode` |
| `z` | Enter [view mode](#view-mode) | N/A |
| `Z` | Enter sticky [view mode](#view-mode) | N/A |
| `Ctrl-w` | Enter [window mode](#window-mode) | N/A |
| `Space` | Enter [space mode](#space-mode) | N/A |
#### View mode
Accessed by typing `z` in [normal mode](#normal-mode).
View mode is intended for scrolling and manipulating the view without changing
the selection. The "sticky" variant of this mode is persistent; use the Escape
key to return to normal mode after usage (useful when you're simply looking
over text and not actively editing it).
the selection. The "sticky" variant of this mode (accessed by typing `Z` in
normal mode) is persistent; use the Escape key to return to normal mode after
usage (useful when you're simply looking over text and not actively editing
it).
| Key | Description | Command |
| ----- | ----------- | ------- |
| `z` , `c` | Vertically center the line | `align_view_center` |
| `t` | Align the line to the top of the screen | `align_view_top` |
| `b` | Align the line to the bottom of the screen | `align_view_bottom` |
| `m` | Align the line to the middle of the screen (horizontally) | `align_view_middle` |
| `j` | Scroll the view downwards | `scroll_down` |
| `k` | Scroll the view upwards | `scroll_up` |
| `f` | Move page down | `page_down` |
| `b` | Move page up | `page_up` |
| `d` | Move half page down | `half_page_down` |
| `u` | Move half page up | `half_page_up` |
| Key | Description | Command |
| ----- | ----------- | ------- |
| `z`, `c` | Vertically center the line | `align_view_center` |
| `t` | Align the line to the top of the screen | `align_view_top` |
| `b` | Align the line to the bottom of the screen | `align_view_bottom` |
| `m` | Align the line to the middle of the screen (horizontally) | `align_view_middle` |
| `j`, `down` | Scroll the view downwards | `scroll_down` |
| `k`, `up` | Scroll the view upwards | `scroll_up` |
| `Ctrl-f`, `PageDown` | Move page down | `page_down` |
| `Ctrl-b`, `PageUp` | Move page up | `page_up` |
| `Ctrl-d` | Move half page down | `half_page_down` |
| `Ctrl-u` | Move half page up | `half_page_up` |
#### Goto mode
Jumps to various locations.
Accessed by typing `g` in [normal mode](#normal-mode).
> NOTE: Some of these features are only available with the LSP present.
Jumps to various locations.
| Key | Description | Command |
| ----- | ----------- | ------- |
| `g` | Go to the start of the file | `goto_file_start` |
| `g` | Go to line number `<n>` else start of file | `goto_file_start` |
| `e` | Go to the end of the file | `goto_last_line` |
| `f` | Go to files in the selection | `goto_file` |
| `h` | Go to the start of the line | `goto_line_start` |
| `l` | Go to the end of the line | `goto_line_end` |
| `s` | Go to first non-whitespace character of the line | `goto_first_nonwhitespace` |
| `t` | Go to the top of the screen | `goto_window_top` |
| `m` | Go to the middle of the screen | `goto_window_middle` |
| `c` | Go to the middle of the screen | `goto_window_center` |
| `b` | Go to the bottom of the screen | `goto_window_bottom` |
| `d` | Go to definition | `goto_definition` |
| `y` | Go to type definition | `goto_type_definition` |
| `r` | Go to references | `goto_reference` |
| `i` | Go to implementation | `goto_implementation` |
| `d` | Go to definition (**LSP**) | `goto_definition` |
| `y` | Go to type definition (**LSP**) | `goto_type_definition` |
| `r` | Go to references (**LSP**) | `goto_reference` |
| `i` | Go to implementation (**LSP**) | `goto_implementation` |
| `a` | Go to the last accessed/alternate file | `goto_last_accessed_file` |
| `m` | Go to the last modified/alternate file | `goto_last_modified_file` |
| `n` | Go to next buffer | `goto_next_buffer` |
| `p` | Go to previous buffer | `goto_previous_buffer` |
| `.` | Go to last modification in current file | `goto_last_modification` |
#### Match mode
Enter this mode using `m` from normal mode. See the relavant section
in [Usage](./usage.md) for an explanation about [surround](./usage.md#surround)
and [textobject](./usage.md#textobject) usage.
Accessed by typing `m` in [normal mode](#normal-mode).
See the relevant section in [Usage](./usage.md) for an explanation about
[surround](./usage.md#surround) and [textobject](./usage.md#textobjects) usage.
| Key | Description | Command |
| ----- | ----------- | ------- |
| `m` | Goto matching bracket | `match_brackets` |
| `m` | Goto matching bracket (**TS**) | `match_brackets` |
| `s` `<char>` | Surround current selection with `<char>` | `surround_add` |
| `r` `<from><to>` | Replace surround character `<from>` with `<to>` | `surround_replace` |
| `d` `<char>` | Delete surround character `<char>` | `surround_delete` |
@@ -181,80 +236,203 @@ TODO: Mappings for selecting syntax nodes (a superset of `[`).
#### Window mode
This layer is similar to vim keybindings as kakoune does not support window.
Accessed by typing `Ctrl-w` in [normal mode](#normal-mode).
| Key | Description | Command |
| ----- | ------------- | ------- |
| `w`, `Ctrl-w` | Switch to next window | `rotate_view` |
| `v`, `Ctrl-v` | Vertical right split | `vsplit` |
| `s`, `Ctrl-s` | Horizontal bottom split | `hsplit` |
| `h`, `Ctrl-h` | Move to left split | `jump_view_left` |
| `j`, `Ctrl-j` | Move to split below | `jump_view_down` |
| `k`, `Ctrl-k` | Move to split above | `jump_view_up` |
| `l`, `Ctrl-l` | Move to right split | `jump_view_right` |
| `q`, `Ctrl-q` | Close current window | `wclose` |
This layer is similar to Vim keybindings as Kakoune does not support window.
| Key | Description | Command |
| ----- | ------------- | ------- |
| `w`, `Ctrl-w` | Switch to next window | `rotate_view` |
| `v`, `Ctrl-v` | Vertical right split | `vsplit` |
| `s`, `Ctrl-s` | Horizontal bottom split | `hsplit` |
| `f` | Go to files in the selection in horizontal splits | `goto_file` |
| `F` | Go to files in the selection in vertical splits | `goto_file` |
| `h`, `Ctrl-h`, `Left` | Move to left split | `jump_view_left` |
| `j`, `Ctrl-j`, `Down` | Move to split below | `jump_view_down` |
| `k`, `Ctrl-k`, `Up` | Move to split above | `jump_view_up` |
| `l`, `Ctrl-l`, `Right` | Move to right split | `jump_view_right` |
| `q`, `Ctrl-q` | Close current window | `wclose` |
| `o`, `Ctrl-o` | Only keep the current window, closing all the others | `wonly` |
| `H` | Swap window to the left | `swap_view_left` |
| `J` | Swap window downwards | `swap_view_down` |
| `K` | Swap window upwards | `swap_view_up` |
| `L` | Swap window to the right | `swap_view_right` |
#### Space mode
Accessed by typing `Space` in [normal mode](#normal-mode).
This layer is a kludge of mappings, mostly pickers.
| Key | Description | Command |
| ----- | ----------- | ------- |
| `k` | Show documentation for the item under the cursor | `hover` |
| `f` | Open file picker | `file_picker` |
| `b` | Open buffer picker | `buffer_picker` |
| `s` | Open symbol picker (current document) | `symbol_picker` |
| `a` | Apply code action | `code_action` |
| `'` | Open last fuzzy picker | `last_picker` |
| `w` | Enter [window mode](#window-mode) | N/A |
| `p` | Paste system clipboard after selections | `paste_clipboard_after` |
| `P` | Paste system clipboard before selections | `paste_clipboard_before` |
| `y` | Join and yank selections to clipboard | `yank_joined_to_clipboard` |
| `Y` | Yank main selection to clipboard | `yank_main_selection_to_clipboard` |
| `R` | Replace selections by clipboard contents | `replace_selections_with_clipboard` |
| `/` | Global search in workspace folder | `global_search` |
| Key | Description | Command |
| ----- | ----------- | ------- |
| `f` | Open file picker | `file_picker` |
| `F` | Open file picker at current working directory | `file_picker_in_current_directory` |
| `b` | Open buffer picker | `buffer_picker` |
| `j` | Open jumplist picker | `jumplist_picker` |
| `k` | Show documentation for item under cursor in a [popup](#popup) (**LSP**) | `hover` |
| `s` | Open document symbol picker (**LSP**) | `symbol_picker` |
| `S` | Open workspace symbol picker (**LSP**) | `workspace_symbol_picker` |
| `d` | Open document diagnostics picker (**LSP**) | `diagnostics_picker` |
| `D` | Open workspace diagnostics picker (**LSP**) | `workspace_diagnostics_picker` |
| `r` | Rename symbol (**LSP**) | `rename_symbol` |
| `a` | Apply code action (**LSP**) | `code_action` |
| `'` | Open last fuzzy picker | `last_picker` |
| `w` | Enter [window mode](#window-mode) | N/A |
| `p` | Paste system clipboard after selections | `paste_clipboard_after` |
| `P` | Paste system clipboard before selections | `paste_clipboard_before` |
| `y` | Join and yank selections to clipboard | `yank_joined_to_clipboard` |
| `Y` | Yank main selection to clipboard | `yank_main_selection_to_clipboard` |
| `R` | Replace selections by clipboard contents | `replace_selections_with_clipboard` |
| `/` | Global search in workspace folder | `global_search` |
| `?` | Open command palette | `command_palette` |
> TIP: Global search displays results in a fuzzy picker, use `Space + '` to bring it back up after opening a file.
##### Popup
Displays documentation for item under cursor.
| Key | Description |
| ---- | ----------- |
| `Ctrl-u` | Scroll up |
| `Ctrl-d` | Scroll down |
> NOTE: Global search display results in a fuzzy picker, use `space + '` to bring it back up after opening a file.
#### Unimpaired
Mappings in the style of [vim-unimpaired](https://github.com/tpope/vim-unimpaired).
| Key | Description | Command |
| ----- | ----------- | ------- |
| `[d` | Go to previous diagnostic | `goto_prev_diag` |
| `]d` | Go to next diagnostic | `goto_next_diag` |
| `[D` | Go to first diagnostic in document | `goto_first_diag` |
| `]D` | Go to last diagnostic in document | `goto_last_diag` |
| `[space` | Add newline above | `add_newline_above` |
| `]space` | Add newline below | `add_newline_below` |
| Key | Description | Command |
| ----- | ----------- | ------- |
| `[d` | Go to previous diagnostic (**LSP**) | `goto_prev_diag` |
| `]d` | Go to next diagnostic (**LSP**) | `goto_next_diag` |
| `[D` | Go to first diagnostic in document (**LSP**) | `goto_first_diag` |
| `]D` | Go to last diagnostic in document (**LSP**) | `goto_last_diag` |
| `]f` | Go to next function (**TS**) | `goto_next_function` |
| `[f` | Go to previous function (**TS**) | `goto_prev_function` |
| `]t` | Go to next type definition (**TS**) | `goto_next_class` |
| `[t` | Go to previous type definition (**TS**) | `goto_prev_class` |
| `]a` | Go to next argument/parameter (**TS**) | `goto_next_parameter` |
| `[a` | Go to previous argument/parameter (**TS**) | `goto_prev_parameter` |
| `]c` | Go to next comment (**TS**) | `goto_next_comment` |
| `[c` | Go to previous comment (**TS**) | `goto_prev_comment` |
| `]T` | Go to next test (**TS**) | `goto_next_test` |
| `]T` | Go to previous test (**TS**) | `goto_prev_test` |
| `]p` | Go to next paragraph | `goto_next_paragraph` |
| `[p` | Go to previous paragraph | `goto_prev_paragraph` |
| `]g` | Go to next change | `goto_next_change` |
| `[g` | Go to previous change | `goto_prev_change` |
| `]G` | Go to first change | `goto_first_change` |
| `[G` | Go to last change | `goto_last_change` |
| `[Space` | Add newline above | `add_newline_above` |
| `]Space` | Add newline below | `add_newline_below` |
## Insert Mode
## Insert mode
| Key | Description | Command |
| ----- | ----------- | ------- |
| `Escape` | Switch to normal mode | `normal_mode` |
| `Ctrl-x` | Autocomplete | `completion` |
| `Ctrl-w` | Delete previous word | `delete_word_backward` |
Insert mode bindings are somewhat minimal by default. Helix is designed to
be a modal editor, and this is reflected in the user experience and internal
mechanics. For example, changes to the text are only saved for undos when
escaping from insert mode to normal mode. For this reason, new users are
strongly encouraged to learn the modal editing paradigm to get the smoothest
experience.
| Key | Description | Command |
| ----- | ----------- | ------- |
| `Escape` | Switch to normal mode | `normal_mode` |
| `Ctrl-s` | Commit undo checkpoint | `commit_undo_checkpoint` |
| `Ctrl-x` | Autocomplete | `completion` |
| `Ctrl-r` | Insert a register content | `insert_register` |
| `Ctrl-w`, `Alt-Backspace` | Delete previous word | `delete_word_backward` |
| `Alt-d`, `Alt-Delete` | Delete next word | `delete_word_forward` |
| `Ctrl-u` | Delete to start of line | `kill_to_line_start` |
| `Ctrl-k` | Delete to end of line | `kill_to_line_end` |
| `Ctrl-h`, `Backspace` | Delete previous char | `delete_char_backward` |
| `Ctrl-d`, `Delete` | Delete next char | `delete_char_forward` |
| `Ctrl-j`, `Enter` | Insert new line | `insert_newline` |
These keys are not recommended, but are included for new users less familiar
with modal editors.
| Key | Description | Command |
| ----- | ----------- | ------- |
| `Up` | Move to previous line | `move_line_up` |
| `Down` | Move to next line | `move_line_down` |
| `Left` | Backward a char | `move_char_left` |
| `Right` | Forward a char | `move_char_right` |
| `PageUp` | Move one page up | `page_up` |
| `PageDown` | Move one page down | `page_down` |
| `Home` | Move to line start | `goto_line_start` |
| `End` | Move to line end | `goto_line_end_newline` |
If you want to disable them in insert mode as you become more comfortable with modal editing, you can use
the following in your `config.toml`:
```toml
[keys.insert]
up = "no_op"
down = "no_op"
left = "no_op"
right = "no_op"
pageup = "no_op"
pagedown = "no_op"
home = "no_op"
end = "no_op"
```
## Select / extend mode
I'm still pondering whether to keep this mode or not. It changes movement
commands (including goto) to extend the existing selection instead of replacing it.
This mode echoes Normal mode, but changes any movements to extend
selections rather than replace them. Goto motions are also changed to
extend, so that `vgl` for example extends the selection to the end of
the line.
> NOTE: It's a bit confusing at the moment because extend hasn't been
> implemented for all movement commands yet.
Search is also affected. By default, `n` and `N` will remove the current
selection and select the next instance of the search term. Toggling this
mode before pressing `n` or `N` makes it possible to keep the current
selection. Toggling it on and off during your iterative searching allows
you to selectively add search terms to your selections.
# Picker
## Picker
Keys to use within picker. Remapping currently not supported.
| Key | Description |
| ----- | ------------- |
| `Up`, `Ctrl-k`, `Ctrl-p` | Previous entry |
| `Down`, `Ctrl-j`, `Ctrl-n` | Next entry |
| `Ctrl-space` | Filter options |
| `Shift-Tab`, `Up`, `Ctrl-p` | Previous entry |
| `Tab`, `Down`, `Ctrl-n` | Next entry |
| `PageUp`, `Ctrl-u` | Page up |
| `PageDown`, `Ctrl-d` | Page down |
| `Home` | Go to first entry |
| `End` | Go to last entry |
| `Enter` | Open selected |
| `Ctrl-s` | Open horizontally |
| `Ctrl-v` | Open vertically |
| `Ctrl-t` | Toggle preview |
| `Escape`, `Ctrl-c` | Close picker |
## Prompt
Keys to use within prompt, Remapping currently not supported.
| Key | Description |
| ----- | ------------- |
| `Escape`, `Ctrl-c` | Close prompt |
| `Alt-b`, `Ctrl-Left` | Backward a word |
| `Ctrl-b`, `Left` | Backward a char |
| `Alt-f`, `Ctrl-Right` | Forward a word |
| `Ctrl-f`, `Right` | Forward a char |
| `Ctrl-e`, `End` | Move prompt end |
| `Ctrl-a`, `Home` | Move prompt start |
| `Ctrl-w`, `Alt-Backspace`, `Ctrl-Backspace` | Delete previous word |
| `Alt-d`, `Alt-Delete`, `Ctrl-Delete` | Delete next word |
| `Ctrl-u` | Delete to start of line |
| `Ctrl-k` | Delete to end of line |
| `Backspace`, `Ctrl-h` | Delete previous char |
| `Delete`, `Ctrl-d` | Delete next char |
| `Ctrl-s` | Insert a word under doc cursor, may be changed to Ctrl-r Ctrl-w later |
| `Ctrl-p`, `Up` | Select previous history |
| `Ctrl-n`, `Down` | Select next history |
| `Ctrl-r` | Insert the content of the register selected by following input char |
| `Tab` | Select next completion item |
| `BackTab` | Select previous completion item |
| `Enter` | Open selected |

16
book/src/lang-support.md Normal file
View File

@@ -0,0 +1,16 @@
# Language Support
The following languages and Language Servers are supported. In order to use
Language Server features, you must first [install][lsp-install-wiki] the
appropriate Language Server.
Check the language support in your installed helix version with `hx --health`.
Also see the [Language Configuration][lang-config] docs and the [Adding
Languages][adding-languages] guide for more language configuration information.
{{#include ./generated/lang-support.md}}
[lsp-install-wiki]: https://github.com/helix-editor/helix/wiki/How-to-install-the-default-language-servers
[lang-config]: ./languages.md
[adding-languages]: ./guides/adding_languages.md

158
book/src/languages.md Normal file
View File

@@ -0,0 +1,158 @@
# Languages
Language-specific settings and settings for language servers are configured
in `languages.toml` files.
## `languages.toml` files
There are three possible `languages.toml` files. The first is compiled into
Helix and lives in the [Helix repository](https://github.com/helix-editor/helix/blob/master/languages.toml).
This provides the default configurations for languages and language servers.
You may define a `languages.toml` in your [configuration directory](./configuration.md)
which overrides values from the built-in language configuration. For example
to disable auto-LSP-formatting in Rust:
```toml
# in <config_dir>/helix/languages.toml
[[language]]
name = "rust"
auto-format = false
```
Language configuration may also be overridden local to a project by creating
a `languages.toml` file under a `.helix` directory. Its settings will be merged
with the language configuration in the configuration directory and the built-in
configuration.
## Language configuration
Each language is configured by adding a `[[language]]` section to a
`languages.toml` file. For example:
```toml
[[language]]
name = "mylang"
scope = "source.mylang"
injection-regex = "^mylang$"
file-types = ["mylang", "myl"]
comment-token = "#"
indent = { tab-width = 2, unit = " " }
language-server = { command = "mylang-lsp", args = ["--stdio"], environment = { "ENV1" = "value1", "ENV2" = "value2" } }
formatter = { command = "mylang-formatter" , args = ["--stdin"] }
```
These configuration keys are available:
| Key | Description |
| ---- | ----------- |
| `name` | The name of the language |
| `scope` | A string like `source.js` that identifies the language. Currently, we strive to match the scope names used by popular TextMate grammars and by the Linguist library. Usually `source.<name>` or `text.<name>` in case of markup languages |
| `injection-regex` | regex pattern that will be tested against a language name in order to determine whether this language should be used for a potential [language injection][treesitter-language-injection] site. |
| `file-types` | The filetypes of the language, for example `["yml", "yaml"]`. See the file-type detection section below. |
| `shebangs` | The interpreters from the shebang line, for example `["sh", "bash"]` |
| `roots` | A set of marker files to look for when trying to find the workspace root. For example `Cargo.lock`, `yarn.lock` |
| `auto-format` | Whether to autoformat this language when saving |
| `diagnostic-severity` | Minimal severity of diagnostic for it to be displayed. (Allowed values: `Error`, `Warning`, `Info`, `Hint`) |
| `comment-token` | The token to use as a comment-token |
| `indent` | The indent to use. Has sub keys `tab-width` and `unit` |
| `language-server` | The Language Server to run. See the Language Server configuration section below. |
| `config` | Language Server configuration |
| `grammar` | The tree-sitter grammar to use (defaults to the value of `name`) |
| `formatter` | The formatter for the language, it will take precedence over the lsp when defined. The formatter must be able to take the original file as input from stdin and write the formatted file to stdout |
| `max-line-length` | Maximum line length. Used for the `:reflow` command |
### File-type detection and the `file-types` key
Helix determines which language configuration to use with the `file-types` key
from the above section. `file-types` is a list of strings or tables, for
example:
```toml
file-types = ["Makefile", "toml", { suffix = ".git/config" }]
```
When determining a language configuration to use, Helix searches the file-types
with the following priorities:
1. Exact match: if the filename of a file is an exact match of a string in a
`file-types` list, that language wins. In the example above, `"Makefile"`
will match against `Makefile` files.
2. Extension: if there are no exact matches, any `file-types` string that
matches the file extension of a given file wins. In the example above, the
`"toml"` matches files like `Cargo.toml` or `languages.toml`.
3. Suffix: if there are still no matches, any values in `suffix` tables
are checked against the full path of the given file. In the example above,
the `{ suffix = ".git/config" }` would match against any `config` files
in `.git` directories. Note: `/` is used as the directory separator but is
replaced at runtime with the appropriate path separator for the operating
system, so this rule would match against `.git\config` files on Windows.
### Language Server configuration
The `language-server` field takes the following keys:
| Key | Description |
| --- | ----------- |
| `command` | The name of the language server binary to execute. Binaries must be in `$PATH` |
| `args` | A list of arguments to pass to the language server binary |
| `timeout` | The maximum time a request to the language server may take, in seconds. Defaults to `20` |
| `language-id` | The language name to pass to the language server. Some language servers support multiple languages and use this field to determine which one is being served in a buffer |
| `environment` | Any environment variables that will be used when starting the language server `{ "KEY1" = "Value1", "KEY2" = "Value2" }` |
The top-level `config` field is used to configure the LSP initialization options. A `format`
sub-table within `config` can be used to pass extra formatting options to
[Document Formatting Requests](https://github.com/microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-16.md#document-formatting-request--leftwards_arrow_with_hook).
For example with typescript:
```toml
[[language]]
name = "typescript"
auto-format = true
# pass format options according to https://github.com/typescript-language-server/typescript-language-server#workspacedidchangeconfiguration omitting the "[language].format." prefix.
config = { format = { "semicolons" = "insert", "insertSpaceBeforeFunctionParenthesis" = true } }
```
## Tree-sitter grammar configuration
The source for a language's tree-sitter grammar is specified in a `[[grammar]]`
section in `languages.toml`. For example:
```toml
[[grammar]]
name = "mylang"
source = { git = "https://github.com/example/mylang", rev = "a250c4582510ff34767ec3b7dcdd3c24e8c8aa68" }
```
Grammar configuration takes these keys:
| Key | Description |
| --- | ----------- |
| `name` | The name of the tree-sitter grammar |
| `source` | The method of fetching the grammar - a table with a schema defined below |
Where `source` is a table with either these keys when using a grammar from a
git repository:
| Key | Description |
| --- | ----------- |
| `git` | A git remote URL from which the grammar should be cloned |
| `rev` | The revision (commit hash or tag) which should be fetched |
| `subpath` | A path within the grammar directory which should be built. Some grammar repositories host multiple grammars (for example `tree-sitter-typescript` and `tree-sitter-ocaml`) in subdirectories. This key is used to point `hx --grammar build` to the correct path for compilation. When omitted, the root of repository is used |
### Choosing grammars
You may use a top-level `use-grammars` key to control which grammars are
fetched and built when using `hx --grammar fetch` and `hx --grammar build`.
```toml
# Note: this key must come **before** the [[language]] and [[grammar]] sections
use-grammars = { only = [ "rust", "c", "cpp" ] }
# or
use-grammars = { except = [ "yaml", "json" ] }
```
When omitted, all grammars are fetched and built.
[treesitter-language-injection]: https://tree-sitter.github.io/tree-sitter/syntax-highlighting#language-injection

View File

@@ -11,17 +11,21 @@ this:
```toml
# At most one section each of 'keys.normal', 'keys.insert' and 'keys.select'
[keys.normal]
C-s = ":w" # Maps the Ctrl-s to the typable command :w which is an alias for :write (save file)
C-o = ":open ~/.config/helix/config.toml" # Maps the Ctrl-o to opening of the helix config file
a = "move_char_left" # Maps the 'a' key to the move_char_left command
w = "move_line_up" # Maps the 'w' key move_line_up
"C-S-esc" = "extend_line" # Maps Control-Shift-Escape to extend_line
"C-S-esc" = "extend_line" # Maps Ctrl-Shift-Escape to extend_line
g = { a = "code_action" } # Maps `ga` to show possible code actions
"ret" = ["open_below", "normal_mode"] # Maps the enter key to open_below then re-enter normal mode
[keys.insert]
"A-x" = "normal_mode" # Maps Alt-X to enter normal mode
j = { k = "normal_mode" } # Maps `jk` to exit insert mode
```
> NOTE: Typable commands can also be remapped, remember to keep the `:` prefix to indicate it's a typable command.
Control, Shift and Alt modifiers are encoded respectively with the prefixes
Ctrl, Shift and Alt modifiers are encoded respectively with the prefixes
`C-`, `S-` and `A-`. Special keys are encoded as follows:
| Key name | Representation |
@@ -29,21 +33,16 @@ Control, Shift and Alt modifiers are encoded respectively with the prefixes
| Backspace | `"backspace"` |
| Space | `"space"` |
| Return/Enter | `"ret"` |
| < | `"lt"` |
| \> | `"gt"` |
| \+ | `"plus"` |
| \- | `"minus"` |
| ; | `"semicolon"` |
| % | `"percent"` |
| Left | `"left"` |
| Right | `"right"` |
| Up | `"up"` |
| Down | `"down"` |
| Home | `"home"` |
| End | `"end"` |
| Page | `"pageup"` |
| Page | `"pagedown"` |
| Page Up | `"pageup"` |
| Page Down | `"pagedown"` |
| Tab | `"tab"` |
| Back | `"backtab"` |
| Delete | `"del"` |
| Insert | `"ins"` |
| Null | `"null"` |
@@ -51,4 +50,5 @@ Control, Shift and Alt modifiers are encoded respectively with the prefixes
Keys can be disabled by binding them to the `no_op` command.
Commands can be found in the source code at [`helix-term/src/commands.rs`](https://github.com/helix-editor/helix/blob/master/helix-term/src/commands.rs)
Commands can be found at [Keymap](https://docs.helix-editor.com/keymap.html) Commands.
> Commands can also be found in the source code at [`helix-term/src/commands.rs`](https://github.com/helix-editor/helix/blob/master/helix-term/src/commands.rs) at the invocation of `static_commands!` macro and the `TypableCommandList`.

View File

@@ -1,22 +1,22 @@
# Themes
First you'll need to place selected themes in your `themes` directory (i.e `~/.config/helix/themes`), the directory might have to be created beforehand.
To use a custom theme add `theme = <name>` to your [`config.toml`](./configuration.md) or override it during runtime using `:theme <name>`.
The default theme.toml can be found [here](https://github.com/helix-editor/helix/blob/master/theme.toml), and user submitted themes [here](https://github.com/helix-editor/helix/blob/master/runtime/themes).
To use a theme add `theme = "<name>"` to your [`config.toml`](./configuration.md) at the very top of the file before the first section or select it during runtime using `:theme <name>`.
## Creating a theme
First create a file with the name of your theme as file name (i.e `mytheme.toml`) and place it in your `themes` directory (i.e `~/.config/helix/themes`).
Create a file with the name of your theme as file name (i.e `mytheme.toml`) and place it in your `themes` directory (i.e `~/.config/helix/themes`). The directory might have to be created beforehand.
The names "default" and "base16_default" are reserved for the builtin themes and cannot be overridden by user defined themes.
The default theme.toml can be found [here](https://github.com/helix-editor/helix/blob/master/theme.toml), and user submitted themes [here](https://github.com/helix-editor/helix/blob/master/runtime/themes).
Each line in the theme file is specified as below:
```toml
key = { fg = "#ffffff", bg = "#000000", modifiers = ["bold", "italic"] }
key = { fg = "#ffffff", bg = "#000000", underline = { color = "#ff0000", style = "curl"}, modifiers = ["bold", "italic"] }
```
where `key` represents what you want to style, `fg` specifies the foreground color, `bg` the background color, and `modifiers` is a list of style modifiers. `bg` and `modifiers` can be omitted to defer to the defaults.
where `key` represents what you want to style, `fg` specifies the foreground color, `bg` the background color, `underline` the underline `style`/`color`, and `modifiers` is a list of style modifiers. `bg`, `underline` and `modifiers` can be omitted to defer to the defaults.
To specify only the foreground color:
@@ -37,8 +37,8 @@ configuration values in your theme. To do this, add a table called
`palette` to your theme file:
```toml
ui.background = "white"
ui.text = "black"
"ui.background" = "white"
"ui.text" = "black"
[palette]
white = "#ffffff"
@@ -77,17 +77,50 @@ The following values may be used as modifiers.
Less common modifiers might not be supported by your terminal emulator.
| Modifier |
| --- |
| `bold` |
| `dim` |
| `italic` |
| `underlined` |
| `slow_blink` |
| `rapid_blink` |
| `reversed` |
| `hidden` |
| `crossed_out` |
> Note: The `underlined` modifier is deprecated and only available for backwards compatibility.
> Its behavior is equivalent to setting `underline.style="line"`.
### Underline Style
One of the following values may be used as a value for `underline.style`.
Some styles might not be supported by your terminal emulator.
| Modifier |
| --- |
| `bold` |
| `dim` |
| `italic` |
| `underlined` |
| `slow_blink` |
| `rapid_blink` |
| `reversed` |
| `hidden` |
| `crossed_out` |
| `line` |
| `curl` |
| `dashed` |
| `dotted` |
| `double_line` |
### Inheritance
Extend upon other themes by setting the `inherits` property to an existing theme.
```toml
inherits = "boo_berry"
# Override the theming for "keyword"s:
"keyword" = { fg = "gold" }
# Override colors in the palette:
[palette]
berry = "#2A2A4D"
```
### Scopes
@@ -103,17 +136,21 @@ We use a similar set of scopes as
[SublimeText](https://www.sublimetext.com/docs/scope_naming.html). See also
[TextMate](https://macromates.com/manual/en/language_grammars) scopes.
- `escape` (TODO: rename to (constant).character.escape)
- `attribute` - Class attributes, html tag attributes
- `type` - Types
- `builtin` - Primitive types provided by the language (`int`, `usize`)
- `constructor`
- `constant` (TODO: constant.other.placeholder for %v)
- `builtin` Special constants provided by the language (`true`, `false`, `nil` etc)
- `boolean`
- `character`
- `escape`
- `numeric` (numbers)
- `integer`
- `float`
- `number` (TODO: rename to constant.number/.numeric.{integer, float, complex})
- `string` (TODO: string.quoted.{single, double}, string.raw/.unquoted)?
- `regexp` - Regular expressions
- `special`
@@ -129,67 +166,135 @@ We use a similar set of scopes as
- `variable` - Variables
- `builtin` - Reserved language variables (`self`, `this`, `super`, etc)
- `parameter` - Function parameters
- `property`
- `function` (TODO: ?)
- `other`
- `member` - Fields of composite data types (e.g. structs, unions)
- `label`
- `punctuation`
- `delimiter` - Commas, colons
- `bracket` - Parentheses, angle brackets, etc.
- `special` - String interpolation brackets.
- `keyword`
- `control`
- `conditional` - `if`, `else`
- `repeat` - `for`, `while`, `loop`
- `import` - `import`, `export`
- (TODO: return?)
- `return`
- `exception`
- `operator` - `or`, `in`
- `directive` - Preprocessor directives (`#if` in C)
- `function` - `fn`, `func`
- `storage` - Keywords describing how things are stored
- `type` - The type of something, `class`, `function`, `var`, `let`, etc.
- `modifier` - Storage modifiers like `static`, `mut`, `const`, `ref`, etc.
- `operator` - `||`, `+=`, `>`, `or`
- `operator` - `||`, `+=`, `>`
- `function`
- `builtin`
- `method`
- `macro`
- `special` (preprocesor in C)
- `special` (preprocessor in C)
- `tag` - Tags (e.g. `<body>` in HTML)
- `namespace`
- `markup`
- `heading`
- `marker`
- `1`, `2`, `3`, `4`, `5`, `6` - heading text for h1 through h6
- `list`
- `unnumbered`
- `numbered`
- `bold`
- `italic`
- `link`
- `url` - urls pointed to by links
- `label` - non-url link references
- `text` - url and image descriptions in links
- `quote`
- `raw`
- `inline`
- `block`
- `diff` - version control changes
- `plus` - additions
- `minus` - deletions
- `delta` - modifications
- `moved` - renamed or moved files/changes
#### Interface
These scopes are used for theming the editor interface.
- `markup`
- `normal`
- `completion` - for completion doc popup ui
- `hover` - for hover popup ui
- `heading`
- `completion` - for completion doc popup ui
- `hover` - for hover popup ui
- `raw`
- `inline`
- `completion` - for completion doc popup ui
- `hover` - for hover popup ui
| Key | Notes |
| --- | --- |
| `ui.background` | |
| `ui.cursor` | |
| `ui.cursor.insert` | |
| `ui.cursor.select` | |
| `ui.cursor.match` | Matching bracket etc. |
| `ui.cursor.primary` | Cursor with primary selection |
| `ui.linenr` | |
| `ui.linenr.selected` | |
| `ui.statusline` | Statusline |
| `ui.statusline.inactive` | Statusline (unfocused document) |
| `ui.popup` | |
| `ui.window` | |
| `ui.help` | |
| `ui.text` | |
| `ui.text.focus` | |
| `ui.info` | |
| `ui.info.text` | |
| `ui.menu` | |
| `ui.menu.selected` | |
| `ui.selection` | For selections in the editing area |
| `ui.selection.primary` | |
| `warning` | Diagnostics warning (gutter) |
| `error` | Diagnostics error (gutter) |
| `info` | Diagnostics info (gutter) |
| `hint` | Diagnostics hint (gutter) |
| `diagnostic` | For text in editing area |
| Key | Notes |
| --- | --- |
| `ui.background` | |
| `ui.background.separator` | Picker separator below input line |
| `ui.cursor` | |
| `ui.cursor.insert` | |
| `ui.cursor.select` | |
| `ui.cursor.match` | Matching bracket etc. |
| `ui.cursor.primary` | Cursor with primary selection |
| `ui.gutter` | Gutter |
| `ui.gutter.selected` | Gutter for the line the cursor is on |
| `ui.linenr` | Line numbers |
| `ui.linenr.selected` | Line number for the line the cursor is on |
| `ui.statusline` | Statusline |
| `ui.statusline.inactive` | Statusline (unfocused document) |
| `ui.statusline.normal` | Statusline mode during normal mode ([only if `editor.color-modes` is enabled][editor-section]) |
| `ui.statusline.insert` | Statusline mode during insert mode ([only if `editor.color-modes` is enabled][editor-section]) |
| `ui.statusline.select` | Statusline mode during select mode ([only if `editor.color-modes` is enabled][editor-section]) |
| `ui.statusline.separator` | Separator character in statusline |
| `ui.popup` | Documentation popups (e.g Space + k) |
| `ui.popup.info` | Prompt for multiple key options |
| `ui.window` | Border lines separating splits |
| `ui.help` | Description box for commands |
| `ui.text` | Command prompts, popup text, etc. |
| `ui.text.focus` | |
| `ui.text.info` | The key: command text in `ui.popup.info` boxes |
| `ui.virtual.ruler` | Ruler columns (see the [`editor.rulers` config][editor-section]) |
| `ui.virtual.whitespace` | Visible whitespace characters |
| `ui.virtual.indent-guide` | Vertical indent width guides |
| `ui.menu` | Code and command completion menus |
| `ui.menu.selected` | Selected autocomplete item |
| `ui.menu.scroll` | `fg` sets thumb color, `bg` sets track color of scrollbar |
| `ui.selection` | For selections in the editing area |
| `ui.selection.primary` | |
| `ui.cursorline.primary` | The line of the primary cursor ([if cursorline is enabled][editor-section]) |
| `ui.cursorline.secondary` | The lines of any other cursors ([if cursorline is enabled][editor-section]) |
| `ui.cursorcolumn.primary` | The column of the primary cursor ([if cursorcolumn is enabled][editor-section]) |
| `ui.cursorcolumn.secondary` | The columns of any other cursors ([if cursorcolumn is enabled][editor-section]) |
| `warning` | Diagnostics warning (gutter) |
| `error` | Diagnostics error (gutter) |
| `info` | Diagnostics info (gutter) |
| `hint` | Diagnostics hint (gutter) |
| `diagnostic` | Diagnostics fallback style (editing area) |
| `diagnostic.hint` | Diagnostics hint (editing area) |
| `diagnostic.info` | Diagnostics info (editing area) |
| `diagnostic.warning` | Diagnostics warning (editing area) |
| `diagnostic.error` | Diagnostics error (editing area) |
You can check compliance to spec with
```shell
cargo xtask themelint onedark # replace onedark with <name>
```
[editor-section]: ./configuration.md#editor-section

17
book/src/title-page.md Normal file
View File

@@ -0,0 +1,17 @@
# Helix
Docs for bleeding edge master can be found at
[https://docs.helix-editor.com/master](https://docs.helix-editor.com/master).
See the [usage] section for a quick overview of the editor, [keymap]
section for all available keybindings and the [configuration] section
for defining custom keybindings, setting themes, etc.
For everything else (e.g., how to install supported language servers), see the [Helix Wiki].
Refer the [FAQ] for common questions.
[FAQ]: https://github.com/helix-editor/helix/wiki/FAQ
[usage]: ./usage.md
[keymap]: ./keymap.md
[configuration]: ./configuration.md
[Helix Wiki]: https://github.com/helix-editor/helix/wiki

View File

@@ -2,7 +2,7 @@
(Currently not fully documented, see the [keymappings](./keymap.md) list for more.)
See [tutor.txt](https://github.com/helix-editor/helix/blob/master/runtime/tutor.txt) (accessible via `hx --tutor` or `:tutor`) for a vimtutor-like introduction.
See [tutor](https://github.com/helix-editor/helix/blob/master/runtime/tutor) (accessible via `hx --tutor` or `:tutor`) for a vimtutor-like introduction.
## Registers
@@ -23,8 +23,10 @@ If there is a selected register before invoking a change or delete command, the
| `/` | Last search |
| `:` | Last executed command |
| `"` | Last yanked text |
| `_` | Black hole |
> There is no special register for copying to system clipboard, instead special commands and keybindings are provided. See the [keymap](keymap.md#space-mode) for the specifics.
> The black hole register works as a no-op register, meaning no data will be written to / read from it.
## Surround
@@ -40,7 +42,7 @@ helix. The keymappings have been inspired from [vim-sandwich](https://github.com
`ms` acts on a selection, so select the text first and use `ms<char>`. `mr` and `md` work
on the closest pairs found and selections are not required; use counts to act in outer pairs.
It can also act on multiple seletions (yay!). For example, to change every occurance of `(use)` to `[use]`:
It can also act on multiple selections (yay!). For example, to change every occurrence of `(use)` to `[use]`:
- `%` to select the whole file
- `s` to split the selections on a search term
@@ -49,25 +51,120 @@ It can also act on multiple seletions (yay!). For example, to change every occur
Multiple characters are currently not supported, but planned.
## Textobjects
## Syntax-tree Motions
Currently supported: `word`, `surround`, `function`, `class`, `parameter`.
`Alt-p`, `Alt-o`, `Alt-i`, and `Alt-n` (or `Alt` and arrow keys) move the primary
selection according to the selection's place in the syntax tree. Let's walk
through an example to get familiar with them. Many languages have a syntax like
so for function calls:
```
func(arg1, arg2, arg3)
```
A function call might be parsed by tree-sitter into a tree like the following.
```tsq
(call
function: (identifier) ; func
arguments:
(arguments ; (arg1, arg2, arg3)
(identifier) ; arg1
(identifier) ; arg2
(identifier))) ; arg3
```
Use `:tree-sitter-subtree` to view the syntax tree of the primary selection. In
a more intuitive tree format:
```
┌────┐
│call│
┌─────┴────┴─────┐
│ │
┌─────▼────┐ ┌────▼────┐
│identifier│ │arguments│
│ "func" │ ┌────┴───┬─────┴───┐
└──────────┘ │ │ │
│ │ │
┌─────────▼┐ ┌────▼─────┐ ┌▼─────────┐
│identifier│ │identifier│ │identifier│
│ "arg1" │ │ "arg2" │ │ "arg3" │
└──────────┘ └──────────┘ └──────────┘
```
Say we have a selection that wraps `arg1`. The selection is on the `arg1` leaf
in the tree above.
```
func([arg1], arg2, arg3)
```
Using `Alt-n` would select the next sibling in the syntax tree: `arg2`.
```
func(arg1, [arg2], arg3)
```
While `Alt-o` would expand the selection to the parent node. In the tree above we
can see that we would select the `arguments` node.
```
func[(arg1, arg2, arg3)]
```
There is also some nuanced behavior that prevents you from getting stuck on a
node with no sibling. If we have a selection on `arg1`, `Alt-p` would bring us
to the previous child node. Since `arg1` doesn't have a sibling to its left,
though, we climb the syntax tree and then take the previous selection. So
`Alt-p` will move the selection over to the "func" `identifier`.
```
[func](arg1, arg2, arg3)
```
## Textobjects
![textobject-demo](https://user-images.githubusercontent.com/23398472/124231131-81a4bb00-db2d-11eb-9d10-8e577ca7b177.gif)
![textobject-treesitter-demo](https://user-images.githubusercontent.com/23398472/132537398-2a2e0a54-582b-44ab-a77f-eb818942203d.gif)
- `ma` - Select around the object (`va` in vim, `<alt-a>` in kakoune)
- `mi` - Select inside the object (`vi` in vim, `<alt-i>` in kakoune)
- `ma` - Select around the object (`va` in Vim, `<alt-a>` in Kakoune)
- `mi` - Select inside the object (`vi` in Vim, `<alt-i>` in Kakoune)
| Key after `mi` or `ma` | Textobject selected |
| --- | --- |
| `w` | Word |
| `W` | WORD |
| `p` | Paragraph |
| `(`, `[`, `'`, etc | Specified surround pairs |
| `m` | Closest surround pair |
| `f` | Function |
| `c` | Class |
| `p` | Parameter |
| `a` | Argument/parameter |
| `o` | Comment |
| `t` | Test |
| `g` | Change |
Note: `f`, `c`, etc need a tree-sitter grammar active for the current
> NOTE: `f`, `c`, etc need a tree-sitter grammar active for the current
document and a special tree-sitter query file to work properly. [Only
some grammars](https://github.com/search?q=repo%3Ahelix-editor%2Fhelix+filename%3Atextobjects.scm&type=Code&ref=advsearch&l=&l=)
currently have the query file implemented. Contributions are welcome !
some grammars][lang-support] currently have the query file implemented.
Contributions are welcome!
## Tree-sitter Textobject Based Navigation
Navigating between functions, classes, parameters, etc is made
possible by leveraging tree-sitter and textobjects queries. For
example to move to the next function use `]f`, to move to previous
class use `[c`, and so on.
![tree-sitter-nav-demo][tree-sitter-nav-demo]
See the [unimpaired][unimpaired-keybinds] section of the keybind
documentation for the full reference.
> NOTE: This feature is dependent on tree-sitter based textobjects
and therefore requires the corresponding query file to work properly.
[lang-support]: ./lang-support.md
[unimpaired-keybinds]: ./keymap.md#unimpaired
[tree-sitter-nav-demo]: https://user-images.githubusercontent.com/23398472/152332550-7dfff043-36a2-4aec-b8f2-77c13eb56d6f.gif

View File

@@ -601,10 +601,10 @@ function playground_text(playground) {
});
})();
(function controllMenu() {
(function controlMenu() {
var menu = document.getElementById('menu-bar');
(function controllPosition() {
(function controlPosition() {
var scrollTop = document.scrollingElement.scrollTop;
var prevScrollTop = scrollTop;
var minMenuY = -menu.clientHeight - 50;
@@ -647,7 +647,7 @@ function playground_text(playground) {
prevScrollTop = scrollTop;
}, { passive: true });
})();
(function controllBorder() {
(function controlBorder() {
menu.classList.remove('bordered');
document.addEventListener('scroll', function () {
if (menu.offsetTop === 0) {

View File

@@ -390,7 +390,7 @@ ul#searchresults span.teaser em {
.chapter li {
display: flex;
color: var(--sidebar-non-existant);
color: var(--sidebar-non-existent);
}
.chapter li a {
display: block;

View File

@@ -16,7 +16,7 @@
--sidebar-bg: #14191f;
--sidebar-fg: #c8c9db;
--sidebar-non-existant: #5c6773;
--sidebar-non-existent: #5c6773;
--sidebar-active: #ffb454;
--sidebar-spacer: #2d334f;
@@ -56,7 +56,7 @@
--sidebar-bg: #292c2f;
--sidebar-fg: #a1adb8;
--sidebar-non-existant: #505254;
--sidebar-non-existent: #505254;
--sidebar-active: #3473ad;
--sidebar-spacer: #393939;
@@ -96,7 +96,7 @@
--sidebar-bg: #fafafa;
--sidebar-fg: hsl(0, 0%, 0%);
--sidebar-non-existant: #aaaaaa;
--sidebar-non-existent: #aaaaaa;
--sidebar-active: #1f1fff;
--sidebar-spacer: #f4f4f4;
@@ -136,7 +136,7 @@
--sidebar-bg: #282d3f;
--sidebar-fg: #c8c9db;
--sidebar-non-existant: #505274;
--sidebar-non-existent: #505274;
--sidebar-active: #2b79a2;
--sidebar-spacer: #2d334f;
@@ -176,7 +176,7 @@
--sidebar-bg: #3b2e2a;
--sidebar-fg: #c8c9db;
--sidebar-non-existant: #505254;
--sidebar-non-existent: #505254;
--sidebar-active: #e69f67;
--sidebar-spacer: #45373a;
@@ -217,7 +217,7 @@
--sidebar-bg: #292c2f;
--sidebar-fg: #a1adb8;
--sidebar-non-existant: #505254;
--sidebar-non-existent: #505254;
--sidebar-active: #3473ad;
--sidebar-spacer: #393939;
@@ -259,7 +259,7 @@
--sidebar-bg: #281733;
--sidebar-fg: #c8c9db;
--sidebar-non-existant: #505274;
--sidebar-non-existent: #505274;
--sidebar-active: #a4a0e8;
--sidebar-spacer: #2d334f;
@@ -304,7 +304,7 @@
--sidebar-bg: #281733;
--sidebar-fg: #c8c9db;
--sidebar-non-existant: #505274;
--sidebar-non-existent: #505274;
--sidebar-active: #a4a0e8;
--sidebar-spacer: #2d334f;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 42 KiB

View File

@@ -1,22 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 199.7 184.2">
<style>
@media (prefers-color-scheme: dark) {
svg { fill: white; }
}
</style>
<path d="M189.5,36.8c0.2,2.8,0,5.1-0.6,6.8L153,162c-0.6,2.1-2,3.7-4.2,5c-2.2,1.2-4.4,1.9-6.7,1.9H31.4c-9.6,0-15.3-2.8-17.3-8.4
c-0.8-2.2-0.8-3.9,0.1-5.2c0.9-1.2,2.4-1.8,4.6-1.8H123c7.4,0,12.6-1.4,15.4-4.1s5.7-8.9,8.6-18.4l32.9-108.6
c1.8-5.9,1-11.1-2.2-15.6S169.9,0,164,0H72.7c-1,0-3.1,0.4-6.1,1.1l0.1-0.4C64.5,0.2,62.6,0,61,0.1s-3,0.5-4.3,1.4
c-1.3,0.9-2.4,1.8-3.2,2.8S52,6.5,51.2,8.1c-0.8,1.6-1.4,3-1.9,4.3s-1.1,2.7-1.8,4.2c-0.7,1.5-1.3,2.7-2,3.7c-0.5,0.6-1.2,1.5-2,2.5
s-1.6,2-2.2,2.8s-0.9,1.5-1.1,2.2c-0.2,0.7-0.1,1.8,0.2,3.2c0.3,1.4,0.4,2.4,0.4,3.1c-0.3,3-1.4,6.9-3.3,11.6
c-1.9,4.7-3.6,8.1-5.1,10.1c-0.3,0.4-1.2,1.3-2.6,2.7c-1.4,1.4-2.3,2.6-2.6,3.7c-0.3,0.4-0.3,1.5-0.1,3.4c0.3,1.8,0.4,3.1,0.3,3.8
c-0.3,2.7-1.3,6.3-3,10.8c-1.7,4.5-3.4,8.2-5,11c-0.2,0.5-0.9,1.4-2,2.8c-1.1,1.4-1.8,2.5-2,3.4c-0.2,0.6-0.1,1.8,0.1,3.4
c0.2,1.6,0.2,2.8-0.1,3.6c-0.6,3-1.8,6.7-3.6,11c-1.8,4.3-3.6,7.9-5.4,11c-0.5,0.8-1.1,1.7-2,2.8c-0.8,1.1-1.5,2-2,2.8
s-0.8,1.6-1,2.5c-0.1,0.5,0,1.3,0.4,2.3c0.3,1.1,0.4,1.9,0.4,2.6c-0.1,1.1-0.2,2.6-0.5,4.4c-0.2,1.8-0.4,2.9-0.4,3.2
c-1.8,4.8-1.7,9.9,0.2,15.2c2.2,6.2,6.2,11.5,11.9,15.8c5.7,4.3,11.7,6.4,17.8,6.4h110.7c5.2,0,10.1-1.7,14.7-5.2s7.7-7.8,9.2-12.9
l33-108.6c1.8-5.8,1-10.9-2.2-15.5C194.9,39.7,192.6,38,189.5,36.8z M59.6,122.8L73.8,80c0,0,7,0,10.8,0s28.8-1.7,25.4,17.5
c-3.4,19.2-18.8,25.2-36.8,25.4S59.6,122.8,59.6,122.8z M78.6,116.8c4.7-0.1,18.9-2.9,22.1-17.1S89.2,86.3,89.2,86.3l-8.9,0
l-10.2,30.5C70.2,116.9,74,116.9,78.6,116.8z M75.3,68.7L89,26.2h9.8l0.8,34l23.6-34h9.9l-13.6,42.5h-7.1l12.5-35.4l-24.5,35.4h-6.8
l-0.8-35L82,68.7H75.3z"/>
</svg>
<!-- Original image Copyright Dave Gandy — CC BY 4.0 License -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;" viewBox="663.38 37.57 575.35 903.75"> <g transform="matrix(1,0,0,1,-31352.7,-1817.25)"> <g transform="matrix(1,0,0,1,31062.7,-20.8972)"> <g transform="matrix(1,0,0,1,-130.173,0.00185558)"> <path d="M1083.58,1875.72L1635.06,2194.12C1649.8,2202.63 1658.88,2218.37 1658.88,2235.39C1658.88,2264.98 1658.88,2311.74 1658.88,2341.33C1658.88,2349.84 1656.61,2358.03 1652.5,2365.16C1652.5,2365.16 1214.7,2112.4 1107.2,2050.33C1092.58,2041.89 1083.58,2026.29 1083.58,2009.41C1083.58,1963.5 1083.58,1875.72 1083.58,1875.72Z" style="fill:#706bc8;"></path> </g> <g transform="matrix(1,0,0,1,-130.173,0.00185558)"> <path d="M1635.26,2604.84C1649.88,2613.28 1658.88,2628.87 1658.88,2645.75C1658.88,2691.67 1658.88,2779.44 1658.88,2779.44L1107.41,2461.05C1092.66,2452.53 1083.58,2436.8 1083.58,2419.78C1083.58,2390.19 1083.58,2343.42 1083.58,2313.84C1083.58,2305.32 1085.85,2297.13 1089.96,2290.01C1089.96,2290.01 1527.76,2542.77 1635.26,2604.84Z" style="fill:#55c5e4;"></path> </g> <g transform="matrix(1,0,0,1,216.062,984.098)"> <path d="M790.407,1432.56C785.214,1435.55 780.717,1439.9 777.509,1445.46C767.862,1462.16 773.473,1483.76 790.004,1493.59L789.998,1493.59L761.173,1476.95C746.427,1468.44 737.344,1452.71 737.344,1435.68C737.344,1406.09 737.344,1359.33 737.344,1329.74C737.344,1312.71 746.427,1296.98 761.173,1288.47L1259.59,1000.74L1259.83,1000.6C1264.92,997.617 1269.33,993.314 1272.48,987.844C1282.13,971.136 1276.52,949.544 1259.99,939.707L1260,939.707L1288.82,956.349C1303.57,964.862 1312.65,980.595 1312.65,997.622C1312.65,1027.21 1312.65,1073.97 1312.65,1103.56C1312.65,1120.59 1303.57,1136.32 1288.82,1144.83L1259.19,1161.94L1259.59,1161.68L790.407,1432.56Z" style="fill:#84ddea;"></path> </g> <g transform="matrix(1,0,0,1,216.062,984.098)"> <path d="M790.407,1686.24C785.214,1689.23 780.717,1693.58 777.509,1699.13C767.862,1715.84 773.473,1737.43 790.004,1747.27L789.998,1747.27L761.173,1730.63C746.427,1722.12 737.344,1706.38 737.344,1689.36C737.344,1659.77 737.344,1613.01 737.344,1583.42C737.344,1566.39 746.427,1550.66 761.173,1542.15L1259.59,1254.42L1259.83,1254.28C1264.92,1251.29 1269.33,1246.99 1272.48,1241.52C1282.13,1224.81 1276.52,1203.22 1259.99,1193.38L1260,1193.38L1288.82,1210.03C1303.57,1218.54 1312.65,1234.27 1312.65,1251.3C1312.65,1280.89 1312.65,1327.65 1312.65,1357.24C1312.65,1374.26 1303.57,1390 1288.82,1398.51L1259.19,1415.61L1259.59,1415.36L790.407,1686.24Z" style="fill:#997bc8;"></path></g></g></g> </svg>

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

89
contrib/Helix.desktop Normal file
View File

@@ -0,0 +1,89 @@
[Desktop Entry]
Name=Helix
GenericName=Text Editor
GenericName[de]=Texteditor
GenericName[fr]=Éditeur de texte
GenericName[ru]=Текстовый редактор
GenericName[sr]=Едитор текст
GenericName[tr]=Metin Düzenleyici
Comment=Edit text files
Comment[af]=Redigeer tekslêers
Comment[am]=የጽሑፍ ፋይሎች ያስተካክሉ
Comment[ar]=حرّر ملفات نصية
Comment[az]=Mətn fayllarını redaktə edin
Comment[be]=Рэдагаваньне тэкставых файлаў
Comment[bg]=Редактиране на текстови файлове
Comment[bn]=টেক্স্ট ফাইল এডিট করুন
Comment[bs]=Izmijeni tekstualne datoteke
Comment[ca]=Edita fitxers de text
Comment[cs]=Úprava textových souborů
Comment[cy]=Golygu ffeiliau testun
Comment[da]=Redigér tekstfiler
Comment[de]=Textdateien bearbeiten
Comment[el]=Επεξεργασία αρχείων κειμένου
Comment[en_CA]=Edit text files
Comment[en_GB]=Edit text files
Comment[es]=Edita archivos de texto
Comment[et]=Redigeeri tekstifaile
Comment[eu]=Editatu testu-fitxategiak
Comment[fa]=ویرایش پرونده‌های متنی
Comment[fi]=Muokkaa tekstitiedostoja
Comment[fr]=Éditer des fichiers texte
Comment[ga]=Eagar comhad Téacs
Comment[gu]=લખાણ ફાઇલોમાં ફેરફાર કરો
Comment[he]=ערוך קבצי טקסט
Comment[hi]=पाठ फ़ाइलें संपादित करें
Comment[hr]=Uređivanje tekstualne datoteke
Comment[hu]=Szövegfájlok szerkesztése
Comment[id]=Edit file teks
Comment[it]=Modifica file di testo
Comment[ja]=テキストファイルを編集します
Comment[kn]=ಪಠ್ಯ ಕಡತಗಳನ್ನು ಸಂಪಾದಿಸು
Comment[ko]=텍스트 파일을 편집합니다
Comment[lt]=Redaguoti tekstines bylas
Comment[lv]=Rediģēt teksta failus
Comment[mk]=Уреди текстуални фајлови
Comment[ml]=വാചക രചനകള് തിരുത്തുക
Comment[mn]=Текст файл боловсруулах
Comment[mr]=गद्य फाइल संपादित करा
Comment[ms]=Edit fail teks
Comment[nb]=Rediger tekstfiler
Comment[ne]=पाठ फाइललाई संशोधन गर्नुहोस्
Comment[nl]=Tekstbestanden bewerken
Comment[nn]=Rediger tekstfiler
Comment[no]=Rediger tekstfiler
Comment[or]=ପାଠ୍ଯ ଫାଇଲଗୁଡ଼ିକୁ ସମ୍ପାଦନ କରନ୍ତୁ
Comment[pa]=ਪਾਠ ਫਾਇਲਾਂ ਸੰਪਾਦਨ
Comment[pl]=Edytor plików tekstowych
Comment[pt]=Editar ficheiros de texto
Comment[pt_BR]=Edite arquivos de texto
Comment[ro]=Editare fişiere text
Comment[ru]=Редактирование текстовых файлов
Comment[sk]=Úprava textových súborov
Comment[sl]=Urejanje datotek z besedili
Comment[sq]=Përpuno files teksti
Comment[sr]=Уређујте текст фајлове
Comment[sr@Latn]=Izmeni tekstualne datoteke
Comment[sv]=Redigera textfiler
Comment[ta]=உரை கோப்புகளை தொகுக்கவும்
Comment[th]=แก้ไขแฟ้มข้อความ
Comment[tk]=Metin faýllary editle
Comment[tr]=Metin dosyaları düzenleyin
Comment[uk]=Редактор текстових файлів
Comment[vi]=Soạn thảo tập tin văn bản
Comment[wa]=Asspougnî des fitchîs tecses
Comment[zh_CN]=编辑文本文件
Comment[zh_TW]=編輯文字檔
TryExec=hx
Exec=hx %F
Terminal=true
Type=Application
Keywords=Text;editor;
Keywords[fr]=Texte;éditeur;
Keywords[ru]=текст;текстовый редактор;
Keywords[sr]=Текст;едитор;
Keywords[tr]=Metin;düzenleyici;
Icon=helix
Categories=Utility;TextEditor;
StartupNotify=false
MimeType=text/english;text/plain;text/x-makefile;text/x-c++hdr;text/x-c++src;text/x-chdr;text/x-csrc;text/x-java;text/x-moc;text/x-pascal;text/x-tcl;text/x-tex;application/x-shellscript;text/x-c;text/x-c++;

View File

@@ -0,0 +1,23 @@
#!/usr/bin/env bash
# Bash completion script for Helix editor
_hx() {
# $1 command name
# $2 word being completed
# $3 word preceding
COMPREPLY=()
case "$3" in
-g | --grammar)
COMPREPLY=($(compgen -W "fetch build" -- $2))
;;
--health)
local languages=$(hx --health |tail -n '+7' |awk '{print $1}' |sed 's/\x1b\[[0-9;]*m//g')
COMPREPLY=($(compgen -W "$languages" -- $2))
;;
*)
COMPREPLY=($(compgen -fd -W "-h --help --tutor -V --version -v -vv -vvv --health -g --grammar --vsplit --hsplit -c --config --log" -- $2))
;;
esac
} && complete -o filenames -F _hx hx

55
contrib/completion/hx.elv Normal file
View File

@@ -0,0 +1,55 @@
# You can move it here ~/.config/elvish/lib/hx.elv
# Or add `eval (slurp < ~/$REPOS/helix/contrib/completion/hx.elv)`
# Be sure to replace `$REPOS` with something that makes sense for you!
### Renders a pretty completion candidate
var candidate = { | _stem _desc |
edit:complex-candidate $_stem &display=(styled $_stem bold)(styled " "$_desc dim)
}
### These commands will invalidate further input (i.e. not react to them)
var skips = [ "--tutor" "--help" "--version" "-V" "--health" ]
### Grammar commands
var grammar = [ "--grammar" "-g" ]
### Config commands
var config = [ "--config" "-c" ]
### Set an arg-completer for the `hx` binary
set edit:completion:arg-completer[hx] = {|@args|
var n = (count $args)
if (>= $n 3) {
# Stop completions if passed arg will take presedence
# and invalidate further input
if (has-value $skips $args[-2]) {
return
}
# If the previous arg == --grammar, then only suggest:
if (has-value $grammar $args[-2]) {
$candidate "fetch" "Fetch the tree-sitter grammars"
$candidate "build" "Build the tree-sitter grammars"
return
}
# When we have --config, we need a file
if (has-values $config $args[-2]) {
edit:complete-filename $args[-1] | each { |v| put $v[stem] }
return
}
# When we have --log, we need a file
if (has-values "log" $args[-2]) {
edit:complete-filename $args[-1] | each { |v| put $v[stem] }
return
}
}
edit:complete-filename $args[-1] | each { |v| put $v[stem]}
$candidate "--help" "(Prints help information)"
$candidate "--version" "(Prints version information)"
$candidate "--tutor" "(Loads the tutorial)"
$candidate "--health" "(Checks for errors in editor setup)"
$candidate "--grammar" "(Fetch or build the tree-sitter grammars)"
$candidate "--vsplit" "(Splits all given files vertically)"
$candidate "--hsplit" "(Splits all given files horizontally)"
$candidate "--config" "(Specifies a file to use for configuration)"
$candidate "--log" "(Specifies a file to write log data into)"
}

View File

@@ -0,0 +1,15 @@
#!/usr/bin/env fish
# Fish completion script for Helix editor
set -l langs (hx --health |tail -n '+7' |awk '{print $1}' |sed 's/\x1b\[[0-9;]*m//g')
complete -c hx -s h -l help -d "Prints help information"
complete -c hx -l tutor -d "Loads the tutorial"
complete -c hx -l health -x -a "$langs" -d "Checks for errors in editor setup"
complete -c hx -s g -l grammar -x -a "fetch build" -d "Fetches or builds tree-sitter grammars"
complete -c hx -s v -o vv -o vvv -d "Increases logging verbosity"
complete -c hx -s V -l version -d "Prints version information"
complete -c hx -l vsplit -d "Splits all given files vertically into different windows"
complete -c hx -l hsplit -d "Splits all given files horizontally into different windows"
complete -c hx -s c -l config -r -d "Specifies a file to use for completion"
complete -c hx -l log -r -d "Specifies a file to write log data into"

34
contrib/completion/hx.zsh Normal file
View File

@@ -0,0 +1,34 @@
#compdef _hx hx
# Zsh completion script for Helix editor
_hx() {
_arguments -C \
"-h[Prints help information]" \
"--help[Prints help information]" \
"-v[Increase logging verbosity]" \
"-vv[Increase logging verbosity]" \
"-vvv[Increase logging verbosity]" \
"-V[Prints version information]" \
"--version[Prints version information]" \
"--tutor[Loads the tutorial]" \
"--health[Checks for errors in editor setup]:language:->health" \
"-g[Fetches or builds tree-sitter grammars]:action:->grammar" \
"--grammar[Fetches or builds tree-sitter grammars]:action:->grammar" \
"--vsplit[Splits all given files vertically into different windows]" \
"--hsplit[Splits all given files horizontally into different windows]" \
"-c[Specifies a file to use for configuration]" \
"--config[Specifies a file to use for configuration]" \
"--log[Specifies a file to write log data into]" \
"*:file:_files"
case "$state" in
health)
local languages=($(hx --health |tail -n '+7' |awk '{print $1}' |sed 's/\x1b\[[0-9;]*m//g'))
_values 'language' $languages
;;
grammar)
_values 'action' fetch build
;;
esac
}

BIN
contrib/helix.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

8
default.nix Normal file
View File

@@ -0,0 +1,8 @@
# Flake's default package for non-flake-enabled nix instances
let
compat = builtins.fetchTarball {
url = "https://github.com/edolstra/flake-compat/archive/b4a34015c698c7793d592d66adbab377907a2be8.tar.gz";
sha256 = "sha256:1qc703yg0babixi6wshn5wm2kgl5y1drcswgszh4xxzbrwkk9sv7";
};
in
(import compat {src = ./.;}).defaultNix.default

52
docs/CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,52 @@
# Contributing
Contributors are very welcome! **No contribution is too small and all contributions are valued.**
Some suggestions to get started:
- You can look at the [good first issue][good-first-issue] label on the issue tracker.
- Help with packaging on various distributions needed!
- To use print debugging to the [Helix log file][log-file], you must:
* Print using `log::info!`, `warn!`, or `error!`. (`log::info!("helix!")`)
* Pass the appropriate verbosity level option for the desired log level. (`hx -v <file>` for info, more `v`s for higher severity inclusive)
- If your preferred language is missing, integrating a tree-sitter grammar for
it and defining syntax highlight queries for it is straight forward and
doesn't require much knowledge of the internals.
We provide an [architecture.md][architecture.md] that should give you
a good overview of the internals.
# Auto generated documentation
Some parts of [the book][docs] are autogenerated from the code itself,
like the list of `:commands` and supported languages. To generate these
files, run
```shell
cargo xtask docgen
```
inside the project. We use [xtask][xtask] as an ad-hoc task runner and
thus do not require any dependencies other than `cargo` (You don't have
to `cargo install` anything either).
# Integration tests
Integration tests for helix-term can be run with `cargo integration-test`. Code
contributors are strongly encouraged to write integration tests for their code.
Existing tests can be used as examples. Helpers can be found in
[helpers.rs][helpers.rs]. The log level can be set with the `HELIX_LOG_LEVEL`
environment variable, e.g. `HELIX_LOG_LEVEL=debug cargo integration-test`.
## Minimum Stable Rust Version (MSRV) Policy
Helix follows the MSRV of Firefox.
The current MSRV and future changes to the MSRV are listed in the [Firefox documentation].
[Firefox documentation]: https://firefox-source-docs.mozilla.org/writing-rust-code/update-policy.html
[good-first-issue]: https://github.com/helix-editor/helix/labels/E-easy
[log-file]: https://github.com/helix-editor/helix/wiki/FAQ#access-the-log-file
[architecture.md]: ./architecture.md
[docs]: https://docs.helix-editor.com/
[xtask]: https://github.com/matklad/cargo-xtask
[helpers.rs]: ../helix-term/tests/test/helpers.rs

View File

@@ -1,12 +1,13 @@
| Crate | Description |
| ----------- | ----------- |
| helix-core | Core editing primitives, functional. |
| helix-syntax | Tree-sitter grammars |
| helix-lsp | Language server client |
| helix-view | UI abstractions for use in backends, imperative shell. |
| helix-term | Terminal UI |
| helix-tui | TUI primitives, forked from tui-rs, inspired by Cursive |
| Crate | Description |
| ----------- | ----------- |
| helix-core | Core editing primitives, functional. |
| helix-lsp | Language server client |
| helix-dap | Debug Adapter Protocol (DAP) client |
| helix-loader | Functions for building, fetching, and loading external resources |
| helix-view | UI abstractions for use in backends, imperative shell. |
| helix-term | Terminal UI |
| helix-tui | TUI primitives, forked from tui-rs, inspired by Cursive |
This document contains a high-level overview of Helix internals.
@@ -31,7 +32,7 @@ represented by a `Selection`. Each `Range` in the selection consists of a moving
a selection with a single range, with the head and the anchor in the same
position.
Ropes are modified by constructing an OT-like `Transaction`. It's represents
Ropes are modified by constructing an OT-like `Transaction`. It represents
a single coherent change to the document and can be applied to the rope.
A transaction can be inverted to produce an undo. Selections and marks can be
mapped over a transaction to translate to a position in the new text state after
@@ -41,7 +42,7 @@ applying the transaction.
> interface used to generate text edits.
`Syntax` is the interface used to interact with tree-sitter ASTs for syntax
highling and other features.
highlighting and other features.
## View
@@ -54,15 +55,40 @@ A `Document` ties together the `Rope`, `Selection`(s), `Syntax`, document
file.
A `View` represents an open split in the UI. It holds the currently open
document ID and other related state.
document ID and other related state. Views encapsulate the gutter, status line,
diagnostics, and the inner area where the code is displayed.
> NOTE: Multiple views are able to display the same document, so the document
> contains selections for each view. To retrieve, `document.selection()` takes
> a `ViewId`.
`Info` is the autoinfo box that shows hints when awaiting another key with bindings
like `g` and `m`. It is attached to the viewport as a whole.
`Surface` is like a buffer to which widgets draw themselves to, and the
surface is then rendered on the screen on each cycle.
`Rect`s are areas (simply an x and y coordinate with the origin at the
screen top left and then a height and width) which are part of a
`Surface`. They can be used to limit the area to which a `Component` can
render. For example if we wrap a `Markdown` component in a `Popup`
(think the documentation popup with space+k), Markdown's render method
will get a Rect that is the exact size of the popup.
Widgets are called `Component`s internally, and you can see most of them
in `helix-term/src/ui`. Some components like `Popup` and `Overlay` can take
other components as children.
`Layer`s are how multiple components are displayed, and is simply a
`Vec<Component>`. Layers are managed by the `Compositor`. On each top
level render call, the compositor renders each component in the order
they were pushed into the stack. This makes multiple components "layer"
on top of one another. Hence we get a file picker displayed over the
editor, etc.
The `Editor` holds the global state: all the open documents, a tree
representation of all the view splits, and a registry of language servers. To
open or close files, interact with the editor.
representation of all the view splits, the configuration, and a registry of
language servers. To open or close files, interact with the editor.
## LSP

59
docs/releases.md Normal file
View File

@@ -0,0 +1,59 @@
## Checklist
Helix releases are versioned in the Calendar Versioning scheme:
`YY.0M(.MICRO)`, for example `22.05` for May of 2022. In these instructions
we'll use `<tag>` as a placeholder for the tag being published.
* Merge the changelog PR
* Tag and push
* `git tag -s -m "<tag>" -a <tag> && git push`
* Make sure to switch to master and pull first
* Edit the `VERSION` file and change the date to the next planned release
* Releases are planned to happen every two months, so `22.05` would change to `22.07`
* Wait for the Release CI to finish
* It will automatically turn the git tag into a GitHub release when it uploads artifacts
* Edit the new release
* Use `<tag>` as the title
* Link to the changelog and release notes
* Merge the release notes PR
* Download the macos and linux binaries and update the `sha256`s in the [homebrew formula]
* Use `sha256sum` on the downloaded `.tar.xz` files to determine the hash
* Link to the release notes in this-week-in-rust
* [Example PR](https://github.com/rust-lang/this-week-in-rust/pull/3300)
* Post to reddit
* [Example post](https://www.reddit.com/r/rust/comments/uzp5ze/helix_editor_2205_released/)
[homebrew formula]: https://github.com/Homebrew/homebrew-core/blob/master/Formula/helix.rb
## Changelog Curation
The changelog is currently created manually by reading through commits in the
log since the last release. GitHub's compare view is a nice way to approach
this. For example when creating the 22.07 release notes, this compare link
may be used
```
https://github.com/helix-editor/helix/compare/22.05...master
```
Either side of the triple-dot may be replaced with an exact revision, so if
you wish to incrementally compile the changelog, you can tackle a weeks worth
or so, record the revision where you stopped, and use that as a starting point
next week:
```
https://github.com/helix-editor/helix/compare/7706a4a0d8b67b943c31d0c5f7b00d357b5d838d...master
```
A work-in-progress commit for a changelog might look like
[this example](https://github.com/helix-editor/helix/commit/831adfd4c709ca16b248799bfef19698d5175e55).
Not every PR or commit needs a blurb in the changelog. Each release section
tends to have a blurb that links to a GitHub comparison between release
versions for convenience:
> As usual, the following is a summary of each of the changes since the last
> release. For the full log, check out the git log.
Typically, small changes like dependencies or documentation updates, refactors,
or meta changes like GitHub Actions work are left out.

142
flake.lock generated
View File

@@ -1,12 +1,29 @@
{
"nodes": {
"devshell": {
"crane": {
"flake": false,
"locked": {
"lastModified": 1632436039,
"narHash": "sha256-OtITeVWcKXn1SpVEnImpTGH91FycCskGBPqmlxiykv4=",
"lastModified": 1661875961,
"narHash": "sha256-f1h/2c6Teeu1ofAHWzrS8TwBPcnN+EEu+z1sRVmMQTk=",
"owner": "ipetkov",
"repo": "crane",
"rev": "d9f394e4e20e97c2a60c3ad82c2b6ef99be19e24",
"type": "github"
},
"original": {
"owner": "ipetkov",
"repo": "crane",
"type": "github"
}
},
"devshell": {
"flake": false,
"locked": {
"lastModified": 1667210711,
"narHash": "sha256-IoErjXZAkzYWHEpQqwu/DeRNJGFdR7X2OGbkhMqMrpw=",
"owner": "numtide",
"repo": "devshell",
"rev": "7a7a7aa0adebe5488e5abaec688fd9ae0f8ea9c6",
"rev": "96a9dd12b8a447840cc246e17a47b81a4268bba7",
"type": "github"
},
"original": {
@@ -15,13 +32,63 @@
"type": "github"
}
},
"dream2nix": {
"inputs": {
"alejandra": [
"nci"
],
"all-cabal-json": [
"nci"
],
"crane": "crane",
"devshell": [
"nci",
"devshell"
],
"flake-utils-pre-commit": [
"nci"
],
"ghc-utils": [
"nci"
],
"gomod2nix": [
"nci"
],
"mach-nix": [
"nci"
],
"nixpkgs": [
"nci",
"nixpkgs"
],
"poetry2nix": [
"nci"
],
"pre-commit-hooks": [
"nci"
]
},
"locked": {
"lastModified": 1668851003,
"narHash": "sha256-X7RCQQynbxStZR2m7HW38r/msMQwVl3afD6UXOCtvx4=",
"owner": "nix-community",
"repo": "dream2nix",
"rev": "c77e8379d8fe01213ba072e40946cbfb7b58e628",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "dream2nix",
"type": "github"
}
},
"flake-utils": {
"locked": {
"lastModified": 1623875721,
"narHash": "sha256-A8BU7bjS5GirpAUv4QA+QnJ4CceLHkcXdRp4xITDB0s=",
"lastModified": 1659877975,
"narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "f7e004a55b120c02ecb6219596820fcd32ca8772",
"rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0",
"type": "github"
},
"original": {
@@ -30,38 +97,23 @@
"type": "github"
}
},
"flakeCompat": {
"flake": false,
"locked": {
"lastModified": 1627913399,
"narHash": "sha256-hY8g6H2KFL8ownSiFeMOjwPC8P0ueXpCVEbxgda3pko=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "12c64ca55c1014cdc1b16ed5a804aa8576601ff2",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"nixCargoIntegration": {
"nci": {
"inputs": {
"devshell": "devshell",
"dream2nix": "dream2nix",
"nixpkgs": [
"nixpkgs"
],
"rustOverlay": [
"rust-overlay": [
"rust-overlay"
]
},
"locked": {
"lastModified": 1634796585,
"narHash": "sha256-CW4yx6omk5qCXUIwXHp/sztA7u0SpyLq9NEACPnkiz8=",
"lastModified": 1669011203,
"narHash": "sha256-Lymj4HktNEFmVXtwI0Os7srDXHZbZW0Nzw3/+5Hf8ko=",
"owner": "yusdacra",
"repo": "nix-cargo-integration",
"rev": "a84a2137a396f303978f1d48341e0390b0e16a8b",
"rev": "c5133b91fc1d549087c91228bd213f2518728a4b",
"type": "github"
},
"original": {
@@ -72,11 +124,11 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1634782485,
"narHash": "sha256-psfh4OQSokGXG0lpq3zKFbhOo3QfoeudRcaUnwMRkQo=",
"lastModified": 1668905981,
"narHash": "sha256-RBQa/+9Uk1eFTqIOXBSBezlEbA3v5OkgP+qptQs1OxY=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "34ad3ffe08adfca17fcb4e4a47bb5f3b113687be",
"rev": "690ffff026b4e635b46f69002c0f4e81c65dfc2e",
"type": "github"
},
"original": {
@@ -86,25 +138,9 @@
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1628186154,
"narHash": "sha256-r2d0wvywFnL9z4iptztdFMhaUIAaGzrSs7kSok0PgmE=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "06552b72346632b6943c8032e57e702ea12413bf",
"type": "github"
},
"original": {
"owner": "NixOS",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"flakeCompat": "flakeCompat",
"nixCargoIntegration": "nixCargoIntegration",
"nci": "nci",
"nixpkgs": "nixpkgs",
"rust-overlay": "rust-overlay"
}
@@ -112,14 +148,16 @@
"rust-overlay": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs_2"
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1634869268,
"narHash": "sha256-RVAcEFlFU3877Mm4q/nbXGEYTDg/wQNhzmXGMTV6wBs=",
"lastModified": 1668998422,
"narHash": "sha256-G/BklIplCHZEeDIabaaxqgITdIXtMolRGlwxn9jG2/Q=",
"owner": "oxalica",
"repo": "rust-overlay",
"rev": "c02c2d86354327317546501af001886fbb53d374",
"rev": "68ab029c93f8f8eed4cf3ce9a89a9fd4504b2d6e",
"type": "github"
},
"original": {

219
flake.nix
View File

@@ -3,73 +3,178 @@
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
rust-overlay.url = "github:oxalica/rust-overlay";
nixCargoIntegration = {
rust-overlay = {
url = "github:oxalica/rust-overlay";
inputs.nixpkgs.follows = "nixpkgs";
};
nci = {
url = "github:yusdacra/nix-cargo-integration";
inputs.nixpkgs.follows = "nixpkgs";
inputs.rustOverlay.follows = "rust-overlay";
};
flakeCompat = {
url = "github:edolstra/flake-compat";
flake = false;
inputs.rust-overlay.follows = "rust-overlay";
};
};
outputs = inputs@{ self, nixCargoIntegration, ... }:
nixCargoIntegration.lib.makeOutputs {
outputs = {
self,
nixpkgs,
nci,
...
}: let
lib = nixpkgs.lib;
ncl = nci.lib.nci-lib;
mkRootPath = rel:
builtins.path {
path = "${toString ./.}/${rel}";
name = rel;
};
filteredSource = let
pathsToIgnore = [
".envrc"
".ignore"
".github"
"runtime"
"screenshot.png"
"book"
"contrib"
"docs"
"README.md"
"CHANGELOG.md"
"shell.nix"
"default.nix"
"grammars.nix"
"flake.nix"
"flake.lock"
];
ignorePaths = path: type: let
# split the nix store path into its components
components = lib.splitString "/" path;
# drop off the `/nix/hash-source` section from the path
relPathComponents = lib.drop 4 components;
# reassemble the path components
relPath = lib.concatStringsSep "/" relPathComponents;
in
lib.all (p: ! (lib.hasPrefix p relPath)) pathsToIgnore;
in
builtins.path {
name = "helix-source";
path = toString ./.;
# filter out unnecessary paths
filter = ignorePaths;
};
outputs = nci.lib.makeOutputs {
root = ./.;
buildPlatform = "crate2nix";
renameOutputs = { "helix-term" = "helix"; };
# Set default app to hx (binary is from helix-term release build)
# Set default package to helix-term release build
defaultOutputs = { app = "hx"; package = "helix"; };
overrides = {
crateOverrides = common: _: {
helix-term = prev: {
# link languages and theme toml files since helix-term expects them (for tests)
preConfigure = "ln -s ${common.root}/{languages.toml,theme.toml} ..";
buildInputs = (prev.buildInputs or [ ]) ++ [ common.cCompiler.cc.lib ];
};
# link languages and theme toml files since helix-view expects them
helix-view = _: { preConfigure = "ln -s ${common.root}/{languages.toml,theme.toml} .."; };
helix-syntax = _prev: {
preConfigure = "mkdir -p ../runtime/grammars";
postInstall = "cp -r ../runtime $out/runtime";
config = common: {
outputs = {
# rename helix-term to helix since it's our main package
rename = {"helix-term" = "helix";};
# Set default app to hx (binary is from helix-term release build)
# Set default package to helix-term release build
defaults = {
app = "hx";
package = "helix";
};
};
mainBuild = common: prev:
let
inherit (common) pkgs lib;
helixSyntax = lib.buildCrate {
root = self;
memberName = "helix-syntax";
defaultCrateOverrides = {
helix-syntax = common.crateOverrides.helix-syntax;
};
release = false;
};
runtimeDir = pkgs.runCommand "helix-runtime" { } ''
mkdir -p $out
ln -s ${common.root}/runtime/* $out
ln -sf ${helixSyntax}/runtime/grammars $out
'';
in
lib.optionalAttrs (common.memberName == "helix-term") {
nativeBuildInputs = [ pkgs.makeWrapper ];
postFixup = ''
if [ -f "$out/bin/hx" ]; then
wrapProgram "$out/bin/hx" --set HELIX_RUNTIME "${runtimeDir}"
fi
'';
};
shell = common: prev: {
packages = prev.packages ++ (with common.pkgs; [ lld_12 lldb cargo-tarpaulin ]);
env = prev.env ++ [
{ name = "HELIX_RUNTIME"; eval = "$PWD/runtime"; }
{ name = "RUST_BACKTRACE"; value = "1"; }
{ name = "RUSTFLAGS"; value = "-C link-arg=-fuse-ld=lld -C target-cpu=native"; }
cCompiler.package = with common.pkgs;
if stdenv.isLinux
then gcc
else clang;
shell = {
packages = with common.pkgs;
[lld_13 cargo-flamegraph rust-analyzer]
++ (lib.optional (stdenv.isx86_64 && stdenv.isLinux) cargo-tarpaulin)
++ (lib.optional stdenv.isLinux lldb);
env = [
{
name = "HELIX_RUNTIME";
eval = "$PWD/runtime";
}
{
name = "RUST_BACKTRACE";
value = "1";
}
{
name = "RUSTFLAGS";
value =
if common.pkgs.stdenv.isLinux
then "-C link-arg=-fuse-ld=lld -C target-cpu=native -Clink-arg=-Wl,--no-rosegment"
else "";
}
];
};
};
pkgConfig = common: {
helix-term = {
# Wrap helix with runtime
wrapper = _: old: let
inherit (common) pkgs;
makeOverridableHelix = old: config: let
grammars = pkgs.callPackage ./grammars.nix config;
runtimeDir = pkgs.runCommand "helix-runtime" {} ''
mkdir -p $out
ln -s ${mkRootPath "runtime"}/* $out
rm -r $out/grammars
ln -s ${grammars} $out/grammars
'';
helix-wrapped =
common.internal.pkgsSet.utils.wrapDerivation old
{
nativeBuildInputs = [pkgs.makeWrapper];
makeWrapperArgs = config.makeWrapperArgs or [];
}
''
rm -rf $out/bin
mkdir -p $out/bin
ln -sf ${old}/bin/* $out/bin/
wrapProgram "$out/bin/hx" ''${makeWrapperArgs[@]} --set HELIX_RUNTIME "${runtimeDir}"
'';
in
helix-wrapped
// {override = makeOverridableHelix old;};
in
makeOverridableHelix old {};
overrides.fix-build.overrideAttrs = prev: {
src = filteredSource;
# disable fetching and building of tree-sitter grammars in the helix-term build.rs
HELIX_DISABLE_AUTO_GRAMMAR_BUILD = "1";
buildInputs = ncl.addBuildInputs prev [common.config.cCompiler.package.cc.lib];
# link languages and theme toml files since helix-term expects them (for tests)
preConfigure = ''
${prev.preConfigure or ""}
${
lib.concatMapStringsSep
"\n"
(path: "ln -sf ${mkRootPath path} ..")
["languages.toml" "theme.toml" "base16_theme.toml"]
}
'';
checkPhase = ":";
meta.mainProgram = "hx";
};
};
};
};
in
outputs
// {
packages =
lib.mapAttrs
(
system: packages:
packages
// {
helix-unwrapped = packages.helix.passthru.unwrapped;
helix-unwrapped-dev = packages.helix-dev.passthru.unwrapped;
}
)
outputs.packages;
};
nixConfig = {
extra-substituters = ["https://helix.cachix.org"];
extra-trusted-public-keys = ["helix.cachix.org-1:ejp9KQpR1FBI2onstMQ34yogDm4OgU2ru6lIwPvuCVs="];
};
}

121
grammars.nix Normal file
View File

@@ -0,0 +1,121 @@
{
stdenv,
lib,
runCommandLocal,
runCommand,
yj,
includeGrammarIf ? _: true,
...
}: let
# HACK: nix < 2.6 has a bug in the toml parser, so we convert to JSON
# before parsing
languages-json = runCommandLocal "languages-toml-to-json" {} ''
${yj}/bin/yj -t < ${./languages.toml} > $out
'';
languagesConfig =
if lib.versionAtLeast builtins.nixVersion "2.6.0"
then builtins.fromTOML (builtins.readFile ./languages.toml)
else builtins.fromJSON (builtins.readFile (builtins.toPath languages-json));
isGitGrammar = grammar:
builtins.hasAttr "source" grammar
&& builtins.hasAttr "git" grammar.source
&& builtins.hasAttr "rev" grammar.source;
isGitHubGrammar = grammar: lib.hasPrefix "https://github.com" grammar.source.git;
toGitHubFetcher = url: let
match = builtins.match "https://github\.com/([^/]*)/([^/]*)/?" url;
in {
owner = builtins.elemAt match 0;
repo = builtins.elemAt match 1;
};
gitGrammars = builtins.filter isGitGrammar languagesConfig.grammar;
buildGrammar = grammar: let
gh = toGitHubFetcher grammar.source.git;
sourceGit = builtins.fetchTree {
type = "git";
url = grammar.source.git;
rev = grammar.source.rev;
ref = grammar.source.ref or "HEAD";
shallow = true;
};
sourceGitHub = builtins.fetchTree {
type = "github";
owner = gh.owner;
repo = gh.repo;
inherit (grammar.source) rev;
};
source =
if isGitHubGrammar grammar
then sourceGitHub
else sourceGit;
in
stdenv.mkDerivation rec {
# see https://github.com/NixOS/nixpkgs/blob/fbdd1a7c0bc29af5325e0d7dd70e804a972eb465/pkgs/development/tools/parsing/tree-sitter/grammar.nix
pname = "helix-tree-sitter-${grammar.name}";
version = grammar.source.rev;
src =
if builtins.hasAttr "subpath" grammar.source
then "${source}/${grammar.source.subpath}"
else source;
dontUnpack = true;
dontConfigure = true;
FLAGS = [
"-I${src}/src"
"-g"
"-O3"
"-fPIC"
"-fno-exceptions"
"-Wl,-z,relro,-z,now"
];
NAME = grammar.name;
buildPhase = ''
runHook preBuild
if [[ -e "$src/src/scanner.cc" ]]; then
$CXX -c "$src/src/scanner.cc" -o scanner.o $FLAGS
elif [[ -e "$src/src/scanner.c" ]]; then
$CC -c "$src/src/scanner.c" -o scanner.o $FLAGS
fi
$CC -c "$src/src/parser.c" -o parser.o $FLAGS
$CXX -shared -o $NAME.so *.o
ls -al
runHook postBuild
'';
installPhase = ''
runHook preInstall
mkdir $out
mv $NAME.so $out/
runHook postInstall
'';
# Strip failed on darwin: strip: error: symbols referenced by indirect symbol table entries that can't be stripped
fixupPhase = lib.optionalString stdenv.isLinux ''
runHook preFixup
$STRIP $out/$NAME.so
runHook postFixup
'';
};
grammarsToBuild = builtins.filter includeGrammarIf gitGrammars;
builtGrammars =
builtins.map (grammar: {
inherit (grammar) name;
artifact = buildGrammar grammar;
})
grammarsToBuild;
grammarLinks =
builtins.map (grammar: "ln -s ${grammar.artifact}/${grammar.name}.so $out/${grammar.name}.so")
builtGrammars;
in
runCommand "consolidated-helix-grammars" {} ''
mkdir -p $out
${builtins.concatStringsSep "\n" grammarLinks}
''

View File

@@ -1,6 +1,6 @@
[package]
name = "helix-core"
version = "0.5.0"
version = "0.6.0"
authors = ["Blaž Hrastnik <blaz@mxxn.io>"]
edition = "2021"
license = "MPL-2.0"
@@ -11,30 +11,41 @@ homepage = "https://helix-editor.com"
include = ["src/**/*", "README.md"]
[features]
unicode-lines = ["ropey/unicode_lines"]
integration = []
[dependencies]
helix-syntax = { version = "0.5", path = "../helix-syntax" }
helix-loader = { version = "0.6", path = "../helix-loader" }
ropey = "1.3"
smallvec = "1.7"
tendril = "0.4.2"
unicode-segmentation = "1.8"
ropey = { version = "1.5.1-alpha", default-features = false, features = ["simd"] }
smallvec = "1.10"
smartstring = "1.0.1"
unicode-segmentation = "1.10"
unicode-width = "0.1"
unicode-general-category = "0.4"
unicode-general-category = "0.6"
# slab = "0.4.2"
slotmap = "1.0"
tree-sitter = "0.20"
once_cell = "1.8"
once_cell = "1.16"
arc-swap = "1"
regex = "1"
bitflags = "1.3"
ahash = "0.8.2"
hashbrown = { version = "0.13.1", features = ["raw"] }
log = "0.4"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
toml = "0.5"
similar = "2.1"
imara-diff = "0.1.0"
etcetera = "0.3"
encoding_rs = "0.8"
chrono = { version = "0.4", default-features = false, features = ["alloc", "std"] }
etcetera = "0.4"
textwrap = "0.16.0"
[dev-dependencies]
quickcheck = { version = "1", default-features = false }

View File

@@ -1,12 +1,13 @@
//! When typing the opening character of one of the possible pairs defined below,
//! this module provides the functionality to insert the paired closing character.
use crate::{Range, Rope, Selection, Tendril, Transaction};
use crate::{graphemes, movement::Direction, Range, Rope, Selection, Tendril, Transaction};
use std::collections::HashMap;
use smallvec::SmallVec;
// Heavily based on https://github.com/codemirror/closebrackets/
pub const PAIRS: &[(char, char)] = &[
pub const DEFAULT_PAIRS: &[(char, char)] = &[
('(', ')'),
('{', '}'),
('[', ']'),
@@ -15,7 +16,95 @@ pub const PAIRS: &[(char, char)] = &[
('`', '`'),
];
const CLOSE_BEFORE: &str = ")]}'\":;> \n\r\u{000B}\u{000C}\u{0085}\u{2028}\u{2029}"; // includes space and newlines
/// The type that represents the collection of auto pairs,
/// keyed by the opener.
#[derive(Debug, Clone)]
pub struct AutoPairs(HashMap<char, Pair>);
/// Represents the config for a particular pairing.
#[derive(Debug, Clone, Copy)]
pub struct Pair {
pub open: char,
pub close: char,
}
impl Pair {
/// true if open == close
pub fn same(&self) -> bool {
self.open == self.close
}
/// true if all of the pair's conditions hold for the given document and range
pub fn should_close(&self, doc: &Rope, range: &Range) -> bool {
let mut should_close = Self::next_is_not_alpha(doc, range);
if self.same() {
should_close &= Self::prev_is_not_alpha(doc, range);
}
should_close
}
pub fn next_is_not_alpha(doc: &Rope, range: &Range) -> bool {
let cursor = range.cursor(doc.slice(..));
let next_char = doc.get_char(cursor);
next_char.map(|c| !c.is_alphanumeric()).unwrap_or(true)
}
pub fn prev_is_not_alpha(doc: &Rope, range: &Range) -> bool {
let cursor = range.cursor(doc.slice(..));
let prev_char = prev_char(doc, cursor);
prev_char.map(|c| !c.is_alphanumeric()).unwrap_or(true)
}
}
impl From<&(char, char)> for Pair {
fn from(&(open, close): &(char, char)) -> Self {
Self { open, close }
}
}
impl From<(&char, &char)> for Pair {
fn from((open, close): (&char, &char)) -> Self {
Self {
open: *open,
close: *close,
}
}
}
impl AutoPairs {
/// Make a new AutoPairs set with the given pairs and default conditions.
pub fn new<'a, V: 'a, A>(pairs: V) -> Self
where
V: IntoIterator<Item = A>,
A: Into<Pair>,
{
let mut auto_pairs = HashMap::new();
for pair in pairs.into_iter() {
let auto_pair = pair.into();
auto_pairs.insert(auto_pair.open, auto_pair);
if auto_pair.open != auto_pair.close {
auto_pairs.insert(auto_pair.close, auto_pair);
}
}
Self(auto_pairs)
}
pub fn get(&self, ch: char) -> Option<&Pair> {
self.0.get(&ch)
}
}
impl Default for AutoPairs {
fn default() -> Self {
AutoPairs::new(DEFAULT_PAIRS.iter())
}
}
// insert hook:
// Fn(doc, selection, char) => Option<Transaction>
@@ -25,139 +114,260 @@ const CLOSE_BEFORE: &str = ")]}'\":;> \n\r\u{000B}\u{000C}\u{0085}\u{2028}\u{202
//
// to simplify, maybe return Option<Transaction> and just reimplement the default
// TODO: delete implementation where it erases the whole bracket (|) -> |
// [TODO]
// * delete implementation where it erases the whole bracket (|) -> |
// * change to multi character pairs to handle cases like placing the cursor in the
// middle of triple quotes, and more exotic pairs like Jinja's {% %}
#[must_use]
pub fn hook(doc: &Rope, selection: &Selection, ch: char) -> Option<Transaction> {
for &(open, close) in PAIRS {
if open == ch {
if open == close {
return handle_same(doc, selection, open);
} else {
return Some(handle_open(doc, selection, open, close, CLOSE_BEFORE));
}
}
pub fn hook(doc: &Rope, selection: &Selection, ch: char, pairs: &AutoPairs) -> Option<Transaction> {
log::trace!("autopairs hook selection: {:#?}", selection);
if close == ch {
if let Some(pair) = pairs.get(ch) {
if pair.same() {
return Some(handle_same(doc, selection, pair));
} else if pair.open == ch {
return Some(handle_open(doc, selection, pair));
} else if pair.close == ch {
// && char_at pos == close
return Some(handle_close(doc, selection, open, close));
return Some(handle_close(doc, selection, pair));
}
}
None
}
// TODO: special handling for lifetimes in rust: if preceeded by & or < don't auto close '
// for example "&'a mut", or "fn<'a>"
fn next_char(doc: &Rope, pos: usize) -> Option<char> {
if pos >= doc.len_chars() {
fn prev_char(doc: &Rope, pos: usize) -> Option<char> {
if pos == 0 {
return None;
}
Some(doc.char(pos))
doc.get_char(pos - 1)
}
// TODO: selections should be extended if range, moved if point.
// TODO: if not cursor but selection, wrap on both sides of selection (surround)
fn handle_open(
doc: &Rope,
selection: &Selection,
open: char,
close: char,
close_before: &str,
) -> Transaction {
let mut ranges = SmallVec::with_capacity(selection.len());
/// calculate what the resulting range should be for an auto pair insertion
fn get_next_range(doc: &Rope, start_range: &Range, offset: usize, len_inserted: usize) -> Range {
// When the character under the cursor changes due to complete pair
// insertion, we must look backward a grapheme and then add the length
// of the insertion to put the resulting cursor in the right place, e.g.
//
// foo[\r\n] - anchor: 3, head: 5
// foo([)]\r\n - anchor: 4, head: 5
//
// foo[\r\n] - anchor: 3, head: 5
// foo'[\r\n] - anchor: 4, head: 6
//
// foo([)]\r\n - anchor: 4, head: 5
// foo()[\r\n] - anchor: 5, head: 7
//
// [foo]\r\n - anchor: 0, head: 3
// [foo(])\r\n - anchor: 0, head: 5
// inserting at the very end of the document after the last newline
if start_range.head == doc.len_chars() && start_range.anchor == doc.len_chars() {
return Range::new(
start_range.anchor + offset + 1,
start_range.head + offset + 1,
);
}
let doc_slice = doc.slice(..);
let single_grapheme = start_range.is_single_grapheme(doc_slice);
// just skip over graphemes
if len_inserted == 0 {
let end_anchor = if single_grapheme {
graphemes::next_grapheme_boundary(doc_slice, start_range.anchor) + offset
// even for backward inserts with multiple grapheme selections,
// we want the anchor to stay where it is so that the relative
// selection does not change, e.g.:
//
// foo([) wor]d -> insert ) -> foo()[ wor]d
} else {
start_range.anchor + offset
};
return Range::new(
end_anchor,
graphemes::next_grapheme_boundary(doc_slice, start_range.head) + offset,
);
}
// trivial case: only inserted a single-char opener, just move the selection
if len_inserted == 1 {
let end_anchor = if single_grapheme || start_range.direction() == Direction::Backward {
start_range.anchor + offset + 1
} else {
start_range.anchor + offset
};
return Range::new(end_anchor, start_range.head + offset + 1);
}
// If the head = 0, then we must be in insert mode with a backward
// cursor, which implies the head will just move
let end_head = if start_range.head == 0 || start_range.direction() == Direction::Backward {
start_range.head + offset + 1
} else {
// We must have a forward cursor, which means we must move to the
// other end of the grapheme to get to where the new characters
// are inserted, then move the head to where it should be
let prev_bound = graphemes::prev_grapheme_boundary(doc_slice, start_range.head);
log::trace!(
"prev_bound: {}, offset: {}, len_inserted: {}",
prev_bound,
offset,
len_inserted
);
prev_bound + offset + len_inserted
};
let end_anchor = match (start_range.len(), start_range.direction()) {
// if we have a zero width cursor, it shifts to the same number
(0, _) => end_head,
// If we are inserting for a regular one-width cursor, the anchor
// moves with the head. This is the fast path for ASCII.
(1, Direction::Forward) => end_head - 1,
(1, Direction::Backward) => end_head + 1,
(_, Direction::Forward) => {
if single_grapheme {
graphemes::prev_grapheme_boundary(doc.slice(..), start_range.head) + 1
// if we are appending, the anchor stays where it is; only offset
// for multiple range insertions
} else {
start_range.anchor + offset
}
}
(_, Direction::Backward) => {
if single_grapheme {
// if we're backward, then the head is at the first char
// of the typed char, so we need to add the length of
// the closing char
graphemes::prev_grapheme_boundary(doc.slice(..), start_range.anchor)
+ len_inserted
+ offset
} else {
// when we are inserting in front of a selection, we need to move
// the anchor over by however many characters were inserted overall
start_range.anchor + offset + len_inserted
}
}
};
Range::new(end_anchor, end_head)
}
fn handle_open(doc: &Rope, selection: &Selection, pair: &Pair) -> Transaction {
let mut end_ranges = SmallVec::with_capacity(selection.len());
let mut offs = 0;
let transaction = Transaction::change_by_selection(doc, selection, |range| {
let pos = range.head;
let next = next_char(doc, pos);
let transaction = Transaction::change_by_selection(doc, selection, |start_range| {
let cursor = start_range.cursor(doc.slice(..));
let next_char = doc.get_char(cursor);
let len_inserted;
let head = pos + offs + open.len_utf8();
// if selection, retain anchor, if cursor, move over
ranges.push(Range::new(
if range.is_empty() {
head
} else {
range.anchor + offs
},
head,
));
match next {
Some(ch) if !close_before.contains(ch) => {
offs += 1;
// TODO: else return (use default handler that inserts open)
(pos, pos, Some(Tendril::from_char(open)))
// Since auto pairs are currently limited to single chars, we're either
// inserting exactly one or two chars. When arbitrary length pairs are
// added, these will need to be changed.
let change = match next_char {
Some(_) if !pair.should_close(doc, start_range) => {
len_inserted = 1;
let mut tendril = Tendril::new();
tendril.push(pair.open);
(cursor, cursor, Some(tendril))
}
// None | Some(ch) if close_before.contains(ch) => {}
_ => {
// insert open & close
let mut pair = Tendril::with_capacity(2);
pair.push_char(open);
pair.push_char(close);
offs += 2;
(pos, pos, Some(pair))
let pair_str = Tendril::from_iter([pair.open, pair.close]);
len_inserted = 2;
(cursor, cursor, Some(pair_str))
}
}
};
let next_range = get_next_range(doc, start_range, offs, len_inserted);
end_ranges.push(next_range);
offs += len_inserted;
change
});
transaction.with_selection(Selection::new(ranges, selection.primary_index()))
let t = transaction.with_selection(Selection::new(end_ranges, selection.primary_index()));
log::debug!("auto pair transaction: {:#?}", t);
t
}
fn handle_close(doc: &Rope, selection: &Selection, _open: char, close: char) -> Transaction {
let mut ranges = SmallVec::with_capacity(selection.len());
fn handle_close(doc: &Rope, selection: &Selection, pair: &Pair) -> Transaction {
let mut end_ranges = SmallVec::with_capacity(selection.len());
let mut offs = 0;
let transaction = Transaction::change_by_selection(doc, selection, |start_range| {
let cursor = start_range.cursor(doc.slice(..));
let next_char = doc.get_char(cursor);
let mut len_inserted = 0;
let change = if next_char == Some(pair.close) {
// return transaction that moves past close
(cursor, cursor, None) // no-op
} else {
len_inserted = 1;
let mut tendril = Tendril::new();
tendril.push(pair.close);
(cursor, cursor, Some(tendril))
};
let next_range = get_next_range(doc, start_range, offs, len_inserted);
end_ranges.push(next_range);
offs += len_inserted;
change
});
let t = transaction.with_selection(Selection::new(end_ranges, selection.primary_index()));
log::debug!("auto pair transaction: {:#?}", t);
t
}
/// handle cases where open and close is the same, or in triples ("""docstring""")
fn handle_same(doc: &Rope, selection: &Selection, pair: &Pair) -> Transaction {
let mut end_ranges = SmallVec::with_capacity(selection.len());
let mut offs = 0;
let transaction = Transaction::change_by_selection(doc, selection, |range| {
let pos = range.head;
let next = next_char(doc, pos);
let transaction = Transaction::change_by_selection(doc, selection, |start_range| {
let cursor = start_range.cursor(doc.slice(..));
let mut len_inserted = 0;
let next_char = doc.get_char(cursor);
let head = pos + offs + close.len_utf8();
// if selection, retain anchor, if cursor, move over
ranges.push(Range::new(
if range.is_empty() {
head
} else {
range.anchor + offs
},
head,
));
if next == Some(close) {
let change = if next_char == Some(pair.open) {
// return transaction that moves past close
(pos, pos, None) // no-op
(cursor, cursor, None) // no-op
} else {
offs += close.len_utf8();
let mut pair_str = Tendril::new();
pair_str.push(pair.open);
// TODO: else return (use default handler that inserts close)
(pos, pos, Some(Tendril::from_char(close)))
}
// for equal pairs, don't insert both open and close if either
// side has a non-pair char
if pair.should_close(doc, start_range) {
pair_str.push(pair.close);
}
len_inserted += pair_str.chars().count();
(cursor, cursor, Some(pair_str))
};
let next_range = get_next_range(doc, start_range, offs, len_inserted);
end_ranges.push(next_range);
offs += len_inserted;
change
});
transaction.with_selection(Selection::new(ranges, selection.primary_index()))
}
// handle cases where open and close is the same, or in triples ("""docstring""")
fn handle_same(_doc: &Rope, _selection: &Selection, _token: char) -> Option<Transaction> {
// if not cursor but selection, wrap
// let next = next char
// if next == bracket {
// // if start of syntax node, insert token twice (new pair because node is complete)
// // elseif colsedBracketAt
// // is_triple == allow triple && next 3 is equal
// // cursor jump over
// }
//} else if allow_triple && followed by triple {
//}
//} else if next != word char && prev != bracket && prev != word char {
// // condition checks for cases like I' where you don't want I'' (or I'm)
// insert pair ("")
//}
None
let t = transaction.with_selection(Selection::new(end_ranges, selection.primary_index()));
log::debug!("auto pair transaction: {:#?}", t);
t
}

View File

@@ -91,12 +91,14 @@ mod test {
#[test]
fn test_categorize() {
const EOL_TEST_CASE: &'static str = "\n\r\u{000B}\u{000C}\u{0085}\u{2028}\u{2029}";
const WORD_TEST_CASE: &'static str =
"_hello_world_あいうえおー1234567890";
const PUNCTUATION_TEST_CASE: &'static str =
#[cfg(not(feature = "unicode-lines"))]
const EOL_TEST_CASE: &str = "\n";
#[cfg(feature = "unicode-lines")]
const EOL_TEST_CASE: &str = "\n\u{000B}\u{000C}\u{0085}\u{2028}\u{2029}";
const WORD_TEST_CASE: &str = "_hello_world_あいうえおー1234567890";
const PUNCTUATION_TEST_CASE: &str =
"!\"#$%&\'()*+,-./:;<=>?@[\\]^`{|}~!”#$%&’()*+、。:;<=>?@「」^`{|}~";
const WHITESPACE_TEST_CASE: &'static str = "  ";
const WHITESPACE_TEST_CASE: &str = "  ";
for ch in EOL_TEST_CASE.chars() {
assert_eq!(CharCategory::Eol, categorize_char(ch));

View File

@@ -63,7 +63,7 @@ pub fn toggle_line_comments(doc: &Rope, selection: &Selection, token: Option<&st
let token = token.unwrap_or("//");
let comment = Tendril::from(format!("{} ", token));
let mut lines: Vec<usize> = Vec::new();
let mut lines: Vec<usize> = Vec::with_capacity(selection.len());
let mut min_next_line = 0;
for selection in selection {
@@ -72,7 +72,7 @@ pub fn toggle_line_comments(doc: &Rope, selection: &Selection, token: Option<&st
let end = (end + 1).min(text.len_lines());
lines.extend(start..end);
min_next_line = end + 1;
min_next_line = end;
}
let (commented, to_change, min, margin) = find_line_comment(token, text, lines);
@@ -100,43 +100,41 @@ mod test {
#[test]
fn test_find_line_comment() {
use crate::State;
// four lines, two space indented, except for line 1 which is blank.
let doc = Rope::from(" 1\n\n 2\n 3");
let mut state = State::new(doc);
let mut doc = Rope::from(" 1\n\n 2\n 3");
// select whole document
state.selection = Selection::single(0, state.doc.len_chars() - 1);
let mut selection = Selection::single(0, doc.len_chars() - 1);
let text = state.doc.slice(..);
let text = doc.slice(..);
let res = find_line_comment("//", text, 0..3);
// (commented = true, to_change = [line 0, line 2], min = col 2, margin = 1)
assert_eq!(res, (false, vec![0, 2], 2, 1));
// comment
let transaction = toggle_line_comments(&state.doc, &state.selection, None);
transaction.apply(&mut state.doc);
state.selection = state.selection.map(transaction.changes());
let transaction = toggle_line_comments(&doc, &selection, None);
transaction.apply(&mut doc);
selection = selection.map(transaction.changes());
assert_eq!(state.doc, " // 1\n\n // 2\n // 3");
assert_eq!(doc, " // 1\n\n // 2\n // 3");
// uncomment
let transaction = toggle_line_comments(&state.doc, &state.selection, None);
transaction.apply(&mut state.doc);
state.selection = state.selection.map(transaction.changes());
assert_eq!(state.doc, " 1\n\n 2\n 3");
let transaction = toggle_line_comments(&doc, &selection, None);
transaction.apply(&mut doc);
selection = selection.map(transaction.changes());
assert_eq!(doc, " 1\n\n 2\n 3");
assert!(selection.len() == 1); // to ignore the selection unused warning
// 0 margin comments
state.doc = Rope::from(" //1\n\n //2\n //3");
doc = Rope::from(" //1\n\n //2\n //3");
// reset the selection.
state.selection = Selection::single(0, state.doc.len_chars() - 1);
selection = Selection::single(0, doc.len_chars() - 1);
let transaction = toggle_line_comments(&state.doc, &state.selection, None);
transaction.apply(&mut state.doc);
state.selection = state.selection.map(transaction.changes());
assert_eq!(state.doc, " 1\n\n 2\n 3");
let transaction = toggle_line_comments(&doc, &selection, None);
transaction.apply(&mut doc);
selection = selection.map(transaction.changes());
assert_eq!(doc, " 1\n\n 2\n 3");
assert!(selection.len() == 1); // to ignore the selection unused warning
// TODO: account for uncommenting with uneven comment indentation
}

10
helix-core/src/config.rs Normal file
View File

@@ -0,0 +1,10 @@
/// Syntax configuration loader based on built-in languages.toml.
pub fn default_syntax_loader() -> crate::syntax::Configuration {
helix_loader::config::default_lang_config()
.try_into()
.expect("Could not serialize built-in languages.toml")
}
/// Syntax configuration loader based on user configured languages.toml.
pub fn user_syntax_loader() -> Result<crate::syntax::Configuration, toml::de::Error> {
helix_loader::config::user_lang_config()?.try_into()
}

View File

@@ -1,26 +1,49 @@
//! LSP diagnostic utility types.
use serde::{Deserialize, Serialize};
/// Describes the severity level of a [`Diagnostic`].
#[derive(Debug, Eq, PartialEq)]
#[derive(Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Deserialize, Serialize)]
pub enum Severity {
Error,
Warning,
Info,
Hint,
Info,
Warning,
Error,
}
impl Default for Severity {
fn default() -> Self {
Self::Hint
}
}
/// A range of `char`s within the text.
#[derive(Debug)]
#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq)]
pub struct Range {
pub start: usize,
pub end: usize,
}
#[derive(Debug, Eq, Hash, PartialEq, Clone, Deserialize, Serialize)]
pub enum NumberOrString {
Number(i32),
String(String),
}
#[derive(Debug, Clone)]
pub enum DiagnosticTag {
Unnecessary,
Deprecated,
}
/// Corresponds to [`lsp_types::Diagnostic`](https://docs.rs/lsp-types/0.91.0/lsp_types/struct.Diagnostic.html)
#[derive(Debug)]
#[derive(Debug, Clone)]
pub struct Diagnostic {
pub range: Range,
pub line: usize,
pub message: String,
pub severity: Option<Severity>,
pub code: Option<NumberOrString>,
pub tags: Vec<DiagnosticTag>,
pub source: Option<String>,
pub data: Option<serde_json::Value>,
}

View File

@@ -1,68 +1,221 @@
use crate::{Rope, Transaction};
use std::ops::Range;
use std::time::Instant;
use imara_diff::intern::InternedInput;
use imara_diff::Algorithm;
use ropey::RopeSlice;
use crate::{ChangeSet, Rope, Tendril, Transaction};
/// A `imara_diff::Sink` that builds a `ChangeSet` for a character diff of a hunk
struct CharChangeSetBuilder<'a> {
res: &'a mut ChangeSet,
hunk: &'a InternedInput<char>,
pos: u32,
}
impl imara_diff::Sink for CharChangeSetBuilder<'_> {
type Out = ();
fn process_change(&mut self, before: Range<u32>, after: Range<u32>) {
self.res.retain((before.start - self.pos) as usize);
self.res.delete(before.len());
self.pos = before.end;
let res = self.hunk.after[after.start as usize..after.end as usize]
.iter()
.map(|&token| self.hunk.interner[token])
.collect();
self.res.insert(res);
}
fn finish(self) -> Self::Out {
self.res.retain(self.hunk.before.len() - self.pos as usize);
}
}
struct LineChangeSetBuilder<'a> {
res: ChangeSet,
after: RopeSlice<'a>,
file: &'a InternedInput<RopeSlice<'a>>,
current_hunk: InternedInput<char>,
pos: u32,
}
impl imara_diff::Sink for LineChangeSetBuilder<'_> {
type Out = ChangeSet;
fn process_change(&mut self, before: Range<u32>, after: Range<u32>) {
let len = self.file.before[self.pos as usize..before.start as usize]
.iter()
.map(|&it| self.file.interner[it].len_chars())
.sum();
self.res.retain(len);
self.pos = before.end;
// do not perform diffs on large hunks
let len_before = before.end - before.start;
let len_after = after.end - after.start;
// Pure insertions/removals do not require a character diff.
// Very large changes are ignored because their character diff is expensive to compute
// TODO adjust heuristic to detect large changes?
if len_before == 0
|| len_after == 0
|| len_after > 5 * len_before
|| 5 * len_after < len_before && len_before > 10
|| len_before + len_after > 200
{
let remove = self.file.before[before.start as usize..before.end as usize]
.iter()
.map(|&it| self.file.interner[it].len_chars())
.sum();
self.res.delete(remove);
let mut fragment = Tendril::new();
if len_after > 500 {
// copying a rope line by line is slower then copying the entire
// rope. Use to_string for very large changes instead..
if self.file.after.len() == after.end as usize {
if after.start == 0 {
fragment = self.after.to_string().into();
} else {
let start = self.after.line_to_char(after.start as usize);
fragment = self.after.slice(start..).to_string().into();
}
} else if after.start == 0 {
let end = self.after.line_to_char(after.end as usize);
fragment = self.after.slice(..end).to_string().into();
} else {
let start = self.after.line_to_char(after.start as usize);
let end = self.after.line_to_char(after.end as usize);
fragment = self.after.slice(start..end).to_string().into();
}
} else {
for &line in &self.file.after[after.start as usize..after.end as usize] {
for chunk in self.file.interner[line].chunks() {
fragment.push_str(chunk)
}
}
};
self.res.insert(fragment);
} else {
// for reasonably small hunks, generating a ChangeSet from char diff can save memory
// TODO use a tokenizer (word diff?) for improved performance
let hunk_before = self.file.before[before.start as usize..before.end as usize]
.iter()
.flat_map(|&it| self.file.interner[it].chars());
let hunk_after = self.file.after[after.start as usize..after.end as usize]
.iter()
.flat_map(|&it| self.file.interner[it].chars());
self.current_hunk.update_before(hunk_before);
self.current_hunk.update_after(hunk_after);
// the histogram heuristic does not work as well
// for characters because the same characters often reoccur
// use myer diff instead
imara_diff::diff(
Algorithm::Myers,
&self.current_hunk,
CharChangeSetBuilder {
res: &mut self.res,
hunk: &self.current_hunk,
pos: 0,
},
);
self.current_hunk.clear();
}
}
fn finish(mut self) -> Self::Out {
let len = self.file.before[self.pos as usize..]
.iter()
.map(|&it| self.file.interner[it].len_chars())
.sum();
self.res.retain(len);
self.res
}
}
struct RopeLines<'a>(RopeSlice<'a>);
impl<'a> imara_diff::intern::TokenSource for RopeLines<'a> {
type Token = RopeSlice<'a>;
type Tokenizer = ropey::iter::Lines<'a>;
fn tokenize(&self) -> Self::Tokenizer {
self.0.lines()
}
fn estimate_tokens(&self) -> u32 {
// we can provide a perfect estimate which is very nice for performance
self.0.len_lines() as u32
}
}
/// Compares `old` and `new` to generate a [`Transaction`] describing
/// the steps required to get from `old` to `new`.
pub fn compare_ropes(old: &Rope, new: &Rope) -> Transaction {
// `similar` only works on contiguous data, so a `Rope` has
// to be temporarily converted into a `String`.
let old_converted = old.to_string();
let new_converted = new.to_string();
pub fn compare_ropes(before: &Rope, after: &Rope) -> Transaction {
let start = Instant::now();
let res = ChangeSet::with_capacity(32);
let after = after.slice(..);
let file = InternedInput::new(RopeLines(before.slice(..)), RopeLines(after));
let builder = LineChangeSetBuilder {
res,
file: &file,
after,
pos: 0,
current_hunk: InternedInput::default(),
};
// A timeout is set so after 1 seconds, the algorithm will start
// approximating. This is especially important for big `Rope`s or
// `Rope`s that are extremely dissimilar to each other.
//
// Note: Ignore the clippy warning, as the trait bounds of
// `Transaction::change()` require an iterator implementing
// `ExactIterator`.
let mut config = similar::TextDiff::configure();
config.timeout(std::time::Duration::from_secs(1));
let res = imara_diff::diff(Algorithm::Histogram, &file, builder).into();
let diff = config.diff_chars(&old_converted, &new_converted);
// The current position of the change needs to be tracked to
// construct the `Change`s.
let mut pos = 0;
Transaction::change(
old,
diff.ops()
.iter()
.map(|op| op.as_tag_tuple())
.filter_map(|(tag, old_range, new_range)| {
// `old_pos..pos` is equivalent to `start..end` for where
// the change should be applied.
let old_pos = pos;
pos += old_range.end - old_range.start;
match tag {
// Semantically, inserts and replacements are the same thing.
similar::DiffTag::Insert | similar::DiffTag::Replace => {
// This is the text from the `new` rope that should be
// inserted into `old`.
let text: &str = {
let start = new.char_to_byte(new_range.start);
let end = new.char_to_byte(new_range.end);
&new_converted[start..end]
};
Some((old_pos, pos, Some(text.into())))
}
similar::DiffTag::Delete => Some((old_pos, pos, None)),
similar::DiffTag::Equal => None,
}
}),
)
log::debug!(
"rope diff took {}s",
Instant::now().duration_since(start).as_secs_f64()
);
res
}
#[cfg(test)]
mod tests {
use super::*;
fn test_identity(a: &str, b: &str) {
let mut old = Rope::from(a);
let new = Rope::from(b);
compare_ropes(&old, &new).apply(&mut old);
assert_eq!(old, new);
}
quickcheck::quickcheck! {
fn test_compare_ropes(a: String, b: String) -> bool {
let mut old = Rope::from(a);
let new = Rope::from(b);
compare_ropes(&old, &new).apply(&mut old);
old.to_string() == new.to_string()
old == new
}
}
#[test]
fn equal_files() {
test_identity("foo", "foo");
}
#[test]
fn trailing_newline() {
test_identity("foo\n", "foo");
test_identity("foo", "foo\n");
}
#[test]
fn new_file() {
test_identity("", "foo");
}
#[test]
fn deleted_file() {
test_identity("foo", "");
}
}

View File

@@ -1,6 +1,6 @@
//! Utility functions to traverse the unicode graphemes of a `Rope`'s text contents.
//!
//! Based on https://github.com/cessen/led/blob/c4fa72405f510b7fd16052f90a598c429b3104a6/src/graphemes.rs
//! Based on <https://github.com/cessen/led/blob/c4fa72405f510b7fd16052f90a598c429b3104a6/src/graphemes.rs>
use ropey::{iter::Chunks, str_utils::byte_to_char_idx, RopeSlice};
use unicode_segmentation::{GraphemeCursor, GraphemeIncomplete};
use unicode_width::UnicodeWidthStr;
@@ -14,7 +14,7 @@ pub fn grapheme_width(g: &str) -> usize {
// Point 1: theoretically, ascii control characters should have zero
// width, but in our case we actually want them to have width: if they
// show up in text, we want to treat them as textual elements that can
// be editied. So we can get away with making all ascii single width
// be edited. So we can get away with making all ascii single width
// here.
// Point 2: we're only examining the first codepoint here, which means
// we're ignoring graphemes formed with combining characters. However,
@@ -120,6 +120,43 @@ pub fn nth_next_grapheme_boundary(slice: RopeSlice, char_idx: usize, n: usize) -
chunk_char_idx + tmp
}
#[must_use]
pub fn nth_next_grapheme_boundary_byte(slice: RopeSlice, mut byte_idx: usize, n: usize) -> usize {
// Bounds check
debug_assert!(byte_idx <= slice.len_bytes());
// Get the chunk with our byte index in it.
let (mut chunk, mut chunk_byte_idx, mut _chunk_char_idx, _) = slice.chunk_at_byte(byte_idx);
// Set up the grapheme cursor.
let mut gc = GraphemeCursor::new(byte_idx, slice.len_bytes(), true);
// Find the nth next grapheme cluster boundary.
for _ in 0..n {
loop {
match gc.next_boundary(chunk, chunk_byte_idx) {
Ok(None) => return slice.len_bytes(),
Ok(Some(n)) => {
byte_idx = n;
break;
}
Err(GraphemeIncomplete::NextChunk) => {
chunk_byte_idx += chunk.len();
let (a, _, _c, _) = slice.chunk_at_byte(chunk_byte_idx);
chunk = a;
// chunk_char_idx = c;
}
Err(GraphemeIncomplete::PreContext(n)) => {
let ctx_chunk = slice.chunk_at_byte(n - 1).0;
gc.provide_context(ctx_chunk, n - ctx_chunk.len());
}
_ => unreachable!(),
}
}
}
byte_idx
}
/// Finds the next grapheme boundary after the given char position.
#[must_use]
#[inline(always)]
@@ -127,6 +164,13 @@ pub fn next_grapheme_boundary(slice: RopeSlice, char_idx: usize) -> usize {
nth_next_grapheme_boundary(slice, char_idx, 1)
}
/// Finds the next grapheme boundary after the given byte position.
#[must_use]
#[inline(always)]
pub fn next_grapheme_boundary_byte(slice: RopeSlice, byte_idx: usize) -> usize {
nth_next_grapheme_boundary_byte(slice, byte_idx, 1)
}
/// Returns the passed char index if it's already a grapheme boundary,
/// or the next grapheme boundary char index if not.
#[must_use]
@@ -151,6 +195,23 @@ pub fn ensure_grapheme_boundary_prev(slice: RopeSlice, char_idx: usize) -> usize
}
}
/// Returns the passed byte index if it's already a grapheme boundary,
/// or the next grapheme boundary byte index if not.
#[must_use]
#[inline]
pub fn ensure_grapheme_boundary_next_byte(slice: RopeSlice, byte_idx: usize) -> usize {
if byte_idx == 0 {
byte_idx
} else {
// TODO: optimize so we're not constructing grapheme cursor twice
if is_grapheme_boundary_byte(slice, byte_idx) {
byte_idx
} else {
next_grapheme_boundary_byte(slice, byte_idx)
}
}
}
/// Returns whether the given char position is a grapheme boundary.
#[must_use]
pub fn is_grapheme_boundary(slice: RopeSlice, char_idx: usize) -> bool {
@@ -179,6 +240,31 @@ pub fn is_grapheme_boundary(slice: RopeSlice, char_idx: usize) -> bool {
}
}
/// Returns whether the given byte position is a grapheme boundary.
#[must_use]
pub fn is_grapheme_boundary_byte(slice: RopeSlice, byte_idx: usize) -> bool {
// Bounds check
debug_assert!(byte_idx <= slice.len_bytes());
// Get the chunk with our byte index in it.
let (chunk, chunk_byte_idx, _, _) = slice.chunk_at_byte(byte_idx);
// Set up the grapheme cursor.
let mut gc = GraphemeCursor::new(byte_idx, slice.len_bytes(), true);
// Determine if the given position is a grapheme cluster boundary.
loop {
match gc.is_boundary(chunk, chunk_byte_idx) {
Ok(n) => return n,
Err(GraphemeIncomplete::PreContext(n)) => {
let (ctx_chunk, ctx_byte_start, _, _) = slice.chunk_at_byte(n - 1);
gc.provide_context(ctx_chunk, ctx_byte_start);
}
Err(_) => unreachable!(),
}
}
}
/// An iterator over the graphemes of a `RopeSlice`.
#[derive(Clone)]
pub struct RopeGraphemes<'a> {
@@ -247,10 +333,7 @@ impl<'a> Iterator for RopeGraphemes<'a> {
}
if a < self.cur_chunk_start {
let a_char = self.text.byte_to_char(a);
let b_char = self.text.byte_to_char(b);
Some(self.text.slice(a_char..b_char))
Some(self.text.byte_slice(a..b))
} else {
let a2 = a - self.cur_chunk_start;
let b2 = b - self.cur_chunk_start;

View File

@@ -1,9 +1,15 @@
use crate::{ChangeSet, Rope, State, Transaction};
use crate::{Assoc, ChangeSet, Range, Rope, Selection, Transaction};
use once_cell::sync::Lazy;
use regex::Regex;
use std::num::NonZeroUsize;
use std::time::{Duration, Instant};
#[derive(Debug, Clone)]
pub struct State {
pub doc: Rope,
pub selection: Selection,
}
/// Stores the history of changes to a buffer.
///
/// Currently the history is represented as a vector of revisions. The vector
@@ -22,10 +28,10 @@ use std::time::{Duration, Instant};
///
/// The current revision is the one currently displayed in the buffer.
///
/// Commiting a new revision to the history will update the last child of the
/// Committing a new revision to the history will update the last child of the
/// current revision, and push a new revision to the end of the vector.
///
/// Revisions are commited with a timestamp. :earlier and :later can be used
/// Revisions are committed with a timestamp. :earlier and :later can be used
/// to jump to the closest revision to a moment in time relative to the timestamp
/// of the current revision plus (:later) or minus (:earlier) the duration
/// given to the command. If a single integer is given, the editor will instead
@@ -33,14 +39,14 @@ use std::time::{Duration, Instant};
///
/// Limitations:
/// * Changes in selections currently don't commit history changes. The selection
/// will only be updated to the state after a commited buffer change.
/// will only be updated to the state after a committed buffer change.
/// * The vector of history revisions is currently unbounded. This might
/// cause the memory consumption to grow significantly large during long
/// editing sessions.
/// * Because delete transactions currently don't store the text that they
/// delete, we also store an inversion of the transaction.
///
/// Using time to navigate the history: https://github.com/helix-editor/helix/pull/194
/// Using time to navigate the history: <https://github.com/helix-editor/helix/pull/194>
#[derive(Debug)]
pub struct History {
revisions: Vec<Revision>,
@@ -48,7 +54,7 @@ pub struct History {
}
/// A single point in history. See [History] for more information.
#[derive(Debug)]
#[derive(Debug, Clone)]
struct Revision {
parent: usize,
last_child: Option<NonZeroUsize>,
@@ -113,6 +119,21 @@ impl History {
self.current == 0
}
/// Returns the changes since the given revision composed into a transaction.
/// Returns None if there are no changes between the current and given revisions.
pub fn changes_since(&self, revision: usize) -> Option<Transaction> {
let lca = self.lowest_common_ancestor(revision, self.current);
let up = self.path_up(revision, lca);
let down = self.path_up(self.current, lca);
let up_txns = up
.iter()
.rev()
.map(|&n| self.revisions[n].inversion.clone());
let down_txns = down.iter().map(|&n| self.revisions[n].transaction.clone());
down_txns.chain(up_txns).reduce(|acc, tx| tx.compose(acc))
}
/// Undo the last edit.
pub fn undo(&mut self) -> Option<&Transaction> {
if self.at_root() {
@@ -133,6 +154,32 @@ impl History {
Some(&self.revisions[last_child.get()].transaction)
}
// Get the position of last change
pub fn last_edit_pos(&self) -> Option<usize> {
if self.current == 0 {
return None;
}
let current_revision = &self.revisions[self.current];
let primary_selection = current_revision
.inversion
.selection()
.expect("inversion always contains a selection")
.primary();
let (_from, to, _fragment) = current_revision
.transaction
.changes_iter()
// find a change that matches the primary selection
.find(|(from, to, _fragment)| Range::new(*from, *to).overlaps(&primary_selection))
// or use the first change
.or_else(|| current_revision.transaction.changes_iter().next())
.unwrap();
let pos = current_revision
.transaction
.changes()
.map_pos(to, Assoc::After);
Some(pos)
}
fn lowest_common_ancestor(&self, mut a: usize, mut b: usize) -> usize {
use std::collections::HashSet;
let mut a_path_set = HashSet::new();
@@ -151,7 +198,7 @@ impl History {
}
}
/// List of nodes on the way from `n` to 'a`. Doesn`t include `a`.
/// List of nodes on the way from `n` to 'a`. Doesn't include `a`.
/// Includes `n` unless `a == n`. `a` must be an ancestor of `n`.
fn path_up(&self, mut n: usize, a: usize) -> Vec<usize> {
let mut path = Vec::new();
@@ -256,13 +303,13 @@ impl History {
}
/// Whether to undo by a number of edits or a duration of time.
#[derive(Debug, PartialEq)]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum UndoKind {
Steps(usize),
TimePeriod(std::time::Duration),
}
/// A subset of sytemd.time time span syntax units.
/// A subset of systemd.time time span syntax units.
const TIME_UNITS: &[(&[&str], &str, u64)] = &[
(&["seconds", "second", "sec", "s"], "seconds", 1),
(&["minutes", "minute", "min", "m"], "minutes", 60),
@@ -340,12 +387,16 @@ impl std::str::FromStr for UndoKind {
#[cfg(test)]
mod test {
use super::*;
use crate::Selection;
#[test]
fn test_undo_redo() {
let mut history = History::default();
let doc = Rope::from("hello");
let mut state = State::new(doc);
let mut state = State {
doc,
selection: Selection::point(0),
};
let transaction1 =
Transaction::change(&state.doc, vec![(5, 5, Some(" world!".into()))].into_iter());
@@ -394,7 +445,10 @@ mod test {
fn test_earlier_later() {
let mut history = History::default();
let doc = Rope::from("a\n");
let mut state = State::new(doc);
let mut state = State {
doc,
selection: Selection::point(0),
};
fn undo(history: &mut History, state: &mut State) {
if let Some(transaction) = history.undo() {
@@ -422,8 +476,8 @@ mod test {
change: crate::transaction::Change,
instant: Instant,
) {
let txn = Transaction::change(&state.doc, vec![change.clone()].into_iter());
history.commit_revision_at_timestamp(&txn, &state, instant);
let txn = Transaction::change(&state.doc, vec![change].into_iter());
history.commit_revision_at_timestamp(&txn, state, instant);
txn.apply(&mut state.doc);
}
@@ -520,8 +574,8 @@ mod test {
// Units are validated.
assert_eq!(
"1 millenium".parse::<UndoKind>(),
Err("incorrect time unit: millenium".to_string())
"1 millennium".parse::<UndoKind>(),
Err("incorrect time unit: millennium".to_string())
);
// Units can't be specified twice.

View File

@@ -0,0 +1,491 @@
use chrono::{Datelike, Duration, NaiveDate, NaiveDateTime, NaiveTime, Timelike};
use once_cell::sync::Lazy;
use regex::Regex;
use ropey::RopeSlice;
use std::borrow::Cow;
use std::cmp;
use std::fmt::Write;
use super::Increment;
use crate::{Range, Tendril};
#[derive(Debug, PartialEq, Eq)]
pub struct DateTimeIncrementor {
date_time: NaiveDateTime,
range: Range,
fmt: &'static str,
field: DateField,
}
impl DateTimeIncrementor {
pub fn from_range(text: RopeSlice, range: Range) -> Option<DateTimeIncrementor> {
let range = if range.is_empty() {
if range.anchor < text.len_chars() {
// Treat empty range as a cursor range.
range.put_cursor(text, range.anchor + 1, true)
} else {
// The range is empty and at the end of the text.
return None;
}
} else {
range
};
FORMATS.iter().find_map(|format| {
let from = range.from().saturating_sub(format.max_len);
let to = (range.from() + format.max_len).min(text.len_chars());
let (from_in_text, to_in_text) = (range.from() - from, range.to() - from);
let text: Cow<str> = text.slice(from..to).into();
let captures = format.regex.captures(&text)?;
if captures.len() - 1 != format.fields.len() {
return None;
}
let date_time = captures.get(0)?;
let offset = range.from() - from_in_text;
let range = Range::new(date_time.start() + offset, date_time.end() + offset);
let field = captures
.iter()
.skip(1)
.enumerate()
.find_map(|(i, capture)| {
let capture = capture?;
let capture_range = capture.range();
if capture_range.contains(&from_in_text)
&& capture_range.contains(&(to_in_text - 1))
{
Some(format.fields[i])
} else {
None
}
})?;
let has_date = format.fields.iter().any(|f| f.unit.is_date());
let has_time = format.fields.iter().any(|f| f.unit.is_time());
let date_time = &text[date_time.start()..date_time.end()];
let date_time = match (has_date, has_time) {
(true, true) => NaiveDateTime::parse_from_str(date_time, format.fmt).ok()?,
(true, false) => {
let date = NaiveDate::parse_from_str(date_time, format.fmt).ok()?;
date.and_hms_opt(0, 0, 0).unwrap()
}
(false, true) => {
let time = NaiveTime::parse_from_str(date_time, format.fmt).ok()?;
NaiveDate::from_ymd_opt(0, 1, 1).unwrap().and_time(time)
}
(false, false) => return None,
};
Some(DateTimeIncrementor {
date_time,
range,
fmt: format.fmt,
field,
})
})
}
}
impl Increment for DateTimeIncrementor {
fn increment(&self, amount: i64) -> (Range, Tendril) {
let date_time = match self.field.unit {
DateUnit::Years => add_years(self.date_time, amount),
DateUnit::Months => add_months(self.date_time, amount),
DateUnit::Days => add_duration(self.date_time, Duration::days(amount)),
DateUnit::Hours => add_duration(self.date_time, Duration::hours(amount)),
DateUnit::Minutes => add_duration(self.date_time, Duration::minutes(amount)),
DateUnit::Seconds => add_duration(self.date_time, Duration::seconds(amount)),
DateUnit::AmPm => toggle_am_pm(self.date_time),
}
.unwrap_or(self.date_time);
(self.range, date_time.format(self.fmt).to_string().into())
}
}
static FORMATS: Lazy<Vec<Format>> = Lazy::new(|| {
vec![
Format::new("%Y-%m-%d %H:%M:%S"), // 2021-11-24 07:12:23
Format::new("%Y/%m/%d %H:%M:%S"), // 2021/11/24 07:12:23
Format::new("%Y-%m-%d %H:%M"), // 2021-11-24 07:12
Format::new("%Y/%m/%d %H:%M"), // 2021/11/24 07:12
Format::new("%Y-%m-%d"), // 2021-11-24
Format::new("%Y/%m/%d"), // 2021/11/24
Format::new("%a %b %d %Y"), // Wed Nov 24 2021
Format::new("%d-%b-%Y"), // 24-Nov-2021
Format::new("%Y %b %d"), // 2021 Nov 24
Format::new("%b %d, %Y"), // Nov 24, 2021
Format::new("%-I:%M:%S %P"), // 7:21:53 am
Format::new("%-I:%M %P"), // 7:21 am
Format::new("%-I:%M:%S %p"), // 7:21:53 AM
Format::new("%-I:%M %p"), // 7:21 AM
Format::new("%H:%M:%S"), // 23:24:23
Format::new("%H:%M"), // 23:24
]
});
#[derive(Debug)]
struct Format {
fmt: &'static str,
fields: Vec<DateField>,
regex: Regex,
max_len: usize,
}
impl Format {
fn new(fmt: &'static str) -> Self {
let mut remaining = fmt;
let mut fields = Vec::new();
let mut regex = String::new();
let mut max_len = 0;
while let Some(i) = remaining.find('%') {
let after = &remaining[i + 1..];
let mut chars = after.chars();
let c = chars.next().unwrap();
let spec_len = if c == '-' {
1 + chars.next().unwrap().len_utf8()
} else {
c.len_utf8()
};
let specifier = &after[..spec_len];
let field = DateField::from_specifier(specifier).unwrap();
fields.push(field);
max_len += field.max_len + remaining[..i].len();
regex += &remaining[..i];
write!(regex, "({})", field.regex).unwrap();
remaining = &after[spec_len..];
}
let regex = Regex::new(&regex).unwrap();
Self {
fmt,
fields,
regex,
max_len,
}
}
}
impl PartialEq for Format {
fn eq(&self, other: &Self) -> bool {
self.fmt == other.fmt && self.fields == other.fields && self.max_len == other.max_len
}
}
impl Eq for Format {}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
struct DateField {
regex: &'static str,
unit: DateUnit,
max_len: usize,
}
impl DateField {
fn from_specifier(specifier: &str) -> Option<Self> {
match specifier {
"Y" => Some(Self {
regex: r"\d{4}",
unit: DateUnit::Years,
max_len: 5,
}),
"y" => Some(Self {
regex: r"\d\d",
unit: DateUnit::Years,
max_len: 2,
}),
"m" => Some(Self {
regex: r"[0-1]\d",
unit: DateUnit::Months,
max_len: 2,
}),
"d" => Some(Self {
regex: r"[0-3]\d",
unit: DateUnit::Days,
max_len: 2,
}),
"-d" => Some(Self {
regex: r"[1-3]?\d",
unit: DateUnit::Days,
max_len: 2,
}),
"a" => Some(Self {
regex: r"Sun|Mon|Tue|Wed|Thu|Fri|Sat",
unit: DateUnit::Days,
max_len: 3,
}),
"A" => Some(Self {
regex: r"Sunday|Monday|Tuesday|Wednesday|Thursday|Friday|Saturday",
unit: DateUnit::Days,
max_len: 9,
}),
"b" | "h" => Some(Self {
regex: r"Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec",
unit: DateUnit::Months,
max_len: 3,
}),
"B" => Some(Self {
regex: r"January|February|March|April|May|June|July|August|September|October|November|December",
unit: DateUnit::Months,
max_len: 9,
}),
"H" => Some(Self {
regex: r"[0-2]\d",
unit: DateUnit::Hours,
max_len: 2,
}),
"M" => Some(Self {
regex: r"[0-5]\d",
unit: DateUnit::Minutes,
max_len: 2,
}),
"S" => Some(Self {
regex: r"[0-5]\d",
unit: DateUnit::Seconds,
max_len: 2,
}),
"I" => Some(Self {
regex: r"[0-1]\d",
unit: DateUnit::Hours,
max_len: 2,
}),
"-I" => Some(Self {
regex: r"1?\d",
unit: DateUnit::Hours,
max_len: 2,
}),
"P" => Some(Self {
regex: r"am|pm",
unit: DateUnit::AmPm,
max_len: 2,
}),
"p" => Some(Self {
regex: r"AM|PM",
unit: DateUnit::AmPm,
max_len: 2,
}),
_ => None,
}
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
enum DateUnit {
Years,
Months,
Days,
Hours,
Minutes,
Seconds,
AmPm,
}
impl DateUnit {
fn is_date(self) -> bool {
matches!(self, DateUnit::Years | DateUnit::Months | DateUnit::Days)
}
fn is_time(self) -> bool {
matches!(
self,
DateUnit::Hours | DateUnit::Minutes | DateUnit::Seconds
)
}
}
fn ndays_in_month(year: i32, month: u32) -> u32 {
// The first day of the next month...
let (y, m) = if month == 12 {
(year + 1, 1)
} else {
(year, month + 1)
};
let d = NaiveDate::from_ymd_opt(y, m, 1).unwrap();
// ...is preceded by the last day of the original month.
d.pred_opt().unwrap().day()
}
fn add_months(date_time: NaiveDateTime, amount: i64) -> Option<NaiveDateTime> {
let month = (date_time.month0() as i64).checked_add(amount)?;
let year = date_time.year() + i32::try_from(month / 12).ok()?;
let year = if month.is_negative() { year - 1 } else { year };
// Normalize month
let month = month % 12;
let month = if month.is_negative() {
month + 12
} else {
month
} as u32
+ 1;
let day = cmp::min(date_time.day(), ndays_in_month(year, month));
NaiveDate::from_ymd_opt(year, month, day).map(|date| date.and_time(date_time.time()))
}
fn add_years(date_time: NaiveDateTime, amount: i64) -> Option<NaiveDateTime> {
let year = i32::try_from((date_time.year() as i64).checked_add(amount)?).ok()?;
let ndays = ndays_in_month(year, date_time.month());
if date_time.day() > ndays {
NaiveDate::from_ymd_opt(year, date_time.month(), ndays)
.and_then(|date| date.succ_opt().map(|date| date.and_time(date_time.time())))
} else {
date_time.with_year(year)
}
}
fn add_duration(date_time: NaiveDateTime, duration: Duration) -> Option<NaiveDateTime> {
date_time.checked_add_signed(duration)
}
fn toggle_am_pm(date_time: NaiveDateTime) -> Option<NaiveDateTime> {
if date_time.hour() < 12 {
add_duration(date_time, Duration::hours(12))
} else {
add_duration(date_time, Duration::hours(-12))
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::Rope;
#[test]
fn test_increment_date_times() {
let tests = [
// (original, cursor, amount, expected)
("2020-02-28", 0, 1, "2021-02-28"),
("2020-02-29", 0, 1, "2021-03-01"),
("2020-01-31", 5, 1, "2020-02-29"),
("2020-01-20", 5, 1, "2020-02-20"),
("2021-01-01", 5, -1, "2020-12-01"),
("2021-01-31", 5, -2, "2020-11-30"),
("2020-02-28", 8, 1, "2020-02-29"),
("2021-02-28", 8, 1, "2021-03-01"),
("2021-02-28", 0, -1, "2020-02-28"),
("2021-03-01", 0, -1, "2020-03-01"),
("2020-02-29", 5, -1, "2020-01-29"),
("2020-02-20", 5, -1, "2020-01-20"),
("2020-02-29", 8, -1, "2020-02-28"),
("2021-03-01", 8, -1, "2021-02-28"),
("1980/12/21", 8, 100, "1981/03/31"),
("1980/12/21", 8, -100, "1980/09/12"),
("1980/12/21", 8, 1000, "1983/09/17"),
("1980/12/21", 8, -1000, "1978/03/27"),
("2021-11-24 07:12:23", 0, 1, "2022-11-24 07:12:23"),
("2021-11-24 07:12:23", 5, 1, "2021-12-24 07:12:23"),
("2021-11-24 07:12:23", 8, 1, "2021-11-25 07:12:23"),
("2021-11-24 07:12:23", 11, 1, "2021-11-24 08:12:23"),
("2021-11-24 07:12:23", 14, 1, "2021-11-24 07:13:23"),
("2021-11-24 07:12:23", 17, 1, "2021-11-24 07:12:24"),
("2021/11/24 07:12:23", 0, 1, "2022/11/24 07:12:23"),
("2021/11/24 07:12:23", 5, 1, "2021/12/24 07:12:23"),
("2021/11/24 07:12:23", 8, 1, "2021/11/25 07:12:23"),
("2021/11/24 07:12:23", 11, 1, "2021/11/24 08:12:23"),
("2021/11/24 07:12:23", 14, 1, "2021/11/24 07:13:23"),
("2021/11/24 07:12:23", 17, 1, "2021/11/24 07:12:24"),
("2021-11-24 07:12", 0, 1, "2022-11-24 07:12"),
("2021-11-24 07:12", 5, 1, "2021-12-24 07:12"),
("2021-11-24 07:12", 8, 1, "2021-11-25 07:12"),
("2021-11-24 07:12", 11, 1, "2021-11-24 08:12"),
("2021-11-24 07:12", 14, 1, "2021-11-24 07:13"),
("2021/11/24 07:12", 0, 1, "2022/11/24 07:12"),
("2021/11/24 07:12", 5, 1, "2021/12/24 07:12"),
("2021/11/24 07:12", 8, 1, "2021/11/25 07:12"),
("2021/11/24 07:12", 11, 1, "2021/11/24 08:12"),
("2021/11/24 07:12", 14, 1, "2021/11/24 07:13"),
("Wed Nov 24 2021", 0, 1, "Thu Nov 25 2021"),
("Wed Nov 24 2021", 4, 1, "Fri Dec 24 2021"),
("Wed Nov 24 2021", 8, 1, "Thu Nov 25 2021"),
("Wed Nov 24 2021", 11, 1, "Thu Nov 24 2022"),
("24-Nov-2021", 0, 1, "25-Nov-2021"),
("24-Nov-2021", 3, 1, "24-Dec-2021"),
("24-Nov-2021", 7, 1, "24-Nov-2022"),
("2021 Nov 24", 0, 1, "2022 Nov 24"),
("2021 Nov 24", 5, 1, "2021 Dec 24"),
("2021 Nov 24", 9, 1, "2021 Nov 25"),
("Nov 24, 2021", 0, 1, "Dec 24, 2021"),
("Nov 24, 2021", 4, 1, "Nov 25, 2021"),
("Nov 24, 2021", 8, 1, "Nov 24, 2022"),
("7:21:53 am", 0, 1, "8:21:53 am"),
("7:21:53 am", 3, 1, "7:22:53 am"),
("7:21:53 am", 5, 1, "7:21:54 am"),
("7:21:53 am", 8, 1, "7:21:53 pm"),
("7:21:53 AM", 0, 1, "8:21:53 AM"),
("7:21:53 AM", 3, 1, "7:22:53 AM"),
("7:21:53 AM", 5, 1, "7:21:54 AM"),
("7:21:53 AM", 8, 1, "7:21:53 PM"),
("7:21 am", 0, 1, "8:21 am"),
("7:21 am", 3, 1, "7:22 am"),
("7:21 am", 5, 1, "7:21 pm"),
("7:21 AM", 0, 1, "8:21 AM"),
("7:21 AM", 3, 1, "7:22 AM"),
("7:21 AM", 5, 1, "7:21 PM"),
("23:24:23", 1, 1, "00:24:23"),
("23:24:23", 3, 1, "23:25:23"),
("23:24:23", 6, 1, "23:24:24"),
("23:24", 1, 1, "00:24"),
("23:24", 3, 1, "23:25"),
];
for (original, cursor, amount, expected) in tests {
let rope = Rope::from_str(original);
let range = Range::new(cursor, cursor + 1);
assert_eq!(
DateTimeIncrementor::from_range(rope.slice(..), range)
.unwrap()
.increment(amount)
.1,
Tendril::from(expected)
);
}
}
#[test]
fn test_invalid_date_times() {
let tests = [
"0000-00-00",
"1980-2-21",
"1980-12-1",
"12345",
"2020-02-30",
"1999-12-32",
"19-12-32",
"1-2-3",
"0000/00/00",
"1980/2/21",
"1980/12/1",
"12345",
"2020/02/30",
"1999/12/32",
"19/12/32",
"1/2/3",
"123:456:789",
"11:61",
"2021-55-12 08:12:54",
];
for invalid in tests {
let rope = Rope::from_str(invalid);
let range = Range::new(0, 1);
assert_eq!(DateTimeIncrementor::from_range(rope.slice(..), range), None)
}
}
}

View File

@@ -0,0 +1,8 @@
pub mod date_time;
pub mod number;
use crate::{Range, Tendril};
pub trait Increment {
fn increment(&self, amount: i64) -> (Range, Tendril);
}

View File

@@ -0,0 +1,507 @@
use std::borrow::Cow;
use ropey::RopeSlice;
use super::Increment;
use crate::{
textobject::{textobject_word, TextObject},
Range, Tendril,
};
#[derive(Debug, PartialEq, Eq)]
pub struct NumberIncrementor<'a> {
value: i64,
radix: u32,
range: Range,
text: RopeSlice<'a>,
}
impl<'a> NumberIncrementor<'a> {
/// Return information about number under rang if there is one.
pub fn from_range(text: RopeSlice, range: Range) -> Option<NumberIncrementor> {
// If the cursor is on the minus sign of a number we want to get the word textobject to the
// right of it.
let range = if range.to() < text.len_chars()
&& range.to() - range.from() <= 1
&& text.char(range.from()) == '-'
{
Range::new(range.from() + 1, range.to() + 1)
} else {
range
};
let range = textobject_word(text, range, TextObject::Inside, 1, false);
// If there is a minus sign to the left of the word object, we want to include it in the range.
let range = if range.from() > 0 && text.char(range.from() - 1) == '-' {
range.extend(range.from() - 1, range.from())
} else {
range
};
let word: String = text
.slice(range.from()..range.to())
.chars()
.filter(|&c| c != '_')
.collect();
let (radix, prefixed) = if word.starts_with("0x") {
(16, true)
} else if word.starts_with("0o") {
(8, true)
} else if word.starts_with("0b") {
(2, true)
} else {
(10, false)
};
let number = if prefixed { &word[2..] } else { &word };
let value = i128::from_str_radix(number, radix).ok()?;
if (value.is_positive() && value.leading_zeros() < 64)
|| (value.is_negative() && value.leading_ones() < 64)
{
return None;
}
let value = value as i64;
Some(NumberIncrementor {
range,
value,
radix,
text,
})
}
}
impl<'a> Increment for NumberIncrementor<'a> {
fn increment(&self, amount: i64) -> (Range, Tendril) {
let old_text: Cow<str> = self.text.slice(self.range.from()..self.range.to()).into();
let old_length = old_text.len();
let new_value = self.value.wrapping_add(amount);
// Get separator indexes from right to left.
let separator_rtl_indexes: Vec<usize> = old_text
.chars()
.rev()
.enumerate()
.filter_map(|(i, c)| if c == '_' { Some(i) } else { None })
.collect();
let format_length = if self.radix == 10 {
match (self.value.is_negative(), new_value.is_negative()) {
(true, false) => old_length - 1,
(false, true) => old_length + 1,
_ => old_text.len(),
}
} else {
old_text.len() - 2
} - separator_rtl_indexes.len();
let mut new_text = match self.radix {
2 => format!("0b{:01$b}", new_value, format_length),
8 => format!("0o{:01$o}", new_value, format_length),
10 if old_text.starts_with('0') || old_text.starts_with("-0") => {
format!("{:01$}", new_value, format_length)
}
10 => format!("{}", new_value),
16 => {
let (lower_count, upper_count): (usize, usize) =
old_text.chars().skip(2).fold((0, 0), |(lower, upper), c| {
(
lower + usize::from(c.is_ascii_lowercase()),
upper + usize::from(c.is_ascii_uppercase()),
)
});
if upper_count > lower_count {
format!("0x{:01$X}", new_value, format_length)
} else {
format!("0x{:01$x}", new_value, format_length)
}
}
_ => unimplemented!("radix not supported: {}", self.radix),
};
// Add separators from original number.
for &rtl_index in &separator_rtl_indexes {
if rtl_index < new_text.len() {
let new_index = new_text.len() - rtl_index;
new_text.insert(new_index, '_');
}
}
// Add in additional separators if necessary.
if new_text.len() > old_length && !separator_rtl_indexes.is_empty() {
let spacing = match separator_rtl_indexes.as_slice() {
[.., b, a] => a - b - 1,
_ => separator_rtl_indexes[0],
};
let prefix_length = if self.radix == 10 { 0 } else { 2 };
if let Some(mut index) = new_text.find('_') {
while index - prefix_length > spacing {
index -= spacing;
new_text.insert(index, '_');
}
}
}
(self.range, new_text.into())
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::Rope;
#[test]
fn test_decimal_at_point() {
let rope = Rope::from_str("Test text 12345 more text.");
let range = Range::point(12);
assert_eq!(
NumberIncrementor::from_range(rope.slice(..), range),
Some(NumberIncrementor {
range: Range::new(10, 15),
value: 12345,
radix: 10,
text: rope.slice(..),
})
);
}
#[test]
fn test_uppercase_hexadecimal_at_point() {
let rope = Rope::from_str("Test text 0x123ABCDEF more text.");
let range = Range::point(12);
assert_eq!(
NumberIncrementor::from_range(rope.slice(..), range),
Some(NumberIncrementor {
range: Range::new(10, 21),
value: 0x123ABCDEF,
radix: 16,
text: rope.slice(..),
})
);
}
#[test]
fn test_lowercase_hexadecimal_at_point() {
let rope = Rope::from_str("Test text 0xfa3b4e more text.");
let range = Range::point(12);
assert_eq!(
NumberIncrementor::from_range(rope.slice(..), range),
Some(NumberIncrementor {
range: Range::new(10, 18),
value: 0xfa3b4e,
radix: 16,
text: rope.slice(..),
})
);
}
#[test]
fn test_octal_at_point() {
let rope = Rope::from_str("Test text 0o1074312 more text.");
let range = Range::point(12);
assert_eq!(
NumberIncrementor::from_range(rope.slice(..), range),
Some(NumberIncrementor {
range: Range::new(10, 19),
value: 0o1074312,
radix: 8,
text: rope.slice(..),
})
);
}
#[test]
fn test_binary_at_point() {
let rope = Rope::from_str("Test text 0b10111010010101 more text.");
let range = Range::point(12);
assert_eq!(
NumberIncrementor::from_range(rope.slice(..), range),
Some(NumberIncrementor {
range: Range::new(10, 26),
value: 0b10111010010101,
radix: 2,
text: rope.slice(..),
})
);
}
#[test]
fn test_negative_decimal_at_point() {
let rope = Rope::from_str("Test text -54321 more text.");
let range = Range::point(12);
assert_eq!(
NumberIncrementor::from_range(rope.slice(..), range),
Some(NumberIncrementor {
range: Range::new(10, 16),
value: -54321,
radix: 10,
text: rope.slice(..),
})
);
}
#[test]
fn test_decimal_with_leading_zeroes_at_point() {
let rope = Rope::from_str("Test text 000045326 more text.");
let range = Range::point(12);
assert_eq!(
NumberIncrementor::from_range(rope.slice(..), range),
Some(NumberIncrementor {
range: Range::new(10, 19),
value: 45326,
radix: 10,
text: rope.slice(..),
})
);
}
#[test]
fn test_negative_decimal_cursor_on_minus_sign() {
let rope = Rope::from_str("Test text -54321 more text.");
let range = Range::point(10);
assert_eq!(
NumberIncrementor::from_range(rope.slice(..), range),
Some(NumberIncrementor {
range: Range::new(10, 16),
value: -54321,
radix: 10,
text: rope.slice(..),
})
);
}
#[test]
fn test_number_under_range_start_of_rope() {
let rope = Rope::from_str("100");
let range = Range::point(0);
assert_eq!(
NumberIncrementor::from_range(rope.slice(..), range),
Some(NumberIncrementor {
range: Range::new(0, 3),
value: 100,
radix: 10,
text: rope.slice(..),
})
);
}
#[test]
fn test_number_under_range_end_of_rope() {
let rope = Rope::from_str("100");
let range = Range::point(2);
assert_eq!(
NumberIncrementor::from_range(rope.slice(..), range),
Some(NumberIncrementor {
range: Range::new(0, 3),
value: 100,
radix: 10,
text: rope.slice(..),
})
);
}
#[test]
fn test_number_surrounded_by_punctuation() {
let rope = Rope::from_str(",100;");
let range = Range::point(1);
assert_eq!(
NumberIncrementor::from_range(rope.slice(..), range),
Some(NumberIncrementor {
range: Range::new(1, 4),
value: 100,
radix: 10,
text: rope.slice(..),
})
);
}
#[test]
fn test_not_a_number_point() {
let rope = Rope::from_str("Test text 45326 more text.");
let range = Range::point(6);
assert_eq!(NumberIncrementor::from_range(rope.slice(..), range), None);
}
#[test]
fn test_number_too_large_at_point() {
let rope = Rope::from_str("Test text 0xFFFFFFFFFFFFFFFFF more text.");
let range = Range::point(12);
assert_eq!(NumberIncrementor::from_range(rope.slice(..), range), None);
}
#[test]
fn test_number_cursor_one_right_of_number() {
let rope = Rope::from_str("100 ");
let range = Range::point(3);
assert_eq!(NumberIncrementor::from_range(rope.slice(..), range), None);
}
#[test]
fn test_number_cursor_one_left_of_number() {
let rope = Rope::from_str(" 100");
let range = Range::point(0);
assert_eq!(NumberIncrementor::from_range(rope.slice(..), range), None);
}
#[test]
fn test_increment_basic_decimal_numbers() {
let tests = [
("100", 1, "101"),
("100", -1, "99"),
("99", 1, "100"),
("100", 1000, "1100"),
("100", -1000, "-900"),
("-1", 1, "0"),
("-1", 2, "1"),
("1", -1, "0"),
("1", -2, "-1"),
];
for (original, amount, expected) in tests {
let rope = Rope::from_str(original);
let range = Range::point(0);
assert_eq!(
NumberIncrementor::from_range(rope.slice(..), range)
.unwrap()
.increment(amount)
.1,
Tendril::from(expected)
);
}
}
#[test]
fn test_increment_basic_hexadecimal_numbers() {
let tests = [
("0x0100", 1, "0x0101"),
("0x0100", -1, "0x00ff"),
("0x0001", -1, "0x0000"),
("0x0000", -1, "0xffffffffffffffff"),
("0xffffffffffffffff", 1, "0x0000000000000000"),
("0xffffffffffffffff", 2, "0x0000000000000001"),
("0xffffffffffffffff", -1, "0xfffffffffffffffe"),
("0xABCDEF1234567890", 1, "0xABCDEF1234567891"),
("0xabcdef1234567890", 1, "0xabcdef1234567891"),
];
for (original, amount, expected) in tests {
let rope = Rope::from_str(original);
let range = Range::point(0);
assert_eq!(
NumberIncrementor::from_range(rope.slice(..), range)
.unwrap()
.increment(amount)
.1,
Tendril::from(expected)
);
}
}
#[test]
fn test_increment_basic_octal_numbers() {
let tests = [
("0o0107", 1, "0o0110"),
("0o0110", -1, "0o0107"),
("0o0001", -1, "0o0000"),
("0o7777", 1, "0o10000"),
("0o1000", -1, "0o0777"),
("0o0107", 10, "0o0121"),
("0o0000", -1, "0o1777777777777777777777"),
("0o1777777777777777777777", 1, "0o0000000000000000000000"),
("0o1777777777777777777777", 2, "0o0000000000000000000001"),
("0o1777777777777777777777", -1, "0o1777777777777777777776"),
];
for (original, amount, expected) in tests {
let rope = Rope::from_str(original);
let range = Range::point(0);
assert_eq!(
NumberIncrementor::from_range(rope.slice(..), range)
.unwrap()
.increment(amount)
.1,
Tendril::from(expected)
);
}
}
#[test]
fn test_increment_basic_binary_numbers() {
let tests = [
("0b00000100", 1, "0b00000101"),
("0b00000100", -1, "0b00000011"),
("0b00000100", 2, "0b00000110"),
("0b00000100", -2, "0b00000010"),
("0b00000001", -1, "0b00000000"),
("0b00111111", 10, "0b01001001"),
("0b11111111", 1, "0b100000000"),
("0b10000000", -1, "0b01111111"),
(
"0b0000",
-1,
"0b1111111111111111111111111111111111111111111111111111111111111111",
),
(
"0b1111111111111111111111111111111111111111111111111111111111111111",
1,
"0b0000000000000000000000000000000000000000000000000000000000000000",
),
(
"0b1111111111111111111111111111111111111111111111111111111111111111",
2,
"0b0000000000000000000000000000000000000000000000000000000000000001",
),
(
"0b1111111111111111111111111111111111111111111111111111111111111111",
-1,
"0b1111111111111111111111111111111111111111111111111111111111111110",
),
];
for (original, amount, expected) in tests {
let rope = Rope::from_str(original);
let range = Range::point(0);
assert_eq!(
NumberIncrementor::from_range(rope.slice(..), range)
.unwrap()
.increment(amount)
.1,
Tendril::from(expected)
);
}
}
#[test]
fn test_increment_with_separators() {
let tests = [
("999_999", 1, "1_000_000"),
("1_000_000", -1, "999_999"),
("-999_999", -1, "-1_000_000"),
("0x0000_0000_0001", 0x1_ffff_0000, "0x0001_ffff_0001"),
("0x0000_0000_0001", 0x1_ffff_0000, "0x0001_ffff_0001"),
("0x0000_0000_0001", 0x1_ffff_0000, "0x0001_ffff_0001"),
("0x0000_0000", -1, "0xffff_ffff_ffff_ffff"),
("0x0000_0000_0000", -1, "0xffff_ffff_ffff_ffff"),
("0b01111111_11111111", 1, "0b10000000_00000000"),
("0b11111111_11111111", 1, "0b1_00000000_00000000"),
];
for (original, amount, expected) in tests {
let rope = Rope::from_str(original);
let range = Range::point(0);
assert_eq!(
NumberIncrementor::from_range(rope.slice(..), range)
.unwrap()
.increment(amount)
.1,
Tendril::from(expected)
);
}
}
}

View File

@@ -1,7 +1,10 @@
use std::collections::HashMap;
use tree_sitter::{Query, QueryCursor, QueryPredicateArg};
use crate::{
chars::{char_is_line_ending, char_is_whitespace},
find_first_non_whitespace_char,
syntax::{IndentQuery, LanguageConfiguration, Syntax},
syntax::{LanguageConfiguration, RopeProvider, Syntax},
tree_sitter::Node,
Rope, RopeSlice,
};
@@ -174,8 +177,7 @@ pub fn auto_detect_indent_style(document_text: &Rope) -> Option<IndentStyle> {
/// To determine indentation of a newly inserted line, figure out the indentation at the last col
/// of the previous line.
#[allow(dead_code)]
fn indent_level_for_line(line: RopeSlice, tab_width: usize) -> usize {
pub fn indent_level_for_line(line: RopeSlice, tab_width: usize) -> usize {
let mut len = 0;
for ch in line.chars() {
match ch {
@@ -188,129 +190,544 @@ fn indent_level_for_line(line: RopeSlice, tab_width: usize) -> usize {
len / tab_width
}
/// Find the highest syntax node at position.
/// This is to identify the column where this node (e.g., an HTML closing tag) ends.
fn get_highest_syntax_node_at_bytepos(syntax: &Syntax, pos: usize) -> Option<Node> {
let tree = syntax.tree();
// named_descendant
let mut node = match tree.root_node().descendant_for_byte_range(pos, pos) {
Some(node) => node,
None => return None,
};
while let Some(parent) = node.parent() {
if parent.start_byte() == node.start_byte() {
node = parent
/// Computes for node and all ancestors whether they are the first node on their line.
/// The first entry in the return value represents the root node, the last one the node itself
fn get_first_in_line(mut node: Node, new_line_byte_pos: Option<usize>) -> Vec<bool> {
let mut first_in_line = Vec::new();
loop {
if let Some(prev) = node.prev_sibling() {
// If we insert a new line, the first node at/after the cursor is considered to be the first in its line
let first = prev.end_position().row != node.start_position().row
|| new_line_byte_pos.map_or(false, |byte_pos| {
node.start_byte() >= byte_pos && prev.start_byte() < byte_pos
});
first_in_line.push(Some(first));
} else {
// Nodes that have no previous siblings are first in their line if and only if their parent is
// (which we don't know yet)
first_in_line.push(None);
}
if let Some(parent) = node.parent() {
node = parent;
} else {
break;
}
}
Some(node)
}
fn calculate_indentation(query: &IndentQuery, node: Option<Node>, newline: bool) -> usize {
// NOTE: can't use contains() on query because of comparing Vec<String> and &str
// https://doc.rust-lang.org/std/vec/struct.Vec.html#method.contains
let mut increment: isize = 0;
let mut node = match node {
Some(node) => node,
None => return 0,
};
let mut prev_start = node.start_position().row;
// if we're calculating indentation for a brand new line then the current node will become the
// parent node. We need to take it's indentation level into account too.
let node_kind = node.kind();
if newline && query.indent.contains(node_kind) {
increment += 1;
}
while let Some(parent) = node.parent() {
let parent_kind = parent.kind();
let start = parent.start_position().row;
// detect deeply nested indents in the same line
// .map(|a| { <-- ({ is two scopes
// let len = 1; <-- indents one level
// }) <-- }) is two scopes
let starts_same_line = start == prev_start;
if query.outdent.contains(node.kind()) && !starts_same_line {
// we outdent by skipping the rules for the current level and jumping up
// node = parent;
increment -= 1;
// continue;
let mut result = Vec::with_capacity(first_in_line.len());
let mut parent_is_first = true; // The root node is by definition the first node in its line
for first in first_in_line.into_iter().rev() {
if let Some(first) = first {
result.push(first);
parent_is_first = first;
} else {
result.push(parent_is_first);
}
if query.indent.contains(parent_kind) // && not_first_or_last_sibling
&& !starts_same_line
{
// println!("is_scope {}", parent_kind);
prev_start = start;
increment += 1
}
// if last_scope && increment > 0 && ...{ ignore }
node = parent;
}
increment.max(0) as usize
result
}
#[allow(dead_code)]
fn suggested_indent_for_line(
language_config: &LanguageConfiguration,
syntax: Option<&Syntax>,
text: RopeSlice,
line_num: usize,
_tab_width: usize,
) -> usize {
if let Some(start) = find_first_non_whitespace_char(text.line(line_num)) {
return suggested_indent_for_pos(
Some(language_config),
syntax,
text,
start + text.line_to_char(line_num),
false,
);
};
// if the line is blank, indent should be zero
0
/// The total indent for some line of code.
/// This is usually constructed in one of 2 ways:
/// - Successively add indent captures to get the (added) indent from a single line
/// - Successively add the indent results for each line
#[derive(Default)]
pub struct Indentation {
/// The total indent (the number of indent levels) is defined as max(0, indent-outdent).
/// The string that this results in depends on the indent style (spaces or tabs, etc.)
indent: usize,
outdent: usize,
}
impl Indentation {
/// Add some other [Indentation] to this.
/// The added indent should be the total added indent from one line
fn add_line(&mut self, added: &Indentation) {
if added.indent > 0 && added.outdent == 0 {
self.indent += 1;
} else if added.outdent > 0 && added.indent == 0 {
self.outdent += 1;
}
}
/// Add an indent capture to this indent.
/// All the captures that are added in this way should be on the same line.
fn add_capture(&mut self, added: IndentCaptureType) {
match added {
IndentCaptureType::Indent => {
self.indent = 1;
}
IndentCaptureType::Outdent => {
self.outdent = 1;
}
}
}
fn as_string(&self, indent_style: &IndentStyle) -> String {
let indent_level = if self.indent >= self.outdent {
self.indent - self.outdent
} else {
log::warn!("Encountered more outdent than indent nodes while calculating indentation: {} outdent, {} indent", self.outdent, self.indent);
0
};
indent_style.as_str().repeat(indent_level)
}
}
// TODO: two usecases: if we are triggering this for a new, blank line:
// - it should return 0 when mass indenting stuff
// - it should look up the wrapper node and count it too when we press o/O
pub fn suggested_indent_for_pos(
language_config: Option<&LanguageConfiguration>,
syntax: Option<&Syntax>,
/// An indent definition which corresponds to a capture from the indent query
struct IndentCapture {
capture_type: IndentCaptureType,
scope: IndentScope,
}
#[derive(Clone, Copy)]
enum IndentCaptureType {
Indent,
Outdent,
}
impl IndentCaptureType {
fn default_scope(&self) -> IndentScope {
match self {
IndentCaptureType::Indent => IndentScope::Tail,
IndentCaptureType::Outdent => IndentScope::All,
}
}
}
/// This defines which part of a node an [IndentCapture] applies to.
/// Each [IndentCaptureType] has a default scope, but the scope can be changed
/// with `#set!` property declarations.
#[derive(Clone, Copy)]
enum IndentScope {
/// The indent applies to the whole node
All,
/// The indent applies to everything except for the first line of the node
Tail,
}
/// A capture from the indent query which does not define an indent but extends
/// the range of a node. This is used before the indent is calculated.
enum ExtendCapture {
Extend,
PreventOnce,
}
/// The result of running a tree-sitter indent query. This stores for
/// each node (identified by its ID) the relevant captures (already filtered
/// by predicates).
struct IndentQueryResult {
indent_captures: HashMap<usize, Vec<IndentCapture>>,
extend_captures: HashMap<usize, Vec<ExtendCapture>>,
}
fn query_indents(
query: &Query,
syntax: &Syntax,
cursor: &mut QueryCursor,
text: RopeSlice,
range: std::ops::Range<usize>,
// Position of the (optional) newly inserted line break.
// Given as (line, byte_pos)
new_line_break: Option<(usize, usize)>,
) -> IndentQueryResult {
let mut indent_captures: HashMap<usize, Vec<IndentCapture>> = HashMap::new();
let mut extend_captures: HashMap<usize, Vec<ExtendCapture>> = HashMap::new();
cursor.set_byte_range(range);
// Iterate over all captures from the query
for m in cursor.matches(query, syntax.tree().root_node(), RopeProvider(text)) {
// Skip matches where not all custom predicates are fulfilled
if !query.general_predicates(m.pattern_index).iter().all(|pred| {
match pred.operator.as_ref() {
"not-kind-eq?" => match (pred.args.get(0), pred.args.get(1)) {
(
Some(QueryPredicateArg::Capture(capture_idx)),
Some(QueryPredicateArg::String(kind)),
) => {
let node = m.nodes_for_capture_index(*capture_idx).next();
match node {
Some(node) => node.kind()!=kind.as_ref(),
_ => true,
}
}
_ => {
panic!("Invalid indent query: Arguments to \"not-kind-eq?\" must be a capture and a string");
}
},
"same-line?" | "not-same-line?" => {
match (pred.args.get(0), pred.args.get(1)) {
(
Some(QueryPredicateArg::Capture(capt1)),
Some(QueryPredicateArg::Capture(capt2))
) => {
let get_line_num = |node: Node| {
let mut node_line = node.start_position().row;
// Adjust for the new line that will be inserted
if let Some((line, byte)) = new_line_break {
if node_line==line && node.start_byte()>=byte {
node_line += 1;
}
}
node_line
};
let n1 = m.nodes_for_capture_index(*capt1).next();
let n2 = m.nodes_for_capture_index(*capt2).next();
match (n1, n2) {
(Some(n1), Some(n2)) => {
let same_line = get_line_num(n1)==get_line_num(n2);
same_line==(pred.operator.as_ref()=="same-line?")
}
_ => true,
}
}
_ => {
panic!("Invalid indent query: Arguments to \"{}\" must be 2 captures", pred.operator);
}
}
}
_ => {
panic!(
"Invalid indent query: Unknown predicate (\"{}\")",
pred.operator
);
}
}
}) {
continue;
}
for capture in m.captures {
let capture_name = query.capture_names()[capture.index as usize].as_str();
let capture_type = match capture_name {
"indent" => IndentCaptureType::Indent,
"outdent" => IndentCaptureType::Outdent,
"extend" => {
extend_captures
.entry(capture.node.id())
.or_insert_with(|| Vec::with_capacity(1))
.push(ExtendCapture::Extend);
continue;
}
"extend.prevent-once" => {
extend_captures
.entry(capture.node.id())
.or_insert_with(|| Vec::with_capacity(1))
.push(ExtendCapture::PreventOnce);
continue;
}
_ => {
// Ignore any unknown captures (these may be needed for predicates such as #match?)
continue;
}
};
let scope = capture_type.default_scope();
let mut indent_capture = IndentCapture {
capture_type,
scope,
};
// Apply additional settings for this capture
for property in query.property_settings(m.pattern_index) {
match property.key.as_ref() {
"scope" => {
indent_capture.scope = match property.value.as_deref() {
Some("all") => IndentScope::All,
Some("tail") => IndentScope::Tail,
Some(s) => {
panic!("Invalid indent query: Unknown value for \"scope\" property (\"{}\")", s);
}
None => {
panic!(
"Invalid indent query: Missing value for \"scope\" property"
);
}
}
}
_ => {
panic!(
"Invalid indent query: Unknown property \"{}\"",
property.key
);
}
}
}
indent_captures
.entry(capture.node.id())
// Most entries only need to contain a single IndentCapture
.or_insert_with(|| Vec::with_capacity(1))
.push(indent_capture);
}
}
IndentQueryResult {
indent_captures,
extend_captures,
}
}
/// Handle extend queries. deepest_preceding is the deepest descendant of node that directly precedes the cursor position.
/// Any ancestor of deepest_preceding which is also a descendant of node may be "extended". In that case, node will be updated,
/// so that the indent computation starts with the correct syntax node.
fn extend_nodes<'a>(
node: &mut Node<'a>,
mut deepest_preceding: Node<'a>,
extend_captures: &HashMap<usize, Vec<ExtendCapture>>,
text: RopeSlice,
line: usize,
tab_width: usize,
) {
let mut stop_extend = false;
while deepest_preceding != *node {
let mut extend_node = false;
// This will be set to true if this node is captured, regardless of whether
// it actually will be extended (e.g. because the cursor isn't indented
// more than the node).
let mut node_captured = false;
if let Some(captures) = extend_captures.get(&deepest_preceding.id()) {
for capture in captures {
match capture {
ExtendCapture::PreventOnce => {
stop_extend = true;
}
ExtendCapture::Extend => {
node_captured = true;
// We extend the node if
// - the cursor is on the same line as the end of the node OR
// - the line that the cursor is on is more indented than the
// first line of the node
if deepest_preceding.end_position().row == line {
extend_node = true;
} else {
let cursor_indent = indent_level_for_line(text.line(line), tab_width);
let node_indent = indent_level_for_line(
text.line(deepest_preceding.start_position().row),
tab_width,
);
if cursor_indent > node_indent {
extend_node = true;
}
}
}
}
}
}
// If we encountered some `StopExtend` capture before, we don't
// extend the node even if we otherwise would
if node_captured && stop_extend {
stop_extend = false;
} else if extend_node && !stop_extend {
*node = deepest_preceding;
break;
}
// If the tree contains a syntax error, `deepest_preceding` may not
// have a parent despite being a descendant of `node`.
deepest_preceding = match deepest_preceding.parent() {
Some(parent) => parent,
None => return,
}
}
}
/// Use the syntax tree to determine the indentation for a given position.
/// This can be used in 2 ways:
///
/// - To get the correct indentation for an existing line (new_line=false), not necessarily equal to the current indentation.
/// - In this case, pos should be inside the first tree-sitter node on that line.
/// In most cases, this can just be the first non-whitespace on that line.
/// - To get the indentation for a new line (new_line=true). This behaves like the first usecase if the part of the current line
/// after pos were moved to a new line.
///
/// The indentation is determined by traversing all the tree-sitter nodes containing the position.
/// Each of these nodes produces some [Indentation] for:
///
/// - The line of the (beginning of the) node. This is defined by the scope `all` if this is the first node on its line.
/// - The line after the node. This is defined by:
/// - The scope `tail`.
/// - The scope `all` if this node is not the first node on its line.
/// Intuitively, `all` applies to everything contained in this node while `tail` applies to everything except for the first line of the node.
/// The indents from different nodes for the same line are then combined.
/// The result [Indentation] is simply the sum of the [Indentation] for all lines.
///
/// Specifying which line exactly an [Indentation] applies to is important because indents on the same line combine differently than indents on different lines:
/// ```ignore
/// some_function(|| {
/// // Both the function parameters as well as the contained block should be indented.
/// // Because they are on the same line, this only yields one indent level
/// });
/// ```
///
/// ```ignore
/// some_function(
/// param1,
/// || {
/// // Here we get 2 indent levels because the 'parameters' and the 'block' node begin on different lines
/// },
/// );
/// ```
#[allow(clippy::too_many_arguments)]
pub fn treesitter_indent_for_pos(
query: &Query,
syntax: &Syntax,
indent_style: &IndentStyle,
tab_width: usize,
text: RopeSlice,
line: usize,
pos: usize,
new_line: bool,
) -> usize {
) -> Option<String> {
let byte_pos = text.char_to_byte(pos);
// The innermost tree-sitter node which is considered for the indent
// computation. It may change if some predeceding node is extended
let mut node = syntax
.tree()
.root_node()
.descendant_for_byte_range(byte_pos, byte_pos)?;
let (query_result, deepest_preceding) = {
// The query range should intersect with all nodes directly preceding
// the position of the indent query in case one of them is extended.
let mut deepest_preceding = None; // The deepest node preceding the indent query position
let mut tree_cursor = node.walk();
for child in node.children(&mut tree_cursor) {
if child.byte_range().end <= byte_pos {
deepest_preceding = Some(child);
}
}
deepest_preceding = deepest_preceding.map(|mut prec| {
// Get the deepest directly preceding node
while prec.child_count() > 0 {
prec = prec.child(prec.child_count() - 1).unwrap();
}
prec
});
let query_range = deepest_preceding
.map(|prec| prec.byte_range().end - 1..byte_pos + 1)
.unwrap_or(byte_pos..byte_pos + 1);
crate::syntax::PARSER.with(|ts_parser| {
let mut ts_parser = ts_parser.borrow_mut();
let mut cursor = ts_parser.cursors.pop().unwrap_or_else(QueryCursor::new);
let query_result = query_indents(
query,
syntax,
&mut cursor,
text,
query_range,
new_line.then(|| (line, byte_pos)),
);
ts_parser.cursors.push(cursor);
(query_result, deepest_preceding)
})
};
let indent_captures = query_result.indent_captures;
let extend_captures = query_result.extend_captures;
// Check for extend captures, potentially changing the node that the indent calculation starts with
if let Some(deepest_preceding) = deepest_preceding {
extend_nodes(
&mut node,
deepest_preceding,
&extend_captures,
text,
line,
tab_width,
);
}
let mut first_in_line = get_first_in_line(node, new_line.then(|| byte_pos));
let mut result = Indentation::default();
// We always keep track of all the indent changes on one line, in order to only indent once
// even if there are multiple "indent" nodes on the same line
let mut indent_for_line = Indentation::default();
let mut indent_for_line_below = Indentation::default();
loop {
// This can safely be unwrapped because `first_in_line` contains
// one entry for each ancestor of the node (which is what we iterate over)
let is_first = *first_in_line.last().unwrap();
// Apply all indent definitions for this node
if let Some(definitions) = indent_captures.get(&node.id()) {
for definition in definitions {
match definition.scope {
IndentScope::All => {
if is_first {
indent_for_line.add_capture(definition.capture_type);
} else {
indent_for_line_below.add_capture(definition.capture_type);
}
}
IndentScope::Tail => {
indent_for_line_below.add_capture(definition.capture_type);
}
}
}
}
if let Some(parent) = node.parent() {
let mut node_line = node.start_position().row;
let mut parent_line = parent.start_position().row;
if node_line == line && new_line {
// Also consider the line that will be inserted
if node.start_byte() >= byte_pos {
node_line += 1;
}
if parent.start_byte() >= byte_pos {
parent_line += 1;
}
};
if node_line != parent_line {
if node_line < line + (new_line as usize) {
// Don't add indent for the line below the line of the query
result.add_line(&indent_for_line_below);
}
if node_line == parent_line + 1 {
indent_for_line_below = indent_for_line;
} else {
result.add_line(&indent_for_line);
indent_for_line_below = Indentation::default();
}
indent_for_line = Indentation::default();
}
node = parent;
first_in_line.pop();
} else {
// Only add the indentation for the line below if that line
// is not after the line that the indentation is calculated for.
if (node.start_position().row < line)
|| (new_line && node.start_position().row == line && node.start_byte() < byte_pos)
{
result.add_line(&indent_for_line_below);
}
result.add_line(&indent_for_line);
break;
}
}
Some(result.as_string(indent_style))
}
/// Returns the indentation for a new line.
/// This is done either using treesitter, or if that's not available by copying the indentation from the current line
#[allow(clippy::too_many_arguments)]
pub fn indent_for_newline(
language_config: Option<&LanguageConfiguration>,
syntax: Option<&Syntax>,
indent_style: &IndentStyle,
tab_width: usize,
text: RopeSlice,
line_before: usize,
line_before_end_pos: usize,
current_line: usize,
) -> String {
if let (Some(query), Some(syntax)) = (
language_config.and_then(|config| config.indent_query()),
syntax,
) {
let byte_start = text.char_to_byte(pos);
let node = get_highest_syntax_node_at_bytepos(syntax, byte_start);
// let config = load indentation query config from Syntax(should contain language_config)
// TODO: special case for comments
// TODO: if preserve_leading_whitespace
calculate_indentation(query, node, new_line)
} else {
// TODO: heuristics for non-tree sitter grammars
0
if let Some(indent) = treesitter_indent_for_pos(
query,
syntax,
indent_style,
tab_width,
text,
line_before,
line_before_end_pos,
true,
) {
return indent;
};
}
let indent_level = indent_level_for_line(text.line(current_line), tab_width);
indent_style.as_str().repeat(indent_level)
}
pub fn get_scopes(syntax: Option<&Syntax>, text: RopeSlice, pos: usize) -> Vec<&'static str> {
@@ -354,141 +771,4 @@ mod test {
let line = Rope::from("\t \tfn new"); // 1 tab, 4 spaces, tab
assert_eq!(indent_level_for_line(line.slice(..), tab_width), 3);
}
#[test]
fn test_suggested_indent_for_line() {
let doc = Rope::from(
"
use std::{
io::{self, stdout, Stdout, Write},
path::PathBuf,
sync::Arc,
time::Duration,
}
mod test {
fn hello_world() {
1 + 1;
let does_indentation_work = 1;
let test_function = function_with_param(this_param,
that_param
);
let test_function = function_with_param(
this_param,
that_param
);
let test_function = function_with_proper_indent(param1,
param2,
);
let selection = Selection::new(
changes
.clone()
.map(|(start, end, text): (usize, usize, Option<Tendril>)| {
let len = text.map(|text| text.len()).unwrap() - 1; // minus newline
let pos = start + len;
Range::new(pos, pos)
})
.collect(),
0,
);
return;
}
}
impl<A, D> MyTrait<A, D> for YourType
where
A: TraitB + TraitC,
D: TraitE + TraitF,
{
}
#[test]
//
match test {
Some(a) => 1,
None => {
unimplemented!()
}
}
std::panic::set_hook(Box::new(move |info| {
hook(info);
}));
{ { {
1
}}}
pub fn change<I>(document: &Document, changes: I) -> Self
where
I: IntoIterator<Item = Change> + ExactSizeIterator,
{
[
1,
2,
3,
];
(
1,
2
);
true
}
",
);
let doc = Rope::from(doc);
use crate::syntax::{
Configuration, IndentationConfiguration, LanguageConfiguration, Loader,
};
use once_cell::sync::OnceCell;
let loader = Loader::new(Configuration {
language: vec![LanguageConfiguration {
scope: "source.rust".to_string(),
file_types: vec!["rs".to_string()],
language_id: "Rust".to_string(),
highlight_config: OnceCell::new(),
config: None,
//
injection_regex: None,
roots: vec![],
comment_token: None,
auto_format: false,
language_server: None,
indent: Some(IndentationConfiguration {
tab_width: 4,
unit: String::from(" "),
}),
indent_query: OnceCell::new(),
textobject_query: OnceCell::new(),
}],
});
// set runtime path so we can find the queries
let mut runtime = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
runtime.push("../runtime");
std::env::set_var("HELIX_RUNTIME", runtime.to_str().unwrap());
let language_config = loader.language_config_for_scope("source.rust").unwrap();
let highlight_config = language_config.highlight_config(&[]).unwrap();
let syntax = Syntax::new(&doc, highlight_config.clone());
let text = doc.slice(..);
let tab_width = 4;
for i in 0..doc.len_lines() {
let line = text.line(i);
let indent = indent_level_for_line(line, tab_width);
assert_eq!(
suggested_indent_for_line(&language_config, Some(&syntax), text, i, tab_width),
indent,
"line {}: {}",
i,
line
);
}
}
}

View File

@@ -1,10 +1,14 @@
pub use encoding_rs as encoding;
pub mod auto_pairs;
pub mod chars;
pub mod comment;
pub mod config;
pub mod diagnostic;
pub mod diff;
pub mod graphemes;
pub mod history;
pub mod increment;
pub mod indent;
pub mod line_ending;
pub mod macros;
@@ -16,11 +20,13 @@ mod position;
pub mod register;
pub mod search;
pub mod selection;
mod state;
pub mod shellwords;
pub mod surround;
pub mod syntax;
pub mod test;
pub mod textobject;
mod transaction;
pub mod wrap;
pub mod unicode {
pub use unicode_general_category as category;
@@ -28,14 +34,18 @@ pub mod unicode {
pub use unicode_width as width;
}
static RUNTIME_DIR: once_cell::sync::Lazy<std::path::PathBuf> =
once_cell::sync::Lazy::new(runtime_dir);
pub fn find_first_non_whitespace_char(line: RopeSlice) -> Option<usize> {
line.chars().position(|ch| !ch.is_whitespace())
}
pub fn find_root(root: Option<&str>) -> Option<std::path::PathBuf> {
/// Find project root.
///
/// Order of detection:
/// * Top-most folder containing a root marker in current git repository
/// * Git repository root if no marker detected
/// * Top-most folder containing a root marker if not git repository detected
/// * Current working directory as fallback
pub fn find_root(root: Option<&str>, root_markers: &[String]) -> std::path::PathBuf {
let current_dir = std::env::current_dir().expect("unable to determine current directory");
let root = match root {
@@ -47,159 +57,51 @@ pub fn find_root(root: Option<&str>) -> Option<std::path::PathBuf> {
current_dir.join(root)
}
}
None => current_dir,
None => current_dir.clone(),
};
let mut top_marker = None;
for ancestor in root.ancestors() {
// TODO: also use defined roots if git isn't found
if ancestor.join(".git").is_dir() {
return Some(ancestor.to_path_buf());
}
}
None
}
pub fn runtime_dir() -> std::path::PathBuf {
if let Ok(dir) = std::env::var("HELIX_RUNTIME") {
return dir.into();
}
const RT_DIR: &str = "runtime";
let conf_dir = config_dir().join(RT_DIR);
if conf_dir.exists() {
return conf_dir;
}
if let Ok(dir) = std::env::var("CARGO_MANIFEST_DIR") {
// this is the directory of the crate being run by cargo, we need the workspace path so we take the parent
return std::path::PathBuf::from(dir).parent().unwrap().join(RT_DIR);
}
// fallback to location of the executable being run
std::env::current_exe()
.ok()
.and_then(|path| path.parent().map(|path| path.to_path_buf().join(RT_DIR)))
.unwrap()
}
pub fn config_dir() -> std::path::PathBuf {
// TODO: allow env var override
let strategy = choose_base_strategy().expect("Unable to find the config directory!");
let mut path = strategy.config_dir();
path.push("helix");
path
}
pub fn cache_dir() -> std::path::PathBuf {
// TODO: allow env var override
let strategy = choose_base_strategy().expect("Unable to find the config directory!");
let mut path = strategy.cache_dir();
path.push("helix");
path
}
// right overrides left
pub fn merge_toml_values(left: toml::Value, right: toml::Value) -> toml::Value {
use toml::Value;
fn get_name(v: &Value) -> Option<&str> {
v.get("name").and_then(Value::as_str)
}
match (left, right) {
(Value::Array(mut left_items), Value::Array(right_items)) => {
left_items.reserve(right_items.len());
for rvalue in right_items {
let lvalue = get_name(&rvalue)
.and_then(|rname| left_items.iter().position(|v| get_name(v) == Some(rname)))
.map(|lpos| left_items.remove(lpos));
let mvalue = match lvalue {
Some(lvalue) => merge_toml_values(lvalue, rvalue),
None => rvalue,
};
left_items.push(mvalue);
}
Value::Array(left_items)
}
(Value::Table(mut left_map), Value::Table(right_map)) => {
for (rname, rvalue) in right_map {
match left_map.remove(&rname) {
Some(lvalue) => {
let merged_value = merge_toml_values(lvalue, rvalue);
left_map.insert(rname, merged_value);
}
None => {
left_map.insert(rname, rvalue);
}
}
}
Value::Table(left_map)
}
// Catch everything else we didn't handle, and use the right value
(_, value) => value,
}
}
#[cfg(test)]
mod merge_toml_tests {
use super::merge_toml_values;
#[test]
fn language_tomls() {
use toml::Value;
const USER: &str = "
[[language]]
name = \"nix\"
test = \"bbb\"
indent = { tab-width = 4, unit = \" \", test = \"aaa\" }
";
let base: Value = toml::from_slice(include_bytes!("../../languages.toml"))
.expect("Couldn't parse built-in langauges config");
let user: Value = toml::from_str(USER).unwrap();
let merged = merge_toml_values(base, user);
let languages = merged.get("language").unwrap().as_array().unwrap();
let nix = languages
if root_markers
.iter()
.find(|v| v.get("name").unwrap().as_str().unwrap() == "nix")
.unwrap();
let nix_indent = nix.get("indent").unwrap();
.any(|marker| ancestor.join(marker).exists())
{
top_marker = Some(ancestor);
}
// We changed tab-width and unit in indent so check them if they are the new values
assert_eq!(
nix_indent.get("tab-width").unwrap().as_integer().unwrap(),
4
);
assert_eq!(nix_indent.get("unit").unwrap().as_str().unwrap(), " ");
// We added a new keys, so check them
assert_eq!(nix.get("test").unwrap().as_str().unwrap(), "bbb");
assert_eq!(nix_indent.get("test").unwrap().as_str().unwrap(), "aaa");
// We didn't change comment-token so it should be same
assert_eq!(nix.get("comment-token").unwrap().as_str().unwrap(), "#");
if ancestor.join(".git").exists() {
// Top marker is repo root if not root marker was detected yet
if top_marker.is_none() {
top_marker = Some(ancestor);
}
// Don't go higher than repo if we're in one
break;
}
}
// Return the found top marker or the current_dir as fallback
top_marker.map_or(current_dir, |a| a.to_path_buf())
}
pub use etcetera::home_dir;
pub use ropey::{self, str_utils, Rope, RopeBuilder, RopeSlice};
use etcetera::base_strategy::{choose_base_strategy, BaseStrategy};
// pub use tendril::StrTendril as Tendril;
pub use smartstring::SmartString;
pub use ropey::{Rope, RopeBuilder, RopeSlice};
pub use tendril::StrTendril as Tendril;
pub type Tendril = SmartString<smartstring::LazyCompact>;
#[doc(inline)]
pub use {regex, tree_sitter};
pub use graphemes::RopeGraphemes;
pub use position::{coords_at_pos, pos_at_coords, Position};
pub use position::{
coords_at_pos, pos_at_coords, pos_at_visual_coords, visual_coords_at_pos, Position,
};
pub use selection::{Range, Selection};
pub use smallvec::SmallVec;
pub use smallvec::{smallvec, SmallVec};
pub use syntax::Syntax;
pub use diagnostic::Diagnostic;
pub use state::State;
pub use line_ending::{LineEnding, DEFAULT_LINE_ENDING};
pub use transaction::{Assoc, Change, ChangeSet, Operation, Transaction};

View File

@@ -6,16 +6,22 @@ pub const DEFAULT_LINE_ENDING: LineEnding = LineEnding::Crlf;
pub const DEFAULT_LINE_ENDING: LineEnding = LineEnding::LF;
/// Represents one of the valid Unicode line endings.
#[derive(PartialEq, Copy, Clone, Debug)]
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
pub enum LineEnding {
Crlf, // CarriageReturn followed by LineFeed
LF, // U+000A -- LineFeed
VT, // U+000B -- VerticalTab
FF, // U+000C -- FormFeed
CR, // U+000D -- CarriageReturn
Nel, // U+0085 -- NextLine
LS, // U+2028 -- Line Separator
PS, // U+2029 -- ParagraphSeparator
#[cfg(feature = "unicode-lines")]
VT, // U+000B -- VerticalTab
#[cfg(feature = "unicode-lines")]
FF, // U+000C -- FormFeed
#[cfg(feature = "unicode-lines")]
CR, // U+000D -- CarriageReturn
#[cfg(feature = "unicode-lines")]
Nel, // U+0085 -- NextLine
#[cfg(feature = "unicode-lines")]
LS, // U+2028 -- Line Separator
#[cfg(feature = "unicode-lines")]
PS, // U+2029 -- ParagraphSeparator
}
impl LineEnding {
@@ -32,11 +38,17 @@ impl LineEnding {
match self {
Self::Crlf => "\u{000D}\u{000A}",
Self::LF => "\u{000A}",
#[cfg(feature = "unicode-lines")]
Self::VT => "\u{000B}",
#[cfg(feature = "unicode-lines")]
Self::FF => "\u{000C}",
#[cfg(feature = "unicode-lines")]
Self::CR => "\u{000D}",
#[cfg(feature = "unicode-lines")]
Self::Nel => "\u{0085}",
#[cfg(feature = "unicode-lines")]
Self::LS => "\u{2028}",
#[cfg(feature = "unicode-lines")]
Self::PS => "\u{2029}",
}
}
@@ -45,11 +57,17 @@ impl LineEnding {
pub const fn from_char(ch: char) -> Option<LineEnding> {
match ch {
'\u{000A}' => Some(LineEnding::LF),
#[cfg(feature = "unicode-lines")]
'\u{000B}' => Some(LineEnding::VT),
#[cfg(feature = "unicode-lines")]
'\u{000C}' => Some(LineEnding::FF),
#[cfg(feature = "unicode-lines")]
'\u{000D}' => Some(LineEnding::CR),
#[cfg(feature = "unicode-lines")]
'\u{0085}' => Some(LineEnding::Nel),
#[cfg(feature = "unicode-lines")]
'\u{2028}' => Some(LineEnding::LS),
#[cfg(feature = "unicode-lines")]
'\u{2029}' => Some(LineEnding::PS),
// Not a line ending
_ => None,
@@ -65,11 +83,17 @@ impl LineEnding {
match g {
"\u{000D}\u{000A}" => Some(LineEnding::Crlf),
"\u{000A}" => Some(LineEnding::LF),
#[cfg(feature = "unicode-lines")]
"\u{000B}" => Some(LineEnding::VT),
#[cfg(feature = "unicode-lines")]
"\u{000C}" => Some(LineEnding::FF),
#[cfg(feature = "unicode-lines")]
"\u{000D}" => Some(LineEnding::CR),
#[cfg(feature = "unicode-lines")]
"\u{0085}" => Some(LineEnding::Nel),
#[cfg(feature = "unicode-lines")]
"\u{2028}" => Some(LineEnding::LS),
#[cfg(feature = "unicode-lines")]
"\u{2029}" => Some(LineEnding::PS),
// Not a line ending
_ => None,
@@ -95,13 +119,20 @@ pub fn str_is_line_ending(s: &str) -> bool {
LineEnding::from_str(s).is_some()
}
#[inline]
pub fn rope_is_line_ending(r: RopeSlice) -> bool {
r.chunks().all(str_is_line_ending)
}
/// Attempts to detect what line ending the passed document uses.
pub fn auto_detect_line_ending(doc: &Rope) -> Option<LineEnding> {
// Return first matched line ending. Not all possible line endings
// are being matched, as they might be special-use only
for line in doc.lines().take(100) {
match get_line_ending(&line) {
None | Some(LineEnding::VT) | Some(LineEnding::FF) | Some(LineEnding::PS) => {}
None => {}
#[cfg(feature = "unicode-lines")]
Some(LineEnding::VT) | Some(LineEnding::FF) | Some(LineEnding::PS) => {}
ending => return ending,
}
}
@@ -128,6 +159,19 @@ pub fn get_line_ending(line: &RopeSlice) -> Option<LineEnding> {
LineEnding::from_str(g2).or_else(|| LineEnding::from_str(g1))
}
#[cfg(not(feature = "unicode-lines"))]
/// Returns the passed line's line ending, if any.
pub fn get_line_ending_of_str(line: &str) -> Option<LineEnding> {
if line.ends_with("\u{000D}\u{000A}") {
Some(LineEnding::Crlf)
} else if line.ends_with('\u{000A}') {
Some(LineEnding::LF)
} else {
None
}
}
#[cfg(feature = "unicode-lines")]
/// Returns the passed line's line ending, if any.
pub fn get_line_ending_of_str(line: &str) -> Option<LineEnding> {
if line.ends_with("\u{000D}\u{000A}") {
@@ -211,6 +255,7 @@ mod line_ending_tests {
#[test]
fn str_to_line_ending() {
#[cfg(feature = "unicode-lines")]
assert_eq!(LineEnding::from_str("\r"), Some(LineEnding::CR));
assert_eq!(LineEnding::from_str("\n"), Some(LineEnding::LF));
assert_eq!(LineEnding::from_str("\r\n"), Some(LineEnding::Crlf));
@@ -220,6 +265,7 @@ mod line_ending_tests {
#[test]
fn rope_slice_to_line_ending() {
let r = Rope::from_str("hello\r\n");
#[cfg(feature = "unicode-lines")]
assert_eq!(
LineEnding::from_rope_slice(&r.slice(5..6)),
Some(LineEnding::CR)
@@ -238,6 +284,7 @@ mod line_ending_tests {
#[test]
fn get_line_ending_rope_slice() {
let r = Rope::from_str("Hello\rworld\nhow\r\nare you?");
#[cfg(feature = "unicode-lines")]
assert_eq!(get_line_ending(&r.slice(..6)), Some(LineEnding::CR));
assert_eq!(get_line_ending(&r.slice(..12)), Some(LineEnding::LF));
assert_eq!(get_line_ending(&r.slice(..17)), Some(LineEnding::Crlf));
@@ -247,19 +294,28 @@ mod line_ending_tests {
#[test]
fn get_line_ending_str() {
let text = "Hello\rworld\nhow\r\nare you?";
#[cfg(feature = "unicode-lines")]
assert_eq!(get_line_ending_of_str(&text[..6]), Some(LineEnding::CR));
assert_eq!(get_line_ending_of_str(&text[..12]), Some(LineEnding::LF));
assert_eq!(get_line_ending_of_str(&text[..17]), Some(LineEnding::Crlf));
assert_eq!(get_line_ending_of_str(&text[..]), None);
assert_eq!(get_line_ending_of_str(text), None);
}
#[test]
fn line_end_char_index_rope_slice() {
let r = Rope::from_str("Hello\rworld\nhow\r\nare you?");
let s = &r.slice(..);
assert_eq!(line_end_char_index(s, 0), 5);
assert_eq!(line_end_char_index(s, 1), 11);
assert_eq!(line_end_char_index(s, 2), 15);
assert_eq!(line_end_char_index(s, 3), 25);
#[cfg(not(feature = "unicode-lines"))]
{
assert_eq!(line_end_char_index(s, 0), 11);
assert_eq!(line_end_char_index(s, 1), 15);
assert_eq!(line_end_char_index(s, 2), 25);
}
#[cfg(feature = "unicode-lines")]
{
assert_eq!(line_end_char_index(s, 0), 5);
assert_eq!(line_end_char_index(s, 1), 11);
assert_eq!(line_end_char_index(s, 2), 15);
}
}
}

View File

@@ -1,48 +1,92 @@
use tree_sitter::Node;
use crate::{Rope, Syntax};
const PAIRS: &[(char, char)] = &[('(', ')'), ('{', '}'), ('[', ']'), ('<', '>')];
// limit matching pairs to only ( ) { } [ ] < >
const PAIRS: &[(char, char)] = &[
('(', ')'),
('{', '}'),
('[', ']'),
('<', '>'),
('\'', '\''),
('\"', '\"'),
];
// limit matching pairs to only ( ) { } [ ] < > ' ' " "
// Returns the position of the matching bracket under cursor.
//
// If the cursor is one the opening bracket, the position of
// the closing bracket is returned. If the cursor in the closing
// bracket, the position of the opening bracket is returned.
//
// If the cursor is not on a bracket, `None` is returned.
#[must_use]
pub fn find(syntax: &Syntax, doc: &Rope, pos: usize) -> Option<usize> {
let tree = syntax.tree();
let byte_pos = doc.char_to_byte(pos);
// most naive implementation: find the innermost syntax node, if we're at the edge of a node,
// return the other edge.
let node = match tree
.root_node()
.named_descendant_for_byte_range(byte_pos, byte_pos)
{
Some(node) => node,
None => return None,
};
if node.is_error() {
pub fn find_matching_bracket(syntax: &Syntax, doc: &Rope, pos: usize) -> Option<usize> {
if pos >= doc.len_chars() || !is_valid_bracket(doc.char(pos)) {
return None;
}
find_pair(syntax, doc, pos, false)
}
// Returns the position of the bracket that is closing the current scope.
//
// If the cursor is on an opening or closing bracket, the function
// behaves equivalent to [`find_matching_bracket`].
//
// If the cursor position is within a scope, the function searches
// for the surrounding scope that is surrounded by brackets and
// returns the position of the closing bracket for that scope.
//
// If no surrounding scope is found, the function returns `None`.
#[must_use]
pub fn find_matching_bracket_fuzzy(syntax: &Syntax, doc: &Rope, pos: usize) -> Option<usize> {
find_pair(syntax, doc, pos, true)
}
fn find_pair(syntax: &Syntax, doc: &Rope, pos: usize, traverse_parents: bool) -> Option<usize> {
let tree = syntax.tree();
let pos = doc.char_to_byte(pos);
let mut node = tree.root_node().named_descendant_for_byte_range(pos, pos)?;
loop {
let (start_byte, end_byte) = surrounding_bytes(doc, &node)?;
let (start_char, end_char) = (doc.byte_to_char(start_byte), doc.byte_to_char(end_byte));
if is_valid_pair(doc, start_char, end_char) {
if end_byte == pos {
return Some(start_char);
}
// We return the end char if the cursor is either on the start char
// or at some arbitrary position between start and end char.
return Some(end_char);
}
if traverse_parents {
node = node.parent()?;
} else {
return None;
}
}
}
fn is_valid_bracket(c: char) -> bool {
PAIRS.iter().any(|(l, r)| *l == c || *r == c)
}
fn is_valid_pair(doc: &Rope, start_char: usize, end_char: usize) -> bool {
PAIRS.contains(&(doc.char(start_char), doc.char(end_char)))
}
fn surrounding_bytes(doc: &Rope, node: &Node) -> Option<(usize, usize)> {
let len = doc.len_bytes();
let start_byte = node.start_byte();
let end_byte = node.end_byte().saturating_sub(1); // it's end exclusive
let end_byte = node.end_byte().saturating_sub(1);
if start_byte >= len || end_byte >= len {
return None;
}
let start_char = doc.byte_to_char(start_byte);
let end_char = doc.byte_to_char(end_byte);
if PAIRS.contains(&(doc.char(start_char), doc.char(end_char))) {
if start_byte == byte_pos {
return Some(end_char);
}
if end_byte == byte_pos {
return Some(start_char);
}
}
None
Some((start_byte, end_byte))
}

View File

@@ -1,15 +1,19 @@
use std::iter;
use ropey::iter::Chars;
use tree_sitter::{Node, QueryCursor};
use crate::{
chars::{categorize_char, char_is_line_ending, CharCategory},
coords_at_pos,
graphemes::{
next_grapheme_boundary, nth_next_grapheme_boundary, nth_prev_grapheme_boundary,
prev_grapheme_boundary,
},
pos_at_coords, Position, Range, RopeSlice,
line_ending::rope_is_line_ending,
pos_at_visual_coords,
syntax::LanguageConfiguration,
textobject::TextObject,
visual_coords_at_pos, Position, Range, RopeSlice,
};
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
@@ -30,6 +34,7 @@ pub fn move_horizontally(
dir: Direction,
count: usize,
behaviour: Movement,
_: usize,
) -> Range {
let pos = range.cursor(slice);
@@ -49,11 +54,12 @@ pub fn move_vertically(
dir: Direction,
count: usize,
behaviour: Movement,
tab_width: usize,
) -> Range {
let pos = range.cursor(slice);
// Compute the current position's 2d coordinates.
let Position { row, col } = coords_at_pos(slice, pos);
let Position { row, col } = visual_coords_at_pos(slice, pos, tab_width);
let horiz = range.horiz.unwrap_or(col as u32);
// Compute the new position.
@@ -62,7 +68,7 @@ pub fn move_vertically(
Direction::Backward => row.saturating_sub(count),
};
let new_col = col.max(horiz as usize);
let new_pos = pos_at_coords(slice, Position::new(new_row, new_col), true);
let new_pos = pos_at_visual_coords(slice, Position::new(new_row, new_col), tab_width);
// Special-case to avoid moving to the end of the last non-empty line.
if behaviour == Movement::Extend && slice.line(new_row).len_chars() == 0 {
@@ -141,6 +147,88 @@ fn word_move(slice: RopeSlice, range: Range, count: usize, target: WordMotionTar
})
}
pub fn move_prev_paragraph(
slice: RopeSlice,
range: Range,
count: usize,
behavior: Movement,
) -> Range {
let mut line = range.cursor_line(slice);
let first_char = slice.line_to_char(line) == range.cursor(slice);
let prev_line_empty = rope_is_line_ending(slice.line(line.saturating_sub(1)));
let curr_line_empty = rope_is_line_ending(slice.line(line));
let prev_empty_to_line = prev_line_empty && !curr_line_empty;
// skip character before paragraph boundary
if prev_empty_to_line && !first_char {
line += 1;
}
let mut lines = slice.lines_at(line);
lines.reverse();
let mut lines = lines.map(rope_is_line_ending).peekable();
for _ in 0..count {
while lines.next_if(|&e| e).is_some() {
line -= 1;
}
while lines.next_if(|&e| !e).is_some() {
line -= 1;
}
}
let head = slice.line_to_char(line);
let anchor = if behavior == Movement::Move {
// exclude first character after paragraph boundary
if prev_empty_to_line && first_char {
range.cursor(slice)
} else {
range.head
}
} else {
range.put_cursor(slice, head, true).anchor
};
Range::new(anchor, head)
}
pub fn move_next_paragraph(
slice: RopeSlice,
range: Range,
count: usize,
behavior: Movement,
) -> Range {
let mut line = range.cursor_line(slice);
let last_char =
prev_grapheme_boundary(slice, slice.line_to_char(line + 1)) == range.cursor(slice);
let curr_line_empty = rope_is_line_ending(slice.line(line));
let next_line_empty =
rope_is_line_ending(slice.line(slice.len_lines().saturating_sub(1).min(line + 1)));
let curr_empty_to_line = curr_line_empty && !next_line_empty;
// skip character after paragraph boundary
if curr_empty_to_line && last_char {
line += 1;
}
let mut lines = slice.lines_at(line).map(rope_is_line_ending).peekable();
for _ in 0..count {
while lines.next_if(|&e| !e).is_some() {
line += 1;
}
while lines.next_if(|&e| e).is_some() {
line += 1;
}
}
let head = slice.line_to_char(line);
let anchor = if behavior == Movement::Move {
if curr_empty_to_line && last_char {
range.head
} else {
range.cursor(slice)
}
} else {
range.put_cursor(slice, head, true).anchor
};
Range::new(anchor, head)
}
// ---- util ------------
#[inline]
@@ -164,7 +252,7 @@ pub fn backwards_skip_while<F>(slice: RopeSlice, pos: usize, fun: F) -> Option<u
where
F: Fn(char) -> bool,
{
let mut chars_starting_from_next = slice.chars_at(pos + 1);
let mut chars_starting_from_next = slice.chars_at(pos);
let mut backwards = iter::from_fn(|| chars_starting_from_next.prev()).enumerate();
backwards.find_map(|(i, c)| {
if !fun(c) {
@@ -182,7 +270,7 @@ pub enum WordMotionTarget {
NextWordEnd,
PrevWordStart,
PrevWordEnd,
// A "Long word" (also known as a WORD in vim/kakoune) is strictly
// A "Long word" (also known as a WORD in Vim/Kakoune) is strictly
// delimited by whitespace, and can consist of punctuation as well
// as alphanumerics.
NextLongWordStart,
@@ -301,12 +389,64 @@ fn reached_target(target: WordMotionTarget, prev_ch: char, next_ch: char) -> boo
}
}
/// Finds the range of the next or previous textobject in the syntax sub-tree of `node`.
/// Returns the range in the forwards direction.
pub fn goto_treesitter_object(
slice: RopeSlice,
range: Range,
object_name: &str,
dir: Direction,
slice_tree: Node,
lang_config: &LanguageConfiguration,
count: usize,
) -> Range {
let get_range = move |range: Range| -> Option<Range> {
let byte_pos = slice.char_to_byte(range.cursor(slice));
let cap_name = |t: TextObject| format!("{}.{}", object_name, t);
let mut cursor = QueryCursor::new();
let nodes = lang_config.textobject_query()?.capture_nodes_any(
&[
&cap_name(TextObject::Movement),
&cap_name(TextObject::Around),
&cap_name(TextObject::Inside),
],
slice_tree,
slice,
&mut cursor,
)?;
let node = match dir {
Direction::Forward => nodes
.filter(|n| n.start_byte() > byte_pos)
.min_by_key(|n| n.start_byte())?,
Direction::Backward => nodes
.filter(|n| n.end_byte() < byte_pos)
.max_by_key(|n| n.end_byte())?,
};
let len = slice.len_bytes();
let start_byte = node.start_byte();
let end_byte = node.end_byte();
if start_byte >= len || end_byte >= len {
return None;
}
let start_char = slice.byte_to_char(start_byte);
let end_char = slice.byte_to_char(end_byte);
// head of range should be at beginning
Some(Range::new(start_char, end_char))
};
(0..count).fold(range, |range, _| get_range(range).unwrap_or(range))
}
#[cfg(test)]
mod test {
use std::array::{self, IntoIter};
use ropey::Rope;
use crate::{coords_at_pos, pos_at_coords};
use super::*;
const SINGLE_LINE_SAMPLE: &str = "This is a simple alphabetic line";
@@ -333,7 +473,7 @@ mod test {
assert_eq!(
coords_at_pos(
slice,
move_vertically(slice, range, Direction::Forward, 1, Movement::Move).head
move_vertically(slice, range, Direction::Forward, 1, Movement::Move, 4).head
),
(1, 3).into()
);
@@ -356,8 +496,8 @@ mod test {
((Direction::Backward, 999usize), (0, 0)), // |This is a simple alphabetic line
];
for ((direction, amount), coordinates) in IntoIter::new(moves_and_expected_coordinates) {
range = move_horizontally(slice, range, direction, amount, Movement::Move);
for ((direction, amount), coordinates) in moves_and_expected_coordinates {
range = move_horizontally(slice, range, direction, amount, Movement::Move, 0);
assert_eq!(coords_at_pos(slice, range.head), coordinates.into())
}
}
@@ -370,7 +510,7 @@ mod test {
let mut range = Range::point(position);
let moves_and_expected_coordinates = IntoIter::new([
let moves_and_expected_coordinates = [
((Direction::Forward, 11usize), (1, 1)), // Multiline\nt|ext sample\n...
((Direction::Backward, 1usize), (1, 0)), // Multiline\n|text sample\n...
((Direction::Backward, 5usize), (0, 5)), // Multi|line\ntext sample\n...
@@ -380,10 +520,10 @@ mod test {
((Direction::Backward, 0usize), (0, 3)), // Mul|tiline\ntext sample\n...
((Direction::Forward, 999usize), (5, 0)), // ...and whitespaced\n|
((Direction::Forward, 999usize), (5, 0)), // ...and whitespaced\n|
]);
];
for ((direction, amount), coordinates) in moves_and_expected_coordinates {
range = move_horizontally(slice, range, direction, amount, Movement::Move);
range = move_horizontally(slice, range, direction, amount, Movement::Move, 0);
assert_eq!(coords_at_pos(slice, range.head), coordinates.into());
assert_eq!(range.head, range.anchor);
}
@@ -398,14 +538,14 @@ mod test {
let mut range = Range::point(position);
let original_anchor = range.anchor;
let moves = IntoIter::new([
let moves = [
(Direction::Forward, 1usize),
(Direction::Forward, 5usize),
(Direction::Backward, 3usize),
]);
];
for (direction, amount) in moves {
range = move_horizontally(slice, range, direction, amount, Movement::Extend);
range = move_horizontally(slice, range, direction, amount, Movement::Extend, 0);
assert_eq!(range.anchor, original_anchor);
}
}
@@ -416,7 +556,7 @@ mod test {
let slice = text.slice(..);
let position = pos_at_coords(slice, (0, 0).into(), true);
let mut range = Range::point(position);
let moves_and_expected_coordinates = IntoIter::new([
let moves_and_expected_coordinates = [
((Direction::Forward, 1usize), (1, 0)),
((Direction::Forward, 2usize), (3, 0)),
((Direction::Forward, 1usize), (4, 0)),
@@ -426,10 +566,10 @@ mod test {
((Direction::Backward, 0usize), (4, 0)),
((Direction::Forward, 5), (5, 0)),
((Direction::Forward, 999usize), (5, 0)),
]);
];
for ((direction, amount), coordinates) in moves_and_expected_coordinates {
range = move_vertically(slice, range, direction, amount, Movement::Move);
range = move_vertically(slice, range, direction, amount, Movement::Move, 4);
assert_eq!(coords_at_pos(slice, range.head), coordinates.into());
assert_eq!(range.head, range.anchor);
}
@@ -446,7 +586,7 @@ mod test {
H,
V,
}
let moves_and_expected_coordinates = IntoIter::new([
let moves_and_expected_coordinates = [
// Places cursor at the end of line
((Axis::H, Direction::Forward, 8usize), (0, 8)),
// First descent preserves column as the target line is wider
@@ -459,12 +599,12 @@ mod test {
((Axis::V, Direction::Backward, 999usize), (0, 8)),
((Axis::V, Direction::Forward, 4usize), (4, 8)),
((Axis::V, Direction::Forward, 999usize), (5, 0)),
]);
];
for ((axis, direction, amount), coordinates) in moves_and_expected_coordinates {
range = match axis {
Axis::H => move_horizontally(slice, range, direction, amount, Movement::Move),
Axis::V => move_vertically(slice, range, direction, amount, Movement::Move),
Axis::H => move_horizontally(slice, range, direction, amount, Movement::Move, 0),
Axis::V => move_vertically(slice, range, direction, amount, Movement::Move, 4),
};
assert_eq!(coords_at_pos(slice, range.head), coordinates.into());
assert_eq!(range.head, range.anchor);
@@ -485,21 +625,21 @@ mod test {
H,
V,
}
let moves_and_expected_coordinates = IntoIter::new([
let moves_and_expected_coordinates = [
// Places cursor at the fourth kana.
((Axis::H, Direction::Forward, 4), (0, 4)),
// Descent places cursor at the 4th character.
((Axis::V, Direction::Forward, 1usize), (1, 4)),
// Moving back 1 character.
((Axis::H, Direction::Backward, 1usize), (1, 3)),
// Descent places cursor at the 8th character.
((Axis::V, Direction::Forward, 1usize), (1, 8)),
// Moving back 2 characters.
((Axis::H, Direction::Backward, 2usize), (1, 6)),
// Jumping back up 1 line.
((Axis::V, Direction::Backward, 1usize), (0, 3)),
]);
];
for ((axis, direction, amount), coordinates) in moves_and_expected_coordinates {
range = match axis {
Axis::H => move_horizontally(slice, range, direction, amount, Movement::Move),
Axis::V => move_vertically(slice, range, direction, amount, Movement::Move),
Axis::H => move_horizontally(slice, range, direction, amount, Movement::Move, 0),
Axis::V => move_vertically(slice, range, direction, amount, Movement::Move, 4),
};
assert_eq!(coords_at_pos(slice, range.head), coordinates.into());
assert_eq!(range.head, range.anchor);
@@ -526,7 +666,7 @@ mod test {
#[test]
fn test_behaviour_when_moving_to_start_of_next_words() {
let tests = array::IntoIter::new([
let tests = [
("Basic forward motion stops at the first space",
vec![(1, Range::new(0, 0), Range::new(0, 6))]),
(" Starting from a boundary advances the anchor",
@@ -600,7 +740,7 @@ mod test {
vec![
(1, Range::new(0, 0), Range::new(0, 6)),
]),
]);
];
for (sample, scenario) in tests {
for (count, begin, expected_end) in scenario.into_iter() {
@@ -612,7 +752,7 @@ mod test {
#[test]
fn test_behaviour_when_moving_to_start_of_next_long_words() {
let tests = array::IntoIter::new([
let tests = [
("Basic forward motion stops at the first space",
vec![(1, Range::new(0, 0), Range::new(0, 6))]),
(" Starting from a boundary advances the anchor",
@@ -684,7 +824,7 @@ mod test {
vec![
(1, Range::new(0, 0), Range::new(0, 8)),
]),
]);
];
for (sample, scenario) in tests {
for (count, begin, expected_end) in scenario.into_iter() {
@@ -696,7 +836,7 @@ mod test {
#[test]
fn test_behaviour_when_moving_to_start_of_previous_words() {
let tests = array::IntoIter::new([
let tests = [
("Basic backward motion from the middle of a word",
vec![(1, Range::new(3, 3), Range::new(4, 0))]),
@@ -769,7 +909,7 @@ mod test {
vec![
(1, Range::new(0, 6), Range::new(6, 0)),
]),
]);
];
for (sample, scenario) in tests {
for (count, begin, expected_end) in scenario.into_iter() {
@@ -781,7 +921,7 @@ mod test {
#[test]
fn test_behaviour_when_moving_to_start_of_previous_long_words() {
let tests = array::IntoIter::new([
let tests = [
(
"Basic backward motion from the middle of a word",
vec![(1, Range::new(3, 3), Range::new(4, 0))],
@@ -866,7 +1006,7 @@ mod test {
vec![
(1, Range::new(0, 8), Range::new(8, 0)),
]),
]);
];
for (sample, scenario) in tests {
for (count, begin, expected_end) in scenario.into_iter() {
@@ -878,7 +1018,7 @@ mod test {
#[test]
fn test_behaviour_when_moving_to_end_of_next_words() {
let tests = array::IntoIter::new([
let tests = [
("Basic forward motion from the start of a word to the end of it",
vec![(1, Range::new(0, 0), Range::new(0, 5))]),
("Basic forward motion from the end of a word to the end of the next",
@@ -950,7 +1090,7 @@ mod test {
vec![
(1, Range::new(0, 0), Range::new(0, 5)),
]),
]);
];
for (sample, scenario) in tests {
for (count, begin, expected_end) in scenario.into_iter() {
@@ -962,7 +1102,7 @@ mod test {
#[test]
fn test_behaviour_when_moving_to_end_of_previous_words() {
let tests = array::IntoIter::new([
let tests = [
("Basic backward motion from the middle of a word",
vec![(1, Range::new(9, 9), Range::new(10, 5))]),
("Starting from after boundary retreats the anchor",
@@ -1032,7 +1172,7 @@ mod test {
vec![
(1, Range::new(0, 10), Range::new(10, 4)),
]),
]);
];
for (sample, scenario) in tests {
for (count, begin, expected_end) in scenario.into_iter() {
@@ -1044,7 +1184,7 @@ mod test {
#[test]
fn test_behaviour_when_moving_to_end_of_next_long_words() {
let tests = array::IntoIter::new([
let tests = [
("Basic forward motion from the start of a word to the end of it",
vec![(1, Range::new(0, 0), Range::new(0, 5))]),
("Basic forward motion from the end of a word to the end of the next",
@@ -1114,7 +1254,7 @@ mod test {
vec![
(1, Range::new(0, 0), Range::new(0, 7)),
]),
]);
];
for (sample, scenario) in tests {
for (count, begin, expected_end) in scenario.into_iter() {
@@ -1123,4 +1263,172 @@ mod test {
}
}
}
#[test]
fn test_behaviour_when_moving_to_prev_paragraph_single() {
let tests = [
("#[|]#", "#[|]#"),
("#[s|]#tart at\nfirst char\n", "#[|s]#tart at\nfirst char\n"),
("start at\nlast char#[\n|]#", "#[|start at\nlast char\n]#"),
(
"goto\nfirst\n\n#[p|]#aragraph",
"#[|goto\nfirst\n\n]#paragraph",
),
(
"goto\nfirst\n#[\n|]#paragraph",
"#[|goto\nfirst\n\n]#paragraph",
),
(
"goto\nsecond\n\np#[a|]#ragraph",
"goto\nsecond\n\n#[|pa]#ragraph",
),
(
"here\n\nhave\nmultiple\nparagraph\n\n\n\n\n#[|]#",
"here\n\n#[|have\nmultiple\nparagraph\n\n\n\n\n]#",
),
];
for (before, expected) in tests {
let (s, selection) = crate::test::print(before);
let text = Rope::from(s.as_str());
let selection =
selection.transform(|r| move_prev_paragraph(text.slice(..), r, 1, Movement::Move));
let actual = crate::test::plain(&s, selection);
assert_eq!(actual, expected, "\nbefore: `{:?}`", before);
}
}
#[test]
fn test_behaviour_when_moving_to_prev_paragraph_double() {
let tests = [
(
"on#[e|]#\n\ntwo\n\nthree\n\n",
"#[|one]#\n\ntwo\n\nthree\n\n",
),
(
"one\n\ntwo\n\nth#[r|]#ee\n\n",
"one\n\n#[|two\n\nthr]#ee\n\n",
),
];
for (before, expected) in tests {
let (s, selection) = crate::test::print(before);
let text = Rope::from(s.as_str());
let selection =
selection.transform(|r| move_prev_paragraph(text.slice(..), r, 2, Movement::Move));
let actual = crate::test::plain(&s, selection);
assert_eq!(actual, expected, "\nbefore: `{:?}`", before);
}
}
#[test]
fn test_behaviour_when_moving_to_prev_paragraph_extend() {
let tests = [
(
"one\n\n#[|two\n\n]#three\n\n",
"#[|one\n\ntwo\n\n]#three\n\n",
),
(
"#[|one\n\ntwo\n\n]#three\n\n",
"#[|one\n\ntwo\n\n]#three\n\n",
),
];
for (before, expected) in tests {
let (s, selection) = crate::test::print(before);
let text = Rope::from(s.as_str());
let selection = selection
.transform(|r| move_prev_paragraph(text.slice(..), r, 1, Movement::Extend));
let actual = crate::test::plain(&s, selection);
assert_eq!(actual, expected, "\nbefore: `{:?}`", before);
}
}
#[test]
fn test_behaviour_when_moving_to_next_paragraph_single() {
let tests = [
("#[|]#", "#[|]#"),
("#[s|]#tart at\nfirst char\n", "#[start at\nfirst char\n|]#"),
("start at\nlast char#[\n|]#", "start at\nlast char#[\n|]#"),
(
"a\nb\n\n#[g|]#oto\nthird\n\nparagraph",
"a\nb\n\n#[goto\nthird\n\n|]#paragraph",
),
(
"a\nb\n#[\n|]#goto\nthird\n\nparagraph",
"a\nb\n\n#[goto\nthird\n\n|]#paragraph",
),
(
"a\nb#[\n|]#\ngoto\nsecond\n\nparagraph",
"a\nb#[\n\n|]#goto\nsecond\n\nparagraph",
),
(
"here\n\nhave\n#[m|]#ultiple\nparagraph\n\n\n\n\n",
"here\n\nhave\n#[multiple\nparagraph\n\n\n\n\n|]#",
),
(
"#[t|]#ext\n\n\nafter two blank lines\n\nmore text\n",
"#[text\n\n\n|]#after two blank lines\n\nmore text\n",
),
(
"#[text\n\n\n|]#after two blank lines\n\nmore text\n",
"text\n\n\n#[after two blank lines\n\n|]#more text\n",
),
];
for (before, expected) in tests {
let (s, selection) = crate::test::print(before);
let text = Rope::from(s.as_str());
let selection =
selection.transform(|r| move_next_paragraph(text.slice(..), r, 1, Movement::Move));
let actual = crate::test::plain(&s, selection);
assert_eq!(actual, expected, "\nbefore: `{:?}`", before);
}
}
#[test]
fn test_behaviour_when_moving_to_next_paragraph_double() {
let tests = [
(
"one\n\ntwo\n\nth#[r|]#ee\n\n",
"one\n\ntwo\n\nth#[ree\n\n|]#",
),
(
"on#[e|]#\n\ntwo\n\nthree\n\n",
"on#[e\n\ntwo\n\n|]#three\n\n",
),
];
for (before, expected) in tests {
let (s, selection) = crate::test::print(before);
let text = Rope::from(s.as_str());
let selection =
selection.transform(|r| move_next_paragraph(text.slice(..), r, 2, Movement::Move));
let actual = crate::test::plain(&s, selection);
assert_eq!(actual, expected, "\nbefore: `{:?}`", before);
}
}
#[test]
fn test_behaviour_when_moving_to_next_paragraph_extend() {
let tests = [
(
"one\n\n#[two\n\n|]#three\n\n",
"one\n\n#[two\n\nthree\n\n|]#",
),
(
"one\n\n#[two\n\nthree\n\n|]#",
"one\n\n#[two\n\nthree\n\n|]#",
),
];
for (before, expected) in tests {
let (s, selection) = crate::test::print(before);
let text = Rope::from(s.as_str());
let selection = selection
.transform(|r| move_next_paragraph(text.slice(..), r, 1, Movement::Extend));
let actual = crate::test::plain(&s, selection);
assert_eq!(actual, expected, "\nbefore: `{:?}`", before);
}
}
}

View File

@@ -1,26 +1,71 @@
use crate::{Range, RopeSlice, Selection, Syntax};
use tree_sitter::Node;
// TODO: to contract_selection we'd need to store the previous ranges before expand.
// Maybe just contract to the first child node?
pub fn expand_selection(syntax: &Syntax, text: RopeSlice, selection: &Selection) -> Selection {
pub fn expand_selection(syntax: &Syntax, text: RopeSlice, selection: Selection) -> Selection {
select_node_impl(syntax, text, selection, |mut node, from, to| {
while node.start_byte() == from && node.end_byte() == to {
node = node.parent()?;
}
Some(node)
})
}
pub fn shrink_selection(syntax: &Syntax, text: RopeSlice, selection: Selection) -> Selection {
select_node_impl(syntax, text, selection, |descendant, _from, _to| {
descendant.child(0).or(Some(descendant))
})
}
pub fn select_sibling<F>(
syntax: &Syntax,
text: RopeSlice,
selection: Selection,
sibling_fn: &F,
) -> Selection
where
F: Fn(Node) -> Option<Node>,
{
select_node_impl(syntax, text, selection, |descendant, _from, _to| {
find_sibling_recursive(descendant, sibling_fn)
})
}
fn find_sibling_recursive<F>(node: Node, sibling_fn: F) -> Option<Node>
where
F: Fn(Node) -> Option<Node>,
{
sibling_fn(node).or_else(|| {
node.parent()
.and_then(|node| find_sibling_recursive(node, sibling_fn))
})
}
fn select_node_impl<F>(
syntax: &Syntax,
text: RopeSlice,
selection: Selection,
select_fn: F,
) -> Selection
where
F: Fn(Node, usize, usize) -> Option<Node>,
{
let tree = syntax.tree();
selection.clone().transform(|range| {
selection.transform(|range| {
let from = text.char_to_byte(range.from());
let to = text.char_to_byte(range.to());
// find parent of a descendant that matches the range
let parent = match tree
let node = match tree
.root_node()
.descendant_for_byte_range(from, to)
.and_then(|node| node.parent())
.and_then(|node| select_fn(node, from, to))
{
Some(parent) => parent,
Some(node) => node,
None => return range,
};
let from = text.byte_to_char(parent.start_byte());
let to = text.byte_to_char(parent.end_byte());
let from = text.byte_to_char(node.start_byte());
let to = text.byte_to_char(node.end_byte());
if range.head < range.anchor {
Range::new(to, from)

View File

@@ -1,26 +1,26 @@
use etcetera::home_dir;
use std::path::{Component, Path, PathBuf};
/// Replaces users home directory from `path` with tilde `~` if the directory
/// is available, otherwise returns the path unchanged.
pub fn fold_home_dir(path: &Path) -> PathBuf {
if let Ok(home) = super::home_dir() {
if path.starts_with(&home) {
// it's ok to unwrap, the path starts with home dir
return PathBuf::from("~").join(path.strip_prefix(&home).unwrap());
if let Ok(home) = home_dir() {
if let Ok(stripped) = path.strip_prefix(&home) {
return PathBuf::from("~").join(stripped);
}
}
path.to_path_buf()
}
/// Expands tilde `~` into users home directory if avilable, otherwise returns the path
/// Expands tilde `~` into users home directory if available, otherwise returns the path
/// unchanged. The tilde will only be expanded when present as the first component of the path
/// and only slash follows it.
pub fn expand_tilde(path: &Path) -> PathBuf {
let mut components = path.components().peekable();
if let Some(Component::Normal(c)) = components.peek() {
if c == &"~" {
if let Ok(home) = super::home_dir() {
if let Ok(home) = home_dir() {
// it's ok to unwrap, the path starts with `~`
return home.join(path.strip_prefix("~").unwrap());
}
@@ -40,7 +40,6 @@ pub fn expand_tilde(path: &Path) -> PathBuf {
/// needs to improve on.
/// Copied from cargo: <https://github.com/rust-lang/cargo/blob/070e459c2d8b79c5b2ac5218064e7603329c92ae/crates/cargo-util/src/paths.rs#L81>
pub fn get_normalized_path(path: &Path) -> PathBuf {
let path = expand_tilde(path);
let mut components = path.components().peekable();
let mut ret = if let Some(c @ Component::Prefix(..)) = components.peek().cloned() {
components.next();
@@ -72,10 +71,11 @@ pub fn get_normalized_path(path: &Path) -> PathBuf {
/// This function is used instead of `std::fs::canonicalize` because we don't want to verify
/// here if the path exists, just normalize it's components.
pub fn get_canonicalized_path(path: &Path) -> std::io::Result<PathBuf> {
let path = expand_tilde(path);
let path = if path.is_relative() {
std::env::current_dir().map(|current_dir| current_dir.join(path))?
} else {
path.to_path_buf()
path
};
Ok(get_normalized_path(path.as_path()))
@@ -90,3 +90,54 @@ pub fn get_relative_path(path: &Path) -> PathBuf {
};
fold_home_dir(path)
}
/// Returns a truncated filepath where the basepart of the path is reduced to the first
/// char of the folder and the whole filename appended.
///
/// Also strip the current working directory from the beginning of the path.
/// Note that this function does not check if the truncated path is unambiguous.
///
/// ```
/// use helix_core::path::get_truncated_path;
/// use std::path::Path;
///
/// assert_eq!(
/// get_truncated_path("/home/cnorris/documents/jokes.txt").as_path(),
/// Path::new("/h/c/d/jokes.txt")
/// );
/// assert_eq!(
/// get_truncated_path("jokes.txt").as_path(),
/// Path::new("jokes.txt")
/// );
/// assert_eq!(
/// get_truncated_path("/jokes.txt").as_path(),
/// Path::new("/jokes.txt")
/// );
/// assert_eq!(
/// get_truncated_path("/h/c/d/jokes.txt").as_path(),
/// Path::new("/h/c/d/jokes.txt")
/// );
/// assert_eq!(get_truncated_path("").as_path(), Path::new(""));
/// ```
///
pub fn get_truncated_path<P: AsRef<Path>>(path: P) -> PathBuf {
let cwd = std::env::current_dir().unwrap_or_default();
let path = path
.as_ref()
.strip_prefix(cwd)
.unwrap_or_else(|_| path.as_ref());
let file = path.file_name().unwrap_or_default();
let base = path.parent().unwrap_or_else(|| Path::new(""));
let mut ret = PathBuf::new();
for d in base {
ret.push(
d.to_string_lossy()
.chars()
.next()
.unwrap_or_default()
.to_string(),
);
}
ret.push(file);
ret
}

View File

@@ -1,6 +1,8 @@
use std::borrow::Cow;
use crate::{
chars::char_is_line_ending,
graphemes::{ensure_grapheme_boundary_prev, RopeGraphemes},
graphemes::{ensure_grapheme_boundary_prev, grapheme_width, RopeGraphemes},
line_ending::line_end_char_index,
RopeSlice,
};
@@ -54,11 +56,8 @@ impl From<Position> for tree_sitter::Point {
}
/// Convert a character index to (line, column) coordinates.
///
/// TODO: this should be split into two methods: one for visual
/// row/column, and one for "objective" row/column (possibly with
/// the column specified in `char`s). The former would be used
/// for cursor movement, and the latter would be used for e.g. the
/// row:column display in the status line.
/// column in `char` count which can be used for row:column display in
/// status line. See [`visual_coords_at_pos`] for a visual one.
pub fn coords_at_pos(text: RopeSlice, pos: usize) -> Position {
let line = text.char_to_line(pos);
@@ -69,6 +68,31 @@ pub fn coords_at_pos(text: RopeSlice, pos: usize) -> Position {
Position::new(line, col)
}
/// Convert a character index to (line, column) coordinates visually.
///
/// Takes \t, double-width characters (CJK) into account as well as text
/// not in the document in the future.
/// See [`coords_at_pos`] for an "objective" one.
pub fn visual_coords_at_pos(text: RopeSlice, pos: usize, tab_width: usize) -> Position {
let line = text.char_to_line(pos);
let line_start = text.line_to_char(line);
let pos = ensure_grapheme_boundary_prev(text, pos);
let mut col = 0;
for grapheme in RopeGraphemes::new(text.slice(line_start..pos)) {
if grapheme == "\t" {
col += tab_width - (col % tab_width);
} else {
let grapheme = Cow::from(grapheme);
col += grapheme_width(&grapheme);
}
}
Position::new(line, col)
}
/// Convert (line, column) coordinates to a character index.
///
/// If the `line` coordinate is beyond the end of the file, the EOF
@@ -85,11 +109,11 @@ pub fn coords_at_pos(text: RopeSlice, pos: usize) -> Position {
/// with left-side block-cursor positions, as this prevents the the block cursor
/// from jumping to the next line. Otherwise you typically want it to be `false`,
/// such as when dealing with raw anchor/head positions.
///
/// TODO: this should be changed to work in terms of visual row/column, not
/// graphemes.
pub fn pos_at_coords(text: RopeSlice, coords: Position, limit_before_line_ending: bool) -> usize {
let Position { row, col } = coords;
let Position { mut row, col } = coords;
if limit_before_line_ending {
row = row.min(text.len_lines() - 1);
};
let line_start = text.line_to_char(row);
let line_end = if limit_before_line_ending {
line_end_char_index(&text, row)
@@ -108,6 +132,43 @@ pub fn pos_at_coords(text: RopeSlice, coords: Position, limit_before_line_ending
line_start + col_char_offset
}
/// Convert visual (line, column) coordinates to a character index.
///
/// If the `line` coordinate is beyond the end of the file, the EOF
/// position will be returned.
///
/// If the `column` coordinate is past the end of the given line, the
/// line-end position (in this case, just before the line ending
/// character) will be returned.
pub fn pos_at_visual_coords(text: RopeSlice, coords: Position, tab_width: usize) -> usize {
let Position { mut row, col } = coords;
row = row.min(text.len_lines() - 1);
let line_start = text.line_to_char(row);
let line_end = line_end_char_index(&text, row);
let mut col_char_offset = 0;
let mut cols_remaining = col;
for grapheme in RopeGraphemes::new(text.slice(line_start..line_end)) {
let grapheme_width = if grapheme == "\t" {
tab_width - ((col - cols_remaining) % tab_width)
} else {
let grapheme = Cow::from(grapheme);
grapheme_width(&grapheme)
};
// If pos is in the middle of a wider grapheme (tab for example)
// return the starting offset.
if grapheme_width > cols_remaining {
break;
}
cols_remaining -= grapheme_width;
col_char_offset += grapheme.chars().count();
}
line_start + col_char_offset
}
#[cfg(test)]
mod test {
use super::*;
@@ -130,7 +191,6 @@ mod test {
assert_eq!(coords_at_pos(slice, 10), (1, 4).into()); // position on d
// Test with wide characters.
// TODO: account for character width.
let text = Rope::from("今日はいい\n");
let slice = text.slice(..);
assert_eq!(coords_at_pos(slice, 0), (0, 0).into());
@@ -151,7 +211,6 @@ mod test {
assert_eq!(coords_at_pos(slice, 9), (1, 0).into());
// Test with wide-character grapheme clusters.
// TODO: account for character width.
let text = Rope::from("किमपि\n");
let slice = text.slice(..);
assert_eq!(coords_at_pos(slice, 0), (0, 0).into());
@@ -161,7 +220,6 @@ mod test {
assert_eq!(coords_at_pos(slice, 6), (1, 0).into());
// Test with tabs.
// Todo: account for tab stops.
let text = Rope::from("\tHello\n");
let slice = text.slice(..);
assert_eq!(coords_at_pos(slice, 0), (0, 0).into());
@@ -169,6 +227,54 @@ mod test {
assert_eq!(coords_at_pos(slice, 2), (0, 2).into());
}
#[test]
fn test_visual_coords_at_pos() {
let text = Rope::from("ḧëḷḷö\nẅöṛḷḋ");
let slice = text.slice(..);
assert_eq!(visual_coords_at_pos(slice, 0, 8), (0, 0).into());
assert_eq!(visual_coords_at_pos(slice, 5, 8), (0, 5).into()); // position on \n
assert_eq!(visual_coords_at_pos(slice, 6, 8), (1, 0).into()); // position on w
assert_eq!(visual_coords_at_pos(slice, 7, 8), (1, 1).into()); // position on o
assert_eq!(visual_coords_at_pos(slice, 10, 8), (1, 4).into()); // position on d
// Test with wide characters.
let text = Rope::from("今日はいい\n");
let slice = text.slice(..);
assert_eq!(visual_coords_at_pos(slice, 0, 8), (0, 0).into());
assert_eq!(visual_coords_at_pos(slice, 1, 8), (0, 2).into());
assert_eq!(visual_coords_at_pos(slice, 2, 8), (0, 4).into());
assert_eq!(visual_coords_at_pos(slice, 3, 8), (0, 6).into());
assert_eq!(visual_coords_at_pos(slice, 4, 8), (0, 8).into());
assert_eq!(visual_coords_at_pos(slice, 5, 8), (0, 10).into());
assert_eq!(visual_coords_at_pos(slice, 6, 8), (1, 0).into());
// Test with grapheme clusters.
let text = Rope::from("a̐éö̲\r\n");
let slice = text.slice(..);
assert_eq!(visual_coords_at_pos(slice, 0, 8), (0, 0).into());
assert_eq!(visual_coords_at_pos(slice, 2, 8), (0, 1).into());
assert_eq!(visual_coords_at_pos(slice, 4, 8), (0, 2).into());
assert_eq!(visual_coords_at_pos(slice, 7, 8), (0, 3).into());
assert_eq!(visual_coords_at_pos(slice, 9, 8), (1, 0).into());
// Test with wide-character grapheme clusters.
// TODO: account for cluster.
let text = Rope::from("किमपि\n");
let slice = text.slice(..);
assert_eq!(visual_coords_at_pos(slice, 0, 8), (0, 0).into());
assert_eq!(visual_coords_at_pos(slice, 2, 8), (0, 2).into());
assert_eq!(visual_coords_at_pos(slice, 3, 8), (0, 3).into());
assert_eq!(visual_coords_at_pos(slice, 5, 8), (0, 5).into());
assert_eq!(visual_coords_at_pos(slice, 6, 8), (1, 0).into());
// Test with tabs.
let text = Rope::from("\tHello\n");
let slice = text.slice(..);
assert_eq!(visual_coords_at_pos(slice, 0, 8), (0, 0).into());
assert_eq!(visual_coords_at_pos(slice, 1, 8), (0, 8).into());
assert_eq!(visual_coords_at_pos(slice, 2, 8), (0, 9).into());
}
#[test]
fn test_pos_at_coords() {
let text = Rope::from("ḧëḷḷö\nẅöṛḷḋ");
@@ -225,5 +331,78 @@ mod test {
assert_eq!(pos_at_coords(slice, (0, 0).into(), false), 0);
assert_eq!(pos_at_coords(slice, (0, 1).into(), false), 1);
assert_eq!(pos_at_coords(slice, (0, 2).into(), false), 2);
// Test out of bounds.
let text = Rope::new();
let slice = text.slice(..);
assert_eq!(pos_at_coords(slice, (10, 0).into(), true), 0);
assert_eq!(pos_at_coords(slice, (0, 10).into(), true), 0);
assert_eq!(pos_at_coords(slice, (10, 10).into(), true), 0);
}
#[test]
fn test_pos_at_visual_coords() {
let text = Rope::from("ḧëḷḷö\nẅöṛḷḋ");
let slice = text.slice(..);
assert_eq!(pos_at_visual_coords(slice, (0, 0).into(), 4), 0);
assert_eq!(pos_at_visual_coords(slice, (0, 5).into(), 4), 5); // position on \n
assert_eq!(pos_at_visual_coords(slice, (0, 6).into(), 4), 5); // position after \n
assert_eq!(pos_at_visual_coords(slice, (1, 0).into(), 4), 6); // position on w
assert_eq!(pos_at_visual_coords(slice, (1, 1).into(), 4), 7); // position on o
assert_eq!(pos_at_visual_coords(slice, (1, 4).into(), 4), 10); // position on d
// Test with wide characters.
let text = Rope::from("今日はいい\n");
let slice = text.slice(..);
assert_eq!(pos_at_visual_coords(slice, (0, 0).into(), 4), 0);
assert_eq!(pos_at_visual_coords(slice, (0, 1).into(), 4), 0);
assert_eq!(pos_at_visual_coords(slice, (0, 2).into(), 4), 1);
assert_eq!(pos_at_visual_coords(slice, (0, 3).into(), 4), 1);
assert_eq!(pos_at_visual_coords(slice, (0, 4).into(), 4), 2);
assert_eq!(pos_at_visual_coords(slice, (0, 5).into(), 4), 2);
assert_eq!(pos_at_visual_coords(slice, (0, 6).into(), 4), 3);
assert_eq!(pos_at_visual_coords(slice, (0, 7).into(), 4), 3);
assert_eq!(pos_at_visual_coords(slice, (0, 8).into(), 4), 4);
assert_eq!(pos_at_visual_coords(slice, (0, 9).into(), 4), 4);
// assert_eq!(pos_at_visual_coords(slice, (0, 10).into(), 4, false), 5);
// assert_eq!(pos_at_visual_coords(slice, (0, 10).into(), 4, true), 5);
assert_eq!(pos_at_visual_coords(slice, (1, 0).into(), 4), 6);
// Test with grapheme clusters.
let text = Rope::from("a̐éö̲\r\n");
let slice = text.slice(..);
assert_eq!(pos_at_visual_coords(slice, (0, 0).into(), 4), 0);
assert_eq!(pos_at_visual_coords(slice, (0, 1).into(), 4), 2);
assert_eq!(pos_at_visual_coords(slice, (0, 2).into(), 4), 4);
assert_eq!(pos_at_visual_coords(slice, (0, 3).into(), 4), 7); // \r\n is one char here
assert_eq!(pos_at_visual_coords(slice, (0, 4).into(), 4), 7);
assert_eq!(pos_at_visual_coords(slice, (1, 0).into(), 4), 9);
// Test with wide-character grapheme clusters.
let text = Rope::from("किमपि");
// 2 - 1 - 2 codepoints
// TODO: delete handling as per https://news.ycombinator.com/item?id=20058454
let slice = text.slice(..);
assert_eq!(pos_at_visual_coords(slice, (0, 0).into(), 4), 0);
assert_eq!(pos_at_visual_coords(slice, (0, 1).into(), 4), 0);
assert_eq!(pos_at_visual_coords(slice, (0, 2).into(), 4), 2);
assert_eq!(pos_at_visual_coords(slice, (0, 3).into(), 4), 3);
// Test with tabs.
let text = Rope::from("\tHello\n");
let slice = text.slice(..);
assert_eq!(pos_at_visual_coords(slice, (0, 0).into(), 4), 0);
assert_eq!(pos_at_visual_coords(slice, (0, 1).into(), 4), 0);
assert_eq!(pos_at_visual_coords(slice, (0, 2).into(), 4), 0);
assert_eq!(pos_at_visual_coords(slice, (0, 3).into(), 4), 0);
assert_eq!(pos_at_visual_coords(slice, (0, 4).into(), 4), 1);
assert_eq!(pos_at_visual_coords(slice, (0, 5).into(), 4), 2);
// Test out of bounds.
let text = Rope::new();
let slice = text.slice(..);
assert_eq!(pos_at_visual_coords(slice, (10, 0).into(), 4), 0);
assert_eq!(pos_at_visual_coords(slice, (0, 10).into(), 4), 0);
assert_eq!(pos_at_visual_coords(slice, (10, 10).into(), 4), 0);
}
}

View File

@@ -46,18 +46,36 @@ impl Registers {
self.inner.get(&name)
}
pub fn get_mut(&mut self, name: char) -> &mut Register {
self.inner
.entry(name)
.or_insert_with(|| Register::new(name))
}
pub fn write(&mut self, name: char, values: Vec<String>) {
self.inner
.insert(name, Register::new_with_values(name, values));
}
pub fn read(&self, name: char) -> Option<&[String]> {
self.get(name).map(|reg| reg.read())
}
pub fn write(&mut self, name: char, values: Vec<String>) {
if name != '_' {
self.inner
.insert(name, Register::new_with_values(name, values));
}
}
pub fn push(&mut self, name: char, value: String) {
if name != '_' {
if let Some(r) = self.inner.get_mut(&name) {
r.push(value);
} else {
self.write(name, vec![value]);
}
}
}
pub fn first(&self, name: char) -> Option<&String> {
self.read(name).and_then(|entries| entries.first())
}
pub fn last(&self, name: char) -> Option<&String> {
self.read(name).and_then(|entries| entries.last())
}
pub fn inner(&self) -> &HashMap<char, Register> {
&self.inner
}
}

View File

@@ -1,6 +1,28 @@
use crate::RopeSlice;
pub fn find_nth_next(text: RopeSlice, ch: char, mut pos: usize, n: usize) -> Option<usize> {
// TODO: switch to std::str::Pattern when it is stable.
pub trait CharMatcher {
fn char_match(&self, ch: char) -> bool;
}
impl CharMatcher for char {
fn char_match(&self, ch: char) -> bool {
*self == ch
}
}
impl<F: Fn(&char) -> bool> CharMatcher for F {
fn char_match(&self, ch: char) -> bool {
(*self)(&ch)
}
}
pub fn find_nth_next<M: CharMatcher>(
text: RopeSlice,
char_matcher: M,
mut pos: usize,
n: usize,
) -> Option<usize> {
if pos >= text.len_chars() || n == 0 {
return None;
}
@@ -13,7 +35,7 @@ pub fn find_nth_next(text: RopeSlice, ch: char, mut pos: usize, n: usize) -> Opt
pos += 1;
if c == ch {
if char_matcher.char_match(c) {
break;
}
}

View File

@@ -7,7 +7,8 @@ use crate::{
ensure_grapheme_boundary_next, ensure_grapheme_boundary_prev, next_grapheme_boundary,
prev_grapheme_boundary,
},
Assoc, ChangeSet, RopeSlice,
movement::Direction,
Assoc, ChangeSet, RopeGraphemes, RopeSlice,
};
use smallvec::{smallvec, SmallVec};
use std::borrow::Cow;
@@ -82,6 +83,13 @@ impl Range {
std::cmp::max(self.anchor, self.head)
}
/// Total length of the range.
#[inline]
#[must_use]
pub fn len(&self) -> usize {
self.to() - self.from()
}
/// The (inclusive) range of lines that the range overlaps.
#[inline]
#[must_use]
@@ -102,6 +110,37 @@ impl Range {
self.anchor == self.head
}
/// `Direction::Backward` when head < anchor.
/// `Direction::Backward` otherwise.
#[inline]
#[must_use]
pub fn direction(&self) -> Direction {
if self.head < self.anchor {
Direction::Backward
} else {
Direction::Forward
}
}
/// Flips the direction of the selection
pub fn flip(&self) -> Self {
Self {
anchor: self.head,
head: self.anchor,
horiz: self.horiz,
}
}
/// Returns the selection if it goes in the direction of `direction`,
/// flipping the selection otherwise.
pub fn with_direction(self, direction: Direction) -> Self {
if self.direction() == direction {
self
} else {
self.flip()
}
}
/// Check two ranges for overlap.
#[must_use]
pub fn overlaps(&self, other: &Self) -> bool {
@@ -111,6 +150,11 @@ impl Range {
self.from() == other.from() || (self.to() > other.from() && other.to() > self.from())
}
#[inline]
pub fn contains_range(&self, other: &Self) -> bool {
self.from() <= other.from() && self.to() >= other.to()
}
pub fn contains(&self, pos: usize) -> bool {
self.from() <= pos && pos < self.to()
}
@@ -188,9 +232,23 @@ impl Range {
// groupAt
/// Returns the text inside this range given the text of the whole buffer.
///
/// The returned `Cow` is a reference if the range of text is inside a single
/// chunk of the rope. Otherwise a copy of the text is returned. Consider
/// using `slice` instead if you do not need a `Cow` or `String` to avoid copying.
#[inline]
pub fn fragment<'a, 'b: 'a>(&'a self, text: RopeSlice<'b>) -> Cow<'b, str> {
text.slice(self.from()..self.to()).into()
self.slice(text).into()
}
/// Returns the text inside this range given the text of the whole buffer.
///
/// The returned value is a reference to the passed slice. This method never
/// copies any contents.
#[inline]
pub fn slice<'a, 'b: 'a>(&'a self, text: RopeSlice<'b>) -> RopeSlice<'b> {
text.slice(self.from()..self.to())
}
//--------------------------------
@@ -305,13 +363,21 @@ impl Range {
pub fn cursor_line(&self, text: RopeSlice) -> usize {
text.char_to_line(self.cursor(text))
}
/// Returns true if this Range covers a single grapheme in the given text
pub fn is_single_grapheme(&self, doc: RopeSlice) -> bool {
let mut graphemes = RopeGraphemes::new(doc.slice(self.from()..self.to()));
let first = graphemes.next();
let second = graphemes.next();
first.is_some() && second.is_none()
}
}
impl From<(usize, usize)> for Range {
fn from(tuple: (usize, usize)) -> Self {
fn from((anchor, head): (usize, usize)) -> Self {
Self {
anchor: tuple.0,
head: tuple.1,
anchor,
head,
horiz: None,
}
}
@@ -360,8 +426,13 @@ impl Selection {
self.normalize()
}
/// Adds a new range to the selection and makes it the primary range.
/// Removes a range from the selection.
pub fn remove(mut self, index: usize) -> Self {
assert!(
self.ranges.len() > 1,
"can't remove the last range from a selection!"
);
self.ranges.remove(index);
if index < self.primary_index || self.primary_index == self.ranges.len() {
self.primary_index -= 1;
@@ -369,6 +440,12 @@ impl Selection {
self
}
/// Replace a range in the selection with a new range.
pub fn replace(mut self, index: usize, range: Range) -> Self {
self.ranges[index] = range;
self.normalize()
}
/// Map selections over a set of changes. Useful for adjusting the selection position after
/// applying changes to a document.
pub fn map(self, changes: &ChangeSet) -> Self {
@@ -495,6 +572,10 @@ impl Selection {
self.ranges.iter().map(move |range| range.fragment(text))
}
pub fn slices<'a>(&'a self, text: RopeSlice<'a>) -> impl Iterator<Item = RopeSlice> + 'a {
self.ranges.iter().map(move |range| range.slice(text))
}
#[inline(always)]
pub fn iter(&self) -> std::slice::Iter<'_, Range> {
self.ranges.iter()
@@ -504,6 +585,39 @@ impl Selection {
pub fn len(&self) -> usize {
self.ranges.len()
}
// returns true if self ⊇ other
pub fn contains(&self, other: &Selection) -> bool {
// can't contain other if it is larger
if other.len() > self.len() {
return false;
}
let (mut iter_self, mut iter_other) = (self.iter(), other.iter());
let (mut ele_self, mut ele_other) = (iter_self.next(), iter_other.next());
loop {
match (ele_self, ele_other) {
(Some(ra), Some(rb)) => {
if !ra.contains_range(rb) {
// `self` doesn't contain next element from `other`, advance `self`, we need to match all from `other`
ele_self = iter_self.next();
} else {
// matched element from `other`, advance `other`
ele_other = iter_other.next();
};
}
(None, Some(_)) => {
// exhausted `self`, we can't match the reminder of `other`
return false;
}
(_, None) => {
// no elements from `other` left to match, `self` contains `other`
return true;
}
}
}
}
}
impl<'a> IntoIterator for &'a Selection {
@@ -517,14 +631,15 @@ impl<'a> IntoIterator for &'a Selection {
// TODO: checkSelection -> check if valid for doc length && sorted
pub fn keep_matches(
pub fn keep_or_remove_matches(
text: RopeSlice,
selection: &Selection,
regex: &crate::regex::Regex,
remove: bool,
) -> Option<Selection> {
let result: SmallVec<_> = selection
.iter()
.filter(|range| regex.is_match(&range.fragment(text)))
.filter(|range| regex.is_match(&range.fragment(text)) ^ remove)
.copied()
.collect();
@@ -554,7 +669,13 @@ pub fn select_on_matches(
let start = text.byte_to_char(start_byte + mat.start());
let end = text.byte_to_char(start_byte + mat.end());
result.push(Range::new(start, end));
let range = Range::new(start, end);
// Make sure the match is not right outside of the selection.
// These invalid matches can come from using RegEx anchors like `^`, `$`
if range != Range::point(sel.to()) {
result.push(range);
}
}
}
@@ -687,16 +808,16 @@ mod test {
fn test_contains() {
let range = Range::new(10, 12);
assert_eq!(range.contains(9), false);
assert_eq!(range.contains(10), true);
assert_eq!(range.contains(11), true);
assert_eq!(range.contains(12), false);
assert_eq!(range.contains(13), false);
assert!(!range.contains(9));
assert!(range.contains(10));
assert!(range.contains(11));
assert!(!range.contains(12));
assert!(!range.contains(13));
let range = Range::new(9, 6);
assert_eq!(range.contains(9), false);
assert_eq!(range.contains(7), true);
assert_eq!(range.contains(6), true);
assert!(!range.contains(9));
assert!(range.contains(7));
assert!(range.contains(6));
}
#[test]
@@ -751,7 +872,7 @@ mod test {
}
#[test]
fn test_graphem_aligned() {
fn test_grapheme_aligned() {
let r = Rope::from_str("\r\nHi\r\n");
let s = r.slice(..);
@@ -824,6 +945,76 @@ mod test {
assert_eq!(Range::new(6, 5).min_width_1(s), Range::new(6, 5));
}
#[test]
fn test_select_on_matches() {
use crate::regex::{Regex, RegexBuilder};
let r = Rope::from_str("Nobody expects the Spanish inquisition");
let s = r.slice(..);
let selection = Selection::single(0, r.len_chars());
assert_eq!(
select_on_matches(s, &selection, &Regex::new(r"[A-Z][a-z]*").unwrap()),
Some(Selection::new(
smallvec![Range::new(0, 6), Range::new(19, 26)],
0
))
);
let r = Rope::from_str("This\nString\n\ncontains multiple\nlines");
let s = r.slice(..);
let start_of_line = RegexBuilder::new(r"^").multi_line(true).build().unwrap();
let end_of_line = RegexBuilder::new(r"$").multi_line(true).build().unwrap();
// line without ending
assert_eq!(
select_on_matches(s, &Selection::single(0, 4), &start_of_line),
Some(Selection::single(0, 0))
);
assert_eq!(
select_on_matches(s, &Selection::single(0, 4), &end_of_line),
None
);
// line with ending
assert_eq!(
select_on_matches(s, &Selection::single(0, 5), &start_of_line),
Some(Selection::single(0, 0))
);
assert_eq!(
select_on_matches(s, &Selection::single(0, 5), &end_of_line),
Some(Selection::single(4, 4))
);
// line with start of next line
assert_eq!(
select_on_matches(s, &Selection::single(0, 6), &start_of_line),
Some(Selection::new(
smallvec![Range::point(0), Range::point(5)],
0
))
);
assert_eq!(
select_on_matches(s, &Selection::single(0, 6), &end_of_line),
Some(Selection::single(4, 4))
);
// multiple lines
assert_eq!(
select_on_matches(
s,
&Selection::single(0, s.len_chars()),
&RegexBuilder::new(r"^[a-z ]*$")
.multi_line(true)
.build()
.unwrap()
),
Some(Selection::new(
smallvec![Range::point(12), Range::new(13, 30), Range::new(31, 36)],
0
))
);
}
#[test]
fn test_line_range() {
let r = Rope::from_str("\r\nHi\r\nthere!");
@@ -941,4 +1132,30 @@ mod test {
&["", "abcd", "efg", "rs", "xyz"]
);
}
#[test]
fn test_selection_contains() {
fn contains(a: Vec<(usize, usize)>, b: Vec<(usize, usize)>) -> bool {
let sela = Selection::new(a.iter().map(|a| Range::new(a.0, a.1)).collect(), 0);
let selb = Selection::new(b.iter().map(|b| Range::new(b.0, b.1)).collect(), 0);
sela.contains(&selb)
}
// exact match
assert!(contains(vec!((1, 1)), vec!((1, 1))));
// larger set contains smaller
assert!(contains(vec!((1, 1), (2, 2), (3, 3)), vec!((2, 2))));
// multiple matches
assert!(contains(vec!((1, 1), (2, 2)), vec!((1, 1), (2, 2))));
// smaller set can't contain bigger
assert!(!contains(vec!((1, 1)), vec!((1, 1), (2, 2))));
assert!(contains(
vec!((1, 1), (2, 4), (5, 6), (7, 9), (10, 13)),
vec!((3, 4), (7, 9))
));
assert!(!contains(vec!((1, 1), (5, 6)), vec!((1, 6))));
}
}

View File

@@ -0,0 +1,336 @@
use std::borrow::Cow;
/// Auto escape for shellwords usage.
pub fn escape(input: Cow<str>) -> Cow<str> {
if !input.chars().any(|x| x.is_ascii_whitespace()) {
input
} else if cfg!(unix) {
Cow::Owned(input.chars().fold(String::new(), |mut buf, c| {
if c.is_ascii_whitespace() {
buf.push('\\');
}
buf.push(c);
buf
}))
} else {
Cow::Owned(format!("\"{}\"", input))
}
}
enum State {
OnWhitespace,
Unquoted,
UnquotedEscaped,
Quoted,
QuoteEscaped,
Dquoted,
DquoteEscaped,
}
pub struct Shellwords<'a> {
state: State,
/// Shellwords where whitespace and escapes has been resolved.
words: Vec<Cow<'a, str>>,
/// The parts of the input that are divided into shellwords. This can be
/// used to retrieve the original text for a given word by looking up the
/// same index in the Vec as the word in `words`.
parts: Vec<&'a str>,
}
impl<'a> From<&'a str> for Shellwords<'a> {
fn from(input: &'a str) -> Self {
use State::*;
let mut state = Unquoted;
let mut words = Vec::new();
let mut parts = Vec::new();
let mut escaped = String::with_capacity(input.len());
let mut part_start = 0;
let mut unescaped_start = 0;
let mut end = 0;
for (i, c) in input.char_indices() {
state = match state {
OnWhitespace => match c {
'"' => {
end = i;
Dquoted
}
'\'' => {
end = i;
Quoted
}
'\\' => {
if cfg!(unix) {
escaped.push_str(&input[unescaped_start..i]);
unescaped_start = i + 1;
UnquotedEscaped
} else {
OnWhitespace
}
}
c if c.is_ascii_whitespace() => {
end = i;
OnWhitespace
}
_ => Unquoted,
},
Unquoted => match c {
'\\' => {
if cfg!(unix) {
escaped.push_str(&input[unescaped_start..i]);
unescaped_start = i + 1;
UnquotedEscaped
} else {
Unquoted
}
}
c if c.is_ascii_whitespace() => {
end = i;
OnWhitespace
}
_ => Unquoted,
},
UnquotedEscaped => Unquoted,
Quoted => match c {
'\\' => {
if cfg!(unix) {
escaped.push_str(&input[unescaped_start..i]);
unescaped_start = i + 1;
QuoteEscaped
} else {
Quoted
}
}
'\'' => {
end = i;
OnWhitespace
}
_ => Quoted,
},
QuoteEscaped => Quoted,
Dquoted => match c {
'\\' => {
if cfg!(unix) {
escaped.push_str(&input[unescaped_start..i]);
unescaped_start = i + 1;
DquoteEscaped
} else {
Dquoted
}
}
'"' => {
end = i;
OnWhitespace
}
_ => Dquoted,
},
DquoteEscaped => Dquoted,
};
if i >= input.len() - 1 && end == 0 {
end = i + 1;
}
if end > 0 {
let esc_trim = escaped.trim();
let inp = &input[unescaped_start..end];
if !(esc_trim.is_empty() && inp.trim().is_empty()) {
if esc_trim.is_empty() {
words.push(inp.into());
parts.push(inp);
} else {
words.push([escaped, inp.into()].concat().into());
parts.push(&input[part_start..end]);
escaped = "".to_string();
}
}
unescaped_start = i + 1;
part_start = i + 1;
end = 0;
}
}
debug_assert!(words.len() == parts.len());
Self {
state,
words,
parts,
}
}
}
impl<'a> Shellwords<'a> {
/// Checks that the input ends with a whitespace character which is not escaped.
///
/// # Examples
///
/// ```rust
/// use helix_core::shellwords::Shellwords;
/// assert_eq!(Shellwords::from(" ").ends_with_whitespace(), true);
/// assert_eq!(Shellwords::from(":open ").ends_with_whitespace(), true);
/// assert_eq!(Shellwords::from(":open foo.txt ").ends_with_whitespace(), true);
/// assert_eq!(Shellwords::from(":open").ends_with_whitespace(), false);
/// #[cfg(unix)]
/// assert_eq!(Shellwords::from(":open a\\ ").ends_with_whitespace(), false);
/// #[cfg(unix)]
/// assert_eq!(Shellwords::from(":open a\\ b.txt").ends_with_whitespace(), false);
/// ```
pub fn ends_with_whitespace(&self) -> bool {
matches!(self.state, State::OnWhitespace)
}
/// Returns the list of shellwords calculated from the input string.
pub fn words(&self) -> &[Cow<'a, str>] {
&self.words
}
/// Returns a list of strings which correspond to [`Self::words`] but represent the original
/// text in the input string - including escape characters - without separating whitespace.
pub fn parts(&self) -> &[&'a str] {
&self.parts
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
#[cfg(windows)]
fn test_normal() {
let input = r#":o single_word twó wörds \three\ \"with\ escaping\\"#;
let shellwords = Shellwords::from(input);
let result = shellwords.words().to_vec();
let expected = vec![
Cow::from(":o"),
Cow::from("single_word"),
Cow::from("twó"),
Cow::from("wörds"),
Cow::from("\\three\\"),
Cow::from("\\"),
Cow::from("with\\ escaping\\\\"),
];
// TODO test is_owned and is_borrowed, once they get stabilized.
assert_eq!(expected, result);
}
#[test]
#[cfg(unix)]
fn test_normal() {
let input = r#":o single_word twó wörds \three\ \"with\ escaping\\"#;
let shellwords = Shellwords::from(input);
let result = shellwords.words().to_vec();
let expected = vec![
Cow::from(":o"),
Cow::from("single_word"),
Cow::from("twó"),
Cow::from("wörds"),
Cow::from(r#"three "with escaping\"#),
];
// TODO test is_owned and is_borrowed, once they get stabilized.
assert_eq!(expected, result);
}
#[test]
#[cfg(unix)]
fn test_quoted() {
let quoted =
r#":o 'single_word' 'twó wörds' '' ' ''\three\' \"with\ escaping\\' 'quote incomplete"#;
let shellwords = Shellwords::from(quoted);
let result = shellwords.words().to_vec();
let expected = vec![
Cow::from(":o"),
Cow::from("single_word"),
Cow::from("twó wörds"),
Cow::from(r#"three' "with escaping\"#),
Cow::from("quote incomplete"),
];
assert_eq!(expected, result);
}
#[test]
#[cfg(unix)]
fn test_dquoted() {
let dquoted = r#":o "single_word" "twó wörds" "" " ""\three\' \"with\ escaping\\" "dquote incomplete"#;
let shellwords = Shellwords::from(dquoted);
let result = shellwords.words().to_vec();
let expected = vec![
Cow::from(":o"),
Cow::from("single_word"),
Cow::from("twó wörds"),
Cow::from(r#"three' "with escaping\"#),
Cow::from("dquote incomplete"),
];
assert_eq!(expected, result);
}
#[test]
#[cfg(unix)]
fn test_mixed() {
let dquoted = r#":o single_word 'twó wörds' "\three\' \"with\ escaping\\""no space before"'and after' $#%^@ "%^&(%^" ')(*&^%''a\\\\\b' '"#;
let shellwords = Shellwords::from(dquoted);
let result = shellwords.words().to_vec();
let expected = vec![
Cow::from(":o"),
Cow::from("single_word"),
Cow::from("twó wörds"),
Cow::from("three' \"with escaping\\"),
Cow::from("no space before"),
Cow::from("and after"),
Cow::from("$#%^@"),
Cow::from("%^&(%^"),
Cow::from(")(*&^%"),
Cow::from(r#"a\\b"#),
//last ' just changes to quoted but since we dont have anything after it, it should be ignored
];
assert_eq!(expected, result);
}
#[test]
fn test_lists() {
let input =
r#":set statusline.center ["file-type","file-encoding"] '["list", "in", "qoutes"]'"#;
let shellwords = Shellwords::from(input);
let result = shellwords.words().to_vec();
let expected = vec![
Cow::from(":set"),
Cow::from("statusline.center"),
Cow::from(r#"["file-type","file-encoding"]"#),
Cow::from(r#"["list", "in", "qoutes"]"#),
];
assert_eq!(expected, result);
}
#[test]
#[cfg(unix)]
fn test_escaping_unix() {
assert_eq!(escape("foobar".into()), Cow::Borrowed("foobar"));
assert_eq!(escape("foo bar".into()), Cow::Borrowed("foo\\ bar"));
assert_eq!(escape("foo\tbar".into()), Cow::Borrowed("foo\\\tbar"));
}
#[test]
#[cfg(windows)]
fn test_escaping_windows() {
assert_eq!(escape("foobar".into()), Cow::Borrowed("foobar"));
assert_eq!(escape("foo bar".into()), Cow::Borrowed("\"foo bar\""));
}
#[test]
#[cfg(unix)]
fn test_parts() {
assert_eq!(Shellwords::from(":o a").parts(), &[":o", "a"]);
assert_eq!(Shellwords::from(":o a\\ ").parts(), &[":o", "a\\ "]);
}
#[test]
#[cfg(windows)]
fn test_parts() {
assert_eq!(Shellwords::from(":o a").parts(), &[":o", "a"]);
assert_eq!(Shellwords::from(":o a\\ ").parts(), &[":o", "a\\"]);
}
}

View File

@@ -1,17 +0,0 @@
use crate::{Rope, Selection};
#[derive(Debug, Clone)]
pub struct State {
pub doc: Rope,
pub selection: Selection,
}
impl State {
#[must_use]
pub fn new(doc: Rope) -> Self {
Self {
doc,
selection: Selection::point(0),
}
}
}

View File

@@ -1,4 +1,6 @@
use crate::{search, Selection};
use std::fmt::Display;
use crate::{search, Range, Selection};
use ropey::RopeSlice;
pub const PAIRS: &[(char, char)] = &[
@@ -11,6 +13,27 @@ pub const PAIRS: &[(char, char)] = &[
('', ''),
];
#[derive(Debug, PartialEq, Eq)]
pub enum Error {
PairNotFound,
CursorOverlap,
RangeExceedsText,
CursorOnAmbiguousPair,
}
impl Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(match *self {
Error::PairNotFound => "Surround pair not found around all cursors",
Error::CursorOverlap => "Cursors overlap for a single surround pair range",
Error::RangeExceedsText => "Cursor range exceeds text length",
Error::CursorOnAmbiguousPair => "Cursor on ambiguous surround pair",
})
}
}
type Result<T> = std::result::Result<T, Error>;
/// Given any char in [PAIRS], return the open and closing chars. If not found in
/// [PAIRS] return (ch, ch).
///
@@ -29,45 +52,83 @@ pub fn get_pair(ch: char) -> (char, char) {
.unwrap_or((ch, ch))
}
pub fn find_nth_closest_pairs_pos(
text: RopeSlice,
range: Range,
n: usize,
) -> Result<(usize, usize)> {
let is_open_pair = |ch| PAIRS.iter().any(|(open, _)| *open == ch);
let is_close_pair = |ch| PAIRS.iter().any(|(_, close)| *close == ch);
let mut stack = Vec::with_capacity(2);
let pos = range.cursor(text);
for ch in text.chars_at(pos) {
if is_open_pair(ch) {
// Track open pairs encountered so that we can step over
// the corresponding close pairs that will come up further
// down the loop. We want to find a lone close pair whose
// open pair is before the cursor position.
stack.push(ch);
continue;
} else if is_close_pair(ch) {
let (open, _) = get_pair(ch);
if stack.last() == Some(&open) {
stack.pop();
continue;
} else {
// In the ideal case the stack would be empty here and the
// current character would be the close pair that we are
// looking for. It could also be the case that the pairs
// are unbalanced and we encounter a close pair that doesn't
// close the last seen open pair. In either case use this
// char as the auto-detected closest pair.
return find_nth_pairs_pos(text, ch, range, n);
}
}
}
Err(Error::PairNotFound)
}
/// Find the position of surround pairs of `ch` which can be either a closing
/// or opening pair. `n` will skip n - 1 pairs (eg. n=2 will discard (only)
/// the first pair found and keep looking)
pub fn find_nth_pairs_pos(
text: RopeSlice,
ch: char,
pos: usize,
range: Range,
n: usize,
) -> Option<(usize, usize)> {
) -> Result<(usize, usize)> {
if text.len_chars() < 2 {
return Err(Error::PairNotFound);
}
if range.to() >= text.len_chars() {
return Err(Error::RangeExceedsText);
}
let (open, close) = get_pair(ch);
let pos = range.cursor(text);
if text.len_chars() < 2 || pos >= text.len_chars() {
return None;
}
if open == close {
let (open, close) = if open == close {
if Some(open) == text.get_char(pos) {
// Special case: cursor is directly on a matching char.
match pos {
0 => Some((pos, search::find_nth_next(text, close, pos + 1, n)?)),
_ if (pos + 1) == text.len_chars() => {
Some((search::find_nth_prev(text, open, pos, n)?, pos))
}
// We return no match because there's no way to know which
// side of the char we should be searching on.
_ => None,
}
} else {
Some((
search::find_nth_prev(text, open, pos, n)?,
search::find_nth_next(text, close, pos, n)?,
))
// Cursor is directly on match char. We return no match
// because there's no way to know which side of the char
// we should be searching on.
return Err(Error::CursorOnAmbiguousPair);
}
(
search::find_nth_prev(text, open, pos, n),
search::find_nth_next(text, close, pos, n),
)
} else {
Some((
find_nth_open_pair(text, open, close, pos, n)?,
find_nth_close_pair(text, open, close, pos, n)?,
))
}
(
find_nth_open_pair(text, open, close, pos, n),
find_nth_close_pair(text, open, close, pos, n),
)
};
Option::zip(open, close).ok_or(Error::PairNotFound)
}
fn find_nth_open_pair(
@@ -151,23 +212,28 @@ fn find_nth_close_pair(
/// Find position of surround characters around every cursor. Returns None
/// if any positions overlap. Note that the positions are in a flat Vec.
/// Use get_surround_pos().chunks(2) to get matching pairs of surround positions.
/// `ch` can be either closing or opening pair.
/// `ch` can be either closing or opening pair. If `ch` is None, surround pairs
/// are automatically detected around each cursor (note that this may result
/// in them selecting different surround characters for each selection).
pub fn get_surround_pos(
text: RopeSlice,
selection: &Selection,
ch: char,
ch: Option<char>,
skip: usize,
) -> Option<Vec<usize>> {
) -> Result<Vec<usize>> {
let mut change_pos = Vec::new();
for range in selection {
let (open_pos, close_pos) = find_nth_pairs_pos(text, ch, range.head, skip)?;
for &range in selection {
let (open_pos, close_pos) = match ch {
Some(ch) => find_nth_pairs_pos(text, ch, range, skip)?,
None => find_nth_closest_pairs_pos(text, range, skip)?,
};
if change_pos.contains(&open_pos) || change_pos.contains(&close_pos) {
return None;
return Err(Error::CursorOverlap);
}
change_pos.extend_from_slice(&[open_pos, close_pos]);
}
Some(change_pos)
Ok(change_pos)
}
#[cfg(test)]
@@ -178,67 +244,92 @@ mod test {
use ropey::Rope;
use smallvec::SmallVec;
#[test]
fn test_find_nth_pairs_pos() {
let doc = Rope::from("some (text) here");
#[allow(clippy::type_complexity)]
fn check_find_nth_pair_pos(
text: &str,
cases: Vec<(usize, char, usize, Result<(usize, usize)>)>,
) {
let doc = Rope::from(text);
let slice = doc.slice(..);
// cursor on [t]ext
assert_eq!(find_nth_pairs_pos(slice, '(', 6, 1), Some((5, 10)));
assert_eq!(find_nth_pairs_pos(slice, ')', 6, 1), Some((5, 10)));
// cursor on so[m]e
assert_eq!(find_nth_pairs_pos(slice, '(', 2, 1), None);
// cursor on bracket itself
assert_eq!(find_nth_pairs_pos(slice, '(', 5, 1), Some((5, 10)));
assert_eq!(find_nth_pairs_pos(slice, '(', 10, 1), Some((5, 10)));
for (cursor_pos, ch, n, expected_range) in cases {
let range = find_nth_pairs_pos(slice, ch, (cursor_pos, cursor_pos + 1).into(), n);
assert_eq!(
range, expected_range,
"Expected {:?}, got {:?}",
expected_range, range
);
}
}
#[test]
fn test_find_nth_pairs_pos() {
check_find_nth_pair_pos(
"some (text) here",
vec![
// cursor on [t]ext
(6, '(', 1, Ok((5, 10))),
(6, ')', 1, Ok((5, 10))),
// cursor on so[m]e
(2, '(', 1, Err(Error::PairNotFound)),
// cursor on bracket itself
(5, '(', 1, Ok((5, 10))),
(10, '(', 1, Ok((5, 10))),
],
);
}
#[test]
fn test_find_nth_pairs_pos_skip() {
let doc = Rope::from("(so (many (good) text) here)");
let slice = doc.slice(..);
// cursor on go[o]d
assert_eq!(find_nth_pairs_pos(slice, '(', 13, 1), Some((10, 15)));
assert_eq!(find_nth_pairs_pos(slice, '(', 13, 2), Some((4, 21)));
assert_eq!(find_nth_pairs_pos(slice, '(', 13, 3), Some((0, 27)));
check_find_nth_pair_pos(
"(so (many (good) text) here)",
vec![
// cursor on go[o]d
(13, '(', 1, Ok((10, 15))),
(13, '(', 2, Ok((4, 21))),
(13, '(', 3, Ok((0, 27))),
],
);
}
#[test]
fn test_find_nth_pairs_pos_same() {
let doc = Rope::from("'so 'many 'good' text' here'");
let slice = doc.slice(..);
// cursor on go[o]d
assert_eq!(find_nth_pairs_pos(slice, '\'', 13, 1), Some((10, 15)));
assert_eq!(find_nth_pairs_pos(slice, '\'', 13, 2), Some((4, 21)));
assert_eq!(find_nth_pairs_pos(slice, '\'', 13, 3), Some((0, 27)));
// cursor on the quotes
assert_eq!(find_nth_pairs_pos(slice, '\'', 10, 1), None);
// this is the best we can do since opening and closing pairs are same
assert_eq!(find_nth_pairs_pos(slice, '\'', 0, 1), Some((0, 4)));
assert_eq!(find_nth_pairs_pos(slice, '\'', 27, 1), Some((21, 27)));
check_find_nth_pair_pos(
"'so 'many 'good' text' here'",
vec![
// cursor on go[o]d
(13, '\'', 1, Ok((10, 15))),
(13, '\'', 2, Ok((4, 21))),
(13, '\'', 3, Ok((0, 27))),
// cursor on the quotes
(10, '\'', 1, Err(Error::CursorOnAmbiguousPair)),
],
)
}
#[test]
fn test_find_nth_pairs_pos_step() {
let doc = Rope::from("((so)((many) good (text))(here))");
let slice = doc.slice(..);
// cursor on go[o]d
assert_eq!(find_nth_pairs_pos(slice, '(', 15, 1), Some((5, 24)));
assert_eq!(find_nth_pairs_pos(slice, '(', 15, 2), Some((0, 31)));
check_find_nth_pair_pos(
"((so)((many) good (text))(here))",
vec![
// cursor on go[o]d
(15, '(', 1, Ok((5, 24))),
(15, '(', 2, Ok((0, 31))),
],
)
}
#[test]
fn test_find_nth_pairs_pos_mixed() {
let doc = Rope::from("(so [many {good} text] here)");
let slice = doc.slice(..);
// cursor on go[o]d
assert_eq!(find_nth_pairs_pos(slice, '{', 13, 1), Some((10, 15)));
assert_eq!(find_nth_pairs_pos(slice, '[', 13, 1), Some((4, 21)));
assert_eq!(find_nth_pairs_pos(slice, '(', 13, 1), Some((0, 27)));
check_find_nth_pair_pos(
"(so [many {good} text] here)",
vec![
// cursor on go[o]d
(13, '{', 1, Ok((10, 15))),
(13, '[', 1, Ok((4, 21))),
(13, '(', 1, Ok((0, 27))),
],
)
}
#[test]
@@ -252,7 +343,7 @@ mod test {
// cursor on s[o]me, c[h]ars, newl[i]ne
assert_eq!(
get_surround_pos(slice, &selection, '(', 1)
get_surround_pos(slice, &selection, Some('('), 1)
.unwrap()
.as_slice(),
&[0, 5, 7, 13, 15, 23]
@@ -266,11 +357,10 @@ mod test {
let selection =
Selection::new(SmallVec::from_slice(&[Range::point(2), Range::point(9)]), 0);
// cursor on s[o]me, c[h]ars
assert_eq!(
get_surround_pos(slice, &selection, '(', 1),
None // different surround chars
get_surround_pos(slice, &selection, Some('('), 1),
Err(Error::PairNotFound) // different surround chars
);
let selection = Selection::new(
@@ -279,8 +369,16 @@ mod test {
);
// cursor on [x]x, newli[n]e
assert_eq!(
get_surround_pos(slice, &selection, '(', 1),
None // overlapping surround chars
get_surround_pos(slice, &selection, Some('('), 1),
Err(Error::PairNotFound) // overlapping surround chars
);
let selection =
Selection::new(SmallVec::from_slice(&[Range::point(2), Range::point(3)]), 0);
// cursor on s[o][m]e
assert_eq!(
get_surround_pos(slice, &selection, Some('['), 1),
Err(Error::CursorOverlap)
);
}
}

File diff suppressed because it is too large Load Diff

265
helix-core/src/test.rs Normal file
View File

@@ -0,0 +1,265 @@
//! Test helpers.
use crate::{Range, Selection};
use smallvec::SmallVec;
use std::cmp::Reverse;
/// Convert annotated test string to test string and selection.
///
/// `#[|` for primary selection with head before anchor followed by `]#`.
/// `#(|` for secondary selection with head before anchor followed by `)#`.
/// `#[` for primary selection with head after anchor followed by `|]#`.
/// `#(` for secondary selection with head after anchor followed by `|)#`.
///
/// # Examples
///
/// ```
/// use helix_core::{Range, Selection, test::print};
/// use smallvec::smallvec;
///
/// assert_eq!(
/// print("#[a|]#b#(|c)#"),
/// ("abc".to_owned(), Selection::new(smallvec![Range::new(0, 1), Range::new(3, 2)], 0))
/// );
/// ```
///
/// # Panics
///
/// Panics when missing primary or appeared more than once.
/// Panics when missing head or anchor.
/// Panics when head come after head or anchor come after anchor.
pub fn print(s: &str) -> (String, Selection) {
let mut primary_idx = None;
let mut ranges = SmallVec::new();
let mut iter = s.chars().peekable();
let mut left = String::with_capacity(s.len());
'outer: while let Some(c) = iter.next() {
let start = left.chars().count();
if c != '#' {
left.push(c);
continue;
}
let (is_primary, close_pair) = match iter.next() {
Some('[') => (true, ']'),
Some('(') => (false, ')'),
Some(ch) => {
left.push('#');
left.push(ch);
continue;
}
None => break,
};
if is_primary && primary_idx.is_some() {
panic!("primary `#[` already appeared {:?} {:?}", left, s);
}
let head_at_beg = iter.next_if_eq(&'|').is_some();
while let Some(c) = iter.next() {
if !(c == close_pair && iter.peek() == Some(&'#')) {
left.push(c);
continue;
}
if !head_at_beg {
let prev = left.pop().unwrap();
if prev != '|' {
left.push(prev);
left.push(c);
continue;
}
}
iter.next(); // skip "#"
if is_primary {
primary_idx = Some(ranges.len());
}
let (anchor, head) = match head_at_beg {
true => (left.chars().count(), start),
false => (start, left.chars().count()),
};
ranges.push(Range::new(anchor, head));
continue 'outer;
}
if head_at_beg {
panic!("missing end `{}#` {:?} {:?}", close_pair, left, s);
} else {
panic!("missing end `|{}#` {:?} {:?}", close_pair, left, s);
}
}
let primary = match primary_idx {
Some(i) => i,
None => panic!("missing primary `#[|]#` {:?}", s),
};
let selection = Selection::new(ranges, primary);
(left, selection)
}
/// Convert test string and selection to annotated test string.
///
/// `#[|` for primary selection with head before anchor followed by `]#`.
/// `#(|` for secondary selection with head before anchor followed by `)#`.
/// `#[` for primary selection with head after anchor followed by `|]#`.
/// `#(` for secondary selection with head after anchor followed by `|)#`.
///
/// # Examples
///
/// ```
/// use helix_core::{Range, Selection, test::plain};
/// use smallvec::smallvec;
///
/// assert_eq!(
/// plain("abc", Selection::new(smallvec![Range::new(0, 1), Range::new(3, 2)], 0)),
/// "#[a|]#b#(|c)#".to_owned()
/// );
/// ```
pub fn plain(s: &str, selection: Selection) -> String {
let primary = selection.primary_index();
let mut out = String::with_capacity(s.len() + 5 * selection.len());
out.push_str(s);
let mut insertion: Vec<_> = selection
.iter()
.enumerate()
.flat_map(|(i, range)| {
// sort like this before reversed so anchor < head later
match (range.anchor < range.head, i == primary) {
(true, true) => [(range.anchor, "#["), (range.head, "|]#")],
(true, false) => [(range.anchor, "#("), (range.head, "|)#")],
(false, true) => [(range.anchor, "]#"), (range.head, "#[|")],
(false, false) => [(range.anchor, ")#"), (range.head, "#(|")],
}
})
.collect();
// insert in reverse order
insertion.sort_unstable_by_key(|k| Reverse(k.0));
for (i, s) in insertion {
out.insert_str(i, s);
}
out
}
#[cfg(test)]
#[allow(clippy::module_inception)]
mod test {
use super::*;
#[test]
fn print_single() {
assert_eq!(
(String::from("hello"), Selection::single(1, 0)),
print("#[|h]#ello")
);
assert_eq!(
(String::from("hello"), Selection::single(0, 1)),
print("#[h|]#ello")
);
assert_eq!(
(String::from("hello"), Selection::single(4, 0)),
print("#[|hell]#o")
);
assert_eq!(
(String::from("hello"), Selection::single(0, 4)),
print("#[hell|]#o")
);
assert_eq!(
(String::from("hello"), Selection::single(5, 0)),
print("#[|hello]#")
);
assert_eq!(
(String::from("hello"), Selection::single(0, 5)),
print("#[hello|]#")
);
}
#[test]
fn print_multi() {
assert_eq!(
(
String::from("hello"),
Selection::new(
SmallVec::from_slice(&[Range::new(1, 0), Range::new(5, 4)]),
0
)
),
print("#[|h]#ell#(|o)#")
);
assert_eq!(
(
String::from("hello"),
Selection::new(
SmallVec::from_slice(&[Range::new(0, 1), Range::new(4, 5)]),
0
)
),
print("#[h|]#ell#(o|)#")
);
assert_eq!(
(
String::from("hello"),
Selection::new(
SmallVec::from_slice(&[Range::new(2, 0), Range::new(5, 3)]),
0
)
),
print("#[|he]#l#(|lo)#")
);
assert_eq!(
(
String::from("hello\r\nhello\r\nhello\r\n"),
Selection::new(
SmallVec::from_slice(&[
Range::new(7, 5),
Range::new(21, 19),
Range::new(14, 12)
]),
0
)
),
print("hello#[|\r\n]#hello#(|\r\n)#hello#(|\r\n)#")
);
}
#[test]
fn print_multi_byte_code_point() {
assert_eq!(
(String::from("„“"), Selection::single(1, 0)),
print("#[|„]#“")
);
assert_eq!(
(String::from("„“"), Selection::single(2, 1)),
print("„#[|“]#")
);
assert_eq!(
(String::from("„“"), Selection::single(0, 1)),
print("#[„|]#“")
);
assert_eq!(
(String::from("„“"), Selection::single(1, 2)),
print("„#[“|]#")
);
assert_eq!(
(String::from("they said „hello“"), Selection::single(11, 10)),
print("they said #[|„]#hello“")
);
}
#[test]
fn print_multi_code_point_grapheme() {
assert_eq!(
(
String::from("hello 👨‍👩‍👧‍👦 goodbye"),
Selection::single(13, 6)
),
print("hello #[|👨‍👩‍👧‍👦]# goodbye")
);
}
}

View File

@@ -4,13 +4,14 @@ use ropey::RopeSlice;
use tree_sitter::{Node, QueryCursor};
use crate::chars::{categorize_char, char_is_whitespace, CharCategory};
use crate::graphemes::next_grapheme_boundary;
use crate::graphemes::{next_grapheme_boundary, prev_grapheme_boundary};
use crate::line_ending::rope_is_line_ending;
use crate::movement::Direction;
use crate::surround;
use crate::syntax::LanguageConfiguration;
use crate::Range;
fn find_word_boundary(slice: RopeSlice, mut pos: usize, direction: Direction) -> usize {
fn find_word_boundary(slice: RopeSlice, mut pos: usize, direction: Direction, long: bool) -> usize {
use CharCategory::{Eol, Whitespace};
let iter = match direction {
@@ -33,7 +34,7 @@ fn find_word_boundary(slice: RopeSlice, mut pos: usize, direction: Direction) ->
match categorize_char(ch) {
Eol | Whitespace => return pos,
category => {
if category != prev_category && pos != 0 && pos != slice.len_chars() {
if !long && category != prev_category && pos != 0 && pos != slice.len_chars() {
return pos;
} else {
match direction {
@@ -53,6 +54,8 @@ fn find_word_boundary(slice: RopeSlice, mut pos: usize, direction: Direction) ->
pub enum TextObject {
Around,
Inside,
/// Used for moving between objects.
Movement,
}
impl Display for TextObject {
@@ -60,6 +63,7 @@ impl Display for TextObject {
f.write_str(match self {
Self::Around => "around",
Self::Inside => "inside",
Self::Movement => "movement",
})
}
}
@@ -70,13 +74,14 @@ pub fn textobject_word(
range: Range,
textobject: TextObject,
_count: usize,
long: bool,
) -> Range {
let pos = range.cursor(slice);
let word_start = find_word_boundary(slice, pos, Direction::Backward);
let word_start = find_word_boundary(slice, pos, Direction::Backward, long);
let word_end = match slice.get_char(pos).map(categorize_char) {
None | Some(CharCategory::Whitespace | CharCategory::Eol) => pos,
_ => find_word_boundary(slice, pos + 1, Direction::Forward),
_ => find_word_boundary(slice, pos + 1, Direction::Forward, long),
};
// Special case.
@@ -103,20 +108,132 @@ pub fn textobject_word(
Range::new(word_start - whitespace_count_left, word_end)
}
}
TextObject::Movement => unreachable!(),
}
}
pub fn textobject_surround(
pub fn textobject_paragraph(
slice: RopeSlice,
range: Range,
textobject: TextObject,
count: usize,
) -> Range {
let mut line = range.cursor_line(slice);
let prev_line_empty = rope_is_line_ending(slice.line(line.saturating_sub(1)));
let curr_line_empty = rope_is_line_ending(slice.line(line));
let next_line_empty = rope_is_line_ending(slice.line(line.saturating_sub(1)));
let last_char =
prev_grapheme_boundary(slice, slice.line_to_char(line + 1)) == range.cursor(slice);
let prev_empty_to_line = prev_line_empty && !curr_line_empty;
let curr_empty_to_line = curr_line_empty && !next_line_empty;
// skip character before paragraph boundary
let mut line_back = line; // line but backwards
if prev_empty_to_line || curr_empty_to_line {
line_back += 1;
}
// do not include current paragraph on paragraph end (include next)
if !(curr_empty_to_line && last_char) {
let mut lines = slice.lines_at(line_back);
lines.reverse();
let mut lines = lines.map(rope_is_line_ending).peekable();
while lines.next_if(|&e| e).is_some() {
line_back -= 1;
}
while lines.next_if(|&e| !e).is_some() {
line_back -= 1;
}
}
// skip character after paragraph boundary
if curr_empty_to_line && last_char {
line += 1;
}
let mut lines = slice.lines_at(line).map(rope_is_line_ending).peekable();
let mut count_done = 0; // count how many non-whitespace paragraphs done
for _ in 0..count {
let mut done = false;
while lines.next_if(|&e| !e).is_some() {
line += 1;
done = true;
}
while lines.next_if(|&e| e).is_some() {
line += 1;
}
count_done += done as usize;
}
// search one paragraph backwards for last paragraph
// makes `map` at the end of the paragraph with trailing newlines useful
let last_paragraph = count_done != count && lines.peek().is_none();
if last_paragraph {
let mut lines = slice.lines_at(line_back);
lines.reverse();
let mut lines = lines.map(rope_is_line_ending).peekable();
while lines.next_if(|&e| e).is_some() {
line_back -= 1;
}
while lines.next_if(|&e| !e).is_some() {
line_back -= 1;
}
}
// handle last whitespaces part separately depending on textobject
match textobject {
TextObject::Around => {}
TextObject::Inside => {
// remove last whitespace paragraph
let mut lines = slice.lines_at(line);
lines.reverse();
let mut lines = lines.map(rope_is_line_ending).peekable();
while lines.next_if(|&e| e).is_some() {
line -= 1;
}
}
TextObject::Movement => unreachable!(),
}
let anchor = slice.line_to_char(line_back);
let head = slice.line_to_char(line);
Range::new(anchor, head)
}
pub fn textobject_pair_surround(
slice: RopeSlice,
range: Range,
textobject: TextObject,
ch: char,
count: usize,
) -> Range {
surround::find_nth_pairs_pos(slice, ch, range.head, count)
textobject_pair_surround_impl(slice, range, textobject, Some(ch), count)
}
pub fn textobject_pair_surround_closest(
slice: RopeSlice,
range: Range,
textobject: TextObject,
count: usize,
) -> Range {
textobject_pair_surround_impl(slice, range, textobject, None, count)
}
fn textobject_pair_surround_impl(
slice: RopeSlice,
range: Range,
textobject: TextObject,
ch: Option<char>,
count: usize,
) -> Range {
let pair_pos = match ch {
Some(ch) => surround::find_nth_pairs_pos(slice, ch, range, count),
// Automatically find the closest surround pairs
None => surround::find_nth_closest_pairs_pos(slice, range, count),
};
pair_pos
.map(|(anchor, head)| match textobject {
TextObject::Inside => Range::new(next_grapheme_boundary(slice, anchor), head),
TextObject::Around => Range::new(anchor, next_grapheme_boundary(slice, head)),
TextObject::Movement => unreachable!(),
})
.unwrap_or(range)
}
@@ -169,7 +286,7 @@ mod test {
#[test]
fn test_textobject_word() {
// (text, [(cursor position, textobject, final range), ...])
// (text, [(char position, textobject, final range), ...])
let tests = &[
(
"cursor at beginning of doc",
@@ -268,7 +385,9 @@ mod test {
let slice = doc.slice(..);
for &case in scenario {
let (pos, objtype, expected_range) = case;
let result = textobject_word(slice, Range::point(pos), objtype, 1);
// cursor is a single width selection
let range = Range::new(pos, pos + 1);
let result = textobject_word(slice, range, objtype, 1, false);
assert_eq!(
result,
expected_range.into(),
@@ -280,9 +399,94 @@ mod test {
}
}
#[test]
fn test_textobject_paragraph_inside_single() {
let tests = [
("#[|]#", "#[|]#"),
("firs#[t|]#\n\nparagraph\n\n", "#[first\n|]#\nparagraph\n\n"),
(
"second\n\npa#[r|]#agraph\n\n",
"second\n\n#[paragraph\n|]#\n",
),
("#[f|]#irst char\n\n", "#[first char\n|]#\n"),
("last char\n#[\n|]#", "#[last char\n|]#\n"),
(
"empty to line\n#[\n|]#paragraph boundary\n\n",
"empty to line\n\n#[paragraph boundary\n|]#\n",
),
(
"line to empty\n\n#[p|]#aragraph boundary\n\n",
"line to empty\n\n#[paragraph boundary\n|]#\n",
),
];
for (before, expected) in tests {
let (s, selection) = crate::test::print(before);
let text = Rope::from(s.as_str());
let selection = selection
.transform(|r| textobject_paragraph(text.slice(..), r, TextObject::Inside, 1));
let actual = crate::test::plain(&s, selection);
assert_eq!(actual, expected, "\nbefore: `{:?}`", before);
}
}
#[test]
fn test_textobject_paragraph_inside_double() {
let tests = [
(
"last two\n\n#[p|]#aragraph\n\nwithout whitespaces\n\n",
"last two\n\n#[paragraph\n\nwithout whitespaces\n|]#\n",
),
(
"last two\n#[\n|]#paragraph\n\nwithout whitespaces\n\n",
"last two\n\n#[paragraph\n\nwithout whitespaces\n|]#\n",
),
];
for (before, expected) in tests {
let (s, selection) = crate::test::print(before);
let text = Rope::from(s.as_str());
let selection = selection
.transform(|r| textobject_paragraph(text.slice(..), r, TextObject::Inside, 2));
let actual = crate::test::plain(&s, selection);
assert_eq!(actual, expected, "\nbefore: `{:?}`", before);
}
}
#[test]
fn test_textobject_paragraph_around_single() {
let tests = [
("#[|]#", "#[|]#"),
("firs#[t|]#\n\nparagraph\n\n", "#[first\n\n|]#paragraph\n\n"),
(
"second\n\npa#[r|]#agraph\n\n",
"second\n\n#[paragraph\n\n|]#",
),
("#[f|]#irst char\n\n", "#[first char\n\n|]#"),
("last char\n#[\n|]#", "#[last char\n\n|]#"),
(
"empty to line\n#[\n|]#paragraph boundary\n\n",
"empty to line\n\n#[paragraph boundary\n\n|]#",
),
(
"line to empty\n\n#[p|]#aragraph boundary\n\n",
"line to empty\n\n#[paragraph boundary\n\n|]#",
),
];
for (before, expected) in tests {
let (s, selection) = crate::test::print(before);
let text = Rope::from(s.as_str());
let selection = selection
.transform(|r| textobject_paragraph(text.slice(..), r, TextObject::Around, 1));
let actual = crate::test::plain(&s, selection);
assert_eq!(actual, expected, "\nbefore: `{:?}`", before);
}
}
#[test]
fn test_textobject_surround() {
// (text, [(cursor position, textobject, final range, count), ...])
// (text, [(cursor position, textobject, final range, surround char, count), ...])
let tests = &[
(
"simple (single) surround pairs",
@@ -358,7 +562,7 @@ mod test {
let slice = doc.slice(..);
for &case in scenario {
let (pos, objtype, expected_range, ch, count) = case;
let result = textobject_surround(slice, Range::point(pos), objtype, ch, count);
let result = textobject_pair_surround(slice, Range::point(pos), objtype, ch, count);
assert_eq!(
result,
expected_range.into(),

View File

@@ -21,8 +21,7 @@ pub enum Assoc {
After,
}
// ChangeSpec = Change | ChangeSet | Vec<Change>
#[derive(Debug, Clone, PartialEq, Eq)]
#[derive(Debug, Default, Clone, PartialEq, Eq)]
pub struct ChangeSet {
pub(crate) changes: Vec<Operation>,
/// The required document length. Will refuse to apply changes unless it matches.
@@ -30,16 +29,6 @@ pub struct ChangeSet {
len_after: usize,
}
impl Default for ChangeSet {
fn default() -> Self {
Self {
changes: Vec::new(),
len: 0,
len_after: 0,
}
}
}
impl ChangeSet {
pub fn with_capacity(capacity: usize) -> Self {
Self {
@@ -60,7 +49,6 @@ impl ChangeSet {
}
// TODO: from iter
//
#[doc(hidden)] // used by lsp to convert to LSP changes
pub fn changes(&self) -> &[Operation] {
@@ -68,7 +56,7 @@ impl ChangeSet {
}
// Changeset builder operations: delete/insert/retain
fn delete(&mut self, n: usize) {
pub(crate) fn delete(&mut self, n: usize) {
use Operation::*;
if n == 0 {
return;
@@ -83,7 +71,7 @@ impl ChangeSet {
}
}
fn insert(&mut self, fragment: Tendril) {
pub(crate) fn insert(&mut self, fragment: Tendril) {
use Operation::*;
if fragment.is_empty() {
@@ -95,7 +83,7 @@ impl ChangeSet {
let new_last = match self.changes.as_mut_slice() {
[.., Insert(prev)] | [.., Insert(prev), Delete(_)] => {
prev.push_tendril(&fragment);
prev.push_str(&fragment);
return;
}
[.., last @ Delete(_)] => std::mem::replace(last, Insert(fragment)),
@@ -105,7 +93,7 @@ impl ChangeSet {
self.changes.push(new_last);
}
fn retain(&mut self, n: usize) {
pub(crate) fn retain(&mut self, n: usize) {
use Operation::*;
if n == 0 {
return;
@@ -199,7 +187,7 @@ impl ChangeSet {
// TODO: cover this with a test
// figure out the byte index of the truncated string end
let (pos, _) = s.char_indices().nth(j).unwrap();
s.pop_front(pos as u32);
s.replace_range(0..pos, "");
head_a = Some(Insert(s));
head_b = changes_b.next();
}
@@ -221,9 +209,11 @@ impl ChangeSet {
Ordering::Greater => {
// figure out the byte index of the truncated string end
let (pos, _) = s.char_indices().nth(j).unwrap();
let pos = pos as u32;
changes.insert(s.subtendril(0, pos));
head_a = Some(Insert(s.subtendril(pos, s.len() as u32 - pos)));
let mut before = s;
let after = before.split_off(pos);
changes.insert(before);
head_a = Some(Insert(after));
head_b = changes_b.next();
}
}
@@ -287,7 +277,7 @@ impl ChangeSet {
}
Delete(n) => {
let text = Cow::from(original_doc.slice(pos..pos + *n));
changes.insert(Tendril::from_slice(&text));
changes.insert(Tendril::from(text.as_ref()));
pos += n;
}
Insert(s) => {
@@ -330,7 +320,7 @@ impl ChangeSet {
/// `true` when the set is empty.
#[inline]
pub fn is_empty(&self) -> bool {
self.changes.is_empty()
self.changes.is_empty() || self.changes == [Operation::Retain(self.len)]
}
/// Map a position through the changes.
@@ -419,12 +409,10 @@ impl ChangeSet {
/// Transaction represents a single undoable unit of changes. Several changes can be grouped into
/// a single transaction.
#[derive(Debug, Default, Clone)]
#[derive(Debug, Default, Clone, PartialEq, Eq)]
pub struct Transaction {
changes: ChangeSet,
selection: Option<Selection>,
// effects, annotations
// scroll_into_view
}
impl Transaction {
@@ -448,14 +436,12 @@ impl Transaction {
/// Returns true if applied successfully.
pub fn apply(&self, doc: &mut Rope) -> bool {
if !self.changes.is_empty() {
// apply changes to the document
if !self.changes.apply(doc) {
return false;
}
if self.changes.is_empty() {
return true;
}
true
// apply changes to the document
self.changes.apply(doc)
}
/// Generate a transaction that reverts this one.
@@ -483,7 +469,7 @@ impl Transaction {
/// Generate a transaction from a set of changes.
pub fn change<I>(doc: &Rope, changes: I) -> Self
where
I: IntoIterator<Item = Change> + Iterator,
I: Iterator<Item = Change>,
{
let len = doc.len_chars();
@@ -491,12 +477,11 @@ impl Transaction {
let size = upper.unwrap_or(lower);
let mut changeset = ChangeSet::with_capacity(2 * size + 1); // rough estimate
// TODO: verify ranges are ordered and not overlapping or change will panic.
// TODO: test for (pos, pos, None) to factor out as nothing
let mut last = 0;
for (from, to, tendril) in changes {
// Verify ranges are ordered and not overlapping
debug_assert!(last <= from);
// Retain from last "to" to current "from"
changeset.retain(from - last);
let span = to - from;
@@ -592,7 +577,7 @@ impl<'a> Iterator for ChangeIterator<'a> {
#[cfg(test)]
mod test {
use super::*;
use crate::State;
use crate::history::State;
#[test]
fn composition() {
@@ -702,7 +687,7 @@ mod test {
let mut doc = Rope::from("hello world!\ntest 123");
let transaction = Transaction::change(
&doc,
// (1, 1, None) is a useless 0-width delete
// (1, 1, None) is a useless 0-width delete that gets factored out
vec![(1, 1, None), (6, 11, Some("void".into())), (12, 17, None)].into_iter(),
);
transaction.apply(&mut doc);
@@ -719,20 +704,23 @@ mod test {
#[test]
fn optimized_composition() {
let mut state = State::new("".into());
let t1 = Transaction::insert(&state.doc, &state.selection, Tendril::from_char('h'));
let mut state = State {
doc: "".into(),
selection: Selection::point(0),
};
let t1 = Transaction::insert(&state.doc, &state.selection, Tendril::from("h"));
t1.apply(&mut state.doc);
state.selection = state.selection.clone().map(t1.changes());
let t2 = Transaction::insert(&state.doc, &state.selection, Tendril::from_char('e'));
let t2 = Transaction::insert(&state.doc, &state.selection, Tendril::from("e"));
t2.apply(&mut state.doc);
state.selection = state.selection.clone().map(t2.changes());
let t3 = Transaction::insert(&state.doc, &state.selection, Tendril::from_char('l'));
let t3 = Transaction::insert(&state.doc, &state.selection, Tendril::from("l"));
t3.apply(&mut state.doc);
state.selection = state.selection.clone().map(t3.changes());
let t4 = Transaction::insert(&state.doc, &state.selection, Tendril::from_char('l'));
let t4 = Transaction::insert(&state.doc, &state.selection, Tendril::from("l"));
t4.apply(&mut state.doc);
state.selection = state.selection.clone().map(t4.changes());
let t5 = Transaction::insert(&state.doc, &state.selection, Tendril::from_char('o'));
let t5 = Transaction::insert(&state.doc, &state.selection, Tendril::from("o"));
t5.apply(&mut state.doc);
state.selection = state.selection.clone().map(t5.changes());
@@ -771,7 +759,7 @@ mod test {
#[test]
fn combine_with_utf8() {
const TEST_CASE: &'static str = "Hello, これはヘリックスエディターです!";
const TEST_CASE: &str = "Hello, これはヘリックスエディターです!";
let empty = Rope::from("");
let a = ChangeSet::new(&empty);

7
helix-core/src/wrap.rs Normal file
View File

@@ -0,0 +1,7 @@
use smartstring::{LazyCompact, SmartString};
/// Given a slice of text, return the text re-wrapped to fit it
/// within the given width.
pub fn reflow_hard_wrap(text: &str, max_line_len: usize) -> SmartString<LazyCompact> {
textwrap::refill(text, max_line_len).into()
}

View File

@@ -0,0 +1 @@
../../../src/indent.rs

View File

@@ -0,0 +1,13 @@
# This languages.toml should contain definitions for all languages for which we have indent tests
[[language]]
name = "rust"
scope = "source.rust"
injection-regex = "rust"
file-types = ["rs"]
comment-token = "//"
roots = ["Cargo.toml", "Cargo.lock"]
indent = { tab-width = 4, unit = " " }
[[grammar]]
name = "rust"
source = { git = "https://github.com/tree-sitter/tree-sitter-rust", rev = "0431a2c60828731f27491ee9fdefe25e250ce9c9" }

View File

@@ -0,0 +1,105 @@
use std::{
io::{self, stdout, Stdout, Write},
path::PathBuf,
sync::Arc,
time::Duration,
};
mod test {
fn hello_world() {
1 + 1;
let does_indentation_work = 1;
let mut really_long_variable_name_using_up_the_line =
really_long_fn_that_should_definitely_go_on_the_next_line();
really_long_variable_name_using_up_the_line =
really_long_fn_that_should_definitely_go_on_the_next_line();
really_long_variable_name_using_up_the_line |=
really_long_fn_that_should_definitely_go_on_the_next_line();
let (
a_long_variable_name_in_this_tuple,
b_long_variable_name_in_this_tuple,
c_long_variable_name_in_this_tuple,
d_long_variable_name_in_this_tuple,
e_long_variable_name_in_this_tuple,
): (usize, usize, usize, usize, usize) =
if really_long_fn_that_should_definitely_go_on_the_next_line() {
(
03294239434,
1213412342314,
21231234134,
834534234549898789,
9879234234543853457,
)
} else {
(0, 1, 2, 3, 4)
};
let test_function = function_with_param(this_param,
that_param
);
let test_function = function_with_param(
this_param,
that_param
);
let test_function = function_with_proper_indent(param1,
param2,
);
let selection = Selection::new(
changes
.clone()
.map(|(start, end, text): (usize, usize, Option<Tendril>)| {
let len = text.map(|text| text.len()).unwrap() - 1; // minus newline
let pos = start + len;
Range::new(pos, pos)
})
.collect(),
0,
);
return;
}
}
impl<A, D> MyTrait<A, D> for YourType
where
A: TraitB + TraitC,
D: TraitE + TraitF,
{
}
#[test]
//
match test {
Some(a) => 1,
None => {
unimplemented!()
}
}
std::panic::set_hook(Box::new(move |info| {
hook(info);
}));
{ { {
1
}}}
pub fn change<I>(document: &Document, changes: I) -> Self
where
I: IntoIterator<Item = Change> + ExactSizeIterator,
{
[
1,
2,
3,
];
(
1,
2
);
true
}

View File

@@ -0,0 +1,69 @@
use helix_core::{
indent::{treesitter_indent_for_pos, IndentStyle},
syntax::Loader,
Syntax,
};
use std::path::PathBuf;
#[test]
fn test_treesitter_indent_rust() {
test_treesitter_indent("rust.rs", "source.rust");
}
#[test]
fn test_treesitter_indent_rust_2() {
test_treesitter_indent("indent.rs", "source.rust");
// TODO Use commands.rs as indentation test.
// Currently this fails because we can't align the parameters of a closure yet
// test_treesitter_indent("commands.rs", "source.rust");
}
fn test_treesitter_indent(file_name: &str, lang_scope: &str) {
let mut test_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
test_dir.push("tests/data/indent");
let mut test_file = test_dir.clone();
test_file.push(file_name);
let test_file = std::fs::File::open(test_file).unwrap();
let doc = ropey::Rope::from_reader(test_file).unwrap();
let mut config_file = test_dir;
config_file.push("languages.toml");
let config = std::fs::read(config_file).unwrap();
let config = toml::from_slice(&config).unwrap();
let loader = Loader::new(config);
// set runtime path so we can find the queries
let mut runtime = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
runtime.push("../runtime");
std::env::set_var("HELIX_RUNTIME", runtime.to_str().unwrap());
let language_config = loader.language_config_for_scope(lang_scope).unwrap();
let highlight_config = language_config.highlight_config(&[]).unwrap();
let syntax = Syntax::new(&doc, highlight_config, std::sync::Arc::new(loader));
let indent_query = language_config.indent_query().unwrap();
let text = doc.slice(..);
for i in 0..doc.len_lines() {
let line = text.line(i);
if let Some(pos) = helix_core::find_first_non_whitespace_char(line) {
let suggested_indent = treesitter_indent_for_pos(
indent_query,
&syntax,
&IndentStyle::Spaces(4),
4,
text,
i,
text.line_to_char(i) + pos,
false,
)
.unwrap();
assert!(
line.get_slice(..pos).map_or(false, |s| s == suggested_indent),
"Wrong indentation on line {}:\n\"{}\" (original line)\n\"{}\" (suggested indentation)\n",
i+1,
line.slice(..line.len_chars()-1),
suggested_indent,
);
}
}
}

25
helix-dap/Cargo.toml Normal file
View File

@@ -0,0 +1,25 @@
[package]
name = "helix-dap"
version = "0.6.0"
authors = ["Blaž Hrastnik <blaz@mxxn.io>"]
edition = "2018"
license = "MPL-2.0"
description = "DAP client implementation for Helix project"
categories = ["editor"]
repository = "https://github.com/helix-editor/helix"
homepage = "https://helix-editor.com"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
helix-core = { version = "0.6", path = "../helix-core" }
anyhow = "1.0"
log = "0.4"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
thiserror = "1.0"
tokio = { version = "1", features = ["rt", "rt-multi-thread", "io-util", "io-std", "time", "process", "macros", "fs", "parking_lot", "net", "sync"] }
which = "4.2"
[dev-dependencies]
fern = "0.6"

480
helix-dap/src/client.rs Normal file
View File

@@ -0,0 +1,480 @@
use crate::{
transport::{Payload, Request, Response, Transport},
types::*,
Error, Result, ThreadId,
};
use helix_core::syntax::DebuggerQuirks;
use serde_json::Value;
use anyhow::anyhow;
pub use log::{error, info};
use std::{
collections::HashMap,
future::Future,
net::{IpAddr, Ipv4Addr, SocketAddr},
path::PathBuf,
process::Stdio,
sync::atomic::{AtomicU64, Ordering},
};
use tokio::{
io::{AsyncBufRead, AsyncWrite, BufReader, BufWriter},
net::TcpStream,
process::{Child, Command},
sync::mpsc::{channel, unbounded_channel, UnboundedReceiver, UnboundedSender},
time,
};
#[derive(Debug)]
pub struct Client {
id: usize,
_process: Option<Child>,
server_tx: UnboundedSender<Payload>,
request_counter: AtomicU64,
pub caps: Option<DebuggerCapabilities>,
// thread_id -> frames
pub stack_frames: HashMap<ThreadId, Vec<StackFrame>>,
pub thread_states: ThreadStates,
pub thread_id: Option<ThreadId>,
/// Currently active frame for the current thread.
pub active_frame: Option<usize>,
pub quirks: DebuggerQuirks,
}
impl Client {
// Spawn a process and communicate with it by either TCP or stdio
pub async fn process(
transport: &str,
command: &str,
args: Vec<&str>,
port_arg: Option<&str>,
id: usize,
) -> Result<(Self, UnboundedReceiver<Payload>)> {
if command.is_empty() {
return Result::Err(Error::Other(anyhow!("Command not provided")));
}
if transport == "tcp" && port_arg.is_some() {
Self::tcp_process(command, args, port_arg.unwrap(), id).await
} else if transport == "stdio" {
Self::stdio(command, args, id)
} else {
Result::Err(Error::Other(anyhow!("Incorrect transport {}", transport)))
}
}
pub fn streams(
rx: Box<dyn AsyncBufRead + Unpin + Send>,
tx: Box<dyn AsyncWrite + Unpin + Send>,
err: Option<Box<dyn AsyncBufRead + Unpin + Send>>,
id: usize,
process: Option<Child>,
) -> Result<(Self, UnboundedReceiver<Payload>)> {
let (server_rx, server_tx) = Transport::start(rx, tx, err, id);
let (client_rx, client_tx) = unbounded_channel();
let client = Self {
id,
_process: process,
server_tx,
request_counter: AtomicU64::new(0),
caps: None,
//
stack_frames: HashMap::new(),
thread_states: HashMap::new(),
thread_id: None,
active_frame: None,
quirks: DebuggerQuirks::default(),
};
tokio::spawn(Self::recv(server_rx, client_rx));
Ok((client, client_tx))
}
pub async fn tcp(
addr: std::net::SocketAddr,
id: usize,
) -> Result<(Self, UnboundedReceiver<Payload>)> {
let stream = TcpStream::connect(addr).await?;
let (rx, tx) = stream.into_split();
Self::streams(Box::new(BufReader::new(rx)), Box::new(tx), None, id, None)
}
pub fn stdio(
cmd: &str,
args: Vec<&str>,
id: usize,
) -> Result<(Self, UnboundedReceiver<Payload>)> {
// Resolve path to the binary
let cmd = which::which(cmd).map_err(|err| anyhow::anyhow!(err))?;
let process = Command::new(cmd)
.args(args)
.stdin(Stdio::piped())
.stdout(Stdio::piped())
// make sure the process is reaped on drop
.kill_on_drop(true)
.spawn();
let mut process = process?;
// TODO: do we need bufreader/writer here? or do we use async wrappers on unblock?
let writer = BufWriter::new(process.stdin.take().expect("Failed to open stdin"));
let reader = BufReader::new(process.stdout.take().expect("Failed to open stdout"));
let errors = process.stderr.take().map(BufReader::new);
Self::streams(
Box::new(BufReader::new(reader)),
Box::new(writer),
// errors.map(|errors| Box::new(BufReader::new(errors))),
match errors {
Some(errors) => Some(Box::new(BufReader::new(errors))),
None => None,
},
id,
Some(process),
)
}
async fn get_port() -> Option<u16> {
Some(
tokio::net::TcpListener::bind(SocketAddr::new(
IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)),
0,
))
.await
.ok()?
.local_addr()
.ok()?
.port(),
)
}
pub async fn tcp_process(
cmd: &str,
args: Vec<&str>,
port_format: &str,
id: usize,
) -> Result<(Self, UnboundedReceiver<Payload>)> {
let port = Self::get_port().await.unwrap();
let process = Command::new(cmd)
.args(args)
.args(port_format.replace("{}", &port.to_string()).split(' '))
// silence messages
.stdin(Stdio::null())
.stdout(Stdio::null())
.stderr(Stdio::null())
// Do not kill debug adapter when leaving, it should exit automatically
.spawn()?;
// Wait for adapter to become ready for connection
time::sleep(time::Duration::from_millis(500)).await;
let stream = TcpStream::connect(SocketAddr::new(
IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)),
port,
))
.await?;
let (rx, tx) = stream.into_split();
Self::streams(
Box::new(BufReader::new(rx)),
Box::new(tx),
None,
id,
Some(process),
)
}
async fn recv(mut server_rx: UnboundedReceiver<Payload>, client_tx: UnboundedSender<Payload>) {
while let Some(msg) = server_rx.recv().await {
match msg {
Payload::Event(ev) => {
client_tx.send(Payload::Event(ev)).expect("Failed to send");
}
Payload::Response(_) => unreachable!(),
Payload::Request(req) => {
client_tx
.send(Payload::Request(req))
.expect("Failed to send");
}
}
}
}
pub fn id(&self) -> usize {
self.id
}
fn next_request_id(&self) -> u64 {
self.request_counter.fetch_add(1, Ordering::Relaxed)
}
// Internal, called by specific DAP commands when resuming
pub fn resume_application(&mut self) {
if let Some(thread_id) = self.thread_id {
self.thread_states.insert(thread_id, "running".to_string());
self.stack_frames.remove(&thread_id);
}
self.active_frame = None;
self.thread_id = None;
}
/// Execute a RPC request on the debugger.
pub fn call<R: crate::types::Request>(
&self,
arguments: R::Arguments,
) -> impl Future<Output = Result<Value>>
where
R::Arguments: serde::Serialize,
{
let server_tx = self.server_tx.clone();
let id = self.next_request_id();
async move {
use std::time::Duration;
use tokio::time::timeout;
let arguments = Some(serde_json::to_value(arguments)?);
let (callback_tx, mut callback_rx) = channel(1);
let req = Request {
back_ch: Some(callback_tx),
seq: id,
command: R::COMMAND.to_string(),
arguments,
};
server_tx
.send(Payload::Request(req))
.map_err(|e| Error::Other(e.into()))?;
// TODO: specifiable timeout, delay other calls until initialize success
timeout(Duration::from_secs(20), callback_rx.recv())
.await
.map_err(|_| Error::Timeout)? // return Timeout
.ok_or(Error::StreamClosed)?
.map(|response| response.body.unwrap_or_default())
// TODO: check response.success
}
}
pub async fn request<R: crate::types::Request>(&self, params: R::Arguments) -> Result<R::Result>
where
R::Arguments: serde::Serialize,
R::Result: core::fmt::Debug, // TODO: temporary
{
// a future that resolves into the response
let json = self.call::<R>(params).await?;
let response = serde_json::from_value(json)?;
Ok(response)
}
pub fn reply(
&self,
request_seq: u64,
command: &str,
result: core::result::Result<Value, Error>,
) -> impl Future<Output = Result<()>> {
let server_tx = self.server_tx.clone();
let command = command.to_string();
async move {
let response = match result {
Ok(result) => Response {
request_seq,
command,
success: true,
message: None,
body: Some(result),
},
Err(error) => Response {
request_seq,
command,
success: false,
message: Some(error.to_string()),
body: None,
},
};
server_tx
.send(Payload::Response(response))
.map_err(|e| Error::Other(e.into()))?;
Ok(())
}
}
pub fn capabilities(&self) -> &DebuggerCapabilities {
self.caps.as_ref().expect("debugger not yet initialized!")
}
pub async fn initialize(&mut self, adapter_id: String) -> Result<()> {
let args = requests::InitializeArguments {
client_id: Some("hx".to_owned()),
client_name: Some("helix".to_owned()),
adapter_id,
locale: Some("en-us".to_owned()),
lines_start_at_one: Some(true),
columns_start_at_one: Some(true),
path_format: Some("path".to_owned()),
supports_variable_type: Some(true),
supports_variable_paging: Some(false),
supports_run_in_terminal_request: Some(true),
supports_memory_references: Some(false),
supports_progress_reporting: Some(false),
supports_invalidated_event: Some(false),
};
let response = self.request::<requests::Initialize>(args).await?;
self.caps = Some(response);
Ok(())
}
pub fn disconnect(&self) -> impl Future<Output = Result<Value>> {
self.call::<requests::Disconnect>(())
}
pub fn launch(&self, args: serde_json::Value) -> impl Future<Output = Result<Value>> {
self.call::<requests::Launch>(args)
}
pub fn attach(&self, args: serde_json::Value) -> impl Future<Output = Result<Value>> {
self.call::<requests::Attach>(args)
}
pub async fn set_breakpoints(
&self,
file: PathBuf,
breakpoints: Vec<SourceBreakpoint>,
) -> Result<Option<Vec<Breakpoint>>> {
let args = requests::SetBreakpointsArguments {
source: Source {
path: Some(file),
name: None,
source_reference: None,
presentation_hint: None,
origin: None,
sources: None,
adapter_data: None,
checksums: None,
},
breakpoints: Some(breakpoints),
source_modified: Some(false),
};
let response = self.request::<requests::SetBreakpoints>(args).await?;
Ok(response.breakpoints)
}
pub async fn configuration_done(&self) -> Result<()> {
self.request::<requests::ConfigurationDone>(()).await
}
pub fn continue_thread(&self, thread_id: ThreadId) -> impl Future<Output = Result<Value>> {
let args = requests::ContinueArguments { thread_id };
self.call::<requests::Continue>(args)
}
pub async fn stack_trace(
&self,
thread_id: ThreadId,
) -> Result<(Vec<StackFrame>, Option<usize>)> {
let args = requests::StackTraceArguments {
thread_id,
start_frame: None,
levels: None,
format: None,
};
let response = self.request::<requests::StackTrace>(args).await?;
Ok((response.stack_frames, response.total_frames))
}
pub fn threads(&self) -> impl Future<Output = Result<Value>> {
self.call::<requests::Threads>(())
}
pub async fn scopes(&self, frame_id: usize) -> Result<Vec<Scope>> {
let args = requests::ScopesArguments { frame_id };
let response = self.request::<requests::Scopes>(args).await?;
Ok(response.scopes)
}
pub async fn variables(&self, variables_reference: usize) -> Result<Vec<Variable>> {
let args = requests::VariablesArguments {
variables_reference,
filter: None,
start: None,
count: None,
format: None,
};
let response = self.request::<requests::Variables>(args).await?;
Ok(response.variables)
}
pub fn step_in(&self, thread_id: ThreadId) -> impl Future<Output = Result<Value>> {
let args = requests::StepInArguments {
thread_id,
target_id: None,
granularity: None,
};
self.call::<requests::StepIn>(args)
}
pub fn step_out(&self, thread_id: ThreadId) -> impl Future<Output = Result<Value>> {
let args = requests::StepOutArguments {
thread_id,
granularity: None,
};
self.call::<requests::StepOut>(args)
}
pub fn next(&self, thread_id: ThreadId) -> impl Future<Output = Result<Value>> {
let args = requests::NextArguments {
thread_id,
granularity: None,
};
self.call::<requests::Next>(args)
}
pub fn pause(&self, thread_id: ThreadId) -> impl Future<Output = Result<Value>> {
let args = requests::PauseArguments { thread_id };
self.call::<requests::Pause>(args)
}
pub async fn eval(
&self,
expression: String,
frame_id: Option<usize>,
) -> Result<requests::EvaluateResponse> {
let args = requests::EvaluateArguments {
expression,
frame_id,
context: None,
format: None,
};
self.request::<requests::Evaluate>(args).await
}
pub fn set_exception_breakpoints(
&self,
filters: Vec<String>,
) -> impl Future<Output = Result<Value>> {
let args = requests::SetExceptionBreakpointsArguments { filters };
self.call::<requests::SetExceptionBreakpoints>(args)
}
}

24
helix-dap/src/lib.rs Normal file
View File

@@ -0,0 +1,24 @@
mod client;
mod transport;
mod types;
pub use client::Client;
pub use events::Event;
pub use transport::{Payload, Response, Transport};
pub use types::*;
use thiserror::Error;
#[derive(Error, Debug)]
pub enum Error {
#[error("failed to parse: {0}")]
Parse(#[from] serde_json::Error),
#[error("IO Error: {0}")]
IO(#[from] std::io::Error),
#[error("request timed out")]
Timeout,
#[error("server closed the stream")]
StreamClosed,
#[error(transparent)]
Other(#[from] anyhow::Error),
}
pub type Result<T> = core::result::Result<T, Error>;

Some files were not shown because too many files have changed in this diff Show More