feat(build): vastly simplify the build system

This commit is contained in:
Brooks J Rady 2021-04-14 19:08:22 +01:00
parent 2dd8d817bb
commit af702b67e6
10 changed files with 92 additions and 141 deletions

View File

@ -20,8 +20,10 @@ jobs:
run: rustup target add wasm32-wasi
- name: Install cargo-make
run: cargo install --debug cargo-make
- name: Build & Test
run: cargo make
- name: Build
run: cargo make build
- name: Test
run: cargo make test
format:
name: Check Formatting

View File

@ -1,6 +1,7 @@
# Global Settings
[env]
CARGO_MAKE_EXTEND_WORKSPACE_MAKEFILE = true
CARGO_TARGET_DIR = "${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/target"
SKIP_TEST = false
# Add clippy to the default flow
@ -27,87 +28,34 @@ dependencies = ["pre-test"]
[tasks.post-test]
env = { "SKIP_TEST" = false }
# Running Zellij using patched layouts
# Running Zellij using the development data directory
[tasks.run]
workspace = false
dependencies = ["build-workspace", "patch-layouts"]
dependencies = ["build-workspace", "build-dev-data-dir"]
run_task = "launch"
[tasks.build-workspace]
run_task = { name = "build", fork = true }
[tasks.patch-layouts]
script_runner = "@rust"
script = '''
//! ```cargo
//! [dependencies]
//! yaml-rust = "0.4"
//! ```
use std::{env, error::Error, fs, path::Path};
use yaml_rust::{Yaml, YamlEmitter, YamlLoader};
fn main() -> Result<(), Box<dyn Error>> {
let root = env::var("CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY")?;
let layout_path = Path::new(&root).join("assets/layouts");
for layout in fs::read_dir(layout_path)? {
let layout = layout?.path();
let yaml = fs::read_to_string(&layout)?;
let yaml = YamlLoader::load_from_str(&yaml)?.remove(0);
let yaml = patch_plugins(&root, yaml);
let new_layout = Path::new(&root)
.join("target")
.join(layout.file_name().unwrap());
let mut new_yaml = String::new();
let mut emitter = YamlEmitter::new(&mut new_yaml);
emitter.dump(&yaml)?;
fs::write(new_layout, new_yaml)?;
}
Ok(())
}
fn patch_plugins(root: &str, part: Yaml) -> Yaml {
let mut map = part.into_hash().unwrap();
if let Some(plugin) = map.get_mut(&Yaml::from_str("plugin")) {
let new_plugin = Path::new(root)
.join("target/wasm32-wasi/debug")
.join(plugin.as_str().unwrap());
*plugin = Yaml::String(new_plugin.to_string_lossy().into_owned());
}
if let Some(parts) = map.get_mut(&Yaml::from_str("parts")) {
let new_parts = parts
.clone()
.into_iter()
.map(|p| patch_plugins(root, p))
.collect();
*parts = Yaml::Array(new_parts);
}
Yaml::Hash(map)
}
'''
[tasks.pre-launch]
[tasks.build-dev-data-dir]
script_runner = "@duckscript"
script = '''
args = split ${CARGO_MAKE_TASK_ARGS} ;
set_env ZELLIJ_LAYOUT default
if not array_is_empty ${args}
first = array_get ${args} 0
if starts_with ${first} -
set_env ZELLIJ_ARGS ${CARGO_MAKE_TASK_ARGS}
else
set_env ZELLIJ_LAYOUT ${first}
array_remove ${args} 0
args = array_join ${args} ;
set_env ZELLIJ_ARGS ${args}
end
asset_dir = set ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/assets
target_dir = set ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/target
data_dir = set ${target_dir}/dev-data
rm -r ${data_dir}
cp ${asset_dir}/layouts ${data_dir}/
plugins = glob_array ${target_dir}/wasm32-wasi/debug/*.wasm
for plugin in ${plugins}
plugin_name = basename ${plugin}
cp ${plugin} ${data_dir}/plugins/${plugin_name}
end
writefile ${data_dir}/VERSION ${CARGO_MAKE_CRATE_VERSION}
'''
[tasks.launch]
dependencies = ["pre-launch"]
command = "cargo"
args = ["run", "--", "-l", "${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/target/${ZELLIJ_LAYOUT}.yaml", "@@split(ZELLIJ_ARGS,;)"]
args = ["run", "--", "--data-dir", "${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/target/dev-data/", "@@split(CARGO_MAKE_TASK_ARGS,;)"]
# Simple clippy tweak
[tasks.clippy]
@ -116,7 +64,7 @@ args = ["clippy", "--", "@@split(CARGO_MAKE_TASK_ARGS,;)"]
# Release building and installing Zellij
[tasks.install]
workspace = false
dependencies = ["build-tiles-release", "wasm-opt-tiles", "build-release", "clear-data-directory"]
dependencies = ["build-tiles-release", "wasm-opt-tiles", "build-release"]
script_runner = "@duckscript"
script = '''
cp ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/target/release/${CARGO_MAKE_CRATE_NAME} ${CARGO_MAKE_TASK_ARGS}
@ -140,33 +88,15 @@ for tile in ${tiles}
end
'''
# FIXME: Maybe this should be more generic? Or just blow away the whole directory?
[tasks.clear-data-directory]
script_runner = "@rust"
script = '''
//! ```cargo
//! [dependencies]
//! directories-next = "2.0"
//! ```
use directories_next::ProjectDirs;
use std::fs;
fn main() {
let project_dirs = ProjectDirs::from("org", "Zellij Contributors", "Zellij").unwrap();
let data_dir = project_dirs.data_dir();
drop(fs::remove_file(data_dir.join("plugins/status-bar.wasm")));
drop(fs::remove_file(data_dir.join("plugins/tab-bar.wasm")));
drop(fs::remove_file(data_dir.join("plugins/strider.wasm")));
drop(fs::remove_file(data_dir.join("layouts/default.yaml")));
drop(fs::remove_file(data_dir.join("layouts/strider.yaml")));
}
'''
# Publishing Zellij
[tasks.publish]
clear = true
workspace = false
dependencies = ["build-tiles-release", "wasm-opt-tiles", "build-release", "publish-zellij-tile", "publish-zellij"]
dependencies = ["build-tiles-release", "wasm-opt-tiles", "build-release"]
run_task = [
{ name = "publish-zellij-tile" },
{ name = "publish-zellij" }
]
[tasks.publish-zellij-tile]
cwd = "zellij-tile"

