Skip to content

Commit 429599b

Browse files
authored
Merge pull request #33 from ethagnawl/publicize-struct-fields
Publicize struct fields
2 parents 87305b3 + 660d184 commit 429599b

File tree

5 files changed

+80
-30
lines changed

5 files changed

+80
-30
lines changed

Cargo.lock

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "rmuxinator"
3-
version = "0.1.0"
3+
version = "1.0.0"
44
authors = ["Peter Doherty <[email protected]>"]
55
edition = "2018"
66
description = "tmux project configuration utility"

README.md

+48-1
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,53 @@ session using a path to a project config file:
122122
Start a tmux session using a path to a project config file:
123123
`rmuxinator start Example.toml`
124124

125+
### Use as a library
126+
rmuxinator can also be used as a library by other programs.
127+
128+
There are two ways to achieve this:
129+
130+
#### Config::new_from_config_path
131+
This option accepts a path to an rmuxinator config file and is how the rmuxinator binary works. This is how this project's binary entrypoint works.
132+
133+
Example:
134+
135+
```
136+
let config = rmuxinator::Config::new_from_config_path(&String::from("/home/pi/foo.toml")).map_err(|error| format!("Problem parsing config file: {}", error))?;
137+
rmuxinator::run_start(config).map_err(|error| format!("Application error: {}", error));
138+
```
139+
140+
#### Config constructor
141+
This option allows the caller to create an rmuxinator `Config` struct and then pass it to the `run_start` function.
142+
143+
The [pi-wall-utils](https://github.com/ethagnawl/pi-wall-utils) project (also maintained by [ethagnawl](https://github.com/ethagnawl)) does this and can be used as a reference.
144+
145+
146+
Example:
147+
148+
```
149+
let rmuxinator_config = rmuxinator::Config {
150+
hooks: vec![],
151+
layout: None,
152+
name: String::from("rmuxinator-library-example"),
153+
windows: vec![
154+
rmuxinator::Window {
155+
layout: None,
156+
name: None,
157+
panes: vec![rmuxinator::Pane {
158+
commands: vec![
159+
String::from("echo 'hello!'"),
160+
],
161+
name: None,
162+
start_directory: None,
163+
}],
164+
start_directory: None,
165+
}
166+
];
167+
168+
};
169+
rmuxinator::run_start(rmuxinator_config).map_err(|error| format!("Rmuxinator error: {}", error))
170+
```
171+
125172
## Known Issues and Workarounds
126173
### Indexes
127174
rmuxinator currently assumes that both `base-index` and `pane-base-index` are
@@ -169,13 +216,13 @@ remove themselves in order to prevent duplicate events.
169216
- Handle shell failures -- `tmux kill-window` was failing silently
170217
- Can commands can all be moved into structs and computed up front? This might
171218
require writing a custom Serde deserializer for the Config type.
219+
- Start detached tmux session
172220
- Select window on attach (can this be handled by a pre-existing hook?)
173221
- Attach if session exists instead of creating sesssion
174222
- Search for project config file on disk (XDG_CONFIG?) instead of parsing
175223
config (I'm not convinced this is necessary)
176224
- Other CLI commands? (stop session, create/edit/delete project)
177225
- Use named args in calls to format! where possible
178-
- Cut v0.0.1 release and publish binaries
179226

180227
## Platforms
181228
Here are the platforms rmuxinator is known to work on:

src/lib.rs

+29-26
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use std::process::Command;
77
use std::str::FromStr;
88

99
use clap::{App, AppSettings, Arg, SubCommand};
10-
use serde::Deserialize;
10+
use serde::{Deserialize, Serialize};
1111

1212
extern crate toml;
1313

@@ -417,12 +417,15 @@ impl FromStr for CliCommand {
417417
#[derive(Debug, PartialEq)]
418418
pub struct CliArgs {
419419
pub command: CliCommand,
420+
// TODO: `project_name` is currently overloaded and also used as the config
421+
// path. We should either make this more explicit or introduce separate
422+
// args.
420423
pub project_name: String,
421424
}
422425

423-
#[derive(Clone, Copy, Debug, Deserialize)]
426+
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
424427
#[serde(rename_all = "kebab-case")]
425-
enum Layout {
428+
pub enum Layout {
426429
EvenHorizontal,
427430
EvenVertical,
428431
MainHorizontal,
@@ -440,23 +443,23 @@ impl fmt::Display for Layout {
440443

441444
type StartDirectory = Option<String>;
442445

443-
#[derive(Debug, Default, Deserialize)]
444-
struct Pane {
445-
commands: Vec<String>,
446-
name: Option<String>,
447-
start_directory: StartDirectory,
446+
#[derive(Debug, Default, Deserialize, Serialize)]
447+
pub struct Pane {
448+
pub commands: Vec<String>,
449+
pub name: Option<String>,
450+
pub start_directory: StartDirectory,
448451
}
449452

450-
#[derive(Debug, Default, Deserialize)]
451-
struct Window {
452-
layout: Option<Layout>,
453-
name: Option<String>,
453+
#[derive(Debug, Default, Deserialize, Serialize)]
454+
pub struct Window {
455+
pub layout: Option<Layout>,
456+
pub name: Option<String>,
454457
#[serde(default)]
455-
panes: Vec<Pane>,
456-
start_directory: StartDirectory,
458+
pub panes: Vec<Pane>,
459+
pub start_directory: StartDirectory,
457460
}
458461

459-
#[derive(Debug, Deserialize)]
462+
#[derive(Debug, Deserialize, Serialize)]
460463
#[serde(rename_all = "kebab-case")]
461464
enum HookName {
462465
// TODO: Does this make sense? If not, document exclusion.
@@ -530,29 +533,29 @@ impl fmt::Display for HookName {
530533
}
531534
}
532535

533-
#[derive(Debug, Deserialize)]
534-
struct Hook {
536+
#[derive(Debug, Deserialize, Serialize)]
537+
pub struct Hook {
535538
command: String,
536539
name: HookName,
537540
}
538541

539-
#[derive(Debug, Deserialize)]
542+
#[derive(Debug, Deserialize, Serialize)]
540543
pub struct Config {
541-
pane_name_user_option: Option<String>,
544+
pub pane_name_user_option: Option<String>,
542545
#[serde(default)]
543-
hooks: Vec<Hook>,
544-
layout: Option<Layout>,
545-
name: String,
546-
start_directory: StartDirectory,
546+
pub hooks: Vec<Hook>,
547+
pub layout: Option<Layout>,
548+
pub name: String,
549+
pub start_directory: StartDirectory,
547550
#[serde(default)]
548-
windows: Vec<Window>,
551+
pub windows: Vec<Window>,
549552
}
550553

551554
impl Config {
552-
pub fn new(cli_args: &CliArgs) -> Result<Config, String> {
555+
pub fn new_from_file_path(config_path: &String) -> Result<Config, String> {
553556
// Need to return String in failure case because toml::from_str may
554557
// return a toml::de::Error.
555-
let mut config_file = match File::open(&cli_args.project_name) {
558+
let mut config_file = match File::open(&config_path) {
556559
Ok(file) => file,
557560
Err(_) => return Err(String::from("Unable to open config file.")),
558561
};

src/main.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ fn main() -> Result<(), String> {
1414

1515
let cli_args = parse_args(env::args_os());
1616

17-
let config = Config::new(&cli_args)
17+
let config = Config::new_from_file_path(&cli_args.project_name)
1818
.map_err(|error| format!("Problem parsing config file: {}", error))?;
1919

2020
match cli_args.command {

0 commit comments

Comments
 (0)