aboutsummaryrefslogtreecommitdiffstats
path: root/src
AgeCommit message (Collapse)Author
2016-04-22Write alias errors to STDERR instead of panickingTeddy Wing
We use an `.ok()` call on the result of the write so that we can ignore these errors. I think we shouldn't really worry too much about not being to write to STDERR, and instead try to print out the full email message as best we can. In order to write the error (`e.to_string()`), we needed to implement `fmt::Display` on `AliasSearchError`. While I was at it also implemented the `error::Error` trait.
2016-04-22main: Simplify the STDOUT writerTeddy Wing
I wrote it the way I originally did because I wanted to be more explicit, but I don't think that was right. Doing it this way because it makes the code much simpler. Also found out there's a `writeln!` macro which I probably should have used instead of manually adding a newline before.
2016-04-22main: Write message to STDOUTTeddy Wing
We need to write the full messgae to STDOUT so that Mutt can read it back in. Remove our two return statements as this will interrupt the message.
2016-04-22tests: Make constant name uppercaseTeddy Wing
The test compiler complained that I should make my constant uppercase. Do this to eliminate our compiler warnings.
2016-04-22Get the full integration working for realTeddy Wing
Rename `handle_alias` to `write_alias` and implement the function. This function integrates all our steps together and writes our new alias if we have one. Alter our `main` function to remove some of the old code. Don't convert STDIN to a vector. That was naïve. Instead iterate over its lines directly. Handle all our errors with either a "no news is good news" or a panic.
2016-04-22main: Remove pseudocodeTeddy Wing
The program is nearly implemented and this information is no longer needed.
2016-04-22Alias#write_to_file: Fix append and ending newlineTeddy Wing
Changed the test to use a file with multiple alias lines for a more real-world scenario. Achieving this by copying the `testdata/aliases` file into a new temporary test file instead of creating a new blank file. Then needed to change our assertion so that we get the correct line from the file to compare on. This is always the last line in the file. Note that `.len() - 2` is used because `.len() - 1` is the final newline. The test change revealed two errors in my code: 1. I needed to open the file for appending, not just for writing. 2. A newline needs to be appended to the end of the file (otherwise all our aliases get written to the same line). Fix the errors.
2016-04-22Add `Alias#write_to_file`Teddy Wing
Writes the alias to a given file. Thinking I should modify the test so that we can know it works with multiple alias lines.
2016-04-22Make `update_alias_id` tests more DRYTeddy Wing
Eliminate some of the repeated setup code in our tests for this method. Instead of doing this work inside the test functions, move them to a new constant binding and function respectively. A `const` seemed like a good fit because our alias identifier is just a string. For the `Alias`, we have a new function that returns a test object for us, making it possible to get two mutable copies of it (one for each of our test functions). Tests still pass, I guess it worked.
2016-04-21Add Alias#update_alias_idTeddy Wing
This function takes a list of aliases and updates the current `Alias`'s alias using an auto-incremented numeric id. Not happy with the repetition in the tests. Need to figure out if there's a way to abstract that.
2016-04-21find_alias_in_file: Return list of aliases not alias linesTeddy Wing
My next step is to get the list produced by this function and use it to build a new alias of `#{alias}-#{id + 1}`. In trying to figure out how best to do that, I realised that it would be easier to do if I had actual aliases to work with instead of full Mutt alias lines that I'd have to parse (again). Update our function to give us a list of aliases instead of full alias lines.
2016-04-21Remove `build_alias` functionTeddy Wing
This has been superseded by the `Alias::new` method (introduced in b182ea18dd664bc36e56601635ceb5ffdd67dc69). We can now safely remove this function.
2016-04-21Add test for `find_alias_in_file` Ok caseTeddy Wing
New test for when alias matches are found in the given file. We want to match all aliases that don't have the searched email and start with the searched alias string. This gives us a list of aliases. We'll then be able to use this list to determine the highest-ranking id of the searched alias and append ${id}+1 to it to create our new alias.
2016-04-21Add a test for the `AliasSearchError::NotFound` caseTeddy Wing
When the given alias being searched for does not appear in the alias file, a `NotFound` error should be returned.
2016-04-21Add test find_alias_in_file_email_already_existsTeddy Wing
When the email of the alias we're looking is already in the file, expect an `AliasSearchError::EmailExists` error. Oh man, this was a tough one. After much searching, finally figured out how to implement the `PartialEq` trait for my error type so that we could actually test it. Many thanks to @peterbudai for an example in the 'redux' project of how to do this (https://github.com/peterbudai/redux/blob/ef5d47a0a64cef9fa9e1e9c6f21badc46fa283fc/src/lib.rs): #[cfg(test)] impl PartialEq<Error> for Error { fn eq(&self, other: &Error) -> bool { match *self { Error::Eof => match *other { Error::Eof => true, _ => false }, Error::InvalidInput => match *other { Error::InvalidInput => true, _ => false }, Error::IoError(_) => match *other { Error::IoError(_) => true, _ => false }, } } } With that example, I was able to correctly build an equality function to get past my compiler errors which complained that an implementation of `std::cmp::PartialEq` might be missing for `std::io::error::Error` when I tried to `#[derive(PartialEq)]` on my `AliasSearchError` type.
2016-04-21find_alias_in_file: Return a vector of matchesTeddy Wing
Instead of returning a boolean value, get all lines that include the alias being searched for. This will give us a list of values like: Ok([ "alias farnsworth-hubert Hubert Farnsworth <professor@planetexpress.com>", "alias farnsworth-hubert-2 Hubert Farnsworth <other@planetexpress.com>", "alias farnsworth-hubert-3 Hubert Farnsworth <other2@planetexpress.com>" ]) Our list will contain all Mutt alias calls that start with the given alias string. Use my new learnings from the Error Handling section of the Rust book (http://doc.rust-lang.org/book/error-handling.html). We return a Result type so that we can communicate both File IO errors and our own custom matching errors. We define a new error type that allows us to provide information about the reason for our own errors. Note that I haven't yet implemented the required `fmt::Display` and `error::Error` methods on my custom error type yet as those didn't appear to be crucial to just getting this working. Change the `line.unwrap()` line to `try!(line)` so that we don't panic in the event of an error, but instead bubble the error upstream. If we come across a Mutt alias that has the same email as the inputted search alias, we want to abort because we shouldn't add a new Mutt alias line for an existing email address that's already been aliased.
2016-04-19Rename is_alias_in_file to find_alias_in_fileTeddy Wing
I think we should return a list of matched aliases from this function instead of a simple boolean value. As such, we'll start by renaming the function to something that makes sense in that context. We now need to modify the function and return type in order to provide that information.
2016-04-19is_alias_in_file_finds_a_match: Change `to_string` to `to_owned`Teddy Wing
Saw this pattern in the Rust book chapter Error Handling (http://doc.rust-lang.org/stable/book/error-handling.html#composing-option-and-result). Not sure if this is right but it seems better and more clearly evokes our intentions, so use `to_owned` here.
2016-04-19is_alias_in_file: Make `file` binding immutableTeddy Wing
Got a compiler warning saying that this doesn't need to be mutable. Sounds good to me, so let's do what it recommends.
2016-04-19main.rs: Remove unused import `std::path::Path`Teddy Wing
2016-04-18is_alias_in_file: Take an Alias instead of an alias stringTeddy Wing
This allows us to more easily compare parts of the alias line. Update our test to pass an `Alias` also.
2016-04-18Merge branch 'master' into check-for-alias-in-fileTeddy Wing
Conflicts: src/tests.rs
2016-04-18Alias#to_string: Don't format `name` if it's emptyTeddy Wing
When we get a "From: " address that doesn't contain a name, the resulting `Alias` object created by `Alias::new` will have an empty name. When `to_string` is called on these kinds of objects, an extra space appears between the alias and the email address because of how the format string is constructed. This caused a test failure for the `new_alias_with_only_email` test method in fc05eb9e2f111642dbec093218b7184f25740b90. Our change here fixes and passes this test.
2016-04-18tests.rs: Use `Alias::new` instead of `build_alias`Teddy Wing
Update tests to use our new `Alias::new` method for building an alias string. The `build_alias` function will be removed and replaced with this new function. We have a test failure in `new_alias_with_only_email` which has an extra space after the alias.
2016-04-17Add a new `Alias` struct and implementationTeddy Wing
This allows us to represent an alias not just as a string, but as an entity where we can ask for and isolate different parts of the alias. This makes it more convenient to get just the "alias" part, or just the "email" part for example. Doing so is necessary for making accurate comparisons/searches to find out whether this email or alias already exists in our alias file. Two functions are implemented on this type. One, `to_string`, creates a Mutt alias line as a string. The other builds a new `Alias` object from a "From: " string, taking nearly the same steps as `build_alias` does. We'll want to transition `build_alias` to this `Alias::new` function, using the new one in the future.
2016-04-17Create a function that will check whether an alias is in a fileTeddy Wing
This will allow us to pass an alias and grep for it in a given file. Just a rough outline to start. Added a super basic test and a file in "testdata" to operate on for testing.
2016-04-06build_alias: Remove comment about special charactersTeddy Wing
This functionality has been handled in de3a9b7f68e1f1b368630f498dd338d8b50444c8. The comment is no longer necessary.
2016-04-06test.rs: Split `build_alias` test into 5 separate testsTeddy Wing
Instead of putting all our asserts in a single test function, make a function for each assert. This allows us to give our test functions more specific names based on what exactly we're testing, and produces better output from `cargo test`. Also, if one of those fails for whatever reason, it's nice to know it will do so with a meaningful name.
2016-04-06build_alias: Remove [,'"] charactersTeddy Wing
Make the function a bit more DRY by taking the `push_str` calls out of the `if` block. Add a new test and some code to remove commas and quotes from aliases.
2016-04-06Implement `build_alias`Teddy Wing
Copy of the functionality in W. Caleb McDaniel's Bash script implemented in Rust: echo "${MESSAGE}" | grep ^"From: " | sed s/[\,\"\']//g | awk '{$1=""; if (NF == 3) {print "alias" $0;} else if (NF == 2) {print "alias" $0 $0;} else if (NF > 3) {print "alias", tolower($(NF-1))"-"tolower($2) $0;}}' Doesn't currently include the [,"'] filtering. Added a couple of new test cases to cover other address formats. Not sure if I should use `if..else if` here or a `match`. I feel like I should return an empty string at the end if we can't build an alias line.
2016-04-06Add a couple tests for `build_alias`Teddy Wing
Create a new `tests` module. This lives in its own file. Not sure if this is idiomatic Rust, but I prefer the idea of my tests living in a different file from my code. This module gets included in `main.rs`. We `use` `build_alias` directly because it's currently a private function, so doing `use super::*` didn't import it. Not sure if I should be making it a public function in order to mitigate this. Add a couple of variant test cases to check the string transformation that this function should be doing.
2016-04-06Create a couple new functions to build our alias (stubs)Teddy Wing
Stub out two new functions. The first, `handle_alias`, will manage the alias appending process. The second, `build_alias`, will transform a `From: ` string into a Mutt alias.
2016-04-05Find "From: " line in inputTeddy Wing
Look for the line that begins "From: " in the email message given to us. When we find it, we'll call a function that we're going to define soon that handles adding an alias to our Mutt aliases file.
2016-04-05Remove old commented code from 55b07581cf2e414460461e9e1591059b5dc459d3Teddy Wing
2016-04-05Read stdinTeddy Wing
Tried a few different times, copying code from different places. Didn't quite get it figured out at first. Wanted to add STDIN lines to a string. Got that working with option 3, but that `push_str` didn't appear to preserve newlines. Ended up using this solution from StackOverflow: http://stackoverflow.com/questions/13579266/how-to-read-user-input-in-rust/36374135#36374135 It adds the lines to a vector instead of a single string. Printing each line individually then gives us out newlines. This way is probably nicer also for getting the first line that starts with "From: ".
2016-04-05Add a comment with some implementation detailsTeddy Wing
Clarify what we want to do.
2016-03-27Initial commit. Base Rust 1.7.0 project.Teddy Wing
Generated with $ cargo new mutt-alias-auto-add --bin