Skip to content
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
- Execute the last executed command(By running `fzf-make --repeat`.)
- Command history
- Support [**make**](https://www.gnu.org/software/make/), [**pnpm**](https://github.com/pnpm/pnpm), [**yarn**](https://github.com/yarnpkg/berry), [**just**](https://github.com/casey/just). **Scheduled to be developed: npm.**
- Support passing additional arguments to the command using popup window. The UI looks like: https://github.com/kyu08/fzf-make/pull/447
- [make] Support `include` directive
- [pnpm] Support workspace(collect scripts all of `package.json` in the directory where fzf-make is launched.)
- [yarn] Support workspace(collect all scripts which is defined in `workspaces` field in root `package.json`.)
Expand Down
2 changes: 1 addition & 1 deletion docs/MANUAL_TEST_CASES.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
## Test cases
- [ ] `fzf-make`
- [ ] Execution
- [ ] A command name executing is shown
- [ ] A command name executing is shown
- [ ] Selected command is executed
- [ ] Narrowing down
- [ ] Placeholder is shown when no characters are typed.
Expand Down
3 changes: 3 additions & 0 deletions src/file/toml.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ impl Histories {
Self { histories }
}

// TODO: impl as From trait
fn from(histories: histories::Histories) -> Self {
let mut result: Vec<History> = vec![];
for h in histories.histories {
Expand All @@ -68,6 +69,7 @@ pub struct History {
}

impl History {
// TODO: impl as From trait
fn from(history: histories::History) -> Self {
let mut commands: Vec<HistoryCommand> = vec![];
for h in history.commands {
Expand Down Expand Up @@ -110,6 +112,7 @@ impl HistoryCommand {
Self { runner_type, args }
}

// TODO: impl as From trait
fn from(command: histories::HistoryCommand) -> Self {
Self {
runner_type: command.runner_type,
Expand Down
38 changes: 34 additions & 4 deletions src/model/command.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
use super::runner_type;
use super::{histories, runner_type};
use std::{fmt, path::PathBuf};

#[derive(PartialEq, Clone, Debug)]
pub struct Command {
pub struct CommandWithPreview {
pub runner_type: runner_type::RunnerType,
pub args: String,
pub file_path: PathBuf,
pub line_number: u32,
}

impl Command {
impl CommandWithPreview {
pub fn new(runner_type: runner_type::RunnerType, args: String, file_path: PathBuf, line_number: u32) -> Self {
Self {
runner_type,
Expand All @@ -20,7 +20,37 @@ impl Command {
}
}

impl fmt::Display for Command {
impl fmt::Display for CommandWithPreview {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{} {}", self.runner_type, self.args)
}
}

#[derive(PartialEq, Clone, Debug)]
pub struct CommandForExec {
pub runner_type: runner_type::RunnerType,
pub args: String,
}

impl From<CommandWithPreview> for CommandForExec {
fn from(c: CommandWithPreview) -> CommandForExec {
CommandForExec {
runner_type: c.runner_type.clone(),
args: c.args.clone(),
}
}
}

impl From<histories::HistoryCommand> for CommandForExec {
fn from(c: histories::HistoryCommand) -> CommandForExec {
CommandForExec {
runner_type: c.runner_type.clone(),
args: c.args.clone(),
}
}
}

impl fmt::Display for CommandForExec {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{} {}", self.runner_type, self.args)
}
Expand Down
60 changes: 24 additions & 36 deletions src/model/histories.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ pub struct Histories {
}

impl Histories {
pub fn append(&self, current_dir: PathBuf, command: command::Command) -> Self {
pub fn append(&self, current_dir: PathBuf, command: command::CommandForExec) -> Self {
// Update the command history for the current directory.
let new_history = {
match self.histories.iter().find(|h| h.path == current_dir) {
Expand Down Expand Up @@ -48,7 +48,7 @@ pub struct History {
}

impl History {
fn append(&self, executed_command: command::Command) -> Self {
fn append(&self, executed_command: command::CommandForExec) -> Self {
let mut updated_commands = self.commands.clone();
// removes the executed_command from the history
updated_commands.retain(|t| *t != HistoryCommand::from(executed_command.clone()));
Expand Down Expand Up @@ -76,8 +76,8 @@ pub struct HistoryCommand {
pub args: String,
}

impl HistoryCommand {
pub fn from(command: command::Command) -> Self {
impl From<command::CommandForExec> for HistoryCommand {
fn from(command: command::CommandForExec) -> Self {
Self {
runner_type: command.runner_type,
args: command.args,
Expand All @@ -96,7 +96,7 @@ mod test {
struct Case {
title: &'static str,
before: Histories,
command_to_append: command::Command,
command_to_append: command::CommandForExec,
after: Histories,
}

Expand Down Expand Up @@ -124,11 +124,9 @@ mod test {
},
],
},
command_to_append: command::Command {
command_to_append: command::CommandForExec {
runner_type: runner_type::RunnerType::Make,
args: "append".to_string(),
file_path: PathBuf::from("Makefile"),
line_number: 1,
},
after: Histories {
histories: vec![
Expand Down Expand Up @@ -166,11 +164,9 @@ mod test {
}],
}],
},
command_to_append: command::Command {
command_to_append: command::CommandForExec {
runner_type: runner_type::RunnerType::Make,
args: "append".to_string(),
file_path: PathBuf::from("Makefile"),
line_number: 1,
},
after: Histories {
histories: vec![
Expand Down Expand Up @@ -208,7 +204,7 @@ mod test {
struct Case {
title: &'static str,
before: History,
command_to_append: command::Command,
command_to_append: command::CommandForExec,
after: History,
}
let path = PathBuf::from("/Users/user/code/fzf-make".to_string());
Expand All @@ -228,12 +224,10 @@ mod test {
},
],
},
command_to_append: command::Command::new(
runner_type::RunnerType::Make,
"history2".to_string(),
PathBuf::from("Makefile"),
1,
),
command_to_append: command::CommandForExec {
runner_type: runner_type::RunnerType::Make,
args: "history2".to_string(),
},
after: History {
path: path.clone(),
commands: vec![
Expand All @@ -258,12 +252,10 @@ mod test {
path: path.clone(),
commands: vec![],
},
command_to_append: command::Command::new(
runner_type::RunnerType::Make,
"history0".to_string(),
PathBuf::from("Makefile"),
4,
),
command_to_append: command::CommandForExec {
runner_type: runner_type::RunnerType::Make,
args: "history0".to_string(),
},
after: History {
path: path.clone(),
commands: vec![HistoryCommand {
Expand Down Expand Up @@ -291,12 +283,10 @@ mod test {
},
],
},
command_to_append: command::Command::new(
runner_type::RunnerType::Make,
"history2".to_string(),
PathBuf::from("Makefile"),
1,
),
command_to_append: command::CommandForExec {
runner_type: runner_type::RunnerType::Make,
args: "history2".to_string(),
},
after: History {
path: path.clone(),
commands: vec![
Expand Down Expand Up @@ -362,12 +352,10 @@ mod test {
},
],
},
command_to_append: command::Command::new(
runner_type::RunnerType::Make,
"history10".to_string(),
PathBuf::from("Makefile"),
1,
),
command_to_append: command::CommandForExec {
runner_type: runner_type::RunnerType::Make,
args: "history10".to_string(),
},
after: History {
path: path.clone(),
commands: vec![
Expand Down
6 changes: 3 additions & 3 deletions src/model/js_package_manager/js_package_manager_main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,21 @@ pub enum JsPackageManager {
}

impl JsPackageManager {
pub fn command_to_run(&self, command: &command::Command) -> Result<String> {
pub fn command_to_run(&self, command: &command::CommandForExec) -> Result<String> {
match self {
JsPackageManager::JsPnpm(pnpm) => pnpm.command_to_run(command),
JsPackageManager::JsYarn(yarn) => yarn.command_to_run(command),
}
}

pub fn to_commands(&self) -> Vec<command::Command> {
pub fn to_commands(&self) -> Vec<command::CommandWithPreview> {
match self {
JsPackageManager::JsPnpm(pnpm) => pnpm.to_commands(),
JsPackageManager::JsYarn(yarn) => yarn.to_commands(),
}
}

pub fn execute(&self, command: &command::Command) -> Result<()> {
pub fn execute(&self, command: &command::CommandForExec) -> Result<()> {
match self {
JsPackageManager::JsPnpm(pnpm) => pnpm.execute(command),
JsPackageManager::JsYarn(yarn) => yarn.execute(command),
Expand Down
32 changes: 8 additions & 24 deletions src/model/js_package_manager/pnpm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,27 +11,15 @@ const PNPM_LOCKFILE_NAME: &str = "pnpm-lock.yaml";
#[derive(Clone, Debug, PartialEq)]
pub struct Pnpm {
pub path: PathBuf,
commands: Vec<command::Command>,
commands: Vec<command::CommandWithPreview>,
}

impl Pnpm {
pub fn command_to_run(&self, command: &command::Command) -> Result<String> {
// To ensure that the command exists, it is necessary to check the command name.
// If implementation is wrong, developers can notice it here.
let command = match self.get_command(command.clone()) {
Some(c) => c,
None => return Err(anyhow!("command not found")),
};

pub fn command_to_run(&self, command: &command::CommandForExec) -> Result<String> {
Ok(format!("pnpm {}", command.args))
}

pub fn execute(&self, command: &command::Command) -> Result<()> {
let command = match self.get_command(command.clone()) {
Some(c) => c,
None => return Err(anyhow!("command not found")),
};

pub fn execute(&self, command: &command::CommandForExec) -> Result<()> {
let child = process::Command::new("pnpm")
.stdin(process::Stdio::inherit())
.args(command.args.split_whitespace().collect::<Vec<&str>>())
Expand Down Expand Up @@ -74,7 +62,7 @@ impl Pnpm {
// 1. Collect scripts defined in package.json in the current directory(which fzf-make is launched)
// 2. Collect the paths of all `package.json` in the workspace.
// 3. Collect all scripts defined in given `package.json` paths.
fn collect_workspace_scripts(current_dir: PathBuf) -> Option<Vec<command::Command>> {
fn collect_workspace_scripts(current_dir: PathBuf) -> Option<Vec<command::CommandWithPreview>> {
// Collect scripts defined in package.json in the current directory(which fzf-make is launched)
let mut result = Self::collect_scripts_in_package_json(current_dir.clone())?;

Expand All @@ -92,7 +80,7 @@ impl Pnpm {
if Self::use_filtering(value) {
continue;
}
result.push(command::Command::new(
result.push(command::CommandWithPreview::new(
runner_type::RunnerType::JsPackageManager(runner_type::JsPackageManager::Pnpm),
// pnpm executes workspace script following format: `pnpm --filter {package_name} {script_name}`
// e.g. `pnpm --filter app4 build`
Expand All @@ -108,7 +96,7 @@ impl Pnpm {
Some(result)
}

fn collect_scripts_in_package_json(current_dir: PathBuf) -> Option<Vec<command::Command>> {
fn collect_scripts_in_package_json(current_dir: PathBuf) -> Option<Vec<command::CommandWithPreview>> {
let parsed_scripts_part_of_package_json =
match path_to_content::path_to_content(&current_dir.join(js::METADATA_FILE_NAME)) {
Ok(c) => match js::JsPackageManager::parse_package_json(&c) {
Expand All @@ -123,7 +111,7 @@ impl Pnpm {
.iter()
.filter(|(_, value, _)| !Self::use_filtering(value.to_string()))
.map(|(key, _value, line_number)| {
command::Command::new(
command::CommandWithPreview::new(
runner_type::RunnerType::JsPackageManager(runner_type::JsPackageManager::Pnpm),
key.to_string(),
current_dir.clone().join(js::METADATA_FILE_NAME),
Expand Down Expand Up @@ -158,14 +146,10 @@ impl Pnpm {
.collect())
}

pub fn to_commands(&self) -> Vec<command::Command> {
pub fn to_commands(&self) -> Vec<command::CommandWithPreview> {
self.commands.clone()
}

fn get_command(&self, command: command::Command) -> Option<&command::Command> {
self.commands.iter().find(|c| **c == command)
}

// ref: https://pnpm.io/filtering
fn use_filtering(value: String) -> bool {
let args = value.split_whitespace().collect::<Vec<&str>>();
Expand Down
Loading