Skip to content

Commit fb42483

Browse files
committed
Gneralized FilterType a bit so it works with Instantiated Filters to.
Also working on integrating new changes into lib, gui, and tui
1 parent 9667c97 commit fb42483

File tree

6 files changed

+116
-67
lines changed

6 files changed

+116
-67
lines changed

cargo-function-history/src/app/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,7 @@ impl App<'_> {
363363
}
364364
filter_name => {
365365
if let Some(filters) =
366-
function_grep::filter::builtin_filters().get(*filter_name)
366+
function_grep::filter::Filters::default().get_filter(*filter_name)
367367
{
368368
let rest = command_iter.copied().collect::<Vec<_>>().join(" ");
369369
let filt = match filters.to_filter(&rest) {

function-grep/src/filter.rs

Lines changed: 95 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
use general_filters::{FunctionInImpl, FunctionInLines, FunctionWithParameterRust};
2-
use std::{collections::HashMap, fmt, hash::Hash};
2+
use std::{
3+
collections::{hash_map, HashMap},
4+
fmt,
5+
hash::Hash,
6+
};
37

48
mod filter_parsers;
59
mod general_filters;
@@ -36,15 +40,9 @@ use crate::SupportedLanguages;
3640
pub trait Filter: HasFilterInformation {
3741
fn parse_filter(&self, s: &str) -> Result<FilterFunction, String>;
3842
// TODO: make way to parse from hashmap of attribute to string
39-
fn to_filter(&self, s: &str) -> Result<InstantiatedFilter, String> {
43+
fn to_filter(&self, s: &str) -> Result<InstantiatedFilter<Self::Supports>, String> {
4044
let filter = self.parse_filter(s)?;
4145
let info = self.filter_info();
42-
let info = FilterInformation {
43-
supported_languages: info.supported_languages.into(),
44-
description: info.description,
45-
attributes: info.attributes,
46-
filter_name: info.filter_name,
47-
};
4846
Ok(InstantiatedFilter {
4947
filter_information: info,
5048
filter_function: filter,
@@ -130,32 +128,37 @@ type FilterFunction = Box<dyn Fn(&Node<'_>) -> bool + Send + Sync>;
130128
// TODO: make our own FromStr that also requires the proggramer to sepcify that attributes each
131129
// filter has and their type so that we can make macro that creates parser, and also so that we can
132130
// communicate to a gui (or tui) that labels, and types of each input
133-
pub struct InstantiatedFilter {
134-
filter_information: FilterInformation<SupportedLanguages>,
131+
// TODO: make something that builds on this like FilterType
132+
pub struct InstantiatedFilter<Supports> {
133+
filter_information: FilterInformation<Supports>,
135134
filter_function: FilterFunction,
136135
}
137136

138-
impl PartialEq for InstantiatedFilter {
137+
impl<Supports: PartialEq> PartialEq for InstantiatedFilter<Supports> {
139138
fn eq(&self, other: &Self) -> bool {
140139
self.filter_information == other.filter_information
141140
}
141+
142+
fn ne(&self, other: &Self) -> bool {
143+
!self.eq(other)
144+
}
142145
}
143-
impl Eq for InstantiatedFilter {}
146+
impl<Supports: PartialEq> Eq for InstantiatedFilter<Supports> {}
144147

145-
impl fmt::Display for InstantiatedFilter {
148+
impl<Supports> fmt::Display for InstantiatedFilter<Supports> {
146149
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
147150
write!(f, "{}", self.filter_information)
148151
}
149152
}
150-
impl std::fmt::Debug for InstantiatedFilter {
153+
impl<Supports: std::fmt::Debug> std::fmt::Debug for InstantiatedFilter<Supports> {
151154
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
152155
f.debug_struct("InstantiatedFilter")
153156
.field("filter_information", &self.filter_information)
154157
.finish()
155158
}
156159
}
157160

158-
impl InstantiatedFilter {
161+
impl<Supports> InstantiatedFilter<Supports> {
159162
#[must_use]
160163
pub fn filter(&self, node: &Node<'_>) -> bool {
161164
(self.filter_function)(node)
@@ -177,7 +180,7 @@ impl InstantiatedFilter {
177180
}
178181

179182
#[must_use]
180-
pub const fn supported_languages(&self) -> &SupportedLanguages {
183+
pub const fn supported_languages(&self) -> &Supports {
181184
self.filter_information.supported_languages()
182185
}
183186
}
@@ -196,46 +199,95 @@ impl From<Language> for SupportedLanguages {
196199
}
197200
}
198201
// impl Language for
202+
// TODO: rework macro to work with the new language per filter system
199203
macro_rules! default_filters {
200204
($($filter:ident),*) => {S
201205
HashMap::from([$(($filter.filter_info().filter_name().to_string(), &$filter as &'static dyn Filter)),*])
202206
};
203207
}
204-
pub struct Many<'a> {
208+
pub struct Many<T: Info<Supported = Language>> {
205209
pub name: String,
206-
pub filters: HashMap<String, &'a dyn Filter<Supports = Language>>,
210+
pub filters: HashMap<String, T>,
207211
}
208212

209-
pub enum FilterType<'a> {
210-
All(&'a dyn Filter<Supports = All>),
211-
Many(Many<'a>),
213+
trait Info {
214+
type Supported;
215+
fn filter_name(&self) -> String;
212216
}
213-
impl<'a> FilterType<'a> {
214-
fn filter_name(&self) -> String {
215-
todo!()
216-
}
217+
// TODO: parameterize over something that is hkt might not work
217218

218-
fn supports(&self) -> SupportedLanguages {
219-
todo!()
219+
pub type FilterType<'a> =
220+
SingleOrMany<&'a dyn Filter<Supports = All>, &'a dyn Filter<Supports = Language>>;
221+
pub type InstantiatedFilterType =
222+
SingleOrMany<InstantiatedFilter<All>, InstantiatedFilter<Language>>;
223+
pub enum SingleOrMany<A: Info<Supported = All>, M: Info<Supported = Language>> {
224+
All(A),
225+
Many(Many<M>),
226+
}
227+
impl<A: Info<Supported = All>, M: Info<Supported = Language>> SingleOrMany<A, M> {
228+
#[must_use]
229+
pub fn filter_name(&self) -> String {
230+
match self {
231+
SingleOrMany::All(f) => f.filter_name(),
232+
SingleOrMany::Many(many) => many.name.clone(),
233+
}
220234
}
221235

222-
// add code here
236+
#[must_use]
237+
pub fn supports(&self) -> SupportedLanguages {
238+
match self {
239+
SingleOrMany::All(_) => SupportedLanguages::All,
240+
SingleOrMany::Many(many) => {
241+
SupportedLanguages::Many(many.filters.keys().cloned().collect())
242+
}
243+
}
244+
}
223245
}
224246
pub struct Filters<'a> {
225247
filters: HashMap<String, FilterType<'a>>,
226248
}
249+
impl<T> Info for &dyn Filter<Supports = T>
250+
where
251+
SupportedLanguages: From<T>,
252+
{
253+
type Supported = T;
254+
255+
fn filter_name(&self) -> String {
256+
self.filter_info().filter_name().to_string()
257+
}
258+
}
259+
impl<T> Info for InstantiatedFilter< T>
260+
where
261+
SupportedLanguages: From<T>,
262+
{
263+
type Supported = T;
264+
265+
fn filter_name(&self) -> String {
266+
self.filter_name().to_string()
267+
}
268+
}
269+
impl<'a> IntoIterator for Filters<'a> {
270+
type Item = (String, FilterType<'a>);
271+
272+
type IntoIter = hash_map::IntoIter<String, FilterType<'a>>;
273+
274+
fn into_iter(self) -> Self::IntoIter {
275+
self.filters.into_iter()
276+
}
277+
}
227278

228279
impl Filters<'static> {
280+
#[must_use]
229281
pub fn default() -> Self {
230282
Self {
231283
filters: HashMap::from([
232284
(
233285
FunctionInLines.filter_info().filter_name().to_string(),
234-
FilterType::All(&FunctionInLines as &'static dyn Filter<Supports = All>),
286+
SingleOrMany::All(&FunctionInLines as &'static dyn Filter<Supports = All>),
235287
),
236288
(
237289
FunctionInImpl.filter_info().filter_name().to_string(),
238-
FilterType::Many(Many {
290+
SingleOrMany::Many(Many {
239291
name: "function_in_impl".to_string(),
240292
filters: HashMap::from([(
241293
"Rust".to_string(),
@@ -248,7 +300,7 @@ impl Filters<'static> {
248300
.filter_info()
249301
.filter_name()
250302
.to_string(),
251-
FilterType::Many(Many {
303+
SingleOrMany::Many(Many {
252304
name: "function_with_parameter".to_string(),
253305
filters: HashMap::from([(
254306
FunctionWithParameterRust.supports().0,
@@ -264,21 +316,21 @@ impl Filters<'static> {
264316
impl<'a> Filters<'a> {
265317
pub fn add_filter(&mut self, filter: impl Into<FilterType<'a>>) -> Result<(), String> {
266318
let filter = filter.into();
267-
let name = filter.filter_name().clone();
268-
{
269-
let this = self.filters.get_mut(&name);
270-
match this {
271-
Some(filters) => match filters {
272-
FilterType::All(_) => Err("cannot add to an all filter".to_string()),
273-
FilterType::Many(Many { filters, .. }) => merge_filters(filters, filter),
274-
},
275-
None => {
276-
self.filters.insert(name, filter);
277-
Ok(())
278-
}
319+
let name = filter.filter_name();
320+
if let Some(filters) = self.filters.get_mut(&name) {
321+
match filters {
322+
SingleOrMany::All(_) => Err("cannot add to an all filter".to_string()),
323+
SingleOrMany::Many(Many { filters, .. }) => merge_filters(filters, filter),
279324
}
325+
} else {
326+
self.filters.insert(name, filter);
327+
Ok(())
280328
}
281329
}
330+
#[must_use]
331+
pub fn get_filter(&self, name: &str) -> Option<&FilterType<'a>> {
332+
self.filters.get(name)
333+
}
282334
}
283335

284336
fn merge_filters<'a>(

function-grep/src/filter/general_filters.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@ use std::collections::HashMap;
22

33
use tree_sitter::Node;
44

5-
use crate::SupportedLanguages;
6-
75
use super::{
86
filter_parsers::{extra, label, number},
97
All, Attribute, AttributeType, Filter, FilterFunction, HasFilterInformation, Language,
@@ -117,15 +115,15 @@ pub struct FunctionWithParameterRust;
117115

118116
impl HasFilterInformation for FunctionWithParameterRust {
119117
fn filter_name(&self) -> String {
120-
todo!()
118+
"function_with_parameter".to_string()
121119
}
122120

123121
fn description(&self) -> String {
124122
todo!()
125123
}
126124

127125
fn supports(&self) -> Self::Supports {
128-
todo!()
126+
Language("Rust".to_owned())
129127
}
130128

131129
fn attributes(&self) -> HashMap<Attribute, AttributeType> {

function-grep/src/lib.rs

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
#![deny(clippy::use_self, rust_2018_idioms)]
77
use core::fmt;
88

9-
use filter::InstantiatedFilter;
9+
use filter::{InstantiatedFilter, InstantiatedFilterType};
1010
use supported_languages::InstantiatedLanguage;
1111
use tree_sitter::{LanguageError, QueryError, Range, Tree};
1212
#[allow(missing_debug_implementations)]
@@ -140,20 +140,19 @@ impl ParsedFile {
140140
///
141141
/// # Errors
142142
/// If the filter [`f`] filters out all the results of this file
143-
pub fn filter(&self, f: &InstantiatedFilter) -> Result<Self, Error> {
144-
match f.supported_languages() {
145-
SupportedLanguages::Many(supported_languages)
146-
if !supported_languages.contains(&self.language().to_string()) =>
147-
{
148-
Err(Error::FilterLangaugeMismatch)?;
143+
pub fn filter(&self, f: &InstantiatedFilterType) -> Result<Self, Error> {
144+
match f {
145+
InstantiatedFilterType::Many(supported_language) => {
146+
let lang = self.language();
147+
let filter = supported_language.filters.get(lang);
148+
let filter = filter.ok_or(Error::FilterLangaugeMismatch);
149+
filter.and_then(|f| self.filter_inner(f))
149150
}
150-
SupportedLanguages::Single(supported_language)
151-
if supported_language != self.language() =>
152-
{
153-
Err(Error::FilterLangaugeMismatch)?;
154-
}
155-
_ => {}
151+
InstantiatedFilterType::All(f) => self.filter_inner(f),
156152
}
153+
}
154+
155+
fn filter_inner<T>(&self, f: &InstantiatedFilter<T>) -> Result<Self, Error> {
157156
let root = self.tree.root_node();
158157
let ranges: Box<[Range]> = self
159158
.ranges()

git-function-history-gui/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,7 @@ impl eframe::App for MyEguiApp {
398398
HistoryFilterType::None,
399399
"none",
400400
);
401-
function_grep::filter::builtin_filters()
401+
function_grep::filter::Filters::default()
402402
.into_iter()
403403
.sorted_by_cached_key(|(key, _)| {
404404
key.clone()

git-function-history-gui/src/types.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use function_grep::filter::Filter;
1+
use function_grep::filter::SingleOrMany;
22
use std::{collections::HashMap, fmt};
33

44
pub enum HistoryFilterType {
@@ -8,7 +8,7 @@ pub enum HistoryFilterType {
88
FileAbsolute(String),
99
FileRelative(String),
1010
Directory(String),
11-
PL(HashMap<String, String>, &'static dyn Filter),
11+
PL(HashMap<String, String>, SingleOrMany<'static>),
1212
None,
1313
}
1414

@@ -21,7 +21,7 @@ impl PartialEq for HistoryFilterType {
2121
(Self::FileAbsolute(l0), Self::FileAbsolute(r0)) => l0 == r0,
2222
(Self::FileRelative(l0), Self::FileRelative(r0)) => l0 == r0,
2323
(Self::Directory(l0), Self::Directory(r0)) => l0 == r0,
24-
(Self::PL(_, l1), Self::PL(_, r1)) => l1.filter_info() == r1.filter_info(),
24+
(Self::PL(_, l1), Self::PL(_, r1)) => l1.filter_name() == r1.filter_name(),
2525
_ => core::mem::discriminant(self) == core::mem::discriminant(other),
2626
}
2727
}
@@ -43,7 +43,7 @@ impl fmt::Debug for HistoryFilterType {
4343
Self::PL(arg0, arg1) => f
4444
.debug_tuple("PL")
4545
.field(arg0)
46-
.field(&arg1.filter_info())
46+
.field(&arg1.filter_name())
4747
.finish(),
4848
Self::None => write!(f, "None"),
4949
}
@@ -59,7 +59,7 @@ impl fmt::Display for HistoryFilterType {
5959
HistoryFilterType::FileAbsolute(_) => write!(f, "file absolute"),
6060
HistoryFilterType::FileRelative(_) => write!(f, "file relative"),
6161
HistoryFilterType::Directory(_) => write!(f, "directory"),
62-
HistoryFilterType::PL(_, pl) => write!(f, "{}", pl.filter_info()),
62+
HistoryFilterType::PL(_, pl) => write!(f, "{}", pl.filter_name()),
6363
HistoryFilterType::None => write!(f, "none"),
6464
}
6565
}

0 commit comments

Comments
 (0)