Refactor keymap to allow showing help
This commit is contained in:
parent
0acbca2e62
commit
18c0f6ea7a
copret/src
|
@ -10,19 +10,37 @@ enum SlideAction:
|
|||
case Next
|
||||
case QuickNext
|
||||
case Quit
|
||||
case Help
|
||||
case Interactive(cmd: Vector[String], wd: Path)
|
||||
case Other(code: List[Int])
|
||||
|
||||
def show: String = this match
|
||||
case Start => "go to first slide"
|
||||
case Goto(slideIndex: Int) => s"jump directly to slide $slideIndex"
|
||||
case GotoSelect => "jump to slide"
|
||||
case Prev => "previous slide (skip animations)"
|
||||
case Next => "next slide"
|
||||
case QuickNext => "next slide (skip animations)"
|
||||
case Quit => "quit"
|
||||
case Help => "show help"
|
||||
case Interactive(cmd: Vector[String], wd: Path) => s"execute command \"${cmd.mkString(" ")}\""
|
||||
case Other(code: List[Int]) => s"Unknown key sequence: $code"
|
||||
|
||||
|
||||
object SlideAction:
|
||||
def runForeground(cmd: String*)(implicit wd: Path) = Interactive(cmd.toVector, wd)
|
||||
|
||||
import SlideAction.*
|
||||
|
||||
case class Keymap(bindings: Map[List[Int], SlideAction]):
|
||||
def apply(keycode: List[Int]): SlideAction = bindings.getOrElse(keycode, Other(keycode))
|
||||
case class Keymap(bindings: Map[Key, SlideAction]):
|
||||
private val lookup = bindings.map((k,v) => k.codes -> v)
|
||||
def apply(keycode: List[Int]): SlideAction = lookup.getOrElse(keycode, Other(keycode))
|
||||
|
||||
def extend(newBindings: Map[Key, SlideAction]) = Keymap(bindings ++ newBindings)
|
||||
def ++(newBindings: Map[Key, SlideAction]) = extend(newBindings)
|
||||
def help: String =
|
||||
bindings.toSeq.sortBy(_._2.toString).map((k,v) => k.show.padTo(8, ' ') + " " + v.show).mkString("\n")
|
||||
|
||||
def extend(newBindings: Map[List[Int], SlideAction]) = Keymap(bindings ++ newBindings)
|
||||
def ++(newBindings: Map[List[Int], SlideAction]) = Keymap(bindings ++ newBindings)
|
||||
object Keymap:
|
||||
val empty = Keymap(Map())
|
||||
val default = Keymap(Map(
|
||||
|
@ -30,53 +48,71 @@ object Keymap:
|
|||
Key.Left -> Prev,
|
||||
Key.PageUp -> Prev,
|
||||
Key('k') -> Prev,
|
||||
Key(' ') -> Next,
|
||||
Key.Space -> Next,
|
||||
Key('j') -> Next,
|
||||
Key.Down -> QuickNext,
|
||||
Key.Right -> QuickNext,
|
||||
Key.PageDown -> QuickNext,
|
||||
Key('q') -> Quit,
|
||||
Key('g') -> Start,
|
||||
Key.Enter -> Start,
|
||||
Key('s') -> GotoSelect,
|
||||
Key('?') -> Help,
|
||||
))
|
||||
|
||||
enum Key:
|
||||
case Code(name: String, codepoints: List[Int])
|
||||
case Printable(char: Char)
|
||||
|
||||
def codes: List[Int] =
|
||||
this match
|
||||
case Code(_, cp) => cp
|
||||
case Printable(char) => List(char.toInt)
|
||||
|
||||
def show: String =
|
||||
this match
|
||||
case Code(name, _) => name
|
||||
case Printable(c) => c.toString
|
||||
|
||||
object Key:
|
||||
def apply(char: Char): Key = Printable(char)
|
||||
def apply(name: String, codepoints: Int*): Key = Code(name, codepoints.toList)
|
||||
object codes:
|
||||
val Esc = 27
|
||||
val Backspace = 127
|
||||
val Esc = List[Int](codes.Esc)
|
||||
val Backspace = List[Int](codes.Backspace)
|
||||
val Delete = List[Int](codes.Esc, '[', '3', '~')
|
||||
val esc = 27
|
||||
val backspace = 127
|
||||
|
||||
val PageUp = List[Int](codes.Esc, '[', '5', '~')
|
||||
val PageDown = List[Int](codes.Esc, '[', '6', '~')
|
||||
val Esc = Key("Escape", codes.esc)
|
||||
val Backspace = Key("Backspace", codes.backspace)
|
||||
val Delete = Key("Delete", codes.esc, '[', '3', '~')
|
||||
|
||||
val Home = List[Int](codes.Esc, '[', 'H')
|
||||
val End = List[Int](codes.Esc, '[', 'F')
|
||||
val PageUp = Key("PageUp", codes.esc, '[', '5', '~')
|
||||
val PageDown = Key("PageDown", codes.esc, '[', '6', '~')
|
||||
|
||||
val F1 = List[Int](codes.Esc, 'P')
|
||||
val F2 = List[Int](codes.Esc, 'Q')
|
||||
val F3 = List[Int](codes.Esc, 'R')
|
||||
val F4 = List[Int](codes.Esc, 'S')
|
||||
val Home = Key("Home", codes.esc, '[', 'H')
|
||||
val End = Key("End", codes.esc, '[', 'F')
|
||||
|
||||
val F5 = List[Int](codes.Esc, '1', '5', '~')
|
||||
val F6 = List[Int](codes.Esc, '1', '7', '~')
|
||||
val F7 = List[Int](codes.Esc, '1', '8', '~')
|
||||
val F8 = List[Int](codes.Esc, '1', '9', '~')
|
||||
val F1 = Key("F1", codes.esc, 'P')
|
||||
val F2 = Key("F2", codes.esc, 'Q')
|
||||
val F3 = Key("F3", codes.esc, 'R')
|
||||
val F4 = Key("F4", codes.esc, 'S')
|
||||
|
||||
val F9 = List[Int](codes.Esc, '2', '0', '~')
|
||||
val F10 = List[Int](codes.Esc, '2', '1', '~')
|
||||
val F11 = List[Int](codes.Esc, '2', '3', '~')
|
||||
val F12 = List[Int](codes.Esc, '2', '4', '~')
|
||||
val F5 = Key("F5", codes.esc, '1', '5', '~')
|
||||
val F6 = Key("F6", codes.esc, '1', '7', '~')
|
||||
val F7 = Key("F7", codes.esc, '1', '8', '~')
|
||||
val F8 = Key("F8", codes.esc, '1', '9', '~')
|
||||
|
||||
val Tab = List[Int]('\t')
|
||||
val F9 = Key("F9", codes.esc, '2', '0', '~')
|
||||
val F10 = Key("F10", codes.esc, '2', '1', '~')
|
||||
val F11 = Key("F11", codes.esc, '2', '3', '~')
|
||||
val F12 = Key("F12", codes.esc, '2', '4', '~')
|
||||
|
||||
val Up = List[Int](codes.Esc, '[', 'A')
|
||||
val Down = List[Int](codes.Esc, '[', 'B')
|
||||
val Right = List[Int](codes.Esc, '[', 'C')
|
||||
val Left = List[Int](codes.Esc, '[', 'D')
|
||||
val Space = Key("<space>", ' ')
|
||||
val Tab = Key("<tab>", '\t')
|
||||
val Enter = Key("<enter>", '\n')
|
||||
|
||||
def apply(char: Char): List[Int] = List(char.toInt)
|
||||
val Up = Key("Up", codes.esc, '[', 'A')
|
||||
val Down = Key("Down", codes.esc, '[', 'B')
|
||||
val Right = Key("Right", codes.esc, '[', 'C')
|
||||
val Left = Key("Left", codes.esc, '[', 'D')
|
||||
|
||||
/* vim:set tw=120: */
|
||||
|
|
|
@ -10,14 +10,14 @@ case class Presentation(slides: Vector[Slide], meta: Map[String, String] = Map.e
|
|||
run()
|
||||
|
||||
import Presentation._
|
||||
def run()(using Keymap) =
|
||||
def run()(using keymap: Keymap) =
|
||||
import SlideAction.*
|
||||
@annotation.tailrec def rec(p: Presentation, pos: Int, action: SlideAction): Unit =
|
||||
action match
|
||||
case Start =>
|
||||
executeSlide(p, pos)()
|
||||
rec(p, 0, waitkey)
|
||||
case Next | Other(_) =>
|
||||
case Next =>
|
||||
if pos + 1 < p.slides.size then
|
||||
executeSlide(p, pos + 1)()
|
||||
rec(p, pos + 1, waitkey)
|
||||
|
@ -55,6 +55,15 @@ case class Presentation(slides: Vector[Slide], meta: Map[String, String] = Map.e
|
|||
target match
|
||||
case Some(i) => rec(p, pos, Goto(i))
|
||||
case None => rec(p, pos - 1, QuickNext)
|
||||
case Help =>
|
||||
Terminal.clear()
|
||||
println(keymap.help)
|
||||
waitkey
|
||||
rec(p, pos - 1, QuickNext)
|
||||
case Other(codes) =>
|
||||
Terminal.cursorTo(Terminal.height, 1)
|
||||
println(action.show)
|
||||
rec(p, pos, waitkey)
|
||||
case Quit =>
|
||||
()
|
||||
rec(this, 0, Start)
|
||||
|
|
Loading…
Reference in a new issue