Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Sinono3 committed Jul 3, 2021
0 parents commit b1e389d
Show file tree
Hide file tree
Showing 5 changed files with 380 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/target
253 changes: 253 additions & 0 deletions Cargo.lock

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

12 changes: 12 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[package]
name = "quiren"
version = "0.1.0"
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
edit = "0.1.3"
osstrtools = "0.2"
thiserror = "1"
main_error = "0.1.1"
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Quiren (Quick Editor Renamer)

Edits the filenames of the current directory on the editor of your choice.

## Installation

```shell
$ git clone https://github.com/Sinono3/quiren.git
$ cargo install --path quiren
```

## Usage

```shell
# On the current directory
$ quiren
# On another directory
$ quiren books
$ quiren /home/dude/abc/
```

## Origin

I was looking for a tool that would let me edit filenames for the current directory in Vim. I found `massren` on the AUR, and I didn't like it at all. It was so bloated to fulfill such a simple task. Why does it automatically create a config file. Why does it a create an SQLite database (For undoing renames, but still, it should have been on the cache directory). Why do I have to scroll through a huge wall of warning texts to actually edit the filenames. Why does it take so long to actually save the changes.

Well, enough rant about that tool. If I looked a little bit more into it I probably would have found something that suited my needs, but I thought trying to make it myself would be a fun project, so here we are.
88 changes: 88 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
use osstrtools::OsStrConcat;
use std::env;
use std::ffi::{OsStr, OsString};
use std::fs;
use std::path::PathBuf;
use thiserror::Error;

#[derive(Error, Debug)]
enum QuirenError {
#[error("the entry '{0}' was assigned an empty name")]
EmptyName(String),
#[error("the filename {0} is duplicated")]
DuplicateName(String),
#[error("lines cannot be deleted or added: {0} -> {1}")]
EntryCountMismatch(usize, usize),
#[error("I/O error {0}")]
IoError(#[from] std::io::Error),
}

fn main() -> Result<(), main_error::MainError> {
let arg = env::args().nth(1);
let dir = arg
.filter(|a| !a.is_empty())
.map(|a| PathBuf::from(a))
.or_else(|| env::current_dir().ok())
.unwrap();

// TODO: clap arguments
// TODO: add retry until correct option

Ok(quiren(dir)?)
}

fn quiren(dir: PathBuf) -> Result<(), QuirenError> {
let mut entries: Vec<_> = dir.read_dir()?.map(|e| e.unwrap()).collect();

entries.sort_by_key(|e| e.file_name());

let text: OsString = entries
.iter()
.map(|e| e.file_name())
.collect::<Vec<OsString>>()
.concat("\n");

let text = text.to_string_lossy().into_owned();

let edited = edit::edit(&text)?;

// check if linecount = entry count
let new_count = edited.lines().count();

if new_count != entries.len() {
return Err(QuirenError::EntryCountMismatch(entries.len(), new_count));
}

// Other checks
for (i, a) in edited.lines().enumerate() {
// Check for empty names
if a.is_empty() {
return Err(QuirenError::EmptyName(
entries[i].file_name().to_string_lossy().to_string(),
));
}

// Check for duplicates
for (j, b) in edited.lines().enumerate() {
if i != j && a == b {
return Err(QuirenError::DuplicateName(a.to_string()));
}
}
}

for (i, line) in edited
.lines()
.enumerate()
// Only rename files with modified names
.filter(|(i, line)| {
let name = OsStr::new(line);
name != entries[*i].file_name()
})
{
let mut new_path = dir.clone();
new_path.push(line);
fs::rename(&entries[i].path(), new_path)?;
}

Ok(())
}

0 comments on commit b1e389d

Please sign in to comment.