| Age | Commit message (Collapse) | Author |
|
Remove code that was commented in
44f6a2d5544e3ad49e5e3c52167c045aed1d56b2. Since we weren't able to
correctly link to the Core Audio framework from the Objective-C code
using this Rust audio code, get rid of it. Instead, we play audio in the
Objective-C application.
|
|
I was getting the following error when building the Objective-C project
with the latest audio playing code:
ld: warning: object file (.../DomeKey/lib/dome-key-map/target/debug/libdome_key_map.a(minimp3.o)) was built for newer OSX version (10.12) than being linked (10.7)
ld: warning: object file (.../DomeKey/lib/dome-key-map/target/debug/libdome_key_map.a(util_helpers.o)) was built for newer OSX version (10.12) than being linked (10.7)
ld: warning: object file (.../DomeKey/lib/dome-key-map/target/debug/libdome_key_map.a(aesni_helpers.o)) was built for newer OSX version (10.12) than being linked (10.7)
Undefined symbols for architecture x86_64:
"_AudioComponentFindNext", referenced from:
coreaudio::audio_unit::AudioUnit::new_with_flags::hc9c3029c77a9ba1d in libdome_key_map.a(cpal-b228ca6a35ab9c25.cpal12.rcgu.o)
"_AudioComponentInstanceNew", referenced from:
coreaudio::audio_unit::AudioUnit::new_with_flags::hc9c3029c77a9ba1d in libdome_key_map.a(cpal-b228ca6a35ab9c25.cpal12.rcgu.o)
"_AudioObjectGetPropertyData", referenced from:
cpal::cpal_impl::Device::name::h96cf527e96e03bec in libdome_key_map.a(cpal-b228ca6a35ab9c25.cpal0.rcgu.o)
cpal::cpal_impl::Device::supported_formats::h9019a8aeda6b1a55 in libdome_key_map.a(cpal-b228ca6a35ab9c25.cpal0.rcgu.o)
cpal::cpal_impl::Device::default_format::h1cffda96edcf1b5f in libdome_key_map.a(cpal-b228ca6a35ab9c25.cpal0.rcgu.o)
cpal::cpal_impl::EventLoop::build_input_stream::rate_listener::he669322d080b4fd0 in libdome_key_map.a(cpal-b228ca6a35ab9c25.cpal0.rcgu.o)
cpal::cpal_impl::enumerate::audio_devices::h35df9cd3ad61905a in libdome_key_map.a(cpal-b228ca6a35ab9c25.cpal8.rcgu.o)
cpal::cpal_impl::enumerate::default_input_device::h4d38066593597777 in libdome_key_map.a(cpal-b228ca6a35ab9c25.cpal8.rcgu.o)
cpal::cpal_impl::enumerate::default_output_device::hfb207f3766c759d9 in libdome_key_map.a(cpal-b228ca6a35ab9c25.cpal8.rcgu.o)
...
"_AudioObjectGetPropertyDataSize", referenced from:
cpal::cpal_impl::Device::supported_formats::h9019a8aeda6b1a55 in libdome_key_map.a(cpal-b228ca6a35ab9c25.cpal0.rcgu.o)
cpal::cpal_impl::enumerate::audio_devices::h35df9cd3ad61905a in libdome_key_map.a(cpal-b228ca6a35ab9c25.cpal8.rcgu.o)
"_AudioOutputUnitStart", referenced from:
coreaudio::audio_unit::AudioUnit::start::h0ceab6edb211b577 in libdome_key_map.a(coreaudio-b5e291d8855015a5.coreaudio3.rcgu.o)
"_AudioOutputUnitStop", referenced from:
coreaudio::audio_unit::AudioUnit::stop::h2929fdfd118ee7be in libdome_key_map.a(coreaudio-b5e291d8855015a5.coreaudio3.rcgu.o)
"_AudioUnitGetProperty", referenced from:
coreaudio::audio_unit::get_property::h58ff3c44f7ccc617 in libdome_key_map.a(coreaudio-b5e291d8855015a5.coreaudio3.rcgu.o)
coreaudio::audio_unit::get_property::habcd9010fa8dc136 in libdome_key_map.a(coreaudio-b5e291d8855015a5.coreaudio3.rcgu.o)
"_AudioUnitInitialize", referenced from:
coreaudio::audio_unit::AudioUnit::new_with_flags::hc9c3029c77a9ba1d in libdome_key_map.a(cpal-b228ca6a35ab9c25.cpal12.rcgu.o)
"_AudioUnitSetProperty", referenced from:
coreaudio::audio_unit::set_property::h5e5a6451ac49ed54 in libdome_key_map.a(rodio-d252ad0025b836aa.rodio15.rcgu.o)
coreaudio::audio_unit::set_property::h86353d3d091c7540 in libdome_key_map.a(coreaudio-b5e291d8855015a5.coreaudio3.rcgu.o)
coreaudio::audio_unit::set_property::hbaa7f6c599c38fa2 in libdome_key_map.a(coreaudio-b5e291d8855015a5.coreaudio3.rcgu.o)
coreaudio::audio_unit::set_property::hf450b8b66e374b66 in libdome_key_map.a(cpal-b228ca6a35ab9c25.cpal12.rcgu.o)
"_AudioUnitUninitialize", referenced from:
_$LT$coreaudio..audio_unit..AudioUnit$u20$as$u20$core..ops..drop..Drop$GT$::drop::h0a1df660f851dad4 in libdome_key_map.a(coreaudio-b5e291d8855015a5.coreaudio3.rcgu.o)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
After setting:
$ export MACOSX_DEPLOYMENT_TARGET=10.7
in the shell, the error changed to:
Undefined symbols for architecture x86_64:
"_AudioComponentFindNext", referenced from:
coreaudio::audio_unit::AudioUnit::new_with_flags::hc9c3029c77a9ba1d in libdome_key_map.a(cpal-b228ca6a35ab9c25.cpal12.rcgu.o)
"_AudioComponentInstanceNew", referenced from:
coreaudio::audio_unit::AudioUnit::new_with_flags::hc9c3029c77a9ba1d in libdome_key_map.a(cpal-b228ca6a35ab9c25.cpal12.rcgu.o)
"_AudioObjectGetPropertyData", referenced from:
cpal::cpal_impl::Device::name::h96cf527e96e03bec in libdome_key_map.a(cpal-b228ca6a35ab9c25.cpal0.rcgu.o)
cpal::cpal_impl::Device::supported_formats::h9019a8aeda6b1a55 in libdome_key_map.a(cpal-b228ca6a35ab9c25.cpal0.rcgu.o)
cpal::cpal_impl::Device::default_format::h1cffda96edcf1b5f in libdome_key_map.a(cpal-b228ca6a35ab9c25.cpal0.rcgu.o)
cpal::cpal_impl::EventLoop::build_input_stream::rate_listener::he669322d080b4fd0 in libdome_key_map.a(cpal-b228ca6a35ab9c25.cpal0.rcgu.o)
cpal::cpal_impl::enumerate::audio_devices::h35df9cd3ad61905a in libdome_key_map.a(cpal-b228ca6a35ab9c25.cpal8.rcgu.o)
cpal::cpal_impl::enumerate::default_input_device::h4d38066593597777 in libdome_key_map.a(cpal-b228ca6a35ab9c25.cpal8.rcgu.o)
cpal::cpal_impl::enumerate::default_output_device::hfb207f3766c759d9 in libdome_key_map.a(cpal-b228ca6a35ab9c25.cpal8.rcgu.o)
...
"_AudioObjectGetPropertyDataSize", referenced from:
cpal::cpal_impl::Device::supported_formats::h9019a8aeda6b1a55 in libdome_key_map.a(cpal-b228ca6a35ab9c25.cpal0.rcgu.o)
cpal::cpal_impl::enumerate::audio_devices::h35df9cd3ad61905a in libdome_key_map.a(cpal-b228ca6a35ab9c25.cpal8.rcgu.o)
"_AudioOutputUnitStart", referenced from:
coreaudio::audio_unit::AudioUnit::start::h0ceab6edb211b577 in libdome_key_map.a(coreaudio-b5e291d8855015a5.coreaudio3.rcgu.o)
"_AudioOutputUnitStop", referenced from:
coreaudio::audio_unit::AudioUnit::stop::h2929fdfd118ee7be in libdome_key_map.a(coreaudio-b5e291d8855015a5.coreaudio3.rcgu.o)
"_AudioUnitGetProperty", referenced from:
coreaudio::audio_unit::get_property::h58ff3c44f7ccc617 in libdome_key_map.a(coreaudio-b5e291d8855015a5.coreaudio3.rcgu.o)
coreaudio::audio_unit::get_property::habcd9010fa8dc136 in libdome_key_map.a(coreaudio-b5e291d8855015a5.coreaudio3.rcgu.o)
"_AudioUnitInitialize", referenced from:
coreaudio::audio_unit::AudioUnit::new_with_flags::hc9c3029c77a9ba1d in libdome_key_map.a(cpal-b228ca6a35ab9c25.cpal12.rcgu.o)
"_AudioUnitSetProperty", referenced from:
coreaudio::audio_unit::set_property::h5e5a6451ac49ed54 in libdome_key_map.a(rodio-d252ad0025b836aa.rodio15.rcgu.o)
coreaudio::audio_unit::set_property::h86353d3d091c7540 in libdome_key_map.a(coreaudio-b5e291d8855015a5.coreaudio3.rcgu.o)
coreaudio::audio_unit::set_property::hbaa7f6c599c38fa2 in libdome_key_map.a(coreaudio-b5e291d8855015a5.coreaudio3.rcgu.o)
coreaudio::audio_unit::set_property::hf450b8b66e374b66 in libdome_key_map.a(cpal-b228ca6a35ab9c25.cpal12.rcgu.o)
"_AudioUnitUninitialize", referenced from:
_$LT$coreaudio..audio_unit..AudioUnit$u20$as$u20$core..ops..drop..Drop$GT$::drop::h0a1df660f851dad4 in libdome_key_map.a(coreaudio-b5e291d8855015a5.coreaudio3.rcgu.o)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Couldn't figure out how to get past this, so decided to move the audio
playing into the Objective-C code. It's been something of a theme, where
if something doesn't work in one language (like
dome_key_event_source_simulator), write it in the other.
Here we just comment out the audio-related code so I can work on
connecting mode activation and deactivation and audio playing. I'll be
completely removing this code soon.
|
|
Success! Using the 'rodio' crate to play an audio file. Include the
audio file in the binary using `include_bytes!`. This makes it so we get
a single self-contained binary.
Struggled a bit with getting the reader/array to `Seek`, but finally
figured out `Cursor` and got it working. Cool.
|
|
|
|
Keep FFI functions separate from the rest.
|
|
|
|
When I first created the file, it was going to be used to call Cocoa
methods using the 'cocoa' crate. It's since turned into a module that
contains C functions called by Objective-C code. This new name makes
more sense.
We'll need to move one or two non-FFI functions outside of this module
for better organisation.
|
|
|
|
Add a new argument that allows users to pass in the path to a license
file. Doing so should get picked up by the Objective-C code which will
copy and validate the license.
In order for the Objective-C code to pick up the path string, we add a
`license` field to the `Config.Args` struct.
The new `license` field is a `*mut c_char`, which means we can't derive
Default any more and need to implement a custom `Default` impl for
`Args`.
Additionally, 'getopts' gives us a Rust string (of course), which needs
to be converted into a raw `CString` before we can stick it in the
`license` field in `Args`. I previously wrote `dkeprintln` to be able to
print an error here at the conversion point between `CString` and raw C
string.
Since we used `CString#into_raw()`, we need to call `from_raw()` on the
pointer to free it, otherwise we end up with a memory leak. This
necessitated adding some additional code to `config_free()` to free the
`license` field if non-null.
In order to access `config.args.license` from within `config_free()`, I
also needed to make the `args` and `license` struct fields public, since
the free function is in a different module. Instead of making only those
two fields public, I decided to make them all public, as all the fields
are technically accessible from C code, and are needed by that C code.
Finally, move the module declaration of `prefix_println` to the top of
the module list instead of listing it alphabetically, because otherwise
any modules declared before it (like `config`) don't get access to its
macro. Also add a `#[macro_use]` attribute to the module declaration
because we do want to export its macro.
(https://stackoverflow.com/questions/26731243/how-do-i-use-a-macro-across-module-files#comment78329437_31749071)
|
|
This macro functions exactly like `eprintln` while prepending the string
"dome-key: error: " to all messages. Allows us to give a uniform prefix
to printed rerrors.
Used the `println` macro as a reference:
https://doc.rust-lang.org/src/std/macros.rs.html#157-162
|
|
This function serves as the entry point to all trial functionality. When
called, it will try to determine the number of days remaining in the
trial.
* If the trial period is in progress, the number of days remaining will
be printed.
* If an error is encountered involving the trial file, or the trial has
expired, an error message is printed and the program exits.
* Finally, if an unrelated error occurs, print the error without
exiting.
Change `DateTime<Local>`s to `DateTime<FixedOffset>`s in order to have
uniform date types. Otherwise we run into trouble when comparing dates
and when querying functions with different date typs.
TODO: This fails the tests (unless your local timezone is UTC
presumably) because the local time gets stripped of its offset and the
correct offset gets reapplied, incorrectly shifting the time. Figure out
a way to have uniform datetime types without muffing up the timezone
offsets.
|
|
Add functions to encrypt and decrypt a timestamp. We'll be using those
functions to write the encrypted timestamp of the first trial launch
date to a file.
Decided to go for some light encryption instead of just storing a plain
or base64-encoded value. Still need to come up with a key, but that will
be stored as a plain string in the binary.
Need a way to capture the results so we don't end up panicking. Trouble
is, 'magic-crypt' doesn't implement the required `Error` traits, so I
can't just slot it into 'error-chain'. Still trying to work out how to
deal with that.
Also add a function to get the days remaining from now.
|
|
This new module will contain functions to calculate trial days.
Here we implement a function to calculate the days remaining in a trial
period.
If there are less than 0 days remaining, it returns an error result.
Couldn't use 'error-chain' because it was complaining about `Debug` and
`PartialEq` not being defined. Don't know if it's possible to implement
those traits on 'error-chain''s ErrorKind`, but it was complicated
enough that I ended up not bothering. Went with 'quick_error' instead to
create a custom error type without having to `impl` all the required
traits.
|
|
Use XDG handling from `state_load_map_group()` to do basically the same
thing here for reading the config from a `config.toml` file.
Use 'error-chain' to handle the `Result`s more easily. No more nested
pattern matching, we'll just have to unwrap one `Result` and write the
error to stderr in an FFI function.
|
|
A new function that will read a TOML config file. Doesn't currently
access the filesystem. This commit is mostly supporting code to allow
that to work.
* Add the 'toml' crate
* `parse_args()`: Take a mutable `Config` and return that config instead
of creating a new one. The recipe will now be to read the config from
a file first and then pass that config to this function to be updated.
* Modify `c_parse_args()` to take a `*Config` and mirror the new method
signature of `parse_args()`
|
|
This new field will be used by the calling Objective-C code as the
timeout between multi-button maps.
It will be defined in a `config.toml` file in the XDG config directory,
with a default if unspecified. That part of the code hasn't been written
yet, but we've prepared by deriving Serde `Deserialize` on the `Config`
struct in order to deserialise a TOML config file.
The latest Serde is v1.0.80, but we can't use it because 'cbindgen'
depends on an older version. We had been using 'cbindgen' v0.6.3, which
depends on serde v1.0.21. Decided to update 'cbindgen' in order to use a
newer version of Serde, but that puts us at v1.0.58 instead of the
latest:
error: failed to select a version for `serde_derive`.
... required by package `cbindgen v0.6.6`
... which is depended on by `dome-key-map v0.0.1 (file:///Users/tw/Documents/Development/dome-key-map)`
versions that meet the requirements `= 1.0.58` are: 1.0.58
all possible versions conflict with previously selected packages.
previously selected package `serde_derive v1.0.80`
... which is depended on by `dome-key-map v0.0.1 (file:///Users/tw/Documents/Development/dome-key-map)`
failed to select a version for `serde_derive` which could resolve this conflict
|
|
These two functions are copied from `autopilot-rs/src/key.rs` at
ab7ebc9fd8bc210717c0210aa20335ea9ceed200. I wanted to use the library
directly, but they're private functions.
I need this code in order to be able to convert the 'autopilot' `Flag`
type into `CGEventFlags`. I need a `CGEventFlags` because my media key
simulator, `dkess_press_key()` (an FFI function), requires a
`CGEventFlags`-typed value.
Needed to change the `from` function to a top-level function due to this
error:
error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
--> src/autopilot_internal.rs:213:1
|
213 | impl From<Flag> for CGEventFlags {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
|
= note: the impl does not reference any types defined in this crate
= note: define and implement a trait or new type instead
Bringing the code into the project seemed to be the easiest way to
leverage the existing 'autopilot' work.
|
|
Segfaults on key_code.rs:184:
error: process didn't exit successfully: `.../dome-key-map/target/debug/deps/dome_key_map-0efa5c8428fad354 send_media_key --nocapture` (signal: 11, SIGSEGV: invalid memory reference)
shell returned 101
This is my attempt to use first the 'cocoa' and 'core-graphics' crates,
then the 'objc' crate (because I hoped that would get around the
segfault), to simulate a media key event.
Once I got the types right and the code compiling, I couldn't get past
segfaults. After struggling with this for over a day and not being able
to figure out what on earth is going on, I wrote the exact same thing in
Objective-C and it just worked. That's it, I'm done with this. This code
is going to be expunged and I'm going to take a C function pointer in
the function that runs map actions that will simulate media key presses
in real Cocoa/Carbon. Enough of this headache.
|
|
Media keys (rewind, play/pause, fast forward on Mac function keys) are
different from normal keys. These use a different API, and sending
events to simulate those keys is different.
Here's a first stab at getting something working for posting simulated
media key events. This will be used for new special keys in mapping
actions. Haven't tested this at all yet, just happy that it finally
compiles.
Follow the two Stack Overflow answers referenced in the comments (from
Albert https://stackoverflow.com/users/133374/albert and Nick Sweeting
https://stackoverflow.com/users/2156113/nick-sweeting).
Add the `core-graphics` crate to give us access to `CGEvent`,
`CGKeyCode`, and related types.
Also include some commented `CGKeyCode` definitions for future use.
|
|
Parse command line options in this library. Need to figure out how to
communicate these over FFI to the Objective-C code.
|
|
Move the key simulation and command execution code to a new method so
that it can be reused in both top-level map and mode branches.
This additionally enables command running from top-level maps
(previously it only worked for in-mode maps).
|
|
Still need to test them though. They'll be used in conjunction with
another new parser, `action_map`, which will parser map-type action
strings.
`key_code` parses `autopilot::key::KeyCode`s, basically all special keys
and modifiers. `special_key` parses key codes inside `<` `>` braces.
Change the test to use `easy_parse` to give a clear error message.
Add `recursion_limit` to the crate on the advice of the compiler in
order for the `choice!` macro in `key_code()` to work properly.
Otherwise it spits out a giant error message complaining about
`rustc --explain E0277`. If I remove a handful of elements from the
`choice!`, it compiles, so it seems there's an upper bound restricted by
the recursion limit.
Modifier keys are included in a commented section as these are part of
the 'autopilot' `KeyCode` enum, but they'll be handled in a separate
parser.
|
|
It will now be a different type of `Vec` depending on whether it
represents a string map or a command. We'll have new parsers to parse
the action definition in a more fine-grained way.
The `String` variant is just there for temporary backward compatibility
while I figure out parsing for the other two.
Still need to update the tests for this change.
|
|
Trying to see if this works. If I call the init function over FFI and
then call functions that use the error macro, will logging work?
|
|
This allows us to log the errors without exiting the program.
|
|
Currently untested. This function is supposed to get a mapping file from
the XDG config directory, parse it, and load it into the state.
|
|
For now this is just a test and doesn't handle modifier keys. Just
trying to see if 'autopilot' will work.
|
|
Make a test `includer.c` program that includes the Rust library and
calls our `c_run_key_action()` to see if it actually works. Currently it
doesn't, we get `(null)` printed to stdout.
Add a Makefile with the build command for the C program.
cbindgen.toml:
Remove `KeyActionResult` from exported types, as the `Option` field it
contains caused `gcc` to complain.
cocoa_bridge.rs:
* Comment out all 'cocoa' crate related code as the 'cocoa' code was
interfering with GCC compilation as a result of my not linking to
Cocoa frameworks.
* Add a new test map definition that corresponds with the one we look
for in `includer.c`.
parser.rs:
Add `#[repr(C)]` to `MapKind` because it needs to be exported in the
library and generated into our C header file.
|
|
Add a new wrapper function for `run_key_action` that uses C appropriate
inputs & outputs and calls into our Rusty `run_key_action`. This new
function now correctly gets a header generated for it by 'cbindgen'.
Immense thanks to Jake Goulding on the Rust FFI Omnibus for showing me
how to pass a slice argument from C:
http://jakegoulding.com/rust-ffi-omnibus/slice_arguments/
In order to pass the slice from C, we need to pass a C array and its
length to the function. Cool.
|
|
* Add the 'cbindgen' crate to help us auto-generate a C header for our
exported FFI enums/structs/functions
* Add a `build.rs` to generate the C header using cbindgen
* Add a rough config for 'cbindgen'
* Export everything from the `cocoa_bridge` crate to include the
`KeyActionResult` struct
* Commit the C header generated by 'cbindgen'
Looks promising. We do, however, have some things to correct. We can't
use `Option` in C, for instance, so we'll need to fix that in our
`KeyActionResult`. Similarly, we need to rework the `run_key_action()`
function to make it accessible as a C interface. Right now it returns an
`Option`, which isn't going to work, and I'm not sure if the slice input
translates. That (any maybe more) is why it doesn't get generated by
'cbindgen' into the header output file.
|
|
* Add `#[repr(C)]` on `HeadphoneButton` to hopefully be able to use it
outside Rust
* Add `#[no_mangle]` to `run_key_action()`
* Export `run_key_action()` as a public function
* Build the crate as a static library
(But holy cow, a 19 MB library file?)
|
|
New `run_key_action()` will be called from Objective C. It will:
* Get the action for a `Map` mapping and return it, so that the
corresponding keys can be pressed in Cocoa/Carbon
* Run a `Command` mapping
* Somehow manage mode scoping in conjunction with the Objective C side
The new `KeyActionResult` allows us to tell Objective C what type of
action should be run (`Map`, `Command`, or `Mode`), along with
additional information (for now just the action keys in the case of a
`Map` mapping).
The question is how to hold on to state, keeping the parsed mappings in
memory on the Rust side when called over FFI.
|
|
Add some more structure to the function that will be called from
Objective C code.
* Give it a name, `parse_mappings` (not very thoroughly considered)
* Initialise some Foundation data structures to mirror our Rust ones
* Add the beginning of a struct that will be the ObjC version of our
`MapGroup` struct, containing `NSDictionary`ies.
* Move the `extern crate` into `lib.rs`, I keep forgetting that's where
they go.
* Add a test that just calls `parse_mappings` to check that the code
compiles.
parser::MapGroup:
Make both its fields public to enable us to access them from
`cocoa_bridge`.
Used this helpful example as a reference for the Rust Cocoa code:
https://github.com/servo/core-foundation-rs/blob/c99c05c/cocoa/examples/hello_world.rs
|
|
My `cocoa` module was conflicting with the `cocoa` crate. Didn't think
about that. Rename it to fix the conflict.
|
|
Add a new `cocoa` module which will hold code to be called from
Objective-C. Currently contains a sketch of a function that will be
called via FFI from Objective-C. Haven't thought of a name for it yet.
For now contains a sample map definition "file" in a hard-coded string.
Tells `MapGroup` to parse the map definitions. Will try to create some
Cocoa objects in the `unsafe` block.
`MapGroup`:
Add `parse()` method. Given a map definition string, this new function
will parse the string into a `MapGroup` and return the result. It will
serve as the entry point to parsing DomeKey map definitions.
Thanks to these references for Combine parser error handling:
- https://github.com/ordian/toml_edit/blob/b02bc3/src/parser/document.rs
- https://github.com/ordian/toml_edit/blob/ee6895f/src/parser/errors.rs
- https://github.com/Marwes/combine/blob/54bcfed/examples/ini.rs
|
|
Put our parsing code in its own module. We'll be creating a new `cocoa`
module and doing this allows us to keep `lib` free as a module
container.
|
|
Very important: file must be terminated by a newline in order to parse
correctly because of the way `Action`s are parsed. Will need to correct
this to work for EOF also.
We can now parse a whole file of map and mode definitions!
|
|
Clear out the commented failed attempts from
e96b453f33345ba08c8150192157077f310f1b01.
|
|
Create a new `Definition` item type that groups `Map` and `Mode` into a
single type that we can expect on a parser. This allows us to make a
parser that can parse both modes & maps.
A bunch of failed attempts, but finally managed to get something
working, yay!
|
|
No dice. Getting this error:
thread 'tests::map_group_parses_a_whole_map_file_string' panicked at 'assertion failed: `(left == right)`
left: `Err(Errors { position: PointerOffset(4376730950), errors: [Unexpected(Token('a')), Expected(Borrowed("mode"))] })`,
right: `Ok(MapGroup { maps: {[Down]: MapAction { action: "/bin/echo nothing", kind: Command }, [Play]: MapAction { action: "/usr/bin/say hello", kind: Command }}, modes: {[Down, Up]: {[Play]: MapAction { action: "p", kind: Map }}} })`', src/lib.rs:421:9
I need a way to parse modes and maps in any order. Here the code is
trying to parse first modes, then maps.
|
|
Add a new `Mode` type to parse into, similar to the `Map` type we made
recently. Parse a mode definition, which contains a `MapCollection`.
Modes cannot contain other modes, so we don't bother worrying about
recursive parsers.
|
|
Add support for blank, whitespace, and comment lines between and around
map definition lines.
Fiddled with the existing functions I had for this, but finally managed
to get it working, still using Combine's `examples/ini.rs` as a
reference.
|
|
Managed to get `MapCollection` parsing working, but only for a single
mapping for now. Need to figure out what I'm doing wrong.
Here's the result of my test:
thread 'tests::map_collection_parses_maps' panicked at 'assertion failed: `(left == right)`
left: `Ok({[Up, Down]: MapAction { action: "test", kind: Map }})`,
right: `Ok({[Down]: MapAction { action: "/usr/bin/say \'hello\'", kind: Command }, [Up, Down]: MapAction { action: "test", kind: Map }})`', src/lib.rs:265:9
note: Run with `RUST_BACKTRACE=1` for a backtrace.
test tests::map_collection_parses_maps ... FAILED
At first the assertion in the test wasn't working, failing to compile
with this error:
error[E0369]: binary operation `==` cannot be applied to type `std::collections::HashMap<std::vec::Vec<HeadphoneButton>, MapAction>`
--> src/lib.rs:266:9
|
266 | assert_eq!(result.unwrap(), expected);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: an implementation of `std::cmp::PartialEq` might be missing for `std::collections::HashMap<std::vec::Vec<HeadphoneButton>, MapAction>`
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
Finally realised that I needed to derive `PartialEq` on `MapAction` to
make it work.
Added a comment parser, based on the `examples/ini.rs` example from
Combine:
fn whitespace<I>() -> impl Parser<Input = I>
where
I: Stream<Item = char>,
I::Error: ParseError<I::Item, I::Range, I::Position>,
{
let comment = (token(';'), skip_many(satisfy(|c| c != '\n'))).map(|_| ());
// Wrap the `spaces().or(comment)` in `skip_many` so that it skips alternating whitespace and
// comments
skip_many(skip_many1(space()).or(comment))
}
Tried writing a test for `comment()`, but couldn't get it to work,
presumably because `comment()` doesn't have any output:
#[test]
fn comment_parses_line_comments() {
let text = "# This is a comment
";
let result = comment().parse(text).map(|t| t.0);
// print!("{:?}", result);
assert_eq!(result, Ok(()));
}
|
|
Parse a map definition line into a `Map`.
Got so stuck on this error:
error[E0277]: the trait bound `(): combine::Parser` is not satisfied
--> src/lib.rs:107:16
|
107 | fn map<I>() -> impl Parser<Input = I, Output = Map>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `combine::Parser` is not implemented for `()`
|
= note: the return type of a function must have a statically known size
error: aborting due to previous error
For more information about this error, try `rustc --explain E0277`.
Turns out the problem was that I had put a semicolon at the end of the
expression in `map()`. Geez. Took hours to finally see that.
|
|
Add a new `Map` type that includes a field for `trigger`. This allows us
to parse a single map definition line into a single struct, making
parsing more granular than going directly to `MapCollection`.
Rename the existing `Map` type to `MapAction` to support this change.
|
|
Can't get this to work. Right now I'm getting this error when running my
test:
Err(Errors { position: PointerOffset(4522385157), errors:
[Unexpected(Token('m')), Expected(Borrowed("lf newline")),
Expected(Borrowed("whitespace")), Expected(Borrowed("tab"))] })
It's supposed to parse a set of map lines, including whitespace and
comments, into a `MapCollection`.
Right now I'm thinking I should split this up more and make a more
fine-grained parser for just a single map line, then build up to the
collection from there.
|
|
For now just parses a string to a newline. In the future this will have
to be more complicated to deal with `<...>`-style special characters and
escaping (darn).
|
|
Should work with `<play>`, `<Play>`, `<PLAY>`, `<PlAy>`.
|
|
So cool! I love parser combinators.
|
|
Parses a headphone button into the `HeadphoneButton` enum.
|