Thanks to visit codestin.com
Credit goes to Github.com

Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ publish = false
dirs = "2.0.2"
rand = "0.7.2"
serde = { version = "1.0.103", features = ["derive"] }
libc = "0.2.66"
2 changes: 2 additions & 0 deletions common/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
extern crate dirs;
extern crate libc;
extern crate rand;
extern crate serde;

pub mod args;
pub mod first_run;
pub mod project_paths;
pub mod rand_names;
pub mod tmux;
File renamed without changes.
110 changes: 106 additions & 4 deletions load/src/tmux/mod.rs → common/src/tmux/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ static TMUX_NAME: &str = "tmux";
/// The gateway to calling any functions on tmux. Most public functions in this
/// module will be fed through this `call` function. This safely creates a new
/// thread to execute the command on. We say "Most" public functions will use
/// this as `attach` specificaly does not use it.
/// this as `attach` specifically does not use it.
///
/// args: The command we will send to tmux on the host system for execution.
///
Expand All @@ -37,7 +37,7 @@ pub fn call(args: &[&str]) -> Result<Output, io::Error> {
Command::new(TMUX_NAME).args(args).output()
}

/// Has session is used firgure out if a named session is already running.
/// Has session is used figure out if a named session is already running.
///
/// `target`: A string represented by the `{named_session}`
///
Expand Down Expand Up @@ -68,11 +68,113 @@ pub fn has_session(target: &str) -> ExitStatus {
/// tmux::get_config();
/// ```
pub fn get_config() -> String {
let output = call(&["start-server", ";", "show-options", "-g", ";", "show-options", "-g", "-w"])
.expect("couldn't get tmux options");
let output = call(&[
"start-server",
";",
"show-options",
"-g",
";",
"show-options",
"-g",
"-w",
])
.expect("couldn't get tmux options");
String::from_utf8_lossy(&output.stdout).to_string()
}

pub struct Session {
pub name: String,
pub id: String,
pub client_attached: usize,
pub created_at: u64,
pub last_attached: u64,
}

pub struct SessionList {
pub sessions: Vec<Session>,
}

impl SessionList {
pub fn new(sessions: Vec<Session>) -> SessionList {
SessionList { sessions }
}

pub fn has_session(&self, name: &str) -> bool {
self.sessions.iter().any(|s| s.name == name)
}

pub fn is_attached(&self, name: &str) -> bool {
self.sessions
.iter()
.any(|s| s.name == name && s.client_attached > 0)
}

pub fn get_last_attached(&self, name: &str) -> Option<u64> {
self.sessions
.iter()
.find(|s| s.name == name)
.map(|s| s.last_attached)
}
}

impl Session {
pub fn from_formatted_str(formatted: &str) -> Session {
let mut split = formatted.split(' ');
let name = split.next().unwrap().to_string();
let id = split.next().unwrap().to_string();
let client_attached = split
.next()
.unwrap()
.parse::<usize>()
.expect("Bad client_attached");
let created_at = split
.next()
.unwrap()
.parse::<u64>()
.expect("Bad created_at");
let last_attached = split
.next()
.unwrap()
.parse::<u64>()
.expect("Bad last_attached");

Session {
name,
id,
client_attached,
created_at,
last_attached,
}
}
}

/// Read the current tmux sessoins from the server
///
/// # Examples
///
/// ```rust
/// extern crate load;
/// use load::tmux;
///
/// let _: tmux::SessionList = tmux::get_sessions();
/// ```
pub fn get_sessions() -> SessionList {
let output = call(&[
"list-sessions",
"-F",
"#{session_name} #{session_id} #{session_attached} #{session_created} #{session_last_attached}",
])
.expect("couldn't get tmux sessions");
let sessions = String::from_utf8_lossy(&output.stdout).to_string();
let sessions = sessions
.trim()
.split('\n')
.map(Session::from_formatted_str)
.collect::<Vec<_>>();

SessionList { sessions }
}

/// Attach is called as the last function in a set of commands. After the tmux
/// env has been setup by all previous commands this attaches the user to their
/// daemonized tmux session.
Expand Down
File renamed without changes.
26 changes: 23 additions & 3 deletions list/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,16 @@ use common::args::Args;
use common::first_run::check_first_run;
use common::project_paths::{project_paths, CONFIG_EXTENSION};

use std::cmp::Reverse;
use std::path::PathBuf;

pub fn exec(args: Args) -> Result<(), String> {
let project_paths = project_paths(&args);
check_first_run(&project_paths.project_directory)?;

let mut projects: Vec<String> = project_paths
let tmux_session = common::tmux::get_sessions();

let mut project_names: Vec<String> = project_paths
.project_directory
.read_dir()
.map_err(|_| "Could not read the dir")?
Expand All @@ -26,15 +29,32 @@ pub fn exec(args: Args) -> Result<(), String> {
})
.collect();

projects.sort();
project_names.sort_by_key(|name| (Reverse(tmux_session.get_last_attached(name)), name.clone()));

let delimiter = if !atty::is(atty::Stream::Stdout) || args.flag_1 {
"\n"
} else {
"\t\t"
};

println!("{}", &projects.join(delimiter));
let project_displays: Vec<String> = project_names
.into_iter()
.map(|name| {
let mut display = name.clone();

if tmux_session.has_session(&name) {
display.push('*');
}

if tmux_session.is_attached(&name) {
display.push_str(" (attached)");
}

display
})
.collect();

println!("{}", &project_displays.join(delimiter));

Ok(())
}
7 changes: 4 additions & 3 deletions list/tests/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,17 @@ mod test {
fn make_files() -> PathBuf {
let dir_name = rand_names::project_path_name();
let dir = PathBuf::from(&dir_name);

dbg!(&dir);
if !&dir.exists() {
println!("{:?}", fs::create_dir(&dir))
};

let configs = ["foo.yml", "bar.yml", "muxed.yml"];
for config in &configs {
let path = PathBuf::from(&dir_name).join(config);
let _ = File::create(&path).expect("Muxed list test failed to create test config files.");
let path = PathBuf::from(&dir_name).join(config);
let _ = File::create(&path)
.expect("Muxed list test failed to create test config files.");
}

dir
Expand Down
1 change: 0 additions & 1 deletion load/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ publish = false
[dependencies]
common = { path = "../common" }
dirs = "2.0.2"
libc = "0.2.66"
yaml-rust = { version = "0.4.5", default-features = false }

[dev-dependencies]
Expand Down
29 changes: 24 additions & 5 deletions load/src/command.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
//! The structures used to manage commands sent over to tmux.

use common::tmux;
use common::tmux::target::*;
use std::io;
use std::path::PathBuf;
use std::process::Output;
use std::rc::Rc;
use std::{process, str};
use tmux;
use tmux::target::*;

pub trait Command {
fn call(&self, debug: bool) -> Result<Output, io::Error> {
Expand Down Expand Up @@ -44,7 +44,14 @@ impl Session {
// TODO: Real logic exists here. Test it!
impl Command for Session {
fn args(&self) -> Vec<&str> {
let args: Vec<&str> = vec!["new", "-d", "-s", &self.target.arg_string, "-n", &self.window_name];
let args: Vec<&str> = vec![
"new",
"-d",
"-s",
&self.target.arg_string,
"-n",
&self.window_name,
];

match self.root_path.as_ref() {
Some(path) => [&args[..], &["-c", path.to_str().unwrap()]].concat(),
Expand Down Expand Up @@ -85,7 +92,13 @@ impl Window {

impl Command for Window {
fn args(&self) -> Vec<&str> {
let args: Vec<&str> = vec!["new-window", "-t", &self.session_target.arg_string, "-n", &self.name];
let args: Vec<&str> = vec![
"new-window",
"-t",
&self.session_target.arg_string,
"-n",
&self.name,
];

match self.path.as_ref() {
Some(path) => [&args[..], &["-c", path.to_str().unwrap()]].concat(),
Expand Down Expand Up @@ -163,7 +176,13 @@ impl SendKeys {

impl Command for SendKeys {
fn args(&self) -> Vec<&str> {
vec!["send-keys", "-t", &self.target.arg_string(), &self.exec, "KPEnter"]
vec![
"send-keys",
"-t",
&self.target.arg_string(),
&self.exec,
"KPEnter",
]
}
}

Expand Down
6 changes: 2 additions & 4 deletions load/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
extern crate dirs;
extern crate libc;
extern crate yaml_rust;

extern crate common;

pub mod command;
pub mod project;
pub mod tmux;

use args::Args;
use command::Commands;
use common::project_paths::project_paths;
use common::{args, first_run};
use common::tmux::config::Config;
use common::{args, first_run, tmux};
use project::parser;
use tmux::config::Config;

pub fn exec(args: Args) -> Result<(), String> {
let project_paths = project_paths(&args);
Expand Down
2 changes: 1 addition & 1 deletion load/src/project/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ pub mod parser;

use command::{Attach, Commands, SwitchClient};
use common::project_paths::ProjectPaths;
use common::tmux::has_session;
use first_run::check_first_run;
use std::env;
use std::fs::File;
use std::io::prelude::*;
use tmux::has_session;
use yaml_rust::{Yaml, YamlLoader};

static TMUX_ENV_VAR: &str = "TMUX";
Expand Down
Loading