View File

@ -20,6 +20,7 @@ _zellij() {
'-o+[Send "open file in new pane" to active zellij session]' \
'--open-file=[Send "open file in new pane" to active zellij session]' \
'--max-panes=[Maximum panes on screen, caution: opening more panes will close old ones]' \
'--data-dir=[Change where zellij looks for layouts and plugins]' \
'-l+[Path to a layout yaml file]' \
'--layout=[Path to a layout yaml file]' \
'-m[Send "move focused pane" to active zellij session]' \

View File

@ -29,7 +29,7 @@ _zellij() {
case "${cmd}" in
zellij)
opts=" -m -d -h -V -s -o -l --move-focus --debug --help --version --split --open-file --max-panes --layout config help c c"
opts=" -m -d -h -V -s -o -l --move-focus --debug --help --version --split --open-file --max-panes --data-dir --layout config help c c"
if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
@ -56,6 +56,10 @@ _zellij() {
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
--data-dir)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
--layout)
COMPREPLY=($(compgen -f "${cur}"))
return 0

View File

@ -1,6 +1,7 @@
complete -c zellij -n "__fish_use_subcommand" -s s -l split -d 'Send "split (direction h == horizontal / v == vertical)" to active zellij session'
complete -c zellij -n "__fish_use_subcommand" -s o -l open-file -d 'Send "open file in new pane" to active zellij session'
complete -c zellij -n "__fish_use_subcommand" -l max-panes -d 'Maximum panes on screen, caution: opening more panes will close old ones'
complete -c zellij -n "__fish_use_subcommand" -l data-dir -d 'Change where zellij looks for layouts and plugins'
complete -c zellij -n "__fish_use_subcommand" -s l -l layout -d 'Path to a layout yaml file'
complete -c zellij -n "__fish_use_subcommand" -s m -l move-focus -d 'Send "move focused pane" to active zellij session'
complete -c zellij -n "__fish_use_subcommand" -s d -l debug

View File

