-
Notifications
You must be signed in to change notification settings - Fork 157
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Design][Pluggable Components] History and searching #86
Comments
I generally like the approach using the enum. It would consolidate the stateful part handling indices relative to the current history datastructure. Would from my point of view resolve my gripe in #55. The peeking list proposed in #60 probably requires would be the ability to peek ahead of the current search cursor i.e. iterator starting there. I would agree that we currently only require one view into the history.
pub trait History {
// append any given string (a command) into the history - store
fn append(&mut self, entry: String) -> ();
}
pub trait HistoryView {
// This moves the cursor backwards respecting the navigation query that is set
// - Results in a no-op if the cursor is at the initial point
fn back(&mut self);
// This moves the cursor forwards respecting the navigation-query that is set
// - Results in a no-op if the cursor is at the latest point
fn forward(&mut self);
// Returns the string (if present) at the cursor
fn string_at_cursor(&self) -> Option<String>;
} Then we could later decide to instead make those stateful searches/browsers independent implementations holding a reference to the datastructure. The implementation for the current proposal could become a larger monolith at some point if all search logic would have to be dispatched based on the enum. |
I am not sure if I understand this completely. Are you saying that we want to have two separate traits (i.e. History and HistoryView) on the same struct? Which would look something like the following -- pub struct FilebackedHistory {}
impl History for FileBackedHistory {}
impl HistoryView for FilebackedHistory {} If this is the case the
I think the updated proposal that you have offered will also result in the same problem. No? Or did you mean, that we return HistoryView from the History object itself? I was thinking along these lines too, but I eventually decided that, a solution like that would be quite tricky to get right. pub trait HistoryNavigationResult {
fn back(&mut self) -> ();
fn forward(&mut self) -> ();
fn string_at_cursor(&self) -> Option<String>;
}
pub trait History {
fn append(&mut self, entry: String) -> ();
fn navigate(&self, history_navigation: HistoryNavigationQuery) -> Box<dyn HistoryNavigationResult>;
} And the implementations for this would look like pub struct FileBackedHistory {
entries: VecDeque<String>,
}
// Need to copy over the whole entries stuff in here too.
pub struct FileBackedHistoryNormalResult {}
impl HistoryNavigationResult for FileBackedHistoryNormalResult {}
// Need to copy over the whole entries stuff in here too or a computed version of entries VecDeque
pub struct FileBackedHistoryPrefixSearchResult {}
impl HistoryNavigationResult for FileBackedHistoryPrefixSearchResult {}
impl ImmutableSearchHistory for FileBackedHistory {
...
fn navigate(&mut self, history_navigation: HistoryNavigationQuery) -> Box<dyn HistoryNavigationResult> {
match history_navigation {
HistoryNavigationQuery::Normal => Box::new(FileBackedHistoryNormalResult::new()),
HistoryNavigationQuery::PrefixSearch(_) => Box::new(FileBackedHistoryPrefixSearchResult::new()),
HistoryNavigationQuery::SubstringSearch(_) => Box::new(FileBackedHistorySubStringSearchResult::new())
}
}
} Here we append to history any new commands that a user will enter. But when the user asks for Navigation Object then we will return a HistoryNavigationResult which has the results of that search, this has the following features I can think of
in addition to this there are a bunch of other questions that we will need to answer.
considering all this I decided that maybe bloating up the match block that operates on the enum is probably the better choice as it is significantly simpler to deal with than this. or did you you mean something else entirely? |
Your proposed API is certainly easier to implement for now and allows to incorporate in a modal/configurable fashion to run different search/navigation strategies. With the addition of a method My thought of those View structs was, that they hold during their lifetime (invalid during appending) a immutable reference to a slice or iterator of the history (handed out by the |
@sholderbach Have you looked into https://github.com/bodil/im-rs, I skimmed through the docs and this will probably help us avoid all the invalidation issues as we will send out a copy to the View objects. Also, this will not hit performance much as behind the scenes there would be structural sharing. Let me know your thoughts on this and I can work on the approach that we agree on. |
Continuing with the theme of more pluggable components as discussed in #61. I wanted to get thoughts of people of the following
History
design. This is very close to what we already have and also takes into consideration #55.Approach
Thinking about the ways we can search history. I could come up with the following ways -
We can encapsulate this sort of a query into a struct like as follows -
Now keeping this in mind we can have a couple of interfaces we can design for our History.
Some features of this particular design
FileBackedHistory
,InMemoryHistory
,DBBackedHistory
, etc.go_back
,go_forward
,go_back_with_prefix
,go_forward_with_prefix
,go_back_with_substring
,go_back_with_fuzzy
, etcImplementation
Based on whatever the discussion we have here I can start working on this. Though this will conflict heavily with #60. I am not super sure of what the state is there.
The text was updated successfully, but these errors were encountered: