···8899## Commands
1010- `tlp new <name>`: Creates a new local package with the given name in the current directory and links it.
1111+- `tlp init`: Creates a new local package with the name from typst.toml in the current directory. Also initializes a git repository, if not one already.
1112- `tlp path <name>`: Get the full path to the local package with the given name (in case you forgot, or need it for other automation)
1213- `tlp bump <name> [--major|--patch]`: Increase the version of the local package with the given name.
1314 This will create a new git tag for the latest version,
1415 then increase said version by modifying the `typst.toml` and renaming the latest-version symlink,
1516 and finally add a new `git worktree` for the previously latest version.
1717+- `tlp rm <name>`: Removes the local package with the given name.
16181719All commands support the `--package-path` option (also available via the `TYPST_PACKAGE_PATH` env variable),
1820which works exactly like it does in `typst` to specify where to look instead of (the equivalent of) `~/.local/share/typst/packages`.
···23252426Alternatively, you can compile this program with the `git2` feature;
2527Then, it will use `libgit2` instead of invoking `git`, so the `--git` option will have no effect.
2828+2929+3030+## ToDo
3131+- [ ] `tlp init`: Populate a version for each tag
3232+- [ ] `tlp init`: Check if there are any `@local/` in the whole code, check if they are available, if not print warnings.
+8
src/args.rs
···2020 /// The name of the local package
2121 name: String,
2222 },
2323+ /// Initialize a local package
2424+ Init {},
2325 /// Print the path of a local package
2426 #[clap(name = "path")]
2527 PrintPath {
···3638 /// Increase the patch instead of the minor version
3739 #[clap(long)]
3840 patch: bool,
4141+ },
4242+ /// Remove a local package
4343+ #[clap(name = "rm")]
4444+ Remove {
4545+ /// The name of the local package
4646+ name: String,
3947 },
4048}
+58
src/main.rs
···8181 eprintln!("which is linked to {pkg_dir:?}");
8282 eprintln!("you can import it with `#import \"@local/{name}:0.1.0\"`");
8383 }
8484+ Init {} => {
8585+ println!("The current directory is {}", current_dir.display());
8686+ let typst_toml = current_dir.join("typst.toml");
8787+ let name = extract_name(&typst_toml).whatever_context("failed to get package name")?;
8888+ verify_name(&name)?;
8989+ let ver =
9090+ extract_version(&typst_toml).whatever_context("failed to get package version")?;
9191+ let current_ver = format!("{}.{}.{}", ver[0], ver[1], ver[2]);
9292+ let pkg_dir = packages_local.join(&name);
9393+ if pkg_dir.exists() {
9494+ whatever!("a local package called {name:?} already exists");
9595+ }
9696+ fs_err::create_dir(&pkg_dir).whatever_context("failed to create package directory")?;
9797+ if !current_dir.join(".git").exists() {
9898+ eprintln!("Initializing git in the current repo!");
9999+ git::init(¤t_dir, &git).whatever_context("failed to create repository")?;
100100+ git::commit(¤t_dir, "*", "Initial commit", &git, true)
101101+ .whatever_context("failed to create initial commit")?;
102102+ }
103103+ symlink_dir(¤t_dir, &pkg_dir.join("source"))
104104+ .whatever_context("failed to create latest version symlink")?;
105105+ symlink_dir(¤t_dir, &pkg_dir.join(¤t_ver))
106106+ .whatever_context("failed to create latest version symlink")?;
107107+ eprintln!("linked current directory to {pkg_dir:?}");
108108+ eprintln!("you can import it with `#import \"@local/{name}:{current_ver}\"`");
109109+ }
84110 PrintPath { name } => {
85111 verify_name(&name)?;
86112 let pkg_dir = packages_local.join(&name);
···155181 .whatever_context("failed to commit typst.toml")?;
156182 eprintln!("bumped version of local package {name:?} from {old_ver} to {new_ver}.");
157183 }
184184+ Remove { name } => {
185185+ verify_name(&name)?;
186186+ let pkg_dir = packages_local.join(&name);
187187+ if !pkg_dir.exists() {
188188+ whatever!("no local package {name:?} found");
189189+ }
190190+ if !pkg_dir.join("source").is_symlink() {
191191+ whatever!(
192192+ "could not find the source code! Might not be added by tlp, remove aborted."
193193+ )
194194+ }
195195+ fs_err::remove_dir_all(pkg_dir)
196196+ .whatever_context("failed to remove the package directory")?;
197197+ println!("Removed local package: {name:?}");
198198+ }
158199 }
159200160201 Ok(())
202202+}
203203+204204+fn extract_name(typst_toml: &Path) -> Result<String, Whatever> {
205205+ let file = fs_err::read_to_string(typst_toml)
206206+ .whatever_context("could not find a typst.toml file the current directory")?;
207207+ let pkg = toml::from_str::<toml::Table>(&file).whatever_context("failed to parse file")?;
208208+ let name = pkg
209209+ .get("package")
210210+ .whatever_context("no `[package]` table")?
211211+ .as_table()
212212+ .whatever_context("`package` is not a table")?
213213+ .get("name")
214214+ .whatever_context("`[package]` table has no `name` key")?
215215+ .as_str()
216216+ .whatever_context("`package.name` is not a string")?;
217217+ // name.whatever_context("invalid `package.version`")
218218+ Ok(name.to_string())
161219}
162220163221fn extract_version(typst_toml: &Path) -> Result<[u32; 3], Whatever> {