Skip to content

Commit

Permalink
Specs and dialyzer
Browse files Browse the repository at this point in the history
  • Loading branch information
doughsay committed Dec 10, 2019
1 parent d75c6ba commit acf31c6
Show file tree
Hide file tree
Showing 15 changed files with 222 additions and 212 deletions.
3 changes: 3 additions & 0 deletions lib/afk/apply_keycode.ex
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
defprotocol AFK.ApplyKeycode do
@moduledoc false

@spec apply_keycode(AFK.Keycode.t(), AFK.State.t(), term) :: AFK.State.t()
def apply_keycode(keycode, state, key)

@spec unapply_keycode(AFK.Keycode.t(), AFK.State.t(), term) :: AFK.State.t()
def unapply_keycode(keycode, state, key)
end
6 changes: 6 additions & 0 deletions lib/afk/keycode.ex
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,10 @@ defmodule AFK.Keycode do
* `AFK.Keycode.None` - A keycode that does nothing
* `AFK.Keycode.Transparent` - A key that is transparent to its layer
"""

alias __MODULE__.{Key, Layer, Modifier, None, Transparent}

@type t :: Key.t() | Layer.t() | Modifier.t() | None.t() | Transparent.t()

@type with_scancode :: Key.t() | Modifier.t()
end
101 changes: 18 additions & 83 deletions lib/afk/keycode/key.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,92 +3,24 @@ defmodule AFK.Keycode.Key do
Represents a basic keyboard keycode, like letters, numbers, etc.
All standard keys on a keyboard except the modifiers can be represented by
`Key` keycodes. The following is a list of currently supported keys:
* `:a`
* `:b`
* `:c`
* `:d`
* `:e`
* `:f`
* `:g`
* `:h`
* `:i`
* `:j`
* `:k`
* `:l`
* `:m`
* `:n`
* `:o`
* `:p`
* `:q`
* `:r`
* `:s`
* `:t`
* `:u`
* `:v`
* `:w`
* `:x`
* `:y`
* `:z`
* `:"1"`
* `:"2"`
* `:"3"`
* `:"4"`
* `:"5"`
* `:"6"`
* `:"7"`
* `:"8"`
* `:"9"`
* `:"0"`
* `:enter`
* `:escape`
* `:backspace`
* `:tab`
* `:space`
* `:minus`
* `:equals`
* `:left_square_bracket`
* `:right_square_bracket`
* `:backslash`
* `:semicolon`
* `:single_quote`
* `:grave`
* `:comma`
* `:period`
* `:slash`
* `:caps_lock`
* `:f1`
* `:f2`
* `:f3`
* `:f4`
* `:f5`
* `:f6`
* `:f7`
* `:f8`
* `:f9`
* `:f10`
* `:f11`
* `:f12`
* `:print_screen`
* `:scroll_lock`
* `:pause`
* `:insert`
* `:home`
* `:page_up`
* `:delete`
* `:end`
* `:page_down`
* `:right`
* `:left`
* `:down`
* `:up`
* `:application`
`Key` keycodes. The currently supported keys are `t:key/0`.
"""

@enforce_keys [:key]
defstruct [:key]

@type key ::
unquote(
AFK.Scancode.keys()
|> Enum.map(&elem(&1, 1))
|> Enum.reverse()
|> Enum.reduce(&{:|, [], [&1, &2]})
)

@type t :: %__MODULE__{
key: key
}

@doc """
Creates a basic key keycode.
Expand All @@ -100,12 +32,15 @@ defmodule AFK.Keycode.Key do
iex> new(:up)
%AFK.Keycode.Key{key: :up}
"""
for {_value, key} <- AFK.Scancode.keyboard() do
@spec new(key) :: t
def new(key)

for {_value, key} <- AFK.Scancode.keys() do
def new(unquote(key)), do: struct!(__MODULE__, key: unquote(key))
end

