Set default sorting order and method with arguments

This commit is contained in:
elandsborough 2024-01-10 19:53:36 +00:00 committed by ElliottLandsborough
parent 9bd740b2d0
commit e5e3ad2fed
No known key found for this signature in database
GPG Key ID: F289F7D124D40C13
7 changed files with 116 additions and 5 deletions

View File

@ -210,6 +210,18 @@ Options:
[env: MINISERVE_HIDDEN=]
-S, --default-sorting-method
Default sort method for file list
[env: MINISERVE_DEFAULT_SORTING_METHOD=]
[possible values: name, date, size]
-O, --default-sorting-order
Default sort order for file list
[env: MINISERVE_DEFAULT_SORTING_ORDER=]
[possible values: asc, desc]
-c, --color-scheme <COLOR_SCHEME>
Default color scheme

View File

@ -113,6 +113,26 @@ pub struct CliArgs {
#[arg(short = 'H', long = "hidden", env = "MINISERVE_HIDDEN")]
pub hidden: bool,
/// Default sorting method for file list
#[arg(
short = 'S',
long = "default-sorting-method",
default_value = "",
ignore_case = true,
env = "MINISERVE_DEFAULT_SORTING_METHOD"
)]
pub default_sorting_method: String,
/// Default sorting order for file list
#[arg(
short = 'O',
long = "default-sorting-order",
default_value = "",
ignore_case = true,
env = "MINISERVE_DEFAULT_SORTING_ORDER"
)]
pub default_sorting_order: String,
/// Default color scheme
#[arg(
short = 'c',

View File

@ -15,6 +15,7 @@ use crate::{
args::{parse_auth, CliArgs, MediaType},
auth::RequiredAuth,
file_utils::sanitize_path,
listing::{SortingMethod, SortingOrder},
renderer::ThemeSlug,
};
@ -50,6 +51,12 @@ pub struct MiniserveConfig {
/// Show hidden files
pub show_hidden: bool,
/// Default sorting method
pub default_sorting_method: Option<SortingMethod>,
/// Default sorting order
pub default_sorting_order: Option<SortingOrder>,
/// Route prefix; Either empty or prefixed with slash
pub route_prefix: String,
@ -265,6 +272,24 @@ impl MiniserveConfig {
.transpose()?
.unwrap_or_default();
let default_sorting_method: Option<SortingMethod> = match args
.default_sorting_method
.to_owned()
.parse::<SortingMethod>()
{
Ok(value) => Some(value),
Err(_) => None,
};
let default_sorting_order: Option<SortingOrder> = match args
.default_sorting_order
.to_owned()
.parse::<SortingOrder>()
{
Ok(value) => Some(value),
Err(_) => None,
};
Ok(MiniserveConfig {
verbose: args.verbose,
path: args.path.unwrap_or_else(|| PathBuf::from(".")),
@ -274,6 +299,8 @@ impl MiniserveConfig {
path_explicitly_chosen,
no_symlinks: args.no_symlinks,
show_hidden: args.hidden,
default_sorting_method,
default_sorting_order,
route_prefix,
favicon_route,
css_route,

View File

@ -223,7 +223,7 @@ pub fn directory_listing(
res
};
let query_params = extract_query_parameters(req);
let mut query_params = extract_query_parameters(req);
let mut entries: Vec<Entry> = Vec::new();
let mut readme: Option<(String, String)> = None;
@ -299,6 +299,14 @@ pub fn directory_listing(
}
}
if query_params.sort.is_none() {
query_params.sort = conf.default_sorting_method
}
if query_params.order.is_none() {
query_params.order = conf.default_sorting_order
}
match query_params.sort.unwrap_or(SortingMethod::Name) {
SortingMethod::Name => entries.sort_by(|e1, e2| {
alphanumeric_sort::compare_str(e1.name.to_lowercase(), e2.name.to_lowercase())
@ -319,7 +327,7 @@ pub fn directory_listing(
}),
};
if let Some(SortingOrder::Descending) = query_params.order {
if let Some(SortingOrder::Ascending) = query_params.order {
entries.reverse()
}

View File

@ -459,7 +459,7 @@ fn build_link(
) -> Markup {
let mut link = format!("?sort={name}&order=asc");
let mut help = format!("Sort by {name} in ascending order");
let mut chevron = chevron_up();
let mut chevron = chevron_down();
let mut class = "";
if let Some(method) = sort_method {
@ -469,7 +469,7 @@ fn build_link(
if order.to_string() == "asc" {
link = format!("?sort={name}&order=desc");
help = format!("Sort by {name} in descending order");
chevron = chevron_down();
chevron = chevron_up();
}
}
}

View File

@ -1,12 +1,13 @@
mod fixtures;
mod utils;
use fixtures::{server, Error, TestServer, DEEPLY_NESTED_FILE, DIRECTORIES};
use fixtures::{server, Error, TestServer, FILES, DEEPLY_NESTED_FILE, DIRECTORIES};
use pretty_assertions::{assert_eq, assert_ne};
use rstest::rstest;
use select::document::Document;
use std::process::{Command, Stdio};
use utils::get_link_from_text;
use utils::get_link_hrefs_from_text_with_prefix;
#[rstest(
input,
@ -147,3 +148,30 @@ fn can_navigate_using_breadcrumbs(
Ok(())
}
#[rstest]
#[case(server(&["--default-sorting-method", "date", "--default-sorting-order", "desc"]))]
#[case(server(&["--default-sorting-method", "date", "--default-sorting-order", "asc"]))]
/// We can specify the default sorting order
fn can_specify_default_sorting_order(#[case] server: TestServer) -> Result<(), Error> {
let slash = String::from("/");
let base_url = server.url();
let nested_url = base_url.join(&slash)?;
let resp = reqwest::blocking::get(nested_url.as_str())?;
let body = resp.error_for_status()?;
let parsed = Document::from_read(body)?;
let links = get_link_hrefs_from_text_with_prefix(&parsed, "/");
let first_created_file = slash + FILES.first().unwrap();
if links.first().unwrap() == &first_created_file {
assert_eq!("/very/?sort=date&order=asc", links.last().unwrap());
}
if links.last().unwrap() == &first_created_file {
assert_eq!("/very/?sort=date&order=desc", links.first().unwrap());
}
Ok(())
}

View File

@ -12,3 +12,19 @@ pub fn get_link_from_text(document: &Document, text: &str) -> Option<String> {
.next()?;
Some(a_elem.attr("href")?.to_string())
}
/// Return the href attributes of all links that start with the specified prefix `text`.
pub fn get_link_hrefs_from_text_with_prefix(document: &Document, text: &str) -> Vec<String> {
let mut vec: Vec<String> = Vec::new();
let a_elem = document.find(Name("a"));
for element in a_elem {
let str = element.attr("href").unwrap_or("");
if str.to_string().starts_with(text) {
vec.push(str.to_string());
}
}
return vec;
}