-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* changelog * CI coverage * rustfmt and clippy Co-authored-by: Sean Lawlor <[email protected]>
- Loading branch information
Showing
10 changed files
with
283 additions
and
25 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
# Changelog | ||
|
||
## 0.1.4 (August 31, 2022) | ||
|
||
* Cleanup licensing headers | ||
* Downgrade further the `dirs` crate dependency for easier compatability | ||
* Starting adding test coverage for CI | ||
|
||
## 0.1.3 (August 31, 2022) | ||
|
||
* More documentation cleanups + status badges on CI pipelines | ||
* Cleanup dependencies to remove `backtrace` feature of `anyhow` | ||
|
||
## 0.1.2 (August 30, 2022) | ||
|
||
* Reducing the dependency on `rustyline` to v7.X | ||
|
||
## 0.1.1 (August 30, 2022) | ||
|
||
* Documentation update | ||
|
||
## 0.1.0 (August 30, 2022) | ||
|
||
* Initial release of rustyrepl |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# Contributing to this library | ||
We want to make contributing to this project as easy and transparent as possible. | ||
|
||
## Pull Requests | ||
We actively welcome your pull requests. | ||
|
||
1. Fork the repo and create your branch from `main`. | ||
2. If you've added code that should be tested, add tests. | ||
3. If you've changed APIs, update the documentation. | ||
4. Ensure the test suite passes. | ||
|
||
## Issues | ||
We use GitHub issues to track public bugs. Please ensure your description is | ||
clear and has sufficient instructions to be able to reproduce the issue. | ||
|
||
## License | ||
By contributing to akd, you agree that your contributions will be | ||
licensed under the LICENSE file in the root directory of this source tree. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
[package] | ||
name = "rustyrepl" | ||
version = "0.1.3" | ||
version = "0.1.4" | ||
authors = ["Sean Lawlor <[email protected]>"] | ||
description = "A Rust read, evaluate, print, loop (REPL) utility " | ||
license = "MIT" | ||
|
@@ -17,7 +17,7 @@ default = [] | |
# Required dependencies | ||
anyhow = { version = "1" } | ||
clap = { version = "3", features = ["derive"] } | ||
dirs = "4" | ||
dirs = "2" | ||
log = { version = "0.4", features = ["kv_unstable"] } | ||
rustyline = "7" | ||
thiserror = "1" | ||
|
@@ -26,4 +26,9 @@ thiserror = "1" | |
async-trait = { version = "0.1", optional = true } | ||
|
||
[dev-dependencies] | ||
colored = "2" | ||
ctor = "0.1" | ||
once_cell = "1" | ||
tempfile = "3" | ||
thread-id = "3" | ||
tokio = { version = "1", features = ["full"] } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
// Copyright (c) Sean Lawlor | ||
// | ||
// This source code is licensed under the MIT license found in the | ||
// LICENSE file in the root directory of this source tree. | ||
|
||
use colored::*; | ||
use log::Level; | ||
use log::Metadata; | ||
use log::Record; | ||
use once_cell::sync::OnceCell; | ||
use std::io::Write; | ||
use tokio::time::Duration; | ||
use tokio::time::Instant; | ||
|
||
pub(crate) static EPOCH: OnceCell<Instant> = OnceCell::new(); | ||
|
||
/// A basic console logging interface with coloring supported of the log messages | ||
pub(crate) struct ConsoleLogger {} | ||
|
||
impl ConsoleLogger { | ||
pub(crate) fn format_log_record(io: &mut (dyn Write + Send), record: &Record, colored: bool) { | ||
let target = { | ||
if let Some(target_str) = record.target().split(':').last() { | ||
if let Some(line) = record.line() { | ||
format!(" ({}:{})", target_str, line) | ||
} else { | ||
format!(" ({})", target_str) | ||
} | ||
} else { | ||
"".to_string() | ||
} | ||
}; | ||
|
||
let toc = if let Some(epoch) = EPOCH.get() { | ||
Instant::now() - *epoch | ||
} else { | ||
Duration::from_millis(0) | ||
}; | ||
|
||
let seconds = toc.as_secs(); | ||
let hours = seconds / 3600; | ||
let minutes = (seconds / 60) % 60; | ||
let seconds = seconds % 60; | ||
let milliseconds = toc.subsec_millis(); | ||
|
||
let msg = format!( | ||
"[{:02}:{:02}:{:02}.{:03}] {:6} {}{}", | ||
hours, | ||
minutes, | ||
seconds, | ||
milliseconds, | ||
record.level(), | ||
record.args(), | ||
target | ||
); | ||
if colored { | ||
let msg = match record.level() { | ||
Level::Trace | Level::Debug => msg.white(), | ||
Level::Info => msg.green(), | ||
Level::Warn => msg.yellow().bold(), | ||
Level::Error => msg.red().bold(), | ||
}; | ||
let _ = writeln!(io, "{}", msg); | ||
} else { | ||
let _ = writeln!(io, "{}", msg); | ||
} | ||
} | ||
} | ||
|
||
impl log::Log for ConsoleLogger { | ||
fn enabled(&self, _metadata: &Metadata) -> bool { | ||
true | ||
} | ||
|
||
fn log(&self, record: &Record) { | ||
if !self.enabled(record.metadata()) { | ||
return; | ||
} | ||
let mut io = std::io::stdout(); | ||
ConsoleLogger::format_log_record(&mut io, record, true); | ||
} | ||
|
||
fn flush(&self) { | ||
let _ = std::io::stdout().flush(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
// Copyright (c) Sean Lawlor | ||
// | ||
// This source code is licensed under the MIT license found in the | ||
// LICENSE file in the root directory of this source tree. | ||
|
||
pub(crate) mod console_logger; | ||
pub(crate) mod util; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
// Copyright (c) Sean Lawlor | ||
// | ||
// This source code is licensed under the MIT license found in the | ||
// LICENSE file in the root directory of this source tree. | ||
|
||
use super::console_logger::*; | ||
use log::Level; | ||
use std::sync::Once; | ||
use tokio::time::Instant; | ||
|
||
static LOGGER: ConsoleLogger = ConsoleLogger {}; | ||
static INIT_ONCE: Once = Once::new(); | ||
|
||
/// Initialize the logger for console logging within test environments. | ||
/// This is safe to call multiple times, but it will only initialize the logger | ||
/// to the log-level _first_ set. If you want a specific log-level (e.g. Debug) | ||
/// for a specific test, make sure to only run that single test after editing that | ||
/// test's log-level. | ||
/// | ||
/// The default level applied everywhere is Info | ||
pub fn init_logger(level: Level) { | ||
EPOCH.get_or_init(Instant::now); | ||
|
||
INIT_ONCE.call_once(|| { | ||
log::set_logger(&LOGGER) | ||
.map(|()| log::set_max_level(level.to_level_filter())) | ||
.unwrap(); | ||
}); | ||
} | ||
|
||
/// Global test startup constructor. Only runs in the TEST profile. Each | ||
/// crate which wants logging enabled in tests being run should make this call | ||
/// itself. | ||
#[cfg(test)] | ||
#[ctor::ctor] | ||
fn test_start() { | ||
init_logger(Level::Debug); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
// Copyright (c) Sean Lawlor | ||
// | ||
// This source code is licensed under the MIT license found in the | ||
// LICENSE file in the root directory of this source tree. | ||
|
||
use super::*; | ||
use anyhow::Result; | ||
use clap::Parser; | ||
use std::io::Write; | ||
use std::path::{Path, PathBuf}; | ||
|
||
#[derive(Parser, Debug)] | ||
struct TestCli {} | ||
|
||
type TestRepl = Repl<TestCli>; | ||
|
||
#[test] | ||
fn test_history_path_parsing() -> Result<()> { | ||
// ========= None ========= // | ||
let no_path: Option<PathBuf> = TestRepl::get_history_file_path(None); | ||
assert_eq!(None, no_path); | ||
|
||
// ========= Just a filename ========= // | ||
let just_a_filename = TestRepl::get_history_file_path(Some("a_test_file.txt".to_string())); | ||
let mut home_dir = dirs::home_dir().unwrap(); | ||
home_dir.push("a_test_file.txt"); | ||
assert_eq!(home_dir, just_a_filename.unwrap()); | ||
|
||
// ========= A real file ========= // | ||
let mut tempfile = tempfile::NamedTempFile::new()?; | ||
// extract the tempfile name | ||
let real_file: String = tempfile.path().to_path_buf().to_str().unwrap().to_string(); | ||
// write some dummy data to the file + close it | ||
tempfile.write_all("some_test_data".as_bytes())?; | ||
info!("The tempfile is {}", real_file); | ||
|
||
let relative_path_to_real_file = TestRepl::get_history_file_path(Some(real_file.clone())); | ||
tempfile.close()?; | ||
assert_eq!( | ||
Path::new(&real_file).to_path_buf(), | ||
relative_path_to_real_file.unwrap() | ||
); | ||
|
||
// ========= A directory ========= // | ||
let mut tempdir = tempfile::tempdir()?.into_path(); | ||
let directory_plus_default_filename = | ||
TestRepl::get_history_file_path(Some(tempdir.to_str().unwrap().to_string())); | ||
tempdir.push(super::DEFAULT_HISTORY_FILE_NAME); | ||
assert_eq!(tempdir, directory_plus_default_filename.unwrap()); | ||
|
||
// ========= Bad paths ========= // | ||
let bad_path = "/some/fake/path.txt".to_string(); | ||
let no_file = TestRepl::get_history_file_path(Some(bad_path)); | ||
assert_eq!(None, no_file); | ||
|
||
Ok(()) | ||
} |