diff --git a/src/mpv/control.gleam b/src/mpv/control.gleam index ad5b38d..2f3f3c7 100644 --- a/src/mpv/control.gleam +++ b/src/mpv/control.gleam @@ -1,14 +1,16 @@ +import gleam/io import gleam/json import gleam/result import gleam/string import mpv/internal/control as internal_control -import mpv/key.{type Key, Char} +import mpv/key.{type Key} import tcp/reason.{type Reason} import tcp/tcp.{type Socket} pub type Control { TogglePlayPause + Exit } @@ -18,7 +20,7 @@ pub type ControlError { pub fn from_key(key: Key) -> Result(Control, Nil) { case key { - Char(char) -> char_control(char) + key.Char(char) -> char_control(char) _ -> Error(Nil) } } diff --git a/src/mpv/key.gleam b/src/mpv/key.gleam index 9ef4a1b..49a87cb 100644 --- a/src/mpv/key.gleam +++ b/src/mpv/key.gleam @@ -1,17 +1,17 @@ import gleam/erlang/atom import gleam/list - import mpv/internal/key as internal_key pub type Key { Char(String) + Input(String) Left Right Up Down - Continue + Continue(buffer: List(String)) Unknown } @@ -20,6 +20,9 @@ pub const esc = "\u{001B}" // control sequence introducer pub const csi = "[" +// input introducer +const input_introducer = "$" + pub fn from_list(l: List(String)) -> Key { case l { [e, c, "D"] if e == esc && c == csi -> Left @@ -27,12 +30,20 @@ pub fn from_list(l: List(String)) -> Key { [e, c, "A"] if e == esc && c == csi -> Up [e, c, "B"] if e == esc && c == csi -> Down - [e, c] if e == esc && c == csi -> Continue + [e, c] if e == esc && c == csi -> Continue(l) - [e] if e == esc -> Continue + [ci] | [ci, _] if ci == input_introducer -> Continue(l) + [ii, cmd, tail] if ii == input_introducer -> { + case tail == "\r" { + True -> Input(cmd) + False -> Continue([ii, cmd <> tail]) + } + } + + [e] if e == esc -> Continue(l) [char] -> Char(char) - [] -> Continue + [] -> Continue([]) _ -> Unknown } } @@ -44,10 +55,13 @@ pub fn start_raw_shell() { } pub fn read_input_until_key(l: List(String)) -> Key { - let l = internal_key.read_input() |> list.wrap |> list.append(l, _) - - case from_list(l) { - Continue -> read_input_until_key(l) + case + internal_key.read_input() + |> list.wrap + |> list.append(l, _) + |> from_list + { + Continue(l) -> read_input_until_key(l) k -> k } } diff --git a/test/mpv/key_test.gleam b/test/mpv/key_test.gleam index c291d88..247e7a3 100644 --- a/test/mpv/key_test.gleam +++ b/test/mpv/key_test.gleam @@ -12,18 +12,30 @@ type TestCase { } pub fn key_from_list_test() { - let test_cases = [ - TestCase(["c"], Char("c")), + let base_tests = [TestCase([], key.Continue([]))] + + let char_tests = [TestCase(["c"], Char("c"))] + + let escape_tests = [ + TestCase([esc, csi], key.Continue([esc, csi])), + TestCase([esc], key.Continue([esc])), + TestCase([esc, csi, "D"], key.Left), TestCase([esc, csi, "C"], key.Right), TestCase([esc, csi, "A"], key.Up), TestCase([esc, csi, "B"], key.Down), - TestCase([esc, csi], key.Continue), - TestCase([esc], key.Continue), - TestCase([], key.Continue), ] - list.each(test_cases, fn(tc) { + let input_tests = [ + TestCase(["$"], key.Continue(["$"])), + TestCase(["$", "a"], key.Continue(["$", "a"])), + TestCase(["$", "a", "b"], key.Continue(["$", "ab"])), + TestCase(["$", "ab", "\r"], key.Input("ab")), + ] + + let test_cases = [base_tests, char_tests, escape_tests, input_tests] + + list.each(list.flatten(test_cases), fn(tc) { assert tc.expected == key.from_list(tc.input) }) }