| Age | Commit message (Collapse) | Author |
|
Non-working attempts.
|
|
Use `autopilot::key::tap()` to simulate each key and modifier in an
action.
Originally tried to do this using a method that takes a closure to
access the `KeyCodeConvertible` types inside `KeyboardKey`. Ended up
with a much cleaner API solution that only requires a single method
call.
|
|
I originally wrapped the contained `Vec` in an `Option` to that we
wouldn't have to initialise whole new empty `Vec` for every key in an
`Action` list.
However, this made less sense once I wrote the parser and ended up with
an empty `Vec` by default that I then had to convert into an `Option`.
Now I've started the code to type keys including modifiers, and the
`Option` no longer makes any sense at all. In order to type keys
(including modifiers), I'll be using Autopilot's `tap()` function:
pub fn tap<T: KeyCodeConvertible + Copy>(key: T, flags: &[Flag], delay_ms: u64) {
This function requires a slice, so I ended up getting a `Vec` from my
parser, converting it to an Option to satisfy my original interface, and
now would have to convert it back into a `Vec` or slice in order to be
able to pass it into `tap()`. Talk about unnecessary.
Get rid of the `Option` because it's more work for absolutely no reason.
|
|
Get rid of old commented code now that we have a working version.
|
|
First, `MapGroup::parse` parses actions to `Action::String`s. We then
run a second pass on the parsed actions to parse them into
`Action::Map`s.
A few failed attempts but finally got it working. Tried a few ways of
doing it and kept running into various borrowing problems. Glad it's
working now.
|
|
This reverts commit 5ef2443642a2d8b223afdf169200a725d2809b76. See that
commit for details.
|
|
Trying to add new escape special keys for '\' and '<' but having a bit
of trouble.
Looks like I'm not using `and` `satisfy` correctly, as I'm getting this
error:
error[E0271]: type mismatch resolving `<(impl combine::Parser, combine::combinator::Satisfy<_, [closure@src/parser.rs:263:56: 263:68]>) as combine::Parser>::Output == char`
--> src/parser.rs:260:18
|
260 | (choice!(
| __________________^
261 | | try(string_case_insensitive("Bslash")).map(|_| '\\'),
262 | | try(string_case_insensitive("lt")).map(|_| '<'),
263 | | try(action_character().and(satisfy(|c| c != '>')))
264 | | ).map(|c|
| |_________________^ expected tuple, found char
|
= note: expected type `(char, _)`
found type `char`
= note: required because of the requirements on the impl of `combine::Parser` for `combine::combinator::Try<(impl combine::Parser, combine::combinator::Satisfy<_, [closure@src/parser.rs:263:56: 263:68]>)>`
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
I had added the `satisfy` not '>' after getting this test failure
without it:
---- parser::tests::action_parses_map_with_bslash_and_lt_special_keys stdout ----
thread 'parser::tests::action_parses_map_with_bslash_and_lt_special_keys' panicked at 'assertion failed: `(left == right)`
left: `Err(Errors { position: PointerOffset(4332007031), errors: [Unexpected(Token('l')), Expected(Token('>'))] })`,
right: `Ok(Map([KeyboardKeyWithModifiers { key: Character(Character(Character('a'))), flags: None }, KeyboardKeyWithModifiers { key: Character(Character(Character('\\'))), flags: None }, KeyboardKeyWithModifiers { key: Character(Character(Character('A'))), flags: None }, KeyboardKeyWithModifiers { key: Character(Character(Character('N'))), flags: None }, KeyboardKeyWithModifiers { key: Character(Character(Character('D'))), flags: None }, KeyboardKeyWithModifiers { key: Character(Character(Character('<'))), flags: None }, KeyboardKeyWithModifiers { key: Character(Character(Character('>'))), flags: None }, KeyboardKeyWithModifiers { key: Character(Character(Character('\\'))), flags: Some([Control]) }, KeyboardKeyWithModifiers { key: Character(Character(Character('<'))), flags: Some([Meta, Shift]) }]))`', src/parser.rs:928:9
as I suspected this was a problem with `<lt>`. But now that I think
about it, it could just as easily have been a problem with `<Bslash>`.
Not sure.
Anyway, I'm thinking of dropping these escapes because they're redundant
(we already have '\' escaping) and because I'm tired of these errors.
|
|
A simple test to check parsing of a simple string without any special
keys or modifiers.
|
|
Make this test do something, validating that it parses multiple modifier
prefixes in a special key.
|
|
Add a '>' closing bracket to the end of the test string to make sure
that the '<' gets escaped even with a '>' following it.
|
|
Previously we were able to parse modifier + KeyCode (`<C-Enter>`) special
keys and plain KeyCode ones (`<Esc>`).
This change adds parsing support for the final type of special key,
modifier + character (e.g. `<C-l>`).
action_character():
Move the `map` outside of this function and into `action_map()` to allow
us to reuse the parsed `char` in `special_key()`.
key_modifier():
* Move the `many()` parser and `Option` handling outside of this
function and into `special_key()`. Doing so enables us to say:
<C-l> // Character special keys _require_ a modifier (thus
// `many1`)
<[C-]Left> // KeyCode special keys may or may not have a modifier
// (thus `many`)
* Rename from `key_modifiers()` to singular now that it only parses a
single modifier.
special_key():
Parse both character and KeyCode special keys with modifiers.
action_parses_map_with_modifier():
Change input string to include a KeyCode-style special key with a
modifier since we didn't have one previously. This ensures we test both
kinds of special keys.
|
|
Add some parsing code for modifier keys inside special keys (`<`-
`>`-wrapped keys).
Currently only works for special keys defined in `special_key()`. Needs
to be extended to work for modified character keys (e.g. <C-l>), thus
the test in this commit doesn't pass.
|
|
Escape '<' and '\' by prepending a backslash. Since special characters
are enclosed in '<' '>' brackets, in order to type a literal '<', we
need a way to escape it. Use backslash, like in Vim.
|
|
Splits up the `action_map()` function and gives the parser a name.
|
|
Additionally, fix a problem in `key_code()` when using special key names
that start with the same character (like any of the F keys, or Enter and
Esc). The parser would discard the first character, like in the
`definitions()` parser. Use the same solution here, by wrapping the
parser choices in `try()`s.
Add `Esc` to the test to confirm that it fails not just for the F keys
but for all key names that start similarly.
|
|
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.
|
|
* Some stub ideas for test text
* Fill in the test for special keys
* Add some convenience methods to more easily create the expected test
result objects
|
|
Ideas for some things we should be testing.
|
|
There's no longer a `parse_mappings()` function (did I write one of
those?), which causes this test to error on compilation. Remove it since
it's just a stub for an old model of the code.
|
|
Fix these tests that were based on the `String` version of `Action`,
before b02e7366c3c4b9edb5afa0d012952fad369b66a9.
|
|
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.
|
|
This reverts commit 16cd3895f7b111544927d71904aab912d9abbf59. See that
commit message for details.
|
|
Such a pain. As soon as I clear one set of compilation errors, another
set crops up. The last one was like the following:
error[E0277]: the trait bound `K: std::default::Default` is not satisfied
--> src/cocoa_bridge.rs:117:1
|
117 | / pub extern "C" fn state_new<K>() -> *mut State<K>
118 | | where K: KeyCodeConvertible {
119 | | Box::into_raw(Box::new(State::default()))
120 | | }
| |_^ the trait `std::default::Default` is not implemented for `K`
|
= help: consider adding a `where K: std::default::Default` bound
note: required by `cocoa_bridge::State`
--> src/cocoa_bridge.rs:100:1
|
100 | / pub struct State<K: KeyCodeConvertible>
101 | | where K: Default {
102 | | in_mode: Option<Vec<HeadphoneButton>>,
103 | | map_group: Option<MapGroup<K>>,
104 | | }
| |_^
error[E0277]: the trait bound `K: std::default::Default` is not satisfied
I'm done with this. Just going to make a darn enum of 'autopilot's
`Character` and `KeyCode` structs so I don't have to deal with this
mess.
|
|
This reverts commit 76ab45d4a5890c4c348b33c32775e45a7c320c58. See that
commit for details.
|
|
Some non-working code where I was trying to get an `Action2` to parse
correctly, with a dependency on the result of the `map_kind()` parser.
Couldn't figure out how to get this to work though, as I couldn't escape
errors like this one:
error[E0271]: type mismatch resolving `<[closure@src/parser.rs:157:36: 186:6] as std::ops::FnOnce<(_,)>>::Output == std::result::Result<parser::Map, <I as combine::StreamOnce>::Error>`
--> src/parser.rs:137:16
|
137 | fn map<I>() -> impl Parser<Input = I, Output = Map>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `std::result::Result`, found struct `parser::Map`
|
= note: expected type `std::result::Result<std::result::Result<(parser::Map, _), _>, _>`
found type `std::result::Result<parser::Map, _>`
= note: required because of the requirements on the impl of `combine::Parser` for `combine::combinator::FlatMap<combine::combinator::TakeUntil<_, combine::char::Newline<I>>, [closure@src/parser.rs:157:36: 186:6]>`
= 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 E0271`.
Feeling like I've spent way too long stuck on this, so I'm just going to
parse actions into new action type (`Action2` for now) by doing a second
parsing pass. It's not going to be as performant, but at least I'm
confident that will work. We can always come back to this later. I'll be
reverting this commit.
|
|
With this new type, I'm trying to set up a way to parse actions more
precisely, to allow us to get special keys and modifier-flagged keys.
Still trying to work out how this is going to work at the parser level
though, since the action parser is going to need to depend on the map
kind parser.
|
|
* No colours
* Add timestamp
|
|
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.
|
|
Facilitate logging to stderr.
|
|
|
|
* Use `state.in_mode` as `in_mode` will always be `None` now
* Use `type_string` for map actions inside a mode. Otherwise the action
wouldn't be typed.
|
|
Now that there can be a `MapGroup` in the `State`, get it from there.
This will allow us to get the `MapGroup` from a configuration file.
|
|
Currently untested. This function is supposed to get a mapping file from
the XDG config directory, parse it, and load it into the state.
|
|
Facilitate interacting with config files in XDG directories.
|
|
For now this is just a test and doesn't handle modifier keys. Just
trying to see if 'autopilot' will work.
|
|
To simulate key presses.
|
|
Enable mode deactivation. If there is a current mode, deactivate it if
the trigger pressed is the current mode's trigger.
Return a BS `KeyActionResult` just to satisfy the return type
requirements of the function. We should really clean this function up
and eliminate this return value, but we can't until we move map action
key simulator handling into Rust.
|
|
Instead of letting the Objective-C code keep track of `in_mode` by
passing it around in `CKeyActionResult`, keep track of it in a `State`
struct.
Derive `Clone` on `HeadphoneButton` to resolve this error:
error[E0277]: the trait bound `parser::HeadphoneButton: std::clone::Clone` is not satisfied
--> src/cocoa_bridge.rs:273:38
|
273 | state.in_mode = Some(trigger.to_vec());
| ^^^^^^ the trait `std::clone::Clone` is not implemented for `parser::HeadphoneButton`
|
|
The plan is to use this as an opaque pointer to be passed between the
Objective-C code and Rust code. It will contain the current mode (if in
a mode) and the parsed `MapGroup` definitions.
For now just some code inspired by the Rust FFI Omnibus
(http://jakegoulding.com/rust-ffi-omnibus/objects/) to create and free a
`State`.
|
|
Finally figured out where the problem was with the `in_mode` on my
`CKeyActionResult` getting freed too early.
It happens because we're trying to use the reference to the `in_mode`
slice from the `KeyActionResult` returned by
`run_key_action_for_mode()`. We were putting that reference in the
`in_mode` of the `CKeyActionResult` returned by `c_run_key_action()`,
but it would get freed in that function.
In order to make it last indefinitely, we needed to convert it into a
raw boxed pointer to prevent Rust from deallocating it. This does mean
we now have a memory leak, but we'll just have to make a call into Rust
to free it from the C code.
|
|
Can't get this working. Tried a bunch of things. Decided to commit this
at a stopping point before messing any further. Sort of getting there,
with some things that seem like they're pointing in the right direction,
but it's not working out so far. Still getting a segfault. Actually,
with the `Box::into_raw` addition, the lifetime of the mode result
actually lasts for a single call (printf), and then gets freed
(weirdly).
Makefile:
* Add `-W` error flags to see if those would give me any extra
information about the pointer problems, but didn't get anything. The
fact that I didn't get errors indicated it was a problem on the Rust
side.
* Change `clean` dependency to `moder.c` so we don't rebuild if the C
file (and lib) hasn't changed.
c_run_key_action():
* Add some `println!`s and debug clutter
* Add a separate `let` binding for `run_key_action_for_mode()` because
that seemed to fix some weirdness in control flow when I was debugging
the code at one point in `lldb`. Not sure it this change still makes
sense to keep.
* Changed function/closure version of `in_mode` to `if`/`else` because
that may have made a difference in some dumb things I was
experimenting with at some point.
* Unsuccessful tries of `mem::forget()`, ultimately commented out.
* Return a `Box::into_raw` pointer to the `CKeyActionResult` instead of
the Rust pointer we were previously returning. This allows the value
to live beyond the function and beyond Rust's control into the calling
C code. This does, however, mean that the value leaks memory, and will
need to be freed manually in the calling C code.
run_key_action_for_mode():
* Wrap map handler in a check to verify `in_mode` is `None`. This
ensures that if we should be returning a `KeyActionResult` for a
mapping inside a mode, we don't run this code that's meant for
mappings outside a mode.
|
|
Add a new `moder.c` based on `includer.c` to test getting a mode and
then getting an action for a mode mapping.
Doesn't completely work currently. Right now all I get is this output:
$ ./moder
2
Segmentation fault: 11
Clearly I'm messing up something with the pointer in
`c_run_key_action()`. Not sure what it is yet.
Changed `CKeyActionResult.in_mode` to be a `Trigger` instead of a
`HeadphoneButton` list. That allows us to pass it directly into the
second argument of `c_run_key_action()` without converting.
But maybe the pointer value isn't living long enough? Not sure what the
problem is yet.
|
|
Add a new field for `in_mode` to the result struct. Return it if
`run_key_action_for_mode()` gives us a `Some` value for it. Removed the
`match` on `action` now that we have a second `Option` type.
|
|
When `trigger` is a mode instead of a map, return a `KeyActionResult`
with the `in_mode` field set to `trigger`.
The `MapKind` enum didn't really fit with the mode here. I couldn't use
`MapKind::{Map,Command}` for this `KeyActionResult` because the trigger
is for a mode, which is neither of those two.
At first I tried to add `Mode` as an option on `MapKind`, but that would
have caused problems. We'd be required to add `MapKind::Mode` as an
additional match arm in the two places we match against the kind in
`run_key_action_for_mode()`, and in that match arm we'd just have to log
an error because a `Mode` kind should never occur in those cases.
Instead of having a useless match arm that only serves to log an error,
I'd much rather not allow it in the first place.
Leaving `MapKind` the same allows us to keep our existing code the way
it is without adding unnecessary functionality.
In order to be able to declare a type of "Mode", though, I ended up
creating a new type that replicates `MapKind` (since I can't just extend
the enum to a new type) and adds a `Mode` option. This `ActionKind` is
only used for `KeyActionResult`, and `MapKind` is used for `Map`s and
`MapAction`s.
|
|
This was added for a432dd2824499959635ac9a7cabec25a31dddb14, but since
we didn't end up using it, we can revert this.
Might end up making the type public again later, but for now it doesn't
need to be.
|
|
This has been moved to `KeyActionResult::with_action()`.
|
|
Return struct values instead of references in the `KeyActionResult` impl
to clear up the borrow errors from
a432dd2824499959635ac9a7cabec25a31dddb14.
Clean up some of the code. Remove the `build()` method because we no
longer need it. The rest of the methods will already return the
`KeyActionResult` we need.
|
|
Make a builder for a new `KeyActionResult`, but without a new "builder"
type (seems like I should be able to get away without one in this simple
case).
I had make `parser::Trigger` public because at first I was using them in
`KeyActionResult` for the `in_mode` field. Oh yeah, there's a new
`in_mode` field on `KeyActionResult`. We'll be using that to store and
pass back the current mode to our FFI caller. This field can be used to
call `c_run_key_action()` with that mode scope.
Well, the idea is here, but I'm getting move errors:
error[E0507]: cannot move out of borrowed content
--> src/cocoa_bridge.rs:79:9
|
79 | *self
| ^^^^^ cannot move out of borrowed content
error[E0596]: cannot borrow immutable borrowed content as mutable
--> src/cocoa_bridge.rs:162:30
|
162 | *KeyActionResult::new(MapKind::Map)
| ______________________________^
163 | | .with_action(&map.action)
| |_________________________________________________________^ cannot borrow as mutable
error[E0507]: cannot move out of borrowed content
--> src/cocoa_bridge.rs:162:29
|
162 | / *KeyActionResult::new(MapKind::Map)
163 | | .with_action(&map.action)
164 | | .in_mode(trigger)
| |_________________________________________________^ cannot move out of borrowed content
Looks like I'll need to change the `KeyActionResult` impl code to pass
by value instead of reference. Committing what I have now, though,
because it's been a while and it's become kind of a mess.
|
|
Just the beginning of a way to get a map inside a mode. Not yet
complete. We need to modify `KeyActionResult` to give it an `in_mode`
field. This will enable us to tell the C code to use that mode scope.
Change the `mode` argument to `in_mode` because we already have a local
`mode` variable inside the function, and `in_mode` makes sense.
|