@ -20,6 +20,10 @@ pub struct CliArgs {
#[structopt(long)]
pub max_panes: Option<usize>,
/// Change where zellij looks for layouts and plugins
#[structopt(long)]
pub data_dir: Option<PathBuf>,
/// Path to a layout yaml file
#[structopt(short, long)]
pub layout: Option<PathBuf>,

View File

@ -1,6 +1,5 @@
use directories_next::ProjectDirs;
use serde::{Deserialize, Serialize};
use std::path::PathBuf;
use std::path::{Path, PathBuf};
use std::{fs::File, io::prelude::*};
use crate::panes::PositionAndSize;
@ -180,11 +179,9 @@ pub struct Layout {
}
impl Layout {
pub fn new(layout_path: PathBuf) -> Self {
let project_dirs = ProjectDirs::from("org", "Zellij Contributors", "Zellij").unwrap();
let layout_dir = project_dirs.data_dir().join("layouts/");
pub fn new(layout_path: &Path, data_dir: &Path) -> Self {
let layout_dir = data_dir.join("layouts/");
let mut layout_file = File::open(&layout_path)
.or_else(|_| File::open(&layout_path.with_extension("yaml")))
.or_else(|_| File::open(&layout_dir.join(&layout_path).with_extension("yaml")))
.unwrap_or_else(|_| panic!("cannot find layout {}", &layout_path.display()));

View File

@ -1,12 +1,41 @@
use std::{fs, path::Path};
const VERSION: &str = env!("CARGO_PKG_VERSION");
#[macro_export]
macro_rules! asset_map {
($($src:literal => $dst:literal),+ $(,)?) => {
{
let mut assets = std::collections::HashMap::new();
$(
assets.insert($dst, include_bytes!(concat!("../", $src)).to_vec());
assets.insert($dst, include_bytes!(concat!(env!("CARGO_MANIFEST_DIR"), "/", $src)).to_vec());
)+
assets
}
}
}
pub fn populate_data_dir(data_dir: &Path) {
// First run installation of default plugins & layouts
let mut assets = asset_map! {
"assets/layouts/default.yaml" => "layouts/default.yaml",
"assets/layouts/strider.yaml" => "layouts/strider.yaml",
};
assets.extend(asset_map! {
"assets/plugins/status-bar.wasm" => "plugins/status-bar.wasm",
"assets/plugins/tab-bar.wasm" => "plugins/tab-bar.wasm",
"assets/plugins/strider.wasm" => "plugins/strider.wasm",
});
assets.insert("VERSION", VERSION.as_bytes().to_vec());
let last_version = fs::read_to_string(data_dir.join("VERSION")).unwrap_or_default();
let out_of_date = VERSION != last_version;
for (path, bytes) in assets {
let path = data_dir.join(path);
fs::create_dir_all(path.parent().unwrap()).unwrap();
if out_of_date || !path.exists() {
fs::write(path, bytes).expect("Failed to install default assets!");
}
}
}

View File

@ -33,6 +33,7 @@ use errors::{
ScreenContext,
};
use input::handler::input_loop;
use install::populate_data_dir;
use os_input_output::OsApi;
use pty_bus::{PtyBus, PtyInstruction};
use screen::{Screen, ScreenInstruction};
@ -167,12 +168,22 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs) {
opts.debug,
);
// Determine and initialize the data directory
let project_dirs = ProjectDirs::from("org", "Zellij Contributors", "Zellij").unwrap();
let data_dir = opts
.data_dir
.unwrap_or_else(|| project_dirs.data_dir().to_path_buf());
populate_data_dir(&data_dir);
// Don't use default layouts in tests, but do everywhere else
#[cfg(not(test))]
let default_layout = Some(PathBuf::from("default"));
#[cfg(test)]
let default_layout = None;
let maybe_layout = opts.layout.or(default_layout).map(Layout::new);
let maybe_layout = opts
.layout
.or(default_layout)
.map(|p| Layout::new(&p, &data_dir));
#[cfg(not(test))]
std::panic::set_hook({
@ -443,9 +454,7 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs) {
err_ctx.add_call(ContextType::Plugin(PluginContext::from(&event)));
match event {
PluginInstruction::Load(pid_tx, path) => {
let project_dirs =
ProjectDirs::from("org", "Zellij Contributors", "Zellij").unwrap();
let plugin_dir = project_dirs.data_dir().join("plugins/");
let plugin_dir = data_dir.join("plugins/");
let wasm_bytes = fs::read(&path)
.or_else(|_| fs::read(&path.with_extension("wasm")))
.or_else(|_| fs::read(&plugin_dir.join(&path).with_extension("wasm")))

View File

@ -1,23 +1,10 @@
#[cfg(test)]
mod tests;
mod cli;
mod common;
#[cfg(test)]
mod tests;
// TODO mod server;
mod client;
use client::{boundaries, layout, panes, tab};
use common::{
command_is_executing, errors, os_input_output, pty_bus, screen, start, utils, wasm_vm,
ApiCommand,
};
use directories_next::ProjectDirs;
use std::os::unix::net::UnixStream;
use std::{fs, io::Write};
use structopt::StructOpt;
use crate::cli::CliArgs;
use crate::command_is_executing::CommandIsExecuting;
use crate::os_input_output::get_os_input;
@ -25,29 +12,16 @@ use crate::utils::{
consts::{ZELLIJ_IPC_PIPE, ZELLIJ_TMP_DIR, ZELLIJ_TMP_LOG_DIR},
logging::*,
};
use client::{boundaries, layout, panes, tab};
use common::{
command_is_executing, errors, os_input_output, pty_bus, screen, start, utils, wasm_vm,
ApiCommand,
};
use std::io::Write;
use std::os::unix::net::UnixStream;
use structopt::StructOpt;
pub fn main() {
// First run installation of default plugins & layouts
let project_dirs = ProjectDirs::from("org", "Zellij Contributors", "Zellij").unwrap();
let data_dir = project_dirs.data_dir();
let mut assets = asset_map! {
"assets/layouts/default.yaml" => "layouts/default.yaml",
"assets/layouts/strider.yaml" => "layouts/strider.yaml",
};
assets.extend(asset_map! {
"assets/plugins/status-bar.wasm" => "plugins/status-bar.wasm",
"assets/plugins/tab-bar.wasm" => "plugins/tab-bar.wasm",
"assets/plugins/strider.wasm" => "plugins/strider.wasm",
});
for (path, bytes) in assets {
let path = data_dir.join(path);
fs::create_dir_all(path.parent().unwrap()).unwrap();
if !path.exists() {
fs::write(path, bytes).expect("Failed to install default assets!");
}
}
let opts = CliArgs::from_args();
if let Some(split_dir) = opts.split {
match split_dir {