diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml new file mode 100644 index 0000000..c9361bf --- /dev/null +++ b/.github/workflows/rust.yml @@ -0,0 +1,44 @@ +name: Rust + +on: + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] + +env: + CARGO_TERM_COLOR: always + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Build + run: cargo build --verbose + - name: Run tests + run: cargo test --verbose + + lint: + name: Check code style + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + name: Checkout repository + - uses: dtolnay/rust-toolchain@master + name: Set up toolchain + with: + toolchain: stable + components: rustfmt, clippy + - uses: Swatinem/rust-cache@v2 + name: Cache toolchain and dependencies + - uses: actions-rs/cargo@v1 + name: Check code with cargo fmt + with: + command: fmt + args: --all -- --check + - uses: actions-rs/cargo@v1 + name: Check code with cargo clippy + with: + command: clippy + args: --all-targets -- -D warnings diff --git a/src/cli.rs b/src/cli.rs index c48453e..7561adf 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -78,11 +78,13 @@ pub struct Options { impl Options { pub fn from_matches(matches: ArgMatches) -> Result { // UNWRAP: It's safe because we define sed-script in the CLI code above, so we are certain it exists. - let sed_script: PathBuf = PathBuf::from_str(matches.get_one::("sed-script").unwrap()) - .with_context(|| "Failed to load sed script path")?; + let sed_script: PathBuf = + PathBuf::from_str(matches.get_one::("sed-script").unwrap()) + .with_context(|| "Failed to load sed script path")?; // UNWRAP: It's safe because we define input-file in the CLI code above, so we are certain it exists. - let input_file: PathBuf = PathBuf::from_str(matches.get_one::("input-file").unwrap()) - .with_context(|| "Failed to load input file path.")?; + let input_file: PathBuf = + PathBuf::from_str(matches.get_one::("input-file").unwrap()) + .with_context(|| "Failed to load input file path.")?; let sed_path: Option = matches.get_one::("sed-path").map(ToOwned::to_owned); diff --git a/src/file_watcher/inotify.rs b/src/file_watcher/inotify.rs index b07ab80..e2d7759 100644 --- a/src/file_watcher/inotify.rs +++ b/src/file_watcher/inotify.rs @@ -7,7 +7,7 @@ use inotify::Inotify; pub struct FileWatcherImpl { inotify: Inotify, - watches: Vec + watches: Vec, } pub struct FileWatchImpl { @@ -15,7 +15,7 @@ pub struct FileWatchImpl { } impl FileWatcherImpl { - pub fn init() -> Result { + pub fn init() -> Result { let ino = match Inotify::init() { Ok(i) => i, Err(msg) => return Result::Err(msg), @@ -23,7 +23,7 @@ impl FileWatcherImpl { Result::Ok(FileWatcherImpl { inotify: ino, - watches: vec![] + watches: vec![], }) } @@ -35,9 +35,7 @@ impl FileWatcherImpl { Err(msg) => return Result::Err(msg), }; - let fw = FileWatchImpl { - descriptor: watch, - }; + let fw = FileWatchImpl { descriptor: watch }; self.watches.push(fw); return Result::Ok(self.watches.last().unwrap()); @@ -54,7 +52,7 @@ impl FileWatcherImpl { Result::Err(Error::new( ErrorKind::InvalidInput, - "Passed FileWatch does not belong to this FileWatcher instance" + "Passed FileWatch does not belong to this FileWatcher instance", )) } diff --git a/src/file_watcher/kqueue.rs b/src/file_watcher/kqueue.rs index 136a465..23d9130 100644 --- a/src/file_watcher/kqueue.rs +++ b/src/file_watcher/kqueue.rs @@ -4,14 +4,14 @@ use std::path::PathBuf; use std::vec::Vec; extern crate kqueue; +use kqueue::FilterFlag; use kqueue::Watcher as KQueue; -use kqueue::FilterFlag as FilterFlag; const FILTER: kqueue::EventFilter = kqueue::EventFilter::EVFILT_VNODE; pub struct FileWatcherImpl { kq: KQueue, - watches: Vec + watches: Vec, } pub struct FileWatchImpl { @@ -25,57 +25,51 @@ impl FileWatcherImpl { Err(msg) => return Result::Err(msg), }; - return Result::Ok(FileWatcherImpl { + Ok(FileWatcherImpl { kq, - watches: vec![] - }); + watches: vec![], + }) } pub fn add_watch(&mut self, file_path: &PathBuf) -> Result<&FileWatchImpl> { - let flags: FilterFlag = - FilterFlag::NOTE_WRITE | - FilterFlag::NOTE_EXTEND | - FilterFlag::NOTE_RENAME | - FilterFlag::NOTE_DELETE | - FilterFlag::NOTE_LINK; + let flags: FilterFlag = FilterFlag::NOTE_WRITE + | FilterFlag::NOTE_EXTEND + | FilterFlag::NOTE_RENAME + | FilterFlag::NOTE_DELETE + | FilterFlag::NOTE_LINK; let file = File::open(file_path)?; - let _ = match self.kq.add_file(&file, FILTER, flags) { - Ok(w) => w, - Err(msg) => return Result::Err(msg), - }; + self.kq.add_file(&file, FILTER, flags)?; - let fw = FileWatchImpl { - file - }; + let fw = FileWatchImpl { file }; self.watches.push(fw); - return Result::Ok(&self.watches.last().unwrap()); + Ok(self.watches.last().unwrap()) } pub fn rm_watch(&mut self, fw: &FileWatchImpl) -> Result<()> { for i in 0..self.watches.len() { let item_ref = self.watches.get(i).unwrap(); - if item_ref as *const FileWatchImpl == fw as *const FileWatchImpl { + if std::ptr::eq(item_ref, fw) { let item = self.watches.remove(i); return self.kq.remove_file(&item.file, FILTER); } } - return Result::Err(Error::new( + Err(Error::new( ErrorKind::InvalidInput, - "Passed FileWatch does not belong to this FileWatcher instance" - )); + "Passed FileWatch does not belong to this FileWatcher instance", + )) } pub fn start(&mut self) -> Result<()> { - return self.kq.watch(); + self.kq.watch() } pub fn any_events(&mut self) -> Result { match self.kq.poll(None) { - Some(_) => return Result::Ok(true), - None => return Result::Ok(false), + Some(_) => Ok(true), + None => Ok(false), } } } diff --git a/src/file_watcher/mock.rs b/src/file_watcher/mock.rs index 8c331be..93a0176 100644 --- a/src/file_watcher/mock.rs +++ b/src/file_watcher/mock.rs @@ -4,7 +4,7 @@ use std::vec::Vec; pub struct FileWatcherImpl { highest_id: usize, - watches: Vec + watches: Vec, } pub struct FileWatchImpl { @@ -12,10 +12,10 @@ pub struct FileWatchImpl { } impl FileWatcherImpl { - pub fn init() -> Result { + pub fn init() -> Result { return Result::Ok(FileWatcherImpl { highest_id: 0, - watches: vec![] + watches: vec![], }); } @@ -41,7 +41,7 @@ impl FileWatcherImpl { return Result::Err(Error::new( ErrorKind::InvalidInput, - "Passed FileWatch does not belong to this FileWatcher instance" + "Passed FileWatch does not belong to this FileWatcher instance", )); } diff --git a/src/main.rs b/src/main.rs index fd90e66..74ed593 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,10 +2,10 @@ mod sed; use sed::debugger::Debugger; mod cli; use cli::Options; -mod ui; mod file_watcher; -use file_watcher::FileWatcher; +mod ui; use anyhow::Result; +use file_watcher::FileWatcher; use ui::generic::{ApplicationExitReason, UiAgent}; use ui::tui::Tui; @@ -41,11 +41,7 @@ fn run(target_state_number: usize) -> Result<()> { let debugger = Debugger::new(settings)?; let tui = Tui::new(&debugger, watcher, target_state_number)?; match tui.start()? { - ApplicationExitReason::UserExit => { - Ok(()) - } - ApplicationExitReason::Reload(instruction_number) => { - run(instruction_number) - } + ApplicationExitReason::UserExit => Ok(()), + ApplicationExitReason::Reload(instruction_number) => run(instruction_number), } } diff --git a/src/sed/communication.rs b/src/sed/communication.rs index d7fc179..16c7f4e 100644 --- a/src/sed/communication.rs +++ b/src/sed/communication.rs @@ -30,7 +30,8 @@ impl SedCommunicator { path_to_be_used = path; } - let mandatory_parameters = ["--debug", + let mandatory_parameters = [ + "--debug", "-f", self.options .sed_script @@ -39,7 +40,8 @@ impl SedCommunicator { self.options .input_file .to_str() - .with_context(|| "Invalid input path. Is it valid UTF-8?".to_string())?]; + .with_context(|| "Invalid input path. Is it valid UTF-8?".to_string())?, + ]; let constructed_cmd_line = self .options .sed_parameters diff --git a/src/sed/debugger.rs b/src/sed/debugger.rs index 2b9b01b..943c989 100644 --- a/src/sed/debugger.rs +++ b/src/sed/debugger.rs @@ -52,7 +52,7 @@ impl Debugger { }) } /// Peek at state with target number (0-based). - /// + /// /// This will return None if the state doesn't exist. pub fn peek_at_state(&self, frame: usize) -> Option<&DebuggingState> { self.state_frames.get(frame)