This type also exists on `Editor`. This change brings it to the
`Document` as well because the replacement for `Syntax` in the child
commits will eliminate `Syntax`'s copy of `syn_loader`. `Syntax` will
also be responsible for returning the highlighter and query iterators
(which will borrow the loader), so the loader must be separated from
that type.
In the long run, when we make a larger refactor to have
`Document::apply` be a function of the `Editor` instead of the
`Document`, we will be able to drop this field on `Document` - it is
currently only necessary for `Document::apply`. Once we make that
refactor, we will be able to eliminate the surrounding `Arc` in
`Arc<ArcSwap<syntax::Loader>>` and use the `ArcSwap` directly instead.
Previously the `call` helper (and its related functions) returned a
`serde_json::Value` which was then decoded either later in the client
(see signature help and hover) or by the client's caller. This led to
some unnecessary boilerplate in the client:
let resp = self.call::<MyRequest>(params);
Some(async move { Ok(serde_json::from_value(resp.await?)?) })
and in the caller. It also allowed for mistakes with the types. The
workspace symbol request's calling code for example mistakenly decoded a
`lsp::WorkspaceSymbolResponse` as `Vec<lsp::SymbolInformation>` - one of
the untagged enum members (so it parsed successfully) but not the
correct type.
With this change, the `call` helper eagerly decodes the response to a
request as the `lsp::request::Request::Result` trait item. This is
similar to the old helper `request` (which has become redundant and has
been eliminated) but all work is done within the same async block which
avoids some awkward lifetimes. The return types of functions like
`Client::text_document_range_inlay_hints` are now more verbose but it is
no longer possible to accidentally decode as an incorrect type.
Additionally `Client::resolve_code_action` now uses the `call_with_ref`
helper to avoid an unnecessary clone.
This adds events for:
* a document being opened
* a document being closed
* a language server sending the initialized notification
* a language server exiting
and also moves some handling done for these scenarios into hooks,
generally moving more into helix-view. A hook is also added on
`DocumentDidChange` which sends the `text_document_did_change`
notification - this resolves a TODO in `document`.
This resolves a TODO in the core diagnostic module to refactor this
type. It was originally an alias of `LanguageServerId` for simplicity.
Refactoring as an enum is a necessary step towards introducing
"internal" diagnostics - diagnostics emitted by core features such as
a spell checker. Fully supporting this use-case will require further
larger changes to the diagnostic type, but the change to the provider
can be made first.
Note that `Copy` is not derived for `DiagnosticProvider` (as it was
previously because `LanguageServerId` is `Copy`). In the child commits
we will add the `identifier` used in LSP pull diagnostics which is a
string - not `Copy`.
Previously LSP notifications were sent within a future and most callers
used a `tokio::spawn` to send the notification, silently discarding any
failures like problems serializing parameters or sending on the channel.
It's possible that tokio could schedule futures out of intended order
though which could cause notifications where order is important, like
document synchronization, to become partially shuffled. This change
removes the future wrapper and logs all internal failures.
Also included in this commit is the same change for `Client::reply`
which was also unnecessarily wrapped in a future.
Co-authored-by: Pascal Kuthe <pascalkuthe@pm.me>
This matches the layout of `shell_impl_async` in `commands.rs` and
avoids a hang or maybe deadlock in `to_writer`'s calls to
`tokio::io::AsyncWriteExt::write_all`. I don't really understand the
underlying cause of the hang but it seems it's necessary to spawn a
new tokio task to provide input to stdin. This is shown in an example
in `tokio::process::Child::wait` but not documented explicitly.
This seems to be a relic from the change which added external formatting
commands - initially it worked by writing the file in place and
reloading it. Now this error type is not possible and can be removed.
This should help debug formatting failures when using external
formatters in the future. Previously we didn't log anything when an
external formatter failed despite having a custom error type for it.
Closes#11351
Also fixed some minor issues related to log
message contents, and removed unnecessary use
of `.as_mut()` as per code review comments on
the PR.
* don't use backup files with hardlinks
* check if the inodes remain the same in the test
* move funcs to faccess and use AsRawHandle
* use a copy as a backup for hardlinks
* delete backup after copy
In the case of network file systems, if the server time is ahead
of the local system time, then helix could annoy with messages
that the file has already been modified by another application.
These changes are ported from
<https://redirect.github.com/helix-editor/helix/pull/9801>. It's a
cleanup of `Document::apply_impl` that uses some early returns to
reduce nesting and some reordering of the steps. The early returns
bail out of `apply_impl` early if the transaction fails to apply or
if the changes are empty (in which case we emit the SelectionDidChange
event). It's a somewhat cosmetic refactor that makes the function easier
to reason about but it also makes it harder to introduce bugs by mapping
positions through empty changesets for example.
Co-authored-by: Pascal Kuthe <pascalkuthe@pm.me>
* replicate t-monaghan's changes
* remove View.offset in favour of Document.view_data.view_position
* improve access patterns for Document.view_data
* better borrow checker wrangling with doc_mut!()
* reintroduce ensure_cursor_in_view in handle_config_events
since we sorted out the borrow checker issues using partial borrows,
there's nothing stopping us from going back to the simpler implementation
* introduce helper functions on Document .view_offset, set_view_offset
* fix rebase breakage
This introduces a custom URI type in core meant to be extended later
if we want to support other schemes. For now it's just a wrapper over a
PathBuf. We use this new URI type to firewall `lsp::Url`. This was
previously done in 8141a4a but using a custom URI type is more flexible
and will improve the way Pickers handle paths for previews in the child
commit(s).
Co-authored-by: soqb <cb.setho@gmail.com>
* Add changes before insert mode undo
Fixes#11077
* Address edge cases for undo like Kakoune does
---------
Co-authored-by: Kaniel Kirby <pirate7007@runbox.com>
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
* Implement check before adding path to files
* fix problem where directories were removed from args.files
* Revert "Implement check before adding path to files"
This reverts commit c123944d9b.
* Dissallow opening of irregular non-symlink files
* Fixed issue with creating new file from command line
* Fixed linting error.
* Optimized regularity check as suggested in review
* Created DocumentOpenError Sum Type to switch on in Application
* Forgot cargo fmt
* Update helix-term/src/application.rs
Accept suggestion in review.
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
* Moved thiserror version configuration to the workspace instead of the individual packages.
---------
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
fsync(2) is a somewhat expensive operation that flushes writes to the
underlying disk/SSD. It's typically used by databases to ensure that
writes survive very hard failure scenarios like your cat kicking the
plug out of the wall. Synchronizing isn't automatically done by
`flush`ing (from the `std::io::Write` or `tokio::io::AsyncWriteExt`
traits). From the [`tokio::fs::File`] moduledocs:
> To ensure that a file is closed immediately when it is dropped, you
> should call `flush` before dropping it. Note that this does not ensure
> that the file has been fully written to disk; the operating system
> might keep the changes around in an in-memory buffer. See the
> `sync_all` method for telling the OS to write the data to disk.
[`tokio::fs::File`]: https://docs.rs/tokio/latest/tokio/fs/struct.File.html
In the `reload-all` command, we should not stop reloading the documents
if one error is found. Instead, we should report the error and continue
trying to reload the current open documents. This is useful in cases
where a backing file does not exist temporarily (e.g. when editing a git
patch in the outstanding chain that doesn't have a file just yet).
This change also remove the error messages in the cases where the
backing is `None`, like in new docs or `tutor`.
`syn_loader` was replaced rather than interior value being replace,
old value was still being referenced and not updated after `:config-refresh`.
By using `ArcSwap` like for `config`, each `.load()` call will return the most
updated value.
Co-authored-by: kyfan <kyfan@email>
Currently, helix implements operations which change the paths of files
incorrectly and inconsistently. This PR ensures that we do the following
whenever a buffer is renamed (`:move` and workspace edits)
* always send did_open/did_close notifications
* send will_rename/did_rename requests correctly
* send them to all LSP servers not just those that are active for a
buffer
* also send these requests for paths that are not yet open in a buffer (if
triggered from workspace edit).
* only send these if the server registered interests in the path
* autodetect language, indent, line ending, ..
This PR also centralizes the infrastructure for path setting and
therefore `:w <path>` benefits from similar fixed (but without didRename)
We use `which::which` in many crates, so `which` was a separate
dependency across all of them. We can centralize `which` into the
stdx crate so it's easy for all crates to depend on it.
I also moved the rest of `helix-view/src/env.rs` into helix-stdx's
`env` module since it only contained a thin wrapper around `which`
and `std::env`.