Merge branch 'main' into multibuffer-following
This commit is contained in:
commit
f797dfb88f
175 changed files with 16722 additions and 8699 deletions
|
@ -5,7 +5,7 @@ use gpui::{
|
|||
Element, Entity, MouseButton, RenderContext, View,
|
||||
};
|
||||
use settings::Settings;
|
||||
use workspace::StatusItemView;
|
||||
use workspace::{item::ItemHandle, StatusItemView};
|
||||
|
||||
pub const NEW_ISSUE_URL: &str = "https://github.com/zed-industries/feedback/issues/new/choose";
|
||||
|
||||
|
@ -43,7 +43,7 @@ impl View for FeedbackLink {
|
|||
impl StatusItemView for FeedbackLink {
|
||||
fn set_active_pane_item(
|
||||
&mut self,
|
||||
_: Option<&dyn workspace::ItemHandle>,
|
||||
_: Option<&dyn ItemHandle>,
|
||||
_: &mut gpui::ViewContext<Self>,
|
||||
) {
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ mod language_plugin;
|
|||
mod python;
|
||||
mod ruby;
|
||||
mod rust;
|
||||
|
||||
mod typescript;
|
||||
|
||||
// 1. Add tree-sitter-{language} parser to zed crate
|
||||
|
@ -127,6 +128,8 @@ pub async fn init(languages: Arc<LanguageRegistry>, _executor: Arc<Background>)
|
|||
tree_sitter_embedded_template::language(),
|
||||
Some(CachedLspAdapter::new(ruby::RubyLanguageServer).await),
|
||||
),
|
||||
("scheme", tree_sitter_scheme::language(), None),
|
||||
("racket", tree_sitter_racket::language(), None),
|
||||
] {
|
||||
languages.add(language(name, grammar, lsp_adapter));
|
||||
}
|
||||
|
|
|
@ -14,17 +14,57 @@
|
|||
declarator: (_) @name) @item
|
||||
|
||||
(declaration
|
||||
type: (_) @context
|
||||
declarator: (function_declarator
|
||||
declarator: (_) @name
|
||||
parameters: (parameter_list
|
||||
"(" @context
|
||||
")" @context))) @item
|
||||
(type_qualifier)? @context
|
||||
type: (_)? @context
|
||||
declarator: [
|
||||
(function_declarator
|
||||
declarator: (_) @name
|
||||
parameters: (parameter_list
|
||||
"(" @context
|
||||
")" @context))
|
||||
(pointer_declarator
|
||||
"*" @context
|
||||
declarator: (function_declarator
|
||||
declarator: (_) @name
|
||||
parameters: (parameter_list
|
||||
"(" @context
|
||||
")" @context)))
|
||||
(pointer_declarator
|
||||
"*" @context
|
||||
declarator: (pointer_declarator
|
||||
"*" @context
|
||||
declarator: (function_declarator
|
||||
declarator: (_) @name
|
||||
parameters: (parameter_list
|
||||
"(" @context
|
||||
")" @context))))
|
||||
]
|
||||
) @item
|
||||
|
||||
(function_definition
|
||||
type: (_) @context
|
||||
declarator: (function_declarator
|
||||
declarator: (_) @name
|
||||
parameters: (parameter_list
|
||||
"(" @context
|
||||
")" @context))) @item
|
||||
(type_qualifier)? @context
|
||||
type: (_)? @context
|
||||
declarator: [
|
||||
(function_declarator
|
||||
declarator: (_) @name
|
||||
parameters: (parameter_list
|
||||
"(" @context
|
||||
")" @context))
|
||||
(pointer_declarator
|
||||
"*" @context
|
||||
declarator: (function_declarator
|
||||
declarator: (_) @name
|
||||
parameters: (parameter_list
|
||||
"(" @context
|
||||
")" @context)))
|
||||
(pointer_declarator
|
||||
"*" @context
|
||||
declarator: (pointer_declarator
|
||||
"*" @context
|
||||
declarator: (function_declarator
|
||||
declarator: (_) @name
|
||||
parameters: (parameter_list
|
||||
"(" @context
|
||||
")" @context))))
|
||||
]
|
||||
) @item
|
||||
|
|
|
@ -51,6 +51,22 @@
|
|||
parameters: (parameter_list
|
||||
"(" @context
|
||||
")" @context)))
|
||||
(pointer_declarator
|
||||
"*" @context
|
||||
declarator: (pointer_declarator
|
||||
"*" @context
|
||||
declarator: (function_declarator
|
||||
declarator: (_) @name
|
||||
parameters: (parameter_list
|
||||
"(" @context
|
||||
")" @context))))
|
||||
(reference_declarator
|
||||
["&" "&&"] @context
|
||||
(function_declarator
|
||||
declarator: (_) @name
|
||||
parameters: (parameter_list
|
||||
"(" @context
|
||||
")" @context)))
|
||||
]
|
||||
(type_qualifier)? @context) @item
|
||||
|
||||
|
@ -74,6 +90,22 @@
|
|||
parameters: (parameter_list
|
||||
"(" @context
|
||||
")" @context)))
|
||||
(pointer_declarator
|
||||
"*" @context
|
||||
declarator: (pointer_declarator
|
||||
"*" @context
|
||||
declarator: (function_declarator
|
||||
declarator: (_) @name
|
||||
parameters: (parameter_list
|
||||
"(" @context
|
||||
")" @context))))
|
||||
(reference_declarator
|
||||
["&" "&&"] @context
|
||||
(function_declarator
|
||||
declarator: (_) @name
|
||||
parameters: (parameter_list
|
||||
"(" @context
|
||||
")" @context)))
|
||||
]
|
||||
(type_qualifier)? @context) @item
|
||||
|
||||
|
@ -97,5 +129,21 @@
|
|||
parameters: (parameter_list
|
||||
"(" @context
|
||||
")" @context)))
|
||||
(pointer_declarator
|
||||
"*" @context
|
||||
declarator: (pointer_declarator
|
||||
"*" @context
|
||||
declarator: (function_declarator
|
||||
declarator: (_) @name
|
||||
parameters: (parameter_list
|
||||
"(" @context
|
||||
")" @context))))
|
||||
(reference_declarator
|
||||
["&" "&&"] @context
|
||||
(function_declarator
|
||||
declarator: (_) @name
|
||||
parameters: (parameter_list
|
||||
"(" @context
|
||||
")" @context)))
|
||||
]
|
||||
(type_qualifier)? @context) @item
|
||||
|
|
3
crates/zed/src/languages/racket/brackets.scm
Normal file
3
crates/zed/src/languages/racket/brackets.scm
Normal file
|
@ -0,0 +1,3 @@
|
|||
("(" @open ")" @close)
|
||||
("[" @open "]" @close)
|
||||
("{" @open "}" @close)
|
9
crates/zed/src/languages/racket/config.toml
Normal file
9
crates/zed/src/languages/racket/config.toml
Normal file
|
@ -0,0 +1,9 @@
|
|||
name = "Racket"
|
||||
path_suffixes = ["rkt"]
|
||||
line_comment = "; "
|
||||
autoclose_before = "])"
|
||||
brackets = [
|
||||
{ start = "[", end = "]", close = true, newline = false },
|
||||
{ start = "(", end = ")", close = true, newline = false },
|
||||
{ start = "\"", end = "\"", close = true, newline = false },
|
||||
]
|
40
crates/zed/src/languages/racket/highlights.scm
Normal file
40
crates/zed/src/languages/racket/highlights.scm
Normal file
File diff suppressed because one or more lines are too long
3
crates/zed/src/languages/racket/indents.scm
Normal file
3
crates/zed/src/languages/racket/indents.scm
Normal file
|
@ -0,0 +1,3 @@
|
|||
(_ "[" "]") @indent
|
||||
(_ "{" "}") @indent
|
||||
(_ "(" ")") @indent
|
10
crates/zed/src/languages/racket/outline.scm
Normal file
10
crates/zed/src/languages/racket/outline.scm
Normal file
|
@ -0,0 +1,10 @@
|
|||
(list
|
||||
.
|
||||
(symbol) @start-symbol @context
|
||||
.
|
||||
[
|
||||
(symbol) @name
|
||||
(list . (symbol) @name)
|
||||
]
|
||||
(#match? @start-symbol "^define")
|
||||
) @item
|
|
@ -11,4 +11,4 @@
|
|||
(begin "begin" @open "end" @close)
|
||||
(module "module" @open "end" @close)
|
||||
(_ . "def" @open "end" @close)
|
||||
(_ . "class" @open "end" @close)
|
||||
(_ . "class" @open "end" @close)
|
3
crates/zed/src/languages/scheme/brackets.scm
Normal file
3
crates/zed/src/languages/scheme/brackets.scm
Normal file
|
@ -0,0 +1,3 @@
|
|||
("(" @open ")" @close)
|
||||
("[" @open "]" @close)
|
||||
("{" @open "}" @close)
|
9
crates/zed/src/languages/scheme/config.toml
Normal file
9
crates/zed/src/languages/scheme/config.toml
Normal file
|
@ -0,0 +1,9 @@
|
|||
name = "Scheme"
|
||||
path_suffixes = ["scm", "ss"]
|
||||
line_comment = "; "
|
||||
autoclose_before = "])"
|
||||
brackets = [
|
||||
{ start = "[", end = "]", close = true, newline = false },
|
||||
{ start = "(", end = ")", close = true, newline = false },
|
||||
{ start = "\"", end = "\"", close = true, newline = false },
|
||||
]
|
28
crates/zed/src/languages/scheme/highlights.scm
Normal file
28
crates/zed/src/languages/scheme/highlights.scm
Normal file
|
@ -0,0 +1,28 @@
|
|||
["(" ")" "[" "]" "{" "}"] @punctuation.bracket
|
||||
|
||||
(number) @number
|
||||
(character) @constant.builtin
|
||||
(boolean) @constant.builtin
|
||||
|
||||
(symbol) @variable
|
||||
(string) @string
|
||||
|
||||
(escape_sequence) @escape
|
||||
|
||||
[(comment)
|
||||
(block_comment)
|
||||
(directive)] @comment
|
||||
|
||||
((symbol) @operator
|
||||
(#match? @operator "^(\\+|-|\\*|/|=|>|<|>=|<=)$"))
|
||||
|
||||
(list
|
||||
.
|
||||
(symbol) @function)
|
||||
|
||||
(list
|
||||
.
|
||||
(symbol) @keyword
|
||||
(#match? @keyword
|
||||
"^(define-syntax|let\\*|lambda|λ|case|=>|quote-splicing|unquote-splicing|set!|let|letrec|letrec-syntax|let-values|let\\*-values|do|else|define|cond|syntax-rules|unquote|begin|quote|let-syntax|and|if|quasiquote|letrec|delay|or|when|unless|identifier-syntax|assert|library|export|import|rename|only|except|prefix)$"
|
||||
))
|
3
crates/zed/src/languages/scheme/indents.scm
Normal file
3
crates/zed/src/languages/scheme/indents.scm
Normal file
|
@ -0,0 +1,3 @@
|
|||
(_ "[" "]") @indent
|
||||
(_ "{" "}") @indent
|
||||
(_ "(" ")") @indent
|
10
crates/zed/src/languages/scheme/outline.scm
Normal file
10
crates/zed/src/languages/scheme/outline.scm
Normal file
|
@ -0,0 +1,10 @@
|
|||
(list
|
||||
.
|
||||
(symbol) @start-symbol @context
|
||||
.
|
||||
[
|
||||
(symbol) @name
|
||||
(list . (symbol) @name)
|
||||
]
|
||||
(#match? @start-symbol "^define")
|
||||
) @item
|
|
@ -23,7 +23,7 @@ use isahc::{config::Configurable, Request};
|
|||
use language::LanguageRegistry;
|
||||
use log::LevelFilter;
|
||||
use parking_lot::Mutex;
|
||||
use project::{Fs, HomeDir, ProjectStore};
|
||||
use project::{Fs, HomeDir};
|
||||
use serde_json::json;
|
||||
use settings::{
|
||||
self, settings_file::SettingsFile, KeymapFileContent, Settings, SettingsFileContent,
|
||||
|
@ -32,17 +32,16 @@ use settings::{
|
|||
use smol::process::Command;
|
||||
use std::fs::OpenOptions;
|
||||
use std::{env, ffi::OsStr, panic, path::PathBuf, sync::Arc, thread, time::Duration};
|
||||
use terminal::terminal_container_view::{get_working_directory, TerminalContainer};
|
||||
use terminal_view::{get_working_directory, TerminalView};
|
||||
|
||||
use fs::RealFs;
|
||||
use settings::watched_json::{watch_keymap_file, watch_settings_file, WatchedJsonFile};
|
||||
use theme::ThemeRegistry;
|
||||
use util::{ResultExt, TryFutureExt};
|
||||
use workspace::{self, AppState, ItemHandle, NewFile, OpenPaths, Workspace};
|
||||
use zed::{
|
||||
self, build_window_options, initialize_workspace, languages, menus, RELEASE_CHANNEL,
|
||||
RELEASE_CHANNEL_NAME,
|
||||
use util::{channel::RELEASE_CHANNEL, paths, ResultExt, TryFutureExt};
|
||||
use workspace::{
|
||||
self, item::ItemHandle, notifications::NotifyResultExt, AppState, NewFile, OpenPaths, Workspace,
|
||||
};
|
||||
use zed::{self, build_window_options, initialize_workspace, languages, menus};
|
||||
|
||||
fn main() {
|
||||
let http = http::client();
|
||||
|
@ -56,10 +55,6 @@ fn main() {
|
|||
.map_or("dev".to_string(), |v| v.to_string());
|
||||
init_panic_hook(app_version, http.clone(), app.background());
|
||||
|
||||
let db = app.background().spawn(async move {
|
||||
project::Db::open(&*zed::paths::DB_DIR, RELEASE_CHANNEL_NAME.as_str())
|
||||
});
|
||||
|
||||
load_embedded_fonts(&app);
|
||||
|
||||
let fs = Arc::new(RealFs);
|
||||
|
@ -91,11 +86,11 @@ fn main() {
|
|||
|
||||
app.run(move |cx| {
|
||||
cx.set_global(*RELEASE_CHANNEL);
|
||||
cx.set_global(HomeDir(zed::paths::HOME.to_path_buf()));
|
||||
cx.set_global(HomeDir(paths::HOME.to_path_buf()));
|
||||
|
||||
let client = client::Client::new(http.clone(), cx);
|
||||
let mut languages = LanguageRegistry::new(login_shell_env_loaded);
|
||||
languages.set_language_server_download_dir(zed::paths::LANGUAGES_DIR.clone());
|
||||
languages.set_language_server_download_dir(paths::LANGUAGES_DIR.clone());
|
||||
let languages = Arc::new(languages);
|
||||
let init_languages = cx
|
||||
.background()
|
||||
|
@ -106,7 +101,7 @@ fn main() {
|
|||
|
||||
//Setup settings global before binding actions
|
||||
cx.set_global(SettingsFile::new(
|
||||
&*zed::paths::SETTINGS,
|
||||
&*paths::SETTINGS,
|
||||
settings_file_content.clone(),
|
||||
fs.clone(),
|
||||
));
|
||||
|
@ -126,7 +121,7 @@ fn main() {
|
|||
diagnostics::init(cx);
|
||||
search::init(cx);
|
||||
vim::init(cx);
|
||||
terminal::init(cx);
|
||||
terminal_view::init(cx);
|
||||
theme_testbench::init(cx);
|
||||
|
||||
cx.spawn(|cx| watch_themes(fs.clone(), themes.clone(), cx))
|
||||
|
@ -146,9 +141,7 @@ fn main() {
|
|||
})
|
||||
.detach();
|
||||
|
||||
let project_store = cx.add_model(|_| ProjectStore::new());
|
||||
let db = cx.background().block(db);
|
||||
client.start_telemetry(db.clone());
|
||||
client.start_telemetry();
|
||||
client.report_event("start app", Default::default());
|
||||
|
||||
let app_state = Arc::new(AppState {
|
||||
|
@ -156,14 +149,15 @@ fn main() {
|
|||
themes,
|
||||
client: client.clone(),
|
||||
user_store,
|
||||
project_store,
|
||||
fs,
|
||||
build_window_options,
|
||||
initialize_workspace,
|
||||
default_item_factory,
|
||||
dock_default_item_factory,
|
||||
});
|
||||
auto_update::init(db, http, cx);
|
||||
auto_update::init(http, client::ZED_SERVER_URL.clone(), cx);
|
||||
|
||||
workspace::init(app_state.clone(), cx);
|
||||
|
||||
journal::init(app_state.clone(), cx);
|
||||
theme_selector::init(app_state.clone(), cx);
|
||||
zed::init(&app_state, cx);
|
||||
|
@ -209,25 +203,10 @@ fn main() {
|
|||
}
|
||||
|
||||
fn init_paths() {
|
||||
std::fs::create_dir_all(&*zed::paths::CONFIG_DIR).expect("could not create config path");
|
||||
std::fs::create_dir_all(&*zed::paths::LANGUAGES_DIR).expect("could not create languages path");
|
||||
std::fs::create_dir_all(&*zed::paths::DB_DIR).expect("could not create database path");
|
||||
std::fs::create_dir_all(&*zed::paths::LOGS_DIR).expect("could not create logs path");
|
||||
|
||||
// Copy setting files from legacy locations. TODO: remove this after a few releases.
|
||||
thread::spawn(|| {
|
||||
if std::fs::metadata(&*zed::paths::legacy::SETTINGS).is_ok()
|
||||
&& std::fs::metadata(&*zed::paths::SETTINGS).is_err()
|
||||
{
|
||||
std::fs::copy(&*zed::paths::legacy::SETTINGS, &*zed::paths::SETTINGS).log_err();
|
||||
}
|
||||
|
||||
if std::fs::metadata(&*zed::paths::legacy::KEYMAP).is_ok()
|
||||
&& std::fs::metadata(&*zed::paths::KEYMAP).is_err()
|
||||
{
|
||||
std::fs::copy(&*zed::paths::legacy::KEYMAP, &*zed::paths::KEYMAP).log_err();
|
||||
}
|
||||
});
|
||||
std::fs::create_dir_all(&*util::paths::CONFIG_DIR).expect("could not create config path");
|
||||
std::fs::create_dir_all(&*util::paths::LANGUAGES_DIR).expect("could not create languages path");
|
||||
std::fs::create_dir_all(&*util::paths::DB_DIR).expect("could not create database path");
|
||||
std::fs::create_dir_all(&*util::paths::LOGS_DIR).expect("could not create logs path");
|
||||
}
|
||||
|
||||
fn init_logger() {
|
||||
|
@ -240,16 +219,15 @@ fn init_logger() {
|
|||
const KIB: u64 = 1024;
|
||||
const MIB: u64 = 1024 * KIB;
|
||||
const MAX_LOG_BYTES: u64 = MIB;
|
||||
if std::fs::metadata(&*zed::paths::LOG)
|
||||
.map_or(false, |metadata| metadata.len() > MAX_LOG_BYTES)
|
||||
if std::fs::metadata(&*paths::LOG).map_or(false, |metadata| metadata.len() > MAX_LOG_BYTES)
|
||||
{
|
||||
let _ = std::fs::rename(&*zed::paths::LOG, &*zed::paths::OLD_LOG);
|
||||
let _ = std::fs::rename(&*paths::LOG, &*paths::OLD_LOG);
|
||||
}
|
||||
|
||||
let log_file = OpenOptions::new()
|
||||
.create(true)
|
||||
.append(true)
|
||||
.open(&*zed::paths::LOG)
|
||||
.open(&*paths::LOG)
|
||||
.expect("could not open logfile");
|
||||
simplelog::WriteLogger::init(level, simplelog::Config::default(), log_file)
|
||||
.expect("could not initialize logger");
|
||||
|
@ -261,7 +239,7 @@ fn init_panic_hook(app_version: String, http: Arc<dyn HttpClient>, background: A
|
|||
.spawn({
|
||||
async move {
|
||||
let panic_report_url = format!("{}/api/panic", &*client::ZED_SERVER_URL);
|
||||
let mut children = smol::fs::read_dir(&*zed::paths::LOGS_DIR).await?;
|
||||
let mut children = smol::fs::read_dir(&*paths::LOGS_DIR).await?;
|
||||
while let Some(child) = children.next().await {
|
||||
let child = child?;
|
||||
let child_path = child.path();
|
||||
|
@ -349,7 +327,7 @@ fn init_panic_hook(app_version: String, http: Arc<dyn HttpClient>, background: A
|
|||
|
||||
let panic_filename = chrono::Utc::now().format("%Y_%m_%d %H_%M_%S").to_string();
|
||||
std::fs::write(
|
||||
zed::paths::LOGS_DIR.join(format!("zed-{}-{}.panic", app_version, panic_filename)),
|
||||
paths::LOGS_DIR.join(format!("zed-{}-{}.panic", app_version, panic_filename)),
|
||||
&message,
|
||||
)
|
||||
.context("error writing panic to disk")
|
||||
|
@ -483,8 +461,8 @@ fn load_config_files(
|
|||
.clone()
|
||||
.spawn(async move {
|
||||
let settings_file =
|
||||
WatchedJsonFile::new(fs.clone(), &executor, zed::paths::SETTINGS.clone()).await;
|
||||
let keymap_file = WatchedJsonFile::new(fs, &executor, zed::paths::KEYMAP.clone()).await;
|
||||
WatchedJsonFile::new(fs.clone(), &executor, paths::SETTINGS.clone()).await;
|
||||
let keymap_file = WatchedJsonFile::new(fs, &executor, paths::KEYMAP.clone()).await;
|
||||
tx.send((settings_file, keymap_file)).ok()
|
||||
})
|
||||
.detach();
|
||||
|
@ -605,10 +583,10 @@ async fn handle_cli_connection(
|
|||
}
|
||||
}
|
||||
|
||||
pub fn default_item_factory(
|
||||
pub fn dock_default_item_factory(
|
||||
workspace: &mut Workspace,
|
||||
cx: &mut ViewContext<Workspace>,
|
||||
) -> Box<dyn ItemHandle> {
|
||||
) -> Option<Box<dyn ItemHandle>> {
|
||||
let strategy = cx
|
||||
.global::<Settings>()
|
||||
.terminal_overrides
|
||||
|
@ -618,6 +596,15 @@ pub fn default_item_factory(
|
|||
|
||||
let working_directory = get_working_directory(workspace, cx, strategy);
|
||||
|
||||
let terminal_handle = cx.add_view(|cx| TerminalContainer::new(working_directory, false, cx));
|
||||
Box::new(terminal_handle)
|
||||
let window_id = cx.window_id();
|
||||
let terminal = workspace
|
||||
.project()
|
||||
.update(cx, |project, cx| {
|
||||
project.create_terminal(working_directory, window_id, cx)
|
||||
})
|
||||
.notify_err(workspace, cx)?;
|
||||
|
||||
let terminal_view = cx.add_view(|cx| TerminalView::new(terminal, workspace.database_id(), cx));
|
||||
|
||||
Some(Box::new(terminal_view))
|
||||
}
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
pub static ref HOME: PathBuf = dirs::home_dir().expect("failed to determine home directory");
|
||||
pub static ref CONFIG_DIR: PathBuf = HOME.join(".config").join("zed");
|
||||
pub static ref LOGS_DIR: PathBuf = HOME.join("Library/Logs/Zed");
|
||||
pub static ref LANGUAGES_DIR: PathBuf = HOME.join("Library/Application Support/Zed/languages");
|
||||
pub static ref DB_DIR: PathBuf = HOME.join("Library/Application Support/Zed/db");
|
||||
pub static ref SETTINGS: PathBuf = CONFIG_DIR.join("settings.json");
|
||||
pub static ref KEYMAP: PathBuf = CONFIG_DIR.join("keymap.json");
|
||||
pub static ref LAST_USERNAME: PathBuf = CONFIG_DIR.join("last-username.txt");
|
||||
pub static ref LOG: PathBuf = LOGS_DIR.join("Zed.log");
|
||||
pub static ref OLD_LOG: PathBuf = LOGS_DIR.join("Zed.log.old");
|
||||
}
|
||||
|
||||
pub mod legacy {
|
||||
use std::path::PathBuf;
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
static ref CONFIG_DIR: PathBuf = super::HOME.join(".zed");
|
||||
pub static ref SETTINGS: PathBuf = CONFIG_DIR.join("settings.json");
|
||||
pub static ref KEYMAP: PathBuf = CONFIG_DIR.join("keymap.json");
|
||||
}
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
mod feedback;
|
||||
pub mod languages;
|
||||
pub mod menus;
|
||||
pub mod paths;
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
pub mod test;
|
||||
|
||||
|
@ -13,7 +12,6 @@ use collab_ui::{CollabTitlebarItem, ToggleCollaborationMenu};
|
|||
use collections::VecDeque;
|
||||
pub use editor;
|
||||
use editor::{Editor, MultiBuffer};
|
||||
use lazy_static::lazy_static;
|
||||
|
||||
use gpui::{
|
||||
actions,
|
||||
|
@ -26,15 +24,16 @@ use gpui::{
|
|||
AssetSource, AsyncAppContext, TitlebarOptions, ViewContext, WindowKind,
|
||||
};
|
||||
use language::Rope;
|
||||
use lazy_static::lazy_static;
|
||||
pub use lsp;
|
||||
pub use project;
|
||||
use project_panel::ProjectPanel;
|
||||
use search::{BufferSearchBar, ProjectSearchBar};
|
||||
use serde::Deserialize;
|
||||
use serde_json::to_string_pretty;
|
||||
use settings::{keymap_file_json_schema, settings_file_json_schema, ReleaseChannel, Settings};
|
||||
use settings::{keymap_file_json_schema, settings_file_json_schema, Settings};
|
||||
use std::{env, path::Path, str, sync::Arc};
|
||||
use util::ResultExt;
|
||||
use util::{channel::ReleaseChannel, paths, ResultExt};
|
||||
pub use workspace;
|
||||
use workspace::{sidebar::SidebarSide, AppState, Workspace};
|
||||
|
||||
|
@ -82,14 +81,6 @@ lazy_static! {
|
|||
.ok()
|
||||
.as_deref()
|
||||
.and_then(parse_pixel_position_env_var);
|
||||
pub static ref RELEASE_CHANNEL_NAME: String =
|
||||
env::var("ZED_RELEASE_CHANNEL").unwrap_or(include_str!("../RELEASE_CHANNEL").to_string());
|
||||
pub static ref RELEASE_CHANNEL: ReleaseChannel = match RELEASE_CHANNEL_NAME.as_str() {
|
||||
"dev" => ReleaseChannel::Dev,
|
||||
"preview" => ReleaseChannel::Preview,
|
||||
"stable" => ReleaseChannel::Stable,
|
||||
_ => panic!("invalid release channel {}", *RELEASE_CHANNEL_NAME),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn init(app_state: &Arc<AppState>, cx: &mut gpui::MutableAppContext) {
|
||||
|
@ -348,6 +339,9 @@ pub fn initialize_workspace(
|
|||
|
||||
auto_update::notify_of_any_new_update(cx.weak_handle(), cx);
|
||||
|
||||
let window_id = cx.window_id();
|
||||
vim::observe_keypresses(window_id, cx);
|
||||
|
||||
cx.on_window_should_close(|workspace, cx| {
|
||||
if let Some(task) = workspace.close(&Default::default(), cx) {
|
||||
task.detach_and_log_err(cx);
|
||||
|
@ -406,7 +400,7 @@ fn quit(_: &Quit, cx: &mut gpui::MutableAppContext) {
|
|||
}
|
||||
|
||||
fn about(_: &mut Workspace, _: &About, cx: &mut gpui::ViewContext<Workspace>) {
|
||||
let app_name = cx.global::<ReleaseChannel>().name();
|
||||
let app_name = cx.global::<ReleaseChannel>().display_name();
|
||||
let version = env!("CARGO_PKG_VERSION");
|
||||
cx.prompt(
|
||||
gpui::PromptLevel::Info,
|
||||
|
@ -479,10 +473,11 @@ fn open_config_file(
|
|||
|
||||
workspace
|
||||
.update(&mut cx, |workspace, cx| {
|
||||
workspace.with_local_workspace(cx, app_state, |workspace, cx| {
|
||||
workspace.with_local_workspace(&app_state, cx, |workspace, cx| {
|
||||
workspace.open_paths(vec![path.to_path_buf()], false, cx)
|
||||
})
|
||||
})
|
||||
.await
|
||||
.await;
|
||||
Ok::<_, anyhow::Error>(())
|
||||
})
|
||||
|
@ -496,51 +491,55 @@ fn open_log_file(
|
|||
) {
|
||||
const MAX_LINES: usize = 1000;
|
||||
|
||||
workspace.with_local_workspace(cx, app_state.clone(), |_, cx| {
|
||||
cx.spawn_weak(|workspace, mut cx| async move {
|
||||
let (old_log, new_log) = futures::join!(
|
||||
app_state.fs.load(&paths::OLD_LOG),
|
||||
app_state.fs.load(&paths::LOG)
|
||||
);
|
||||
workspace
|
||||
.with_local_workspace(&app_state.clone(), cx, move |_, cx| {
|
||||
cx.spawn_weak(|workspace, mut cx| async move {
|
||||
let (old_log, new_log) = futures::join!(
|
||||
app_state.fs.load(&paths::OLD_LOG),
|
||||
app_state.fs.load(&paths::LOG)
|
||||
);
|
||||
|
||||
if let Some(workspace) = workspace.upgrade(&cx) {
|
||||
let mut lines = VecDeque::with_capacity(MAX_LINES);
|
||||
for line in old_log
|
||||
.iter()
|
||||
.flat_map(|log| log.lines())
|
||||
.chain(new_log.iter().flat_map(|log| log.lines()))
|
||||
{
|
||||
if lines.len() == MAX_LINES {
|
||||
lines.pop_front();
|
||||
if let Some(workspace) = workspace.upgrade(&cx) {
|
||||
let mut lines = VecDeque::with_capacity(MAX_LINES);
|
||||
for line in old_log
|
||||
.iter()
|
||||
.flat_map(|log| log.lines())
|
||||
.chain(new_log.iter().flat_map(|log| log.lines()))
|
||||
{
|
||||
if lines.len() == MAX_LINES {
|
||||
lines.pop_front();
|
||||
}
|
||||
lines.push_back(line);
|
||||
}
|
||||
lines.push_back(line);
|
||||
}
|
||||
let log = lines
|
||||
.into_iter()
|
||||
.flat_map(|line| [line, "\n"])
|
||||
.collect::<String>();
|
||||
let log = lines
|
||||
.into_iter()
|
||||
.flat_map(|line| [line, "\n"])
|
||||
.collect::<String>();
|
||||
|
||||
workspace.update(&mut cx, |workspace, cx| {
|
||||
let project = workspace.project().clone();
|
||||
let buffer = project
|
||||
.update(cx, |project, cx| project.create_buffer("", None, cx))
|
||||
.expect("creating buffers on a local workspace always succeeds");
|
||||
buffer.update(cx, |buffer, cx| buffer.edit([(0..0, log)], None, cx));
|
||||
workspace.update(&mut cx, |workspace, cx| {
|
||||
let project = workspace.project().clone();
|
||||
let buffer = project
|
||||
.update(cx, |project, cx| project.create_buffer("", None, cx))
|
||||
.expect("creating buffers on a local workspace always succeeds");
|
||||
buffer.update(cx, |buffer, cx| buffer.edit([(0..0, log)], None, cx));
|
||||
|
||||
let buffer = cx.add_model(|cx| {
|
||||
MultiBuffer::singleton(buffer, cx).with_title("Log".into())
|
||||
let buffer = cx.add_model(|cx| {
|
||||
MultiBuffer::singleton(buffer, cx).with_title("Log".into())
|
||||
});
|
||||
workspace.add_item(
|
||||
Box::new(
|
||||
cx.add_view(|cx| {
|
||||
Editor::for_multibuffer(buffer, Some(project), cx)
|
||||
}),
|
||||
),
|
||||
cx,
|
||||
);
|
||||
});
|
||||
workspace.add_item(
|
||||
Box::new(
|
||||
cx.add_view(|cx| Editor::for_multibuffer(buffer, Some(project), cx)),
|
||||
),
|
||||
cx,
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
})
|
||||
.detach();
|
||||
});
|
||||
}
|
||||
|
||||
fn open_telemetry_log_file(
|
||||
|
@ -548,7 +547,7 @@ fn open_telemetry_log_file(
|
|||
app_state: Arc<AppState>,
|
||||
cx: &mut ViewContext<Workspace>,
|
||||
) {
|
||||
workspace.with_local_workspace(cx, app_state.clone(), |_, cx| {
|
||||
workspace.with_local_workspace(&app_state.clone(), cx, move |_, cx| {
|
||||
cx.spawn_weak(|workspace, mut cx| async move {
|
||||
let workspace = workspace.upgrade(&cx)?;
|
||||
let path = app_state.client.telemetry_log_file_path()?;
|
||||
|
@ -596,31 +595,36 @@ fn open_telemetry_log_file(
|
|||
Some(())
|
||||
})
|
||||
.detach();
|
||||
});
|
||||
}).detach();
|
||||
}
|
||||
|
||||
fn open_bundled_config_file(
|
||||
workspace: &mut Workspace,
|
||||
app_state: Arc<AppState>,
|
||||
asset_path: &'static str,
|
||||
title: &str,
|
||||
title: &'static str,
|
||||
cx: &mut ViewContext<Workspace>,
|
||||
) {
|
||||
workspace.with_local_workspace(cx, app_state, |workspace, cx| {
|
||||
let project = workspace.project().clone();
|
||||
let buffer = project.update(cx, |project, cx| {
|
||||
let text = Assets::get(asset_path).unwrap().data;
|
||||
let text = str::from_utf8(text.as_ref()).unwrap();
|
||||
project
|
||||
.create_buffer(text, project.languages().get_language("JSON"), cx)
|
||||
.expect("creating buffers on a local workspace always succeeds")
|
||||
});
|
||||
let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx).with_title(title.into()));
|
||||
workspace.add_item(
|
||||
Box::new(cx.add_view(|cx| Editor::for_multibuffer(buffer, Some(project.clone()), cx))),
|
||||
cx,
|
||||
);
|
||||
});
|
||||
workspace
|
||||
.with_local_workspace(&app_state.clone(), cx, |workspace, cx| {
|
||||
let project = workspace.project().clone();
|
||||
let buffer = project.update(cx, |project, cx| {
|
||||
let text = Assets::get(asset_path).unwrap().data;
|
||||
let text = str::from_utf8(text.as_ref()).unwrap();
|
||||
project
|
||||
.create_buffer(text, project.languages().get_language("JSON"), cx)
|
||||
.expect("creating buffers on a local workspace always succeeds")
|
||||
});
|
||||
let buffer =
|
||||
cx.add_model(|cx| MultiBuffer::singleton(buffer, cx).with_title(title.into()));
|
||||
workspace.add_item(
|
||||
Box::new(
|
||||
cx.add_view(|cx| Editor::for_multibuffer(buffer, Some(project.clone()), cx)),
|
||||
),
|
||||
cx,
|
||||
);
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
|
||||
fn schema_file_match(path: &Path) -> &Path {
|
||||
|
@ -639,7 +643,7 @@ fn parse_pixel_position_env_var(value: &str) -> Option<Vector2F> {
|
|||
mod tests {
|
||||
use super::*;
|
||||
use assets::Assets;
|
||||
use editor::{Autoscroll, DisplayPoint, Editor};
|
||||
use editor::{scroll::autoscroll::Autoscroll, DisplayPoint, Editor};
|
||||
use gpui::{
|
||||
executor::Deterministic, AssetSource, MutableAppContext, TestAppContext, ViewHandle,
|
||||
};
|
||||
|
@ -651,7 +655,8 @@ mod tests {
|
|||
};
|
||||
use theme::ThemeRegistry;
|
||||
use workspace::{
|
||||
open_paths, pane, Item, ItemHandle, NewFile, Pane, SplitDirection, WorkspaceHandle,
|
||||
item::{Item, ItemHandle},
|
||||
open_new, open_paths, pane, NewFile, Pane, SplitDirection, WorkspaceHandle,
|
||||
};
|
||||
|
||||
#[gpui::test]
|
||||
|
@ -787,7 +792,8 @@ mod tests {
|
|||
#[gpui::test]
|
||||
async fn test_new_empty_workspace(cx: &mut TestAppContext) {
|
||||
let app_state = init(cx);
|
||||
cx.dispatch_global_action(workspace::NewFile);
|
||||
cx.update(|cx| open_new(&app_state, cx)).await;
|
||||
|
||||
let window_id = *cx.window_ids().first().unwrap();
|
||||
let workspace = cx.root_view::<Workspace>(window_id).unwrap();
|
||||
let editor = workspace.update(cx, |workspace, cx| {
|
||||
|
@ -831,8 +837,9 @@ mod tests {
|
|||
.await;
|
||||
|
||||
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
|
||||
let (_, workspace) =
|
||||
cx.add_window(|cx| Workspace::new(project, |_, _| unimplemented!(), cx));
|
||||
let (_, workspace) = cx.add_window(|cx| {
|
||||
Workspace::new(Default::default(), 0, project, |_, _| unimplemented!(), cx)
|
||||
});
|
||||
|
||||
let entries = cx.read(|cx| workspace.file_project_paths(cx));
|
||||
let file1 = entries[0].clone();
|
||||
|
@ -951,8 +958,9 @@ mod tests {
|
|||
.await;
|
||||
|
||||
let project = Project::test(app_state.fs.clone(), ["/dir1".as_ref()], cx).await;
|
||||
let (_, workspace) =
|
||||
cx.add_window(|cx| Workspace::new(project, |_, _| unimplemented!(), cx));
|
||||
let (_, workspace) = cx.add_window(|cx| {
|
||||
Workspace::new(Default::default(), 0, project, |_, _| unimplemented!(), cx)
|
||||
});
|
||||
|
||||
// Open a file within an existing worktree.
|
||||
cx.update(|cx| {
|
||||
|
@ -1111,8 +1119,9 @@ mod tests {
|
|||
.await;
|
||||
|
||||
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
|
||||
let (window_id, workspace) =
|
||||
cx.add_window(|cx| Workspace::new(project, |_, _| unimplemented!(), cx));
|
||||
let (window_id, workspace) = cx.add_window(|cx| {
|
||||
Workspace::new(Default::default(), 0, project, |_, _| unimplemented!(), cx)
|
||||
});
|
||||
|
||||
// Open a file within an existing worktree.
|
||||
cx.update(|cx| {
|
||||
|
@ -1154,8 +1163,9 @@ mod tests {
|
|||
|
||||
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
|
||||
project.update(cx, |project, _| project.languages().add(rust_lang()));
|
||||
let (window_id, workspace) =
|
||||
cx.add_window(|cx| Workspace::new(project, |_, _| unimplemented!(), cx));
|
||||
let (window_id, workspace) = cx.add_window(|cx| {
|
||||
Workspace::new(Default::default(), 0, project, |_, _| unimplemented!(), cx)
|
||||
});
|
||||
let worktree = cx.read(|cx| workspace.read(cx).worktrees(cx).next().unwrap());
|
||||
|
||||
// Create a new untitled buffer
|
||||
|
@ -1244,8 +1254,9 @@ mod tests {
|
|||
|
||||
let project = Project::test(app_state.fs.clone(), [], cx).await;
|
||||
project.update(cx, |project, _| project.languages().add(rust_lang()));
|
||||
let (window_id, workspace) =
|
||||
cx.add_window(|cx| Workspace::new(project, |_, _| unimplemented!(), cx));
|
||||
let (window_id, workspace) = cx.add_window(|cx| {
|
||||
Workspace::new(Default::default(), 0, project, |_, _| unimplemented!(), cx)
|
||||
});
|
||||
|
||||
// Create a new untitled buffer
|
||||
cx.dispatch_action(window_id, NewFile);
|
||||
|
@ -1298,8 +1309,9 @@ mod tests {
|
|||
.await;
|
||||
|
||||
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
|
||||
let (window_id, workspace) =
|
||||
cx.add_window(|cx| Workspace::new(project, |_, _| unimplemented!(), cx));
|
||||
let (window_id, workspace) = cx.add_window(|cx| {
|
||||
Workspace::new(Default::default(), 0, project, |_, _| unimplemented!(), cx)
|
||||
});
|
||||
|
||||
let entries = cx.read(|cx| workspace.file_project_paths(cx));
|
||||
let file1 = entries[0].clone();
|
||||
|
@ -1373,8 +1385,15 @@ mod tests {
|
|||
.await;
|
||||
|
||||
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
|
||||
let (_, workspace) =
|
||||
cx.add_window(|cx| Workspace::new(project.clone(), |_, _| unimplemented!(), cx));
|
||||
let (_, workspace) = cx.add_window(|cx| {
|
||||
Workspace::new(
|
||||
Default::default(),
|
||||
0,
|
||||
project.clone(),
|
||||
|_, _| unimplemented!(),
|
||||
cx,
|
||||
)
|
||||
});
|
||||
|
||||
let entries = cx.read(|cx| workspace.file_project_paths(cx));
|
||||
let file1 = entries[0].clone();
|
||||
|
@ -1638,8 +1657,15 @@ mod tests {
|
|||
.await;
|
||||
|
||||
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
|
||||
let (_, workspace) =
|
||||
cx.add_window(|cx| Workspace::new(project.clone(), |_, _| unimplemented!(), cx));
|
||||
let (_, workspace) = cx.add_window(|cx| {
|
||||
Workspace::new(
|
||||
Default::default(),
|
||||
0,
|
||||
project.clone(),
|
||||
|_, _| unimplemented!(),
|
||||
cx,
|
||||
)
|
||||
});
|
||||
let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone());
|
||||
|
||||
let entries = cx.read(|cx| workspace.file_project_paths(cx));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue