Rename runnables into tasks (#8119)

Kirill Bulatov created

Release Notes:

- N/A

Change summary

Cargo.lock                                 | 98 ++++++++++++------------
Cargo.toml                                 |  8 
assets/settings/initial_tasks.json         |  8 
crates/project/Cargo.toml                  |  2 
crates/project/src/project.rs              | 18 ++--
crates/project/src/task_inventory.rs       | 36 +++----
crates/project/src/terminals.rs            | 20 ++--
crates/settings/src/settings.rs            |  4 
crates/task/Cargo.toml                     |  2 
crates/task/LICENSE-GPL                    |  0 
crates/task/src/lib.rs                     | 44 +++++-----
crates/task/src/static_source.rs           | 43 +++++-----
crates/task/src/static_task.rs             | 22 ++--
crates/tasks_ui/Cargo.toml                 |  4 
crates/tasks_ui/LICENSE-GPL                |  0 
crates/tasks_ui/src/lib.rs                 | 41 ++++-----
crates/tasks_ui/src/modal.rs               | 55 ++++++------
crates/tasks_ui/src/oneshot_source.rs      | 36 ++++----
crates/terminal/Cargo.toml                 |  2 
crates/terminal/src/terminal.rs            | 53 ++++++------
crates/terminal_view/Cargo.toml            |  2 
crates/terminal_view/src/terminal_panel.rs | 82 ++++++++-----------
crates/terminal_view/src/terminal_view.rs  | 10 +-
crates/util/src/paths.rs                   |  2 
crates/workspace/Cargo.toml                |  2 
crates/workspace/src/workspace.rs          | 22 ++--
crates/zed/Cargo.toml                      |  4 
crates/zed/src/languages/json.rs           |  6 
crates/zed/src/main.rs                     |  2 
crates/zed/src/zed.rs                      | 20 ++--
30 files changed, 316 insertions(+), 332 deletions(-)

Detailed changes

Cargo.lock 🔗

@@ -6898,7 +6898,6 @@ dependencies = [
  "regex",
  "release_channel",
  "rpc",
- "runnable",
  "schemars",
  "serde",
  "serde_derive",
@@ -6908,6 +6907,7 @@ dependencies = [
  "similar",
  "smol",
  "sum_tree",
+ "task",
  "tempfile",
  "terminal",
  "text",
@@ -7756,49 +7756,6 @@ dependencies = [
  "zeroize",
 ]
 
-[[package]]
-name = "runnable"
-version = "0.1.0"
-dependencies = [
- "anyhow",
- "collections",
- "futures 0.3.28",
- "gpui",
- "parking_lot 0.11.2",
- "schemars",
- "serde",
- "serde_json",
- "serde_json_lenient",
- "settings",
- "smol",
- "util",
-]
-
-[[package]]
-name = "runnables_ui"
-version = "0.1.0"
-dependencies = [
- "anyhow",
- "db",
- "editor",
- "fs",
- "futures 0.3.28",
- "fuzzy",
- "gpui",
- "log",
- "menu",
- "picker",
- "project",
- "runnable",
- "schemars",
- "serde",
- "serde_json",
- "theme",
- "ui",
- "util",
- "workspace",
-]
-
 [[package]]
 name = "rusqlite"
 version = "0.29.0"
@@ -9371,6 +9328,49 @@ version = "0.12.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "69758bda2e78f098e4ccb393021a0963bb3442eac05f135c30f61b7370bbafae"
 
+[[package]]
+name = "task"
+version = "0.1.0"
+dependencies = [
+ "anyhow",
+ "collections",
+ "futures 0.3.28",
+ "gpui",
+ "parking_lot 0.11.2",
+ "schemars",
+ "serde",
+ "serde_json",
+ "serde_json_lenient",
+ "settings",
+ "smol",
+ "util",
+]
+
+[[package]]
+name = "tasks_ui"
+version = "0.1.0"
+dependencies = [
+ "anyhow",
+ "db",
+ "editor",
+ "fs",
+ "futures 0.3.28",
+ "fuzzy",
+ "gpui",
+ "log",
+ "menu",
+ "picker",
+ "project",
+ "schemars",
+ "serde",
+ "serde_json",
+ "task",
+ "theme",
+ "ui",
+ "util",
+ "workspace",
+]
+
 [[package]]
 name = "tempfile"
 version = "3.9.0"
@@ -9422,7 +9422,6 @@ dependencies = [
  "ordered-float 2.10.0",
  "procinfo",
  "rand 0.8.5",
- "runnable",
  "schemars",
  "serde",
  "serde_derive",
@@ -9431,6 +9430,7 @@ dependencies = [
  "shellexpand",
  "smallvec",
  "smol",
+ "task",
  "theme",
  "thiserror",
  "util",
@@ -9457,7 +9457,6 @@ dependencies = [
  "procinfo",
  "project",
  "rand 0.8.5",
- "runnable",
  "search",
  "serde",
  "serde_derive",
@@ -9466,6 +9465,7 @@ dependencies = [
  "shellexpand",
  "smallvec",
  "smol",
+ "task",
  "terminal",
  "theme",
  "thiserror",
@@ -11724,7 +11724,6 @@ dependencies = [
  "parking_lot 0.11.2",
  "postage",
  "project",
- "runnable",
  "schemars",
  "serde",
  "serde_derive",
@@ -11732,6 +11731,7 @@ dependencies = [
  "settings",
  "smallvec",
  "sqlez",
+ "task",
  "terminal",
  "theme",
  "ui",
@@ -11985,8 +11985,6 @@ dependencies = [
  "rope",
  "rpc",
  "rsa 0.4.0",
- "runnable",
- "runnables_ui",
  "rust-embed",
  "schemars",
  "search",
@@ -12000,6 +11998,8 @@ dependencies = [
  "smallvec",
  "smol",
  "sum_tree",
+ "task",
+ "tasks_ui",
  "tempfile",
  "terminal_view",
  "text",

Cargo.toml 🔗

@@ -63,8 +63,8 @@ members = [
     "crates/rich_text",
     "crates/rope",
     "crates/rpc",
-    "crates/runnable",
-    "crates/runnables_ui",
+    "crates/task",
+    "crates/tasks_ui",
     "crates/search",
     "crates/semantic_index",
     "crates/settings",
@@ -155,8 +155,8 @@ release_channel = { path = "crates/release_channel" }
 rich_text = { path = "crates/rich_text" }
 rope = { path = "crates/rope" }
 rpc = { path = "crates/rpc" }
-runnable = { path = "crates/runnable" }
-runnables_ui = { path = "crates/runnables_ui" }
+task = { path = "crates/task" }
+tasks_ui = { path = "crates/tasks_ui" }
 search = { path = "crates/search" }
 semantic_index = { path = "crates/semantic_index" }
 settings = { path = "crates/settings" }

assets/settings/initial_runnables.json → assets/settings/initial_tasks.json 🔗

@@ -1,9 +1,9 @@
-// Static runnables configuration.
+// Static tasks configuration.
 //
 // Example:
 // {
 //     "version": "1",
-//     "runnables": [
+//     "tasks": [
 //         {
 //             "label": "human-readable label for UI",
 //             "command": "bash",
@@ -15,7 +15,7 @@
 //             "cwd": "/path/to/working/directory",
 //             // Whether to use a new terminal tab or reuse the existing one to spawn the process, defaults to `false`.
 //             "use_new_terminal": false,
-//             // Whether to allow multiple instances of the same runnable to be run, or rather wait for the existing ones to finish, defaults to `false`.
+//             // Whether to allow multiple instances of the same task to be run, or rather wait for the existing ones to finish, defaults to `false`.
 //             "allow_concurrent_runs": false
 //         }
 //     ]
@@ -23,5 +23,5 @@
 //
 {
     "version": "1",
-    "runnables": []
+    "tasks": []
 }

crates/project/Cargo.toml 🔗

@@ -50,7 +50,7 @@ prettier.workspace = true
 rand.workspace = true
 regex.workspace = true
 rpc.workspace = true
-runnable.workspace = true
+task.workspace = true
 schemars.workspace = true
 serde.workspace = true
 serde_derive.workspace = true

crates/project/src/project.rs 🔗

@@ -4,8 +4,8 @@ pub mod lsp_command;
 pub mod lsp_ext_command;
 mod prettier_support;
 pub mod project_settings;
-mod runnable_inventory;
 pub mod search;
+mod task_inventory;
 pub mod terminals;
 pub mod worktree;
 
@@ -94,7 +94,7 @@ use util::{
 pub use fs::*;
 #[cfg(any(test, feature = "test-support"))]
 pub use prettier::FORMAT_SUFFIX as TEST_PRETTIER_FORMAT_SUFFIX;
-pub use runnable_inventory::Inventory;
+pub use task_inventory::Inventory;
 pub use worktree::*;
 
 const MAX_SERVER_REINSTALL_ATTEMPT_COUNT: u64 = 4;
@@ -158,7 +158,7 @@ pub struct Project {
     default_prettier: DefaultPrettier,
     prettiers_per_worktree: HashMap<WorktreeId, HashSet<Option<PathBuf>>>,
     prettier_instances: HashMap<PathBuf, PrettierInstance>,
-    runnables: Model<Inventory>,
+    tasks: Model<Inventory>,
 }
 
 pub enum LanguageServerToQuery {
@@ -621,7 +621,7 @@ impl Project {
                 .detach();
             let copilot_lsp_subscription =
                 Copilot::global(cx).map(|copilot| subscribe_for_copilot_events(&copilot, cx));
-            let runnables = Inventory::new(cx);
+            let tasks = Inventory::new(cx);
 
             Self {
                 worktrees: Vec::new(),
@@ -673,7 +673,7 @@ impl Project {
                 default_prettier: DefaultPrettier::default(),
                 prettiers_per_worktree: HashMap::default(),
                 prettier_instances: HashMap::default(),
-                runnables,
+                tasks,
             }
         })
     }
@@ -697,7 +697,7 @@ impl Project {
             .await?;
         let this = cx.new_model(|cx| {
             let replica_id = response.payload.replica_id as ReplicaId;
-            let runnables = Inventory::new(cx);
+            let tasks = Inventory::new(cx);
             // BIG CAUTION NOTE: The order in which we initialize fields here matters and it should match what's done in Self::local.
             // Otherwise, you might run into issues where worktree id on remote is different than what's on local host.
             // That's because Worktree's identifier is entity id, which should probably be changed.
@@ -782,7 +782,7 @@ impl Project {
                 default_prettier: DefaultPrettier::default(),
                 prettiers_per_worktree: HashMap::default(),
                 prettier_instances: HashMap::default(),
-                runnables,
+                tasks,
             };
             this.set_role(role, cx);
             for worktree in worktrees {
@@ -1065,8 +1065,8 @@ impl Project {
         cx.notify();
     }
 
-    pub fn runnable_inventory(&self) -> &Model<Inventory> {
-        &self.runnables
+    pub fn task_inventory(&self) -> &Model<Inventory> {
+        &self.tasks
     }
 
     pub fn collaborators(&self) -> &HashMap<proto::PeerId, Collaborator> {

crates/project/src/runnable_inventory.rs → crates/project/src/task_inventory.rs 🔗

@@ -1,14 +1,14 @@
-//! Project-wide storage of the runnables available, capable of updating itself from the sources set.
+//! Project-wide storage of the tasks available, capable of updating itself from the sources set.
 
 use std::{any::TypeId, path::Path, sync::Arc};
 
 use gpui::{AppContext, Context, Model, ModelContext, Subscription};
-use runnable::{Runnable, RunnableId, Source};
+use task::{Source, Task, TaskId};
 
-/// Inventory tracks available runnables for a given project.
+/// Inventory tracks available tasks for a given project.
 pub struct Inventory {
     sources: Vec<SourceInInventory>,
-    pub last_scheduled_runnable: Option<RunnableId>,
+    pub last_scheduled_task: Option<TaskId>,
 }
 
 struct SourceInInventory {
@@ -21,11 +21,11 @@ impl Inventory {
     pub(crate) fn new(cx: &mut AppContext) -> Model<Self> {
         cx.new_model(|_| Self {
             sources: Vec::new(),
-            last_scheduled_runnable: None,
+            last_scheduled_task: None,
         })
     }
 
-    /// Registers a new runnables source, that would be fetched for available runnables.
+    /// Registers a new tasks source, that would be fetched for available tasks.
     pub fn add_source(&mut self, source: Model<Box<dyn Source>>, cx: &mut ModelContext<Self>) {
         let _subscription = cx.observe(&source, |_, _, cx| {
             cx.notify();
@@ -55,29 +55,25 @@ impl Inventory {
     }
 
     /// Pulls its sources to list runanbles for the path given (up to the source to decide what to return for no path).
-    pub fn list_runnables(
-        &self,
-        path: Option<&Path>,
-        cx: &mut AppContext,
-    ) -> Vec<Arc<dyn Runnable>> {
-        let mut runnables = Vec::new();
+    pub fn list_tasks(&self, path: Option<&Path>, cx: &mut AppContext) -> Vec<Arc<dyn Task>> {
+        let mut tasks = Vec::new();
         for source in &self.sources {
-            runnables.extend(
+            tasks.extend(
                 source
                     .source
-                    .update(cx, |source, cx| source.runnables_for_path(path, cx)),
+                    .update(cx, |source, cx| source.tasks_for_path(path, cx)),
             );
         }
-        runnables
+        tasks
     }
 
-    /// Returns the last scheduled runnable, if any of the sources contains one with the matching id.
-    pub fn last_scheduled_runnable(&self, cx: &mut AppContext) -> Option<Arc<dyn Runnable>> {
-        self.last_scheduled_runnable.as_ref().and_then(|id| {
+    /// Returns the last scheduled task, if any of the sources contains one with the matching id.
+    pub fn last_scheduled_task(&self, cx: &mut AppContext) -> Option<Arc<dyn Task>> {
+        self.last_scheduled_task.as_ref().and_then(|id| {
             // TODO straighten the `Path` story to understand what has to be passed here: or it will break in the future.
-            self.list_runnables(None, cx)
+            self.list_tasks(None, cx)
                 .into_iter()
-                .find(|runnable| runnable.id() == id)
+                .find(|task| task.id() == id)
         })
     }
 }

crates/project/src/terminals.rs 🔗

@@ -5,7 +5,7 @@ use smol::channel::bounded;
 use std::path::{Path, PathBuf};
 use terminal::{
     terminal_settings::{self, Shell, TerminalSettings, VenvSettingsContent},
-    RunableState, SpawnRunnable, Terminal, TerminalBuilder,
+    SpawnTask, TaskState, Terminal, TerminalBuilder,
 };
 
 // #[cfg(target_os = "macos")]
@@ -19,7 +19,7 @@ impl Project {
     pub fn create_terminal(
         &mut self,
         working_directory: Option<PathBuf>,
-        spawn_runnable: Option<SpawnRunnable>,
+        spawn_task: Option<SpawnTask>,
         window: AnyWindowHandle,
         cx: &mut ModelContext<Self>,
     ) -> anyhow::Result<Model<Terminal>> {
@@ -32,18 +32,18 @@ impl Project {
         let python_settings = settings.detect_venv.clone();
         let (completion_tx, completion_rx) = bounded(1);
         let mut env = settings.env.clone();
-        let (spawn_runnable, shell) = if let Some(spawn_runnable) = spawn_runnable {
-            env.extend(spawn_runnable.env);
+        let (spawn_task, shell) = if let Some(spawn_task) = spawn_task {
+            env.extend(spawn_task.env);
             (
-                Some(RunableState {
-                    id: spawn_runnable.id,
-                    label: spawn_runnable.label,
+                Some(TaskState {
+                    id: spawn_task.id,
+                    label: spawn_task.label,
                     completed: false,
                     completion_rx,
                 }),
                 Shell::WithArguments {
-                    program: spawn_runnable.command,
-                    args: spawn_runnable.args,
+                    program: spawn_task.command,
+                    args: spawn_task.args,
                 },
             )
         } else {
@@ -52,7 +52,7 @@ impl Project {
 
         let terminal = TerminalBuilder::new(
             working_directory.clone(),
-            spawn_runnable,
+            spawn_task,
             shell,
             env,
             Some(settings.blinking.clone()),

crates/settings/src/settings.rs 🔗

@@ -43,6 +43,6 @@ pub fn initial_local_settings_content() -> Cow<'static, str> {
     asset_str::<SettingsAssets>("settings/initial_local_settings.json")
 }
 
-pub fn initial_runnables_content() -> Cow<'static, str> {
-    asset_str::<SettingsAssets>("settings/initial_runnables.json")
+pub fn initial_tasks_content() -> Cow<'static, str> {
+    asset_str::<SettingsAssets>("settings/initial_tasks.json")
 }

crates/runnable/Cargo.toml → crates/task/Cargo.toml 🔗

@@ -1,5 +1,5 @@
 [package]
-name = "runnable"
+name = "task"
 version = "0.1.0"
 edition = "2021"
 publish = false

crates/runnable/src/lib.rs → crates/task/src/lib.rs 🔗

@@ -1,10 +1,10 @@
-//! Baseline interface of Runnables in Zed: all runnables in Zed are intended to use those for implementing their own logic.
+//! Baseline interface of Tasks in Zed: all tasks in Zed are intended to use those for implementing their own logic.
 #![deny(missing_docs)]
 
-mod static_runnable;
 pub mod static_source;
+mod static_task;
 
-pub use static_runnable::StaticRunnable;
+pub use static_task::StaticTask;
 
 use collections::HashMap;
 use gpui::ModelContext;
@@ -12,16 +12,16 @@ use std::any::Any;
 use std::path::{Path, PathBuf};
 use std::sync::Arc;
 
-/// Runnable identifier, unique within the application.
-/// Based on it, runnable reruns and terminal tabs are managed.
+/// Task identifier, unique within the application.
+/// Based on it, task reruns and terminal tabs are managed.
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct RunnableId(pub String);
+pub struct TaskId(pub String);
 
-/// Contains all information needed by Zed to spawn a new terminal tab for the given runnable.
+/// Contains all information needed by Zed to spawn a new terminal tab for the given task.
 #[derive(Debug, Clone)]
 pub struct SpawnInTerminal {
-    /// Id of the runnable to use when determining task tab affinity.
-    pub id: RunnableId,
+    /// Id of the task to use when determining task tab affinity.
+    pub id: TaskId,
     /// Human readable name of the terminal tab.
     pub label: String,
     /// Executable command to spawn.
@@ -34,37 +34,37 @@ pub struct SpawnInTerminal {
     pub env: HashMap<String, String>,
     /// Whether to use a new terminal tab or reuse the existing one to spawn the process.
     pub use_new_terminal: bool,
-    /// Whether to allow multiple instances of the same runnable to be run, or rather wait for the existing ones to finish.
+    /// Whether to allow multiple instances of the same task to be run, or rather wait for the existing ones to finish.
     pub allow_concurrent_runs: bool,
     /// Whether the command should be spawned in a separate shell instance.
     pub separate_shell: bool,
 }
 
-/// Represents a short lived recipe of a runnable, whose main purpose
+/// Represents a short lived recipe of a task, whose main purpose
 /// is to get spawned.
-pub trait Runnable {
-    /// Unique identifier of the runnable to spawn.
-    fn id(&self) -> &RunnableId;
-    /// Human readable name of the runnable to display in the UI.
+pub trait Task {
+    /// Unique identifier of the task to spawn.
+    fn id(&self) -> &TaskId;
+    /// Human readable name of the task to display in the UI.
     fn name(&self) -> &str;
     /// Task's current working directory. If `None`, current project's root will be used.
     fn cwd(&self) -> Option<&Path>;
-    /// Sets up everything needed to spawn the runnable in the given directory (`cwd`).
-    /// If a runnable is intended to be spawned in the terminal, it should return the corresponding struct filled with the data necessary.
+    /// Sets up everything needed to spawn the task in the given directory (`cwd`).
+    /// If a task is intended to be spawned in the terminal, it should return the corresponding struct filled with the data necessary.
     fn exec(&self, cwd: Option<PathBuf>) -> Option<SpawnInTerminal>;
 }
 
-/// [`Source`] produces runnables that can be scheduled.
+/// [`Source`] produces tasks that can be scheduled.
 ///
-/// Implementations of this trait could be e.g. [`StaticSource`] that parses runnables from a .json files and provides process templates to be spawned;
+/// Implementations of this trait could be e.g. [`StaticSource`] that parses tasks from a .json files and provides process templates to be spawned;
 /// another one could be a language server providing lenses with tests or build server listing all targets for a given project.
 pub trait Source: Any {
     /// A way to erase the type of the source, processing and storing them generically.
     fn as_any(&mut self) -> &mut dyn Any;
-    /// Collects all runnables available for scheduling, for the path given.
-    fn runnables_for_path(
+    /// Collects all tasks available for scheduling, for the path given.
+    fn tasks_for_path(
         &mut self,
         path: Option<&Path>,
         cx: &mut ModelContext<Box<dyn Source>>,
-    ) -> Vec<Arc<dyn Runnable>>;
+    ) -> Vec<Arc<dyn Task>>;
 }

crates/runnable/src/static_source.rs → crates/task/src/static_source.rs 🔗

@@ -1,4 +1,4 @@
-//! A source of runnables, based on a static configuration, deserialized from the runnables config file, and related infrastructure for tracking changes to the file.
+//! A source of tasks, based on a static configuration, deserialized from the tasks config file, and related infrastructure for tracking changes to the file.
 
 use std::{
     path::{Path, PathBuf},
@@ -12,20 +12,20 @@ use schemars::{gen::SchemaSettings, JsonSchema};
 use serde::{Deserialize, Serialize};
 use util::ResultExt;
 
-use crate::{Runnable, Source, StaticRunnable};
+use crate::{Source, StaticTask, Task};
 use futures::channel::mpsc::UnboundedReceiver;
 
-/// The source of runnables defined in a runnables config file.
+/// The source of tasks defined in a tasks config file.
 pub struct StaticSource {
-    runnables: Vec<StaticRunnable>,
+    tasks: Vec<StaticTask>,
     _definitions: Model<TrackedFile<DefinitionProvider>>,
     _subscription: Subscription,
 }
 
-/// Static runnable definition from the runnables config file.
+/// Static task definition from the tasks config file.
 #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
 pub(crate) struct Definition {
-    /// Human readable name of the runnable to display in the UI.
+    /// Human readable name of the task to display in the UI.
     pub label: String,
     /// Executable command to spawn.
     pub command: String,
@@ -41,20 +41,20 @@ pub(crate) struct Definition {
     /// Whether to use a new terminal tab or reuse the existing one to spawn the process.
     #[serde(default)]
     pub use_new_terminal: bool,
-    /// Whether to allow multiple instances of the same runnable to be run, or rather wait for the existing ones to finish.
+    /// Whether to allow multiple instances of the same task to be run, or rather wait for the existing ones to finish.
     #[serde(default)]
     pub allow_concurrent_runs: bool,
 }
 
-/// A group of Runnables defined in a JSON file.
+/// A group of Tasks defined in a JSON file.
 #[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
 pub struct DefinitionProvider {
     version: String,
-    runnables: Vec<Definition>,
+    tasks: Vec<Definition>,
 }
 
 impl DefinitionProvider {
-    /// Generates JSON schema of Runnables JSON definition format.
+    /// Generates JSON schema of Tasks JSON definition format.
     pub fn generate_json_schema() -> serde_json_lenient::Value {
         let schema = SchemaSettings::draft07()
             .with(|settings| settings.option_add_null_type = false)
@@ -107,33 +107,32 @@ impl<T: for<'a> Deserialize<'a> + PartialEq + 'static> TrackedFile<T> {
 }
 
 impl StaticSource {
-    /// Initializes the static source, reacting on runnables config changes.
+    /// Initializes the static source, reacting on tasks config changes.
     pub fn new(
-        runnables_file_tracker: UnboundedReceiver<String>,
+        tasks_file_tracker: UnboundedReceiver<String>,
         cx: &mut AppContext,
     ) -> Model<Box<dyn Source>> {
-        let definitions =
-            TrackedFile::new(DefinitionProvider::default(), runnables_file_tracker, cx);
+        let definitions = TrackedFile::new(DefinitionProvider::default(), tasks_file_tracker, cx);
         cx.new_model(|cx| {
             let _subscription = cx.observe(
                 &definitions,
                 |source: &mut Box<(dyn Source + 'static)>, new_definitions, cx| {
                     if let Some(static_source) = source.as_any().downcast_mut::<Self>() {
-                        static_source.runnables = new_definitions
+                        static_source.tasks = new_definitions
                             .read(cx)
                             .get()
-                            .runnables
+                            .tasks
                             .clone()
                             .into_iter()
                             .enumerate()
-                            .map(|(id, definition)| StaticRunnable::new(id, definition))
+                            .map(|(id, definition)| StaticTask::new(id, definition))
                             .collect();
                         cx.notify();
                     }
                 },
             );
             Box::new(Self {
-                runnables: Vec::new(),
+                tasks: Vec::new(),
                 _definitions: definitions,
                 _subscription,
             })
@@ -142,15 +141,15 @@ impl StaticSource {
 }
 
 impl Source for StaticSource {
-    fn runnables_for_path(
+    fn tasks_for_path(
         &mut self,
         _: Option<&Path>,
         _: &mut ModelContext<Box<dyn Source>>,
-    ) -> Vec<Arc<dyn Runnable>> {
-        self.runnables
+    ) -> Vec<Arc<dyn Task>> {
+        self.tasks
             .clone()
             .into_iter()
-            .map(|runnable| Arc::new(runnable) as Arc<dyn Runnable>)
+            .map(|task| Arc::new(task) as Arc<dyn Task>)
             .collect()
     }
 

crates/runnable/src/static_runnable.rs → crates/task/src/static_task.rs 🔗

@@ -1,26 +1,26 @@
-//! Definitions of runnables with a static file config definition, not dependent on the application state.
+//! Definitions of tasks with a static file config definition, not dependent on the application state.
 
 use std::path::{Path, PathBuf};
 
-use crate::{static_source::Definition, Runnable, RunnableId, SpawnInTerminal};
+use crate::{static_source::Definition, SpawnInTerminal, Task, TaskId};
 
-/// A single config file entry with the deserialized runnable definition.
+/// A single config file entry with the deserialized task definition.
 #[derive(Clone, Debug, PartialEq)]
-pub struct StaticRunnable {
-    id: RunnableId,
+pub struct StaticTask {
+    id: TaskId,
     definition: Definition,
 }
 
-impl StaticRunnable {
-    pub(super) fn new(id: usize, runnable: Definition) -> Self {
+impl StaticTask {
+    pub(super) fn new(id: usize, task_definition: Definition) -> Self {
         Self {
-            id: RunnableId(format!("static_{}_{}", runnable.label, id)),
-            definition: runnable,
+            id: TaskId(format!("static_{}_{}", task_definition.label, id)),
+            definition: task_definition,
         }
     }
 }
 
-impl Runnable for StaticRunnable {
+impl Task for StaticTask {
     fn exec(&self, cwd: Option<PathBuf>) -> Option<SpawnInTerminal> {
         Some(SpawnInTerminal {
             id: self.id.clone(),
@@ -39,7 +39,7 @@ impl Runnable for StaticRunnable {
         &self.definition.label
     }
 
-    fn id(&self) -> &RunnableId {
+    fn id(&self) -> &TaskId {
         &self.id
     }
 

crates/runnables_ui/Cargo.toml → crates/tasks_ui/Cargo.toml 🔗

@@ -1,5 +1,5 @@
 [package]
-name = "runnables_ui"
+name = "tasks_ui"
 version = "0.1.0"
 edition = "2021"
 publish = false
@@ -17,7 +17,7 @@ log.workspace = true
 menu.workspace = true
 picker.workspace = true
 project.workspace = true
-runnable.workspace = true
+task.workspace = true
 schemars.workspace = true
 serde.workspace = true
 serde_json.workspace = true

crates/runnables_ui/src/lib.rs → crates/tasks_ui/src/lib.rs 🔗

@@ -1,9 +1,9 @@
 use std::path::PathBuf;
 
 use gpui::{AppContext, ViewContext, WindowContext};
-use modal::RunnablesModal;
+use modal::TasksModal;
 pub use oneshot_source::OneshotSource;
-use runnable::Runnable;
+use task::Task;
 use util::ResultExt;
 use workspace::Workspace;
 
@@ -15,19 +15,18 @@ pub fn init(cx: &mut AppContext) {
         |workspace: &mut Workspace, _: &mut ViewContext<Workspace>| {
             workspace
                 .register_action(|workspace, _: &modal::Spawn, cx| {
-                    let inventory = workspace.project().read(cx).runnable_inventory().clone();
+                    let inventory = workspace.project().read(cx).task_inventory().clone();
                     let workspace_handle = workspace.weak_handle();
-                    workspace.toggle_modal(cx, |cx| {
-                        RunnablesModal::new(inventory, workspace_handle, cx)
-                    })
+                    workspace
+                        .toggle_modal(cx, |cx| TasksModal::new(inventory, workspace_handle, cx))
                 })
                 .register_action(move |workspace, _: &modal::Rerun, cx| {
-                    if let Some(runnable) = workspace.project().update(cx, |project, cx| {
+                    if let Some(task) = workspace.project().update(cx, |project, cx| {
                         project
-                            .runnable_inventory()
-                            .update(cx, |inventory, cx| inventory.last_scheduled_runnable(cx))
+                            .task_inventory()
+                            .update(cx, |inventory, cx| inventory.last_scheduled_task(cx))
                     }) {
-                        schedule_runnable(workspace, runnable.as_ref(), cx)
+                        schedule_task(workspace, task.as_ref(), cx)
                     };
                 });
         },
@@ -35,27 +34,23 @@ pub fn init(cx: &mut AppContext) {
     .detach();
 }
 
-fn schedule_runnable(
-    workspace: &Workspace,
-    runnable: &dyn Runnable,
-    cx: &mut ViewContext<'_, Workspace>,
-) {
-    let cwd = match runnable.cwd() {
+fn schedule_task(workspace: &Workspace, task: &dyn Task, cx: &mut ViewContext<'_, Workspace>) {
+    let cwd = match task.cwd() {
         Some(cwd) => Some(cwd.to_path_buf()),
-        None => runnable_cwd(workspace, cx).log_err().flatten(),
+        None => task_cwd(workspace, cx).log_err().flatten(),
     };
-    let spawn_in_terminal = runnable.exec(cwd);
+    let spawn_in_terminal = task.exec(cwd);
     if let Some(spawn_in_terminal) = spawn_in_terminal {
         workspace.project().update(cx, |project, cx| {
-            project.runnable_inventory().update(cx, |inventory, _| {
-                inventory.last_scheduled_runnable = Some(runnable.id().clone());
+            project.task_inventory().update(cx, |inventory, _| {
+                inventory.last_scheduled_task = Some(task.id().clone());
             })
         });
-        cx.emit(workspace::Event::SpawnRunnable(spawn_in_terminal));
+        cx.emit(workspace::Event::SpawnTask(spawn_in_terminal));
     }
 }
 
-fn runnable_cwd(workspace: &Workspace, cx: &mut WindowContext) -> anyhow::Result<Option<PathBuf>> {
+fn task_cwd(workspace: &Workspace, cx: &mut WindowContext) -> anyhow::Result<Option<PathBuf>> {
     let project = workspace.project().read(cx);
     let available_worktrees = project
         .worktrees()
@@ -82,7 +77,7 @@ fn runnable_cwd(workspace: &Workspace, cx: &mut WindowContext) -> anyhow::Result
             });
             anyhow::ensure!(
                 cwd_for_active_entry.is_some(),
-                "Cannot determine runnable cwd for multiple worktrees"
+                "Cannot determine task cwd for multiple worktrees"
             );
             cwd_for_active_entry
         }

crates/runnables_ui/src/modal.rs → crates/tasks_ui/src/modal.rs 🔗

@@ -3,24 +3,24 @@ use std::sync::Arc;
 use fuzzy::{StringMatch, StringMatchCandidate};
 use gpui::{
     actions, rems, AppContext, DismissEvent, EventEmitter, FocusableView, InteractiveElement,
-    Model, ParentElement, Render, SharedString, Styled, Subscription, Task, View, ViewContext,
+    Model, ParentElement, Render, SharedString, Styled, Subscription, View, ViewContext,
     VisualContext, WeakView,
 };
 use picker::{Picker, PickerDelegate};
 use project::Inventory;
-use runnable::Runnable;
+use task::Task;
 use ui::{v_flex, HighlightedLabel, ListItem, ListItemSpacing, Selectable};
 use util::ResultExt;
 use workspace::{ModalView, Workspace};
 
-use crate::{schedule_runnable, OneshotSource};
+use crate::{schedule_task, OneshotSource};
 
-actions!(runnables, [Spawn, Rerun]);
+actions!(task, [Spawn, Rerun]);
 
-/// A modal used to spawn new runnables.
-pub(crate) struct RunnablesModalDelegate {
+/// A modal used to spawn new tasks.
+pub(crate) struct TasksModalDelegate {
     inventory: Model<Inventory>,
-    candidates: Vec<Arc<dyn Runnable>>,
+    candidates: Vec<Arc<dyn Task>>,
     matches: Vec<StringMatch>,
     selected_index: usize,
     placeholder_text: Arc<str>,
@@ -28,7 +28,7 @@ pub(crate) struct RunnablesModalDelegate {
     last_prompt: String,
 }
 
-impl RunnablesModalDelegate {
+impl TasksModalDelegate {
     fn new(inventory: Model<Inventory>, workspace: WeakView<Workspace>) -> Self {
         Self {
             inventory,
@@ -36,12 +36,12 @@ impl RunnablesModalDelegate {
             candidates: Vec::new(),
             matches: Vec::new(),
             selected_index: 0,
-            placeholder_text: Arc::from("Select runnable..."),
+            placeholder_text: Arc::from("Select task..."),
             last_prompt: String::default(),
         }
     }
 
-    fn spawn_oneshot(&mut self, cx: &mut AppContext) -> Option<Arc<dyn Runnable>> {
+    fn spawn_oneshot(&mut self, cx: &mut AppContext) -> Option<Arc<dyn Task>> {
         let oneshot_source = self
             .inventory
             .update(cx, |this, _| this.source::<OneshotSource>())?;
@@ -54,20 +54,19 @@ impl RunnablesModalDelegate {
     }
 }
 
-pub(crate) struct RunnablesModal {
-    picker: View<Picker<RunnablesModalDelegate>>,
+pub(crate) struct TasksModal {
+    picker: View<Picker<TasksModalDelegate>>,
     _subscription: Subscription,
 }
 
-impl RunnablesModal {
+impl TasksModal {
     pub(crate) fn new(
         inventory: Model<Inventory>,
         workspace: WeakView<Workspace>,
         cx: &mut ViewContext<Self>,
     ) -> Self {
-        let picker = cx.new_view(|cx| {
-            Picker::uniform_list(RunnablesModalDelegate::new(inventory, workspace), cx)
-        });
+        let picker = cx
+            .new_view(|cx| Picker::uniform_list(TasksModalDelegate::new(inventory, workspace), cx));
         let _subscription = cx.subscribe(&picker, |_, _, _, cx| {
             cx.emit(DismissEvent);
         });
@@ -77,7 +76,8 @@ impl RunnablesModal {
         }
     }
 }
-impl Render for RunnablesModal {
+
+impl Render for TasksModal {
     fn render(&mut self, cx: &mut ViewContext<Self>) -> impl gpui::prelude::IntoElement {
         v_flex()
             .w(rems(34.))
@@ -90,15 +90,17 @@ impl Render for RunnablesModal {
     }
 }
 
-impl EventEmitter<DismissEvent> for RunnablesModal {}
-impl FocusableView for RunnablesModal {
+impl EventEmitter<DismissEvent> for TasksModal {}
+
+impl FocusableView for TasksModal {
     fn focus_handle(&self, cx: &gpui::AppContext) -> gpui::FocusHandle {
         self.picker.read(cx).focus_handle(cx)
     }
 }
-impl ModalView for RunnablesModal {}
 
-impl PickerDelegate for RunnablesModalDelegate {
+impl ModalView for TasksModal {}
+
+impl PickerDelegate for TasksModalDelegate {
     type ListItem = ListItem;
 
     fn match_count(&self) -> usize {
@@ -121,14 +123,14 @@ impl PickerDelegate for RunnablesModalDelegate {
         &mut self,
         query: String,
         cx: &mut ViewContext<picker::Picker<Self>>,
-    ) -> Task<()> {
+    ) -> gpui::Task<()> {
         cx.spawn(move |picker, mut cx| async move {
             let Some(candidates) = picker
                 .update(&mut cx, |picker, cx| {
                     picker.delegate.candidates = picker
                         .delegate
                         .inventory
-                        .update(cx, |inventory, cx| inventory.list_runnables(None, cx));
+                        .update(cx, |inventory, cx| inventory.list_tasks(None, cx));
                     picker
                         .delegate
                         .candidates
@@ -178,7 +180,7 @@ impl PickerDelegate for RunnablesModalDelegate {
 
     fn confirm(&mut self, secondary: bool, cx: &mut ViewContext<picker::Picker<Self>>) {
         let current_match_index = self.selected_index();
-        let Some(runnable) = secondary
+        let Some(task) = secondary
             .then(|| self.spawn_oneshot(cx))
             .flatten()
             .or_else(|| {
@@ -193,7 +195,7 @@ impl PickerDelegate for RunnablesModalDelegate {
 
         self.workspace
             .update(cx, |workspace, cx| {
-                schedule_runnable(workspace, runnable.as_ref(), cx);
+                schedule_task(workspace, task.as_ref(), cx);
             })
             .ok();
         cx.emit(DismissEvent);
@@ -210,10 +212,9 @@ impl PickerDelegate for RunnablesModalDelegate {
         _cx: &mut ViewContext<picker::Picker<Self>>,
     ) -> Option<Self::ListItem> {
         let hit = &self.matches[ix];
-        //let runnable = self.candidates[target_index].metadata();
         let highlights: Vec<_> = hit.positions.iter().copied().collect();
         Some(
-            ListItem::new(SharedString::from(format!("runnables-modal-{ix}")))
+            ListItem::new(SharedString::from(format!("tasks-modal-{ix}")))
                 .inset(true)
                 .spacing(ListItemSpacing::Sparse)
                 .selected(selected)

crates/runnables_ui/src/oneshot_source.rs → crates/tasks_ui/src/oneshot_source.rs 🔗

@@ -1,28 +1,26 @@
 use std::sync::Arc;
 
 use gpui::{AppContext, Model};
-use runnable::{Runnable, RunnableId, Source};
+use task::{Source, SpawnInTerminal, Task, TaskId};
 use ui::Context;
 
 pub struct OneshotSource {
-    runnables: Vec<Arc<dyn runnable::Runnable>>,
+    tasks: Vec<Arc<dyn Task>>,
 }
 
 #[derive(Clone)]
-struct OneshotRunnable {
-    id: RunnableId,
+struct OneshotTask {
+    id: TaskId,
 }
 
-impl OneshotRunnable {
+impl OneshotTask {
     fn new(prompt: String) -> Self {
-        Self {
-            id: RunnableId(prompt),
-        }
+        Self { id: TaskId(prompt) }
     }
 }
 
-impl Runnable for OneshotRunnable {
-    fn id(&self) -> &runnable::RunnableId {
+impl Task for OneshotTask {
+    fn id(&self) -> &TaskId {
         &self.id
     }
 
@@ -34,11 +32,11 @@ impl Runnable for OneshotRunnable {
         None
     }
 
-    fn exec(&self, cwd: Option<std::path::PathBuf>) -> Option<runnable::SpawnInTerminal> {
+    fn exec(&self, cwd: Option<std::path::PathBuf>) -> Option<SpawnInTerminal> {
         if self.id().0.is_empty() {
             return None;
         }
-        Some(runnable::SpawnInTerminal {
+        Some(SpawnInTerminal {
             id: self.id().clone(),
             label: self.name().to_owned(),
             command: self.id().0.clone(),
@@ -54,12 +52,12 @@ impl Runnable for OneshotRunnable {
 
 impl OneshotSource {
     pub fn new(cx: &mut AppContext) -> Model<Box<dyn Source>> {
-        cx.new_model(|_| Box::new(Self { runnables: vec![] }) as Box<dyn Source>)
+        cx.new_model(|_| Box::new(Self { tasks: Vec::new() }) as Box<dyn Source>)
     }
 
-    pub fn spawn(&mut self, prompt: String) -> Arc<dyn runnable::Runnable> {
-        let ret = Arc::new(OneshotRunnable::new(prompt));
-        self.runnables.push(ret.clone());
+    pub fn spawn(&mut self, prompt: String) -> Arc<dyn Task> {
+        let ret = Arc::new(OneshotTask::new(prompt));
+        self.tasks.push(ret.clone());
         ret
     }
 }
@@ -69,11 +67,11 @@ impl Source for OneshotSource {
         self
     }
 
-    fn runnables_for_path(
+    fn tasks_for_path(
         &mut self,
         _path: Option<&std::path::Path>,
         _cx: &mut gpui::ModelContext<Box<dyn Source>>,
-    ) -> Vec<Arc<dyn runnable::Runnable>> {
-        self.runnables.clone()
+    ) -> Vec<Arc<dyn Task>> {
+        self.tasks.clone()
     }
 }

crates/terminal/Cargo.toml 🔗

@@ -24,7 +24,7 @@ libc = "0.2"
 mio-extras = "2.0.6"
 ordered-float.workspace = true
 procinfo = { git = "https://github.com/zed-industries/wezterm", rev = "0c13436f4fa8b126f46dd4a20106419b41666897", default-features = false }
-runnable.workspace = true
+task.workspace = true
 schemars.workspace = true
 serde.workspace = true
 serde_derive.workspace = true

crates/terminal/src/terminal.rs 🔗

@@ -1,5 +1,7 @@
 pub mod mappings;
+
 pub use alacritty_terminal;
+
 pub mod terminal_settings;
 
 use alacritty_terminal::{
@@ -33,10 +35,10 @@ use mappings::mouse::{
 use collections::{HashMap, VecDeque};
 use futures::StreamExt;
 use procinfo::LocalProcessInfo;
-use runnable::RunnableId;
 use serde::{Deserialize, Serialize};
 use settings::Settings;
 use smol::channel::{Receiver, Sender};
+use task::TaskId;
 use terminal_settings::{AlternateScroll, Shell, TerminalBlink, TerminalSettings};
 use theme::{ActiveTheme, Theme};
 use util::truncate_and_trailoff;
@@ -179,6 +181,7 @@ impl TerminalSize {
         self.line_height
     }
 }
+
 impl Default for TerminalSize {
     fn default() -> Self {
         TerminalSize::new(
@@ -282,8 +285,8 @@ impl Display for TerminalError {
     }
 }
 
-pub struct SpawnRunnable {
-    pub id: RunnableId,
+pub struct SpawnTask {
+    pub id: TaskId,
     pub label: String,
     pub command: String,
     pub args: Vec<String>,
@@ -302,7 +305,7 @@ pub struct TerminalBuilder {
 impl TerminalBuilder {
     pub fn new(
         working_directory: Option<PathBuf>,
-        runnable: Option<RunableState>,
+        task: Option<TaskState>,
         shell: Shell,
         env: HashMap<String, String>,
         blink_settings: Option<TerminalBlink>,
@@ -340,9 +343,9 @@ impl TerminalBuilder {
         std::env::set_var("LC_ALL", "en_US.UTF-8");
         std::env::set_var("ZED_TERM", "true");
 
-        let scrolling_history = if runnable.is_some() {
-            // Runnables like `cargo build --all` may produce a lot of output, ergo allow maximum scrolling.
-            // After the runnable finishes, we do not allow appending to that terminal, so small runnables output should not
+        let scrolling_history = if task.is_some() {
+            // Tasks like `cargo build --all` may produce a lot of output, ergo allow maximum scrolling.
+            // After the task finishes, we do not allow appending to that terminal, so small tasks output should not
             // cause excessive memory usage over time.
             MAX_SCROLL_HISTORY_LINES
         } else {
@@ -417,7 +420,7 @@ impl TerminalBuilder {
         let word_regex = RegexSearch::new(r#"[\w.\[\]:/@\-~]+"#).unwrap();
 
         let terminal = Terminal {
-            runnable,
+            task,
             pty_tx: Notifier(pty_tx),
             completion_tx,
             term,
@@ -593,11 +596,11 @@ pub struct Terminal {
     hovered_word: bool,
     url_regex: RegexSearch,
     word_regex: RegexSearch,
-    runnable: Option<RunableState>,
+    task: Option<TaskState>,
 }
 
-pub struct RunableState {
-    pub id: RunnableId,
+pub struct TaskState {
+    pub id: TaskId,
     pub label: String,
     pub completed: bool,
     pub completion_rx: Receiver<()>,
@@ -632,9 +635,9 @@ impl Terminal {
             AlacTermEvent::Bell => {
                 cx.emit(Event::Bell);
             }
-            AlacTermEvent::Exit => match &mut self.runnable {
-                Some(runnable) => {
-                    runnable.completed = true;
+            AlacTermEvent::Exit => match &mut self.task {
+                Some(task) => {
+                    task.completed = true;
                     self.completion_tx.try_send(()).ok();
                 }
                 None => cx.emit(Event::CloseTerminal),
@@ -1361,8 +1364,8 @@ impl Terminal {
 
     pub fn title(&self, truncate: bool) -> String {
         const MAX_CHARS: usize = 25;
-        match &self.runnable {
-            Some(runnable_state) => truncate_and_trailoff(&runnable_state.label, MAX_CHARS),
+        match &self.task {
+            Some(task_state) => truncate_and_trailoff(&task_state.label, MAX_CHARS),
             None => self
                 .foreground_process_info
                 .as_ref()
@@ -1399,17 +1402,17 @@ impl Terminal {
         self.cmd_pressed && self.hovered_word
     }
 
-    pub fn runnable(&self) -> Option<&RunableState> {
-        self.runnable.as_ref()
+    pub fn task(&self) -> Option<&TaskState> {
+        self.task.as_ref()
     }
 
-    pub fn wait_for_completed_runnable(&self, cx: &mut AppContext) -> Task<()> {
-        match self.runnable() {
-            Some(runnable) => {
-                if runnable.completed {
+    pub fn wait_for_completed_task(&self, cx: &mut AppContext) -> Task<()> {
+        match self.task() {
+            Some(task) => {
+                if task.completed {
                     Task::ready(())
                 } else {
-                    let mut completion_receiver = runnable.completion_rx.clone();
+                    let mut completion_receiver = task.completion_rx.clone();
                     cx.spawn(|_| async move {
                         completion_receiver.next().await;
                     })
@@ -1642,7 +1645,7 @@ mod tests {
         assert_eq!(
             content.cells[content_index_for_mouse(
                 point(Pixels::from(-10.), Pixels::from(-10.)),
-                &content.size
+                &content.size,
             )]
             .c,
             cells[0][0]
@@ -1650,7 +1653,7 @@ mod tests {
         assert_eq!(
             content.cells[content_index_for_mouse(
                 point(Pixels::from(1000.), Pixels::from(1000.)),
-                &content.size
+                &content.size,
             )]
             .c,
             cells[9][9]

crates/terminal_view/Cargo.toml 🔗

@@ -25,7 +25,7 @@ mio-extras = "2.0.6"
 ordered-float.workspace = true
 procinfo = { git = "https://github.com/zed-industries/wezterm", rev = "0c13436f4fa8b126f46dd4a20106419b41666897", default-features = false }
 project.workspace = true
-runnable.workspace = true
+task.workspace = true
 search.workspace = true
 serde.workspace = true
 serde_derive.workspace = true

crates/terminal_view/src/terminal_panel.rs 🔗

@@ -11,13 +11,13 @@ use gpui::{
 };
 use itertools::Itertools;
 use project::{Fs, ProjectEntryId};
-use runnable::RunnableId;
 use search::{buffer_search::DivRegistrar, BufferSearchBar};
 use serde::{Deserialize, Serialize};
 use settings::Settings;
+use task::{SpawnInTerminal, TaskId};
 use terminal::{
     terminal_settings::{Shell, TerminalDockPosition, TerminalSettings},
-    SpawnRunnable,
+    SpawnTask,
 };
 use ui::{h_flex, ButtonCommon, Clickable, IconButton, IconSize, Selectable, Tooltip};
 use util::{ResultExt, TryFutureExt};
@@ -57,7 +57,7 @@ pub struct TerminalPanel {
     pending_serialization: Task<Option<()>>,
     pending_terminals_to_add: usize,
     _subscriptions: Vec<Subscription>,
-    deferred_runnables: HashMap<RunnableId, Task<()>>,
+    deferred_tasks: HashMap<TaskId, Task<()>>,
 }
 
 impl TerminalPanel {
@@ -166,7 +166,7 @@ impl TerminalPanel {
             width: None,
             height: None,
             pending_terminals_to_add: 0,
-            deferred_runnables: HashMap::default(),
+            deferred_tasks: HashMap::default(),
             _subscriptions: subscriptions,
         };
         this
@@ -223,8 +223,8 @@ impl TerminalPanel {
                     panel._subscriptions.push(cx.subscribe(
                         &workspace,
                         |terminal_panel, _, e, cx| {
-                            if let workspace::Event::SpawnRunnable(spawn_in_terminal) = e {
-                                terminal_panel.spawn_runnable(spawn_in_terminal, cx);
+                            if let workspace::Event::SpawnTask(spawn_in_terminal) = e {
+                                terminal_panel.spawn_task(spawn_in_terminal, cx);
                             };
                         },
                     ))
@@ -295,12 +295,8 @@ impl TerminalPanel {
         })
     }
 
-    pub fn spawn_runnable(
-        &mut self,
-        spawn_in_terminal: &runnable::SpawnInTerminal,
-        cx: &mut ViewContext<Self>,
-    ) {
-        let mut spawn_runnable = SpawnRunnable {
+    pub fn spawn_task(&mut self, spawn_in_terminal: &SpawnInTerminal, cx: &mut ViewContext<Self>) {
+        let mut spawn_task = SpawnTask {
             id: spawn_in_terminal.id.clone(),
             label: spawn_in_terminal.label.clone(),
             command: spawn_in_terminal.command.clone(),
@@ -317,28 +313,28 @@ impl TerminalPanel {
                 return;
             };
 
-            let command = std::mem::take(&mut spawn_runnable.command);
-            let args = std::mem::take(&mut spawn_runnable.args);
-            spawn_runnable.command = shell;
+            let command = std::mem::take(&mut spawn_task.command);
+            let args = std::mem::take(&mut spawn_task.args);
+            spawn_task.command = shell;
             user_args.extend(["-c".to_owned(), command]);
             user_args.extend(args);
-            spawn_runnable.args = user_args;
+            spawn_task.args = user_args;
         }
         let working_directory = spawn_in_terminal.cwd.clone();
         let allow_concurrent_runs = spawn_in_terminal.allow_concurrent_runs;
         let use_new_terminal = spawn_in_terminal.use_new_terminal;
 
         if allow_concurrent_runs && use_new_terminal {
-            self.spawn_in_new_terminal(spawn_runnable, working_directory, cx);
+            self.spawn_in_new_terminal(spawn_task, working_directory, cx);
             return;
         }
 
-        let terminals_for_runnable = self.terminals_for_runnable(&spawn_in_terminal.id, cx);
-        if terminals_for_runnable.is_empty() {
-            self.spawn_in_new_terminal(spawn_runnable, working_directory, cx);
+        let terminals_for_task = self.terminals_for_task(&spawn_in_terminal.id, cx);
+        if terminals_for_task.is_empty() {
+            self.spawn_in_new_terminal(spawn_task, working_directory, cx);
             return;
         }
-        let (existing_item_index, existing_terminal) = terminals_for_runnable
+        let (existing_item_index, existing_terminal) = terminals_for_task
             .last()
             .expect("covered no terminals case above")
             .clone();
@@ -349,28 +345,28 @@ impl TerminalPanel {
             );
             self.replace_terminal(
                 working_directory,
-                spawn_runnable,
+                spawn_task,
                 existing_item_index,
                 existing_terminal,
                 cx,
             );
         } else {
-            self.deferred_runnables.insert(
+            self.deferred_tasks.insert(
                 spawn_in_terminal.id.clone(),
                 cx.spawn(|terminal_panel, mut cx| async move {
-                    wait_for_terminals_tasks(terminals_for_runnable, &mut cx).await;
+                    wait_for_terminals_tasks(terminals_for_task, &mut cx).await;
                     terminal_panel
                         .update(&mut cx, |terminal_panel, cx| {
                             if use_new_terminal {
                                 terminal_panel.spawn_in_new_terminal(
-                                    spawn_runnable,
+                                    spawn_task,
                                     working_directory,
                                     cx,
                                 );
                             } else {
                                 terminal_panel.replace_terminal(
                                     working_directory,
-                                    spawn_runnable,
+                                    spawn_task,
                                     existing_item_index,
                                     existing_terminal,
                                     cx,
@@ -385,11 +381,11 @@ impl TerminalPanel {
 
     fn spawn_in_new_terminal(
         &mut self,
-        spawn_runnable: SpawnRunnable,
+        spawn_task: SpawnTask,
         working_directory: Option<PathBuf>,
         cx: &mut ViewContext<Self>,
     ) {
-        self.add_terminal(working_directory, Some(spawn_runnable), cx);
+        self.add_terminal(working_directory, Some(spawn_task), cx);
         let task_workspace = self.workspace.clone();
         cx.spawn(|_, mut cx| async move {
             task_workspace
@@ -412,9 +408,9 @@ impl TerminalPanel {
         this.update(cx, |this, cx| this.add_terminal(None, None, cx))
     }
 
-    fn terminals_for_runnable(
+    fn terminals_for_task(
         &self,
-        id: &RunnableId,
+        id: &TaskId,
         cx: &mut AppContext,
     ) -> Vec<(usize, View<TerminalView>)> {
         self.pane
@@ -423,8 +419,8 @@ impl TerminalPanel {
             .enumerate()
             .filter_map(|(index, item)| Some((index, item.act_as::<TerminalView>(cx)?)))
             .filter_map(|(index, terminal_view)| {
-                let runnable_state = terminal_view.read(cx).terminal().read(cx).runnable()?;
-                if &runnable_state.id == id {
+                let task_state = terminal_view.read(cx).terminal().read(cx).task()?;
+                if &task_state.id == id {
                     Some((index, terminal_view))
                 } else {
                     None
@@ -442,7 +438,7 @@ impl TerminalPanel {
     fn add_terminal(
         &mut self,
         working_directory: Option<PathBuf>,
-        spawn_runnable: Option<SpawnRunnable>,
+        spawn_task: Option<SpawnTask>,
         cx: &mut ViewContext<Self>,
     ) {
         let workspace = self.workspace.clone();
@@ -461,7 +457,7 @@ impl TerminalPanel {
                 let window = cx.window_handle();
                 if let Some(terminal) = workspace.project().update(cx, |project, cx| {
                     project
-                        .create_terminal(working_directory, spawn_runnable, window, cx)
+                        .create_terminal(working_directory, spawn_task, window, cx)
                         .log_err()
                 }) {
                     let terminal = Box::new(cx.new_view(|cx| {
@@ -495,13 +491,7 @@ impl TerminalPanel {
             .items()
             .filter_map(|item| {
                 let terminal_view = item.act_as::<TerminalView>(cx)?;
-                if terminal_view
-                    .read(cx)
-                    .terminal()
-                    .read(cx)
-                    .runnable()
-                    .is_some()
-                {
+                if terminal_view.read(cx).terminal().read(cx).task().is_some() {
                     None
                 } else {
                     let id = item.item_id().as_u64();
@@ -540,7 +530,7 @@ impl TerminalPanel {
     fn replace_terminal(
         &self,
         working_directory: Option<PathBuf>,
-        spawn_runnable: SpawnRunnable,
+        spawn_task: SpawnTask,
         terminal_item_index: usize,
         terminal_to_replace: View<TerminalView>,
         cx: &mut ViewContext<'_, Self>,
@@ -552,7 +542,7 @@ impl TerminalPanel {
         let window = cx.window_handle();
         let new_terminal = project.update(cx, |project, cx| {
             project
-                .create_terminal(working_directory, Some(spawn_runnable), window, cx)
+                .create_terminal(working_directory, Some(spawn_task), window, cx)
                 .log_err()
         })?;
         terminal_to_replace.update(cx, |terminal_to_replace, cx| {
@@ -571,15 +561,15 @@ impl TerminalPanel {
 }
 
 async fn wait_for_terminals_tasks(
-    terminals_for_runnable: Vec<(usize, View<TerminalView>)>,
+    terminals_for_task: Vec<(usize, View<TerminalView>)>,
     cx: &mut AsyncWindowContext,
 ) {
-    let pending_tasks = terminals_for_runnable.iter().filter_map(|(_, terminal)| {
+    let pending_tasks = terminals_for_task.iter().filter_map(|(_, terminal)| {
         terminal
             .update(cx, |terminal_view, cx| {
                 terminal_view
                     .terminal()
-                    .update(cx, |terminal, cx| terminal.wait_for_completed_runnable(cx))
+                    .update(cx, |terminal, cx| terminal.wait_for_completed_task(cx))
             })
             .ok()
     });

crates/terminal_view/src/terminal_view.rs 🔗

@@ -441,7 +441,7 @@ fn subscribe_for_terminal_events(
             Event::TitleChanged => {
                 cx.emit(ItemEvent::UpdateTab);
                 let terminal = this.terminal().read(cx);
-                if !terminal.runnable().is_some() {
+                if !terminal.task().is_some() {
                     if let Some(foreground_info) = &terminal.foreground_process_info {
                         let cwd = foreground_info.cwd.clone();
 
@@ -777,7 +777,7 @@ impl Item for TerminalView {
     ) -> AnyElement {
         let terminal = self.terminal().read(cx);
         let title = terminal.title(true);
-        let icon = if terminal.runnable().is_some() {
+        let icon = if terminal.task().is_some() {
             IconName::Play
         } else {
             IconName::Terminal
@@ -817,8 +817,8 @@ impl Item for TerminalView {
     }
 
     fn is_dirty(&self, cx: &gpui::AppContext) -> bool {
-        match self.terminal.read(cx).runnable() {
-            Some(runnable) => !runnable.completed,
+        match self.terminal.read(cx).task() {
+            Some(task) => !task.completed,
             None => self.has_bell(),
         }
     }
@@ -883,7 +883,7 @@ impl Item for TerminalView {
     }
 
     fn added_to_workspace(&mut self, workspace: &mut Workspace, cx: &mut ViewContext<Self>) {
-        if !self.terminal().read(cx).runnable().is_some() {
+        if !self.terminal().read(cx).task().is_some() {
             cx.background_executor()
                 .spawn(TERMINAL_DB.update_workspace_id(
                     workspace.database_id(),

crates/util/src/paths.rs 🔗

@@ -39,7 +39,7 @@ lazy_static::lazy_static! {
     };
     pub static ref SETTINGS: PathBuf = CONFIG_DIR.join("settings.json");
     pub static ref KEYMAP: PathBuf = CONFIG_DIR.join("keymap.json");
-    pub static ref RUNNABLES: PathBuf = CONFIG_DIR.join("runnables.json");
+    pub static ref TASKS: PathBuf = CONFIG_DIR.join("tasks.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");

crates/workspace/Cargo.toml 🔗

@@ -40,7 +40,7 @@ node_runtime.workspace = true
 parking_lot.workspace = true
 postage.workspace = true
 project.workspace = true
-runnable.workspace = true
+task.workspace = true
 schemars.workspace = true
 serde.workspace = true
 serde_derive.workspace = true

crates/workspace/src/workspace.rs 🔗

@@ -50,7 +50,6 @@ pub use persistence::{
 };
 use postage::stream::Stream;
 use project::{Project, ProjectEntryId, ProjectPath, Worktree, WorktreeId};
-use runnable::SpawnInTerminal;
 use serde::Deserialize;
 use settings::Settings;
 use shared_screen::SharedScreen;
@@ -66,6 +65,7 @@ use std::{
     sync::{atomic::AtomicUsize, Arc, Weak},
     time::Duration,
 };
+use task::SpawnInTerminal;
 use theme::{ActiveTheme, SystemAppearance, ThemeSettings};
 pub use toolbar::{Toolbar, ToolbarItemEvent, ToolbarItemLocation, ToolbarItemView};
 pub use ui;
@@ -468,7 +468,7 @@ pub enum Event {
     PaneAdded(View<Pane>),
     ContactRequestedJoin(u64),
     WorkspaceCreated(WeakView<Workspace>),
-    SpawnRunnable(SpawnInTerminal),
+    SpawnTask(SpawnInTerminal),
 }
 
 pub enum OpenVisible {
@@ -3004,7 +3004,9 @@ impl Workspace {
             let mut item_tasks = Vec::new();
             let mut leader_view_ids = Vec::new();
             for view in &views {
-                let Some(id) = &view.id else { continue };
+                let Some(id) = &view.id else {
+                    continue;
+                };
                 let id = ViewId::from_proto(id.clone())?;
                 let mut variant = view.variant.clone();
                 if variant.is_none() {
@@ -3749,7 +3751,7 @@ enum ActivateInDirectionTarget {
 }
 
 fn notify_if_database_failed(workspace: WindowHandle<Workspace>, cx: &mut AsyncAppContext) {
-    const REPORT_ISSUE_URL: &str ="https://github.com/zed-industries/zed/issues/new?assignees=&labels=defect%2Ctriage&template=2_bug_report.yml";
+    const REPORT_ISSUE_URL: &str = "https://github.com/zed-industries/zed/issues/new?assignees=&labels=defect%2Ctriage&template=2_bug_report.yml";
 
     workspace
         .update(cx, |workspace, cx| {
@@ -4193,7 +4195,7 @@ async fn join_channel_internal(
             Status::SignedOut => return Err(ErrorCode::SignedOut.into()),
             Status::UpgradeRequired => return Err(ErrorCode::UpgradeRequired.into()),
             Status::ConnectionError | Status::ConnectionLost | Status::ReconnectionError { .. } => {
-                return Err(ErrorCode::Disconnected.into())
+                return Err(ErrorCode::Disconnected.into());
             }
         }
     }
@@ -4270,7 +4272,7 @@ pub fn join_channel(
             &active_call,
             &mut cx,
         )
-        .await;
+            .await;
 
         // join channel succeeded, and opened a window
         if matches!(result, Ok(true)) {
@@ -4305,16 +4307,16 @@ pub fn join_channel(
                         let detail: SharedString = match err.error_code() {
                             ErrorCode::SignedOut => {
                                 "Please sign in to continue.".into()
-                            },
+                            }
                             ErrorCode::UpgradeRequired => {
                                 "Your are running an unsupported version of Zed. Please update to continue.".into()
-                            },
+                            }
                             ErrorCode::NoSuchChannel => {
                                 "No matching channel was found. Please check the link and try again.".into()
-                            },
+                            }
                             ErrorCode::Forbidden => {
                                 "This channel is private, and you do not have access. Please ask someone to add you and try again.".into()
-                            },
+                            }
                             ErrorCode::Disconnected => "Please check your internet connection and try again.".into(),
                             _ => format!("{}\n\nPlease try again.", err).into(),
                         };

crates/zed/Cargo.toml 🔗

@@ -88,8 +88,8 @@ release_channel.workspace = true
 rope.workspace = true
 rpc.workspace = true
 rsa = "0.4"
-runnable.workspace = true
-runnables_ui.workspace = true
+task.workspace = true
+tasks_ui.workspace = true
 rust-embed.workspace = true
 schemars.workspace = true
 search.workspace = true

crates/zed/src/languages/json.rs 🔗

@@ -53,7 +53,7 @@ impl JsonLspAdapter {
             },
             cx,
         );
-        let runnables_schema = runnable::static_source::DefinitionProvider::generate_json_schema();
+        let tasks_schema = task::static_source::DefinitionProvider::generate_json_schema();
         serde_json::json!({
             "json": {
                 "format": {
@@ -72,8 +72,8 @@ impl JsonLspAdapter {
                         "schema": KeymapFile::generate_json_schema(&action_names),
                     },
                     {
-                        "fileMatch": [schema_file_match(&paths::RUNNABLES)],
-                        "schema": runnables_schema,
+                        "fileMatch": [schema_file_match(&paths::TASKS)],
+                        "schema": tasks_schema,
                     }
                 ]
             }

crates/zed/src/main.rs 🔗

@@ -244,7 +244,7 @@ fn main() {
         outline::init(cx);
         project_symbols::init(cx);
         project_panel::init(Assets, cx);
-        runnables_ui::init(cx);
+        tasks_ui::init(cx);
         channel::init(&client, user_store.clone(), cx);
         search::init(cx);
         semantic_index::init(fs.clone(), http.clone(), languages.clone(), cx);

crates/zed/src/zed.rs 🔗

@@ -22,14 +22,14 @@ use project_panel::ProjectPanel;
 use quick_action_bar::QuickActionBar;
 use release_channel::{AppCommitSha, ReleaseChannel};
 use rope::Rope;
-use runnable::static_source::StaticSource;
-use runnables_ui::OneshotSource;
 use search::project_search::ProjectSearchBar;
 use settings::{
     initial_local_settings_content, watch_config_file, KeymapFile, Settings, SettingsStore,
     DEFAULT_KEYMAP_PATH,
 };
 use std::{borrow::Cow, ops::Deref, path::Path, sync::Arc};
+use task::static_source::StaticSource;
+use tasks_ui::OneshotSource;
 use terminal_view::terminal_panel::{self, TerminalPanel};
 use util::{
     asset_str,
@@ -59,7 +59,7 @@ actions!(
         OpenDefaultKeymap,
         OpenDefaultSettings,
         OpenKeymap,
-        OpenRunnables,
+        OpenTasks,
         OpenLicenses,
         OpenLocalSettings,
         OpenLog,
@@ -159,16 +159,16 @@ pub fn initialize_workspace(app_state: Arc<AppState>, cx: &mut AppContext) {
 
         let project = workspace.project().clone();
         if project.read(cx).is_local() {
-            let runnables_file_rx = watch_config_file(
+            let tasks_file_rx = watch_config_file(
                 &cx.background_executor(),
                 app_state.fs.clone(),
-                paths::RUNNABLES.clone(),
+                paths::TASKS.clone(),
             );
-            let static_source = StaticSource::new(runnables_file_rx, cx);
+            let static_source = StaticSource::new(tasks_file_rx, cx);
             let oneshot_source = OneshotSource::new(cx);
 
             project.update(cx, |project, cx| {
-                project.runnable_inventory().update(cx, |inventory, cx| {
+                project.task_inventory().update(cx, |inventory, cx| {
                     inventory.add_source(oneshot_source, cx);
                     inventory.add_source(static_source, cx);
                 })
@@ -278,10 +278,10 @@ pub fn initialize_workspace(app_state: Arc<AppState>, cx: &mut AppContext) {
                 },
             )
             .register_action(
-                move |_: &mut Workspace, _: &OpenRunnables, cx: &mut ViewContext<Workspace>| {
+                move |_: &mut Workspace, _: &OpenTasks, cx: &mut ViewContext<Workspace>| {
                     open_settings_file(
-                        &paths::RUNNABLES,
-                        || settings::initial_runnables_content().as_ref().into(),
+                        &paths::TASKS,
+                        || settings::initial_tasks_content().as_ref().into(),
                         cx,
                     );
                 },