defimpl AFK.Scancode.Protocol do
for {value, key} <- AFK.Scancode.keyboard() do
for {value, key} <- AFK.Scancode.keys() do
def scancode(%AFK.Keycode.Key{key: unquote(key)}), do: unquote(value)
end
end
Expand Down
37 changes: 23 additions & 14 deletions lib/afk/keycode/layer.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,16 @@ defmodule AFK.Keycode.Layer do
* `:default` - Sets a layer as the default layer
"""

@enforce_keys [:type, :layer]
defstruct [:type, :layer]
@enforce_keys [:mode, :layer]
defstruct [:mode, :layer]

@type mode :: :default | :hold | :toggle
@type layer :: non_neg_integer

@type t :: %__MODULE__{
mode: mode,
layer: layer
}

@doc """
Creates a layer activation keycode.
Expand All @@ -24,20 +32,21 @@ defmodule AFK.Keycode.Layer do
## Examples
iex> new(:hold, 1)
%AFK.Keycode.Layer{layer: 1, type: :hold}
%AFK.Keycode.Layer{layer: 1, mode: :hold}
iex> new(:hold, 2)
%AFK.Keycode.Layer{layer: 2, type: :hold}
%AFK.Keycode.Layer{layer: 2, mode: :hold}
iex> new(:toggle, 1)
%AFK.Keycode.Layer{layer: 1, type: :toggle}
%AFK.Keycode.Layer{layer: 1, mode: :toggle}
iex> new(:default, 2)
%AFK.Keycode.Layer{layer: 2, type: :default}
%AFK.Keycode.Layer{layer: 2, mode: :default}
"""
def new(type, layer) when type in ~w(hold toggle default)a and is_integer(layer) and layer >= 0 do
@spec new(mode, layer) :: t
def new(mode, layer) do
struct!(__MODULE__,
type: type,
mode: mode,
layer: layer
)
end
Expand All @@ -46,35 +55,35 @@ defmodule AFK.Keycode.Layer do
alias AFK.Keycode.Layer
alias AFK.State.Keymap

def apply_keycode(%Layer{type: :hold} = keycode, state, key) do
def apply_keycode(%Layer{mode: :hold} = keycode, state, key) do
keymap = Keymap.add_activation(state.keymap, keycode, key)

%{state | keymap: keymap}
end

def apply_keycode(%Layer{type: :toggle} = keycode, state, key) do
def apply_keycode(%Layer{mode: :toggle} = keycode, state, key) do
keymap = Keymap.toggle_activation(state.keymap, keycode, key)

%{state | keymap: keymap}
end

def apply_keycode(%Layer{type: :default} = keycode, state, key) do
def apply_keycode(%Layer{mode: :default} = keycode, state, key) do
keymap = Keymap.set_default(state.keymap, keycode, key)

%{state | keymap: keymap}
end

def unapply_keycode(%Layer{type: :hold} = keycode, state, key) do
def unapply_keycode(%Layer{mode: :hold} = keycode, state, key) do
keymap = Keymap.remove_activation(state.keymap, keycode, key)

%{state | keymap: keymap}
end

def unapply_keycode(%Layer{type: :toggle}, state, _key) do
def unapply_keycode(%Layer{mode: :toggle}, state, _key) do
state
end

def unapply_keycode(%Layer{type: :default}, state, _key) do
def unapply_keycode(%Layer{mode: :default}, state, _key) do
state
end
end
Expand Down
26 changes: 16 additions & 10 deletions lib/afk/keycode/modifier.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,24 @@ defmodule AFK.Keycode.Modifier do
Represents a basic modifier keycode, like control, shift, etc.
All standard modifiers on a keyboard can be represented by `Modifier`
keycodes. The following is a list of all supported modifiers:
* `:left_control`
* `:left_shift`
* `:left_alt`
* `:left_super`
* `:right_control`
* `:right_shift`
* `:right_alt`
* `:right_super`
keycodes. The currently supported modifiers are `t:modifier/0`.
"""

@enforce_keys [:modifier]
defstruct [:modifier]

@type modifier ::
unquote(
AFK.Scancode.modifiers()
|> Enum.map(&elem(&1, 1))
|> Enum.reverse()
|> Enum.reduce(&{:|, [], [&1, &2]})
)

@type t :: %__MODULE__{
modifier: modifier
}

@doc """
Creates a basic modifier keycode.
Expand All @@ -29,6 +32,9 @@ defmodule AFK.Keycode.Modifier do
iex> new(:right_super)
%AFK.Keycode.Modifier{modifier: :right_super}
"""
@spec new(modifier) :: t
def new(modifier)

for {_value, modifier} <- AFK.Scancode.modifiers() do
def new(unquote(modifier)), do: struct!(__MODULE__, modifier: unquote(modifier))
end
Expand Down
3 changes: 3 additions & 0 deletions lib/afk/keycode/none.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@ defmodule AFK.Keycode.None do

defstruct []

@type t :: %__MODULE__{}

@doc """
Creates a `None` keycode.
"""
@spec new :: t
def new, do: %__MODULE__{}

defimpl AFK.ApplyKeycode do
Expand Down
3 changes: 3 additions & 0 deletions lib/afk/keycode/transparent.ex
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@ defmodule AFK.Keycode.Transparent do

defstruct []

@type t :: %__MODULE__{}

@doc """
Creates a `Transparent` keycode.
"""
@spec new :: t
def new, do: %__MODULE__{}
end
7 changes: 7 additions & 0 deletions lib/afk/keymap.ex
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,16 @@ defmodule AFK.Keymap do
}
]
"""
@type layer :: %{
atom => AFK.Keycode.t()
}

@type t :: [layer]

@doc """
Loads a keymap from a file.
"""
@spec load_from_file!(binary) :: t
def load_from_file!(filename) do
filename
|> File.read!()
Expand All @@ -40,6 +46,7 @@ defmodule AFK.Keymap do
@doc """
Saves a keymap to a file.
"""
@spec save_to_file!(t, binary) :: :ok
def save_to_file!(keymap, filename) do
keymap
|> :erlang.term_to_binary()
Expand Down
Loading

0 comments on commit acf31c6

Please sign in to comment.