#![feature(map_try_insert)]
#![feature(mapped_lock_guards)]
use napi::bindgen_prelude;
use napi_derive::napi;
use crate::event_loop::Event;
mod event_loop;
mod inline_credit;
mod repository;
mod uri;
mod vscode_sys;
const BUILD_INFO: extension_build_info::Build = extension_build_info::include_build_info!();
pub const PIJUL_SCHEME: &str = "pijul";
#[tracing::instrument(skip_all)]
fn provide_file_decoration<'env>(
env: &'env napi::Env,
vscode_uri: vscode_sys::Uri,
_cancellation_token: bindgen_prelude::Object,
) -> Result<bindgen_prelude::Object<'env>, napi::Error> {
let uri = uri::from_vscode(&vscode_uri)?;
let (deferred_promise, promise_object) = env.create_deferred()?;
event_loop::send(Event::RequestFileDecoration {
uri,
deferred_promise,
});
Ok(promise_object)
}
#[tracing::instrument(skip_all)]
fn provide_text_document_content<'env>(
env: &'env napi::Env,
encoded_uri: vscode_sys::Uri,
_cancellation_token: bindgen_prelude::Object,
) -> Result<bindgen_prelude::Object<'env>, napi::Error> {
let decoded_uri = uri::decode(&encoded_uri)?;
let (deferred_promise, promise_object) = env.create_deferred()?;
event_loop::send(Event::RequestTrackedContents {
uri: decoded_uri,
deferred_promise,
});
Ok(promise_object)
}
fn provide_original_resource<'env>(
env: &'env napi::Env,
uri_to_encode: vscode_sys::Uri<'env>,
_cancellation_token: bindgen_prelude::Object,
) -> Result<Option<vscode_sys::Uri<'env>>, napi::Error> {
let encoded_uri = uri::encode(&uri_to_encode)?;
let vscode_uri = uri::to_vscode(env, &encoded_uri)?;
Ok(Some(vscode_uri))
}
#[tracing::instrument(skip_all)]
fn on_did_change_text_document(
_env: &napi::Env,
event: vscode_sys::TextDocumentChangeEvent,
) -> Result<(), napi::Error> {
let text_document = event.get_document()?;
let document_uri = text_document.get_uri()?;
if document_uri.get_scheme()? == "output" {
return Ok(());
}
let uri = uri::from_vscode(&document_uri)?;
let change_events = event.get_content_changes()?;
let mut changes = Vec::with_capacity(change_events.len());
for change_event in &change_events {
changes.push(event_loop::EditorContentsChange {
character_offset: change_event.get_range_offset()?,
characters_replaced: change_event.get_range_length()?,
replacement_text: change_event.get_text()?,
})
}
event_loop::send(Event::ChangeEditorContents { uri, changes });
Ok(())
}
#[tracing::instrument(skip_all)]
fn on_did_change_text_editor_selections(
_env: &napi::Env,
event: vscode_sys::TextEditorSelectionChangeEvent,
) -> Result<(), napi::Error> {
let editor = event.get_text_editor()?;
let document = editor.get_document()?;
let vscode_uri = document.get_uri()?;
if vscode_uri.get_scheme()? == "output" {
return Ok(());
}
let uri = uri::from_vscode(&vscode_uri)?;
event_loop::send(Event::RequestInlineCredit { uri });
Ok(())
}
#[tracing::instrument(skip_all)]
fn on_did_change_workspace_folders(
_env: &napi::Env,
event: vscode_sys::WorkspaceFoldersChangeEvent,
) -> Result<(), napi::Error> {
let added_workspaces = event.get_added()?;
let removed_workspaces = event.get_removed()?;
for added_workspace in added_workspaces {
let added_workspace_uri = added_workspace.get_uri()?;
let added_uri = uri::from_vscode(&added_workspace_uri)?;
event_loop::send(Event::OpenWorkspaceFolder {
workspace_uri: added_uri,
});
}
for removed_workspace in removed_workspaces {
}
Ok(())
}
#[tracing::instrument(skip_all)]
fn on_did_change_visible_text_editors(
_env: &napi::Env,
visible_text_editors: Vec<vscode_sys::TextEditor>,
) -> Result<(), napi::Error> {
for text_editor in &visible_text_editors {
let document_uri = text_editor.get_document()?.get_uri()?;
let uri = uri::from_vscode(&document_uri)?;
event_loop::send(Event::OpenTextEditor {
uri,
text_editor: text_editor.create_ref()?,
});
}
Ok(())
}
#[tracing::instrument(skip_all)]
pub fn handle_fs_watcher_event(
_env: &napi::Env,
vscode_uri: vscode_sys::Uri,
) -> Result<(), napi::Error> {
let uri = uri::from_vscode(&vscode_uri)?;
event_loop::send(Event::ChangedFilesystemContents { uri });
Ok(())
}
#[tracing::instrument(skip_all)]
pub fn on_did_move_files(
_env: &napi::Env,
event: vscode_sys::FileRenameEvent,
) -> Result<(), napi::Error> {
for renamed_file in event.get_files()? {
let old_vscode_uri = renamed_file.get_old_uri()?;
let new_vscode_uri = renamed_file.get_new_uri()?;
let old_uri = uri::from_vscode(&old_vscode_uri)?;
let new_uri = uri::from_vscode(&new_vscode_uri)?;
event_loop::send(Event::MovePath { old_uri, new_uri });
}
Ok(())
}
#[napi(catch_unwind)]
pub fn activate(
env: &napi::Env,
vscode_object: bindgen_prelude::Object,
extension_context: bindgen_prelude::Object,
) -> Result<(), napi::Error> {
vscode_sys::activate(&vscode_object, &extension_context)?;
vscode_sys::log::init(
env,
"Pijul",
tracing_subscriber::fmt::format::DefaultFields::new(),
)?;
let decoration_change_event_emitter = vscode_sys::EventEmitter::new(env)?;
let decoration_change_event = decoration_change_event_emitter.get_event()?;
let mut file_decoration_provider =
vscode_sys::FileDecorationProvider::new(env, provide_file_decoration)?;
file_decoration_provider.set_on_did_change_file_decorations(decoration_change_event)?;
vscode_sys::window::register_file_decoration_provider(
env,
&extension_context,
file_decoration_provider,
)?;
let mut quick_diff_provider = vscode_sys::QuickDiffProvider::new(env)?;
quick_diff_provider.set_provide_original_resource(env, provide_original_resource)?;
event_loop::start(
env,
&vscode_object,
decoration_change_event_emitter,
quick_diff_provider,
)?;
for workspace_folder in vscode_sys::workspace::get_workspace_folders(env)? {
let vscode_uri = workspace_folder.get_uri()?;
let workspace_uri = uri::from_vscode(&vscode_uri)?;
event_loop::send(Event::OpenWorkspaceFolder { workspace_uri });
}
let visible_text_editors = vscode_sys::window::get_visible_text_editors(env)?;
for text_editor in visible_text_editors {
let document_uri = text_editor.get_document()?.get_uri()?;
let uri = uri::from_vscode(&document_uri)?;
event_loop::send(Event::OpenTextEditor {
uri,
text_editor: text_editor.create_ref()?,
});
}
let text_document_provider =
vscode_sys::TextDocumentContentProvider::new(env, provide_text_document_content)?;
vscode_sys::workspace::register_text_document_content_provider(
env,
&extension_context,
PIJUL_SCHEME,
text_document_provider,
)?;
vscode_sys::window::on_did_change_text_editor_selections(
env,
on_did_change_text_editor_selections,
)?;
vscode_sys::window::on_did_change_visible_text_editors(
env,
on_did_change_visible_text_editors,
)?;
vscode_sys::workspace::on_did_change_text_document(env, on_did_change_text_document)?;
vscode_sys::workspace::on_did_change_workspace_folders(env, on_did_change_workspace_folders)?;
vscode_sys::workspace::on_did_rename_files(env, on_did_move_files)?;
let file_system_watcher = vscode_sys::workspace::create_file_system_watcher(env, "**")?;
file_system_watcher.on_did_change(env, handle_fs_watcher_event)?;
file_system_watcher.on_did_create(env, handle_fs_watcher_event)?;
file_system_watcher.on_did_delete(env, handle_fs_watcher_event)?;
tracing::info!(message = "Extension activated", ?BUILD_INFO);
Ok(())
}