message: Add code documentation to shell::completer
diff: @@ -29,20 +29,48 @@ impl IonFileCompleter {
  }
  impl Completer for IonFileCompleter {
  + /// When the tab key is pressed, **Liner** will use this method to perform completions of
  + /// filenames. As our `IonFileCompleter` is a wrapper around **Liner**'s `FilenameCompleter`,
  + /// the purpose of our custom `Completer` is to expand possible `~` characters in the `start`
  + /// value that we receive from the prompt, grab completions from the inner `FilenameCompleter`,
  + /// and then escape the resulting filenames, as well as remove the expanded form of the `~`
  + /// character and re-add the `~` character in it's place.
  fn completions(&self, start: &str) -> Vec<String> {
  + // Only if the first character is a tilde character will we perform expansions
  if start.starts_with('~') {
  + // Dereferencing the raw pointers here should be entirely safe, theoretically,
  + // because no changes will occur to either of the underlying references in the
  + // duration between creation of the completers and execution of their completions.
  if let Some(expanded) = unsafe{ (*self.vars).tilde_expansion(start, &*self.dir_stack) } {
  + // Now we obtain completions for the `expanded` form of the `start` value.
  + let completions = self.inner.completions(&expanded);
  + let mut iterator = completions.iter();
  +
  + // And then we will need to take those completions and remove the expanded form
  + // of the tilde pattern and replace it with that pattern yet again.
  + let mut completions = Vec::new();
  +
  + // We can do that by obtaining the index position where the tilde character ends.
  + // We don't search with `~` because we also want to handle other tilde variants.
  let t_index = start.find('/').unwrap_or(1);
  + // `tilde` is the tilde pattern, and `search` is the pattern that follows.
  let (tilde, search) = start.split_at(t_index as usize);
  - let iterator = self.inner.completions(&expanded);
  - let mut iterator = iterator.iter();
  - let mut completions = Vec::new();
  - if search.len() <= 1 {
  + if search.len() < 2 {
  + // If the length of the search pattern is less than 2, the search pattern is
  + // empty, and thus the completions actually contain files and directories in
  + // the home directory.
  +
  + // The tilde pattern will actually be our `start` command in itself,
  + // and the completed form will be all of the characters beyond the length of
  + // the expanded form of the tilde pattern.
  for completion in iterator {
  completions.push([start, &completion[expanded.len()..]].concat());
  }
  } else {
  + // To save processing time, we should get obtain the index position where our
  + // search pattern begins, and re-use that index to slice the completions so
  + // that we may re-add the tilde character with the completion that follows.
  if let Some(completion) = iterator.next() {
  if let Some(e_index) = completion.find(search) {
  completions.push(escape(&[tilde, &completion[e_index..]].concat()));
  @@ -62,6 +90,10 @@ impl Completer for IonFileCompleter {
  }
  }
  +/// Escapes filenames from the completer so that special characters will be properly escaped.
  +///
  +/// NOTE: Perhaps we should submit a PR to Liner to add a &'static [u8] field to
  +/// `FilenameCompleter` so that we don't have to perform the escaping ourselves?
  fn escape(input: &str) -> String {
  let mut output = Vec::with_capacity(input.len());
  for character in input.bytes() {
  