fst
fst copied to clipboard
Add next_start_node function to Stream
What is this?
This adds a function to the Stream
trait that allows you to see the current node that the dyn Stream
will start from on the next call to Stream::next
.
My use case
I'm trying to use an fst to implement auto-completion in a file dialog. Basically, I put all the files and directories into an fst, then I traverse the fst to the current partial file/folder name, then based on if the node I end up on has only 1 transition or not, I decide to either partially, or completely, complete the file or directory that the user is looking for, if that condition is true.
Or display a tooltip with the possible files/directories, if that condition is false
In order to do this, I need to traverse the fst to find the node to check for transitions on, then I need to traverse it again to initialize the searching stream for the tooltip, which isn't ideal.
let mut node = self.root();
for &b in key {
node = match node.find_input(b) {
None => return false,
Some(i) => self.node(node.transition_addr(i)),
}
}
if !node.is_final() {
if node.transitions().count() == 1 {
/* Complete file name */
while node.transitions().count() == 1 {
let t = node.transitions().next().unwrap();
self.path_edit.push(t.inp as char);
node = self.completion.machine.node(t.addr);
}
} else {
let matcher = fst::automaton::Str::new(file_name).starts_with();
let mut stream = self
.completion
.machine
.search(matcher)
.gt(file_name)
.into_stream();
/* Traverse stream to display tooltip */
}
}
What this PR does, is it allows you to just initialize the stream from the get-go, and then call next_start_node
to find where we end up after initializing the stream with a range
let matcher = fst::automaton::Str::new(file_name).starts_with();
let mut stream = self
.completion
.machine
.search(matcher)
.gt(file_name)
.into_stream();
if let Some(mut node) = stream.next_start_node() {
if node.transitions().count() == 1 {
/* Complete file name */
while node.transitions().count() == 1 {
let t = node.transitions().next().unwrap();
self.path_edit.push(t.inp as char);
node = self.completion.machine.node(t.addr);
}
} else {
/* Traverse stream to display tooltip */
}
}
This way, I only have to traverse the fst once, for both cases. And I don't have to start over for the tooltip case.