{"id":20270398,"url":"https://github.com/zcaudate/eta","last_synced_at":"2025-03-03T23:12:52.821Z","repository":{"id":55555292,"uuid":"323391119","full_name":"zcaudate/eta","owner":"zcaudate","description":"multi dispatch key bindings for emacs","archived":false,"fork":false,"pushed_at":"2021-01-15T17:00:31.000Z","size":24,"stargazers_count":11,"open_issues_count":0,"forks_count":2,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-01-14T05:42:31.099Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Emacs Lisp","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zcaudate.png","metadata":{"files":{"readme":"README.org","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-12-21T16:30:57.000Z","updated_at":"2021-11-22T16:49:01.000Z","dependencies_parsed_at":"2022-08-15T03:10:23.730Z","dependency_job_id":null,"html_url":"https://github.com/zcaudate/eta","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zcaudate%2Feta","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zcaudate%2Feta/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zcaudate%2Feta/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zcaudate%2Feta/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zcaudate","download_url":"https://codeload.github.com/zcaudate/eta/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241753145,"owners_count":20014252,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-14T12:30:13.098Z","updated_at":"2025-03-03T23:12:52.774Z","avatar_url":"https://github.com/zcaudate.png","language":"Emacs Lisp","funding_links":[],"categories":[],"sub_categories":[],"readme":"#+AUTHOR:  Chris Zheng\n#+EMAIL:   z@caudate.me\n#+OPTIONS: toc:nil\n#+STARTUP: showall\n\n** Introduction\n\n[[https://github.com/zcaudate/eta][eta]] a *micro-framework* for customising key-bindings built on top of\n[[https://github.com/jwiegley/use-package/blob/master/bind-key.el][bind-key]]. It provides two macros for standardising and associating\nintent with key-bindings: a standard version ~eta-bind~ and\nmulti-dispatch version for standardisation of functionality across\nmajor modes: ~eta-modal-init~ and ~eta-modal~.\n\n** Installation\n\nInstall from Melpa:\n\n~quepa~\n#+BEGIN_SRC emacs-lisp\n(use-package eta :ensure t)\n#+END_SRC\n\n** Usage\n\nLet's see these macros in action:\n\n*** ~eta-bind~\n\n#+BEGIN_SRC emacs-lisp\n;; First argument is a [vector]\n;; [*] means cannot be overriden\n;; [] means global but can be overriden by other modes\n;; [\u003ckeymap\u003e] means bind for given mode only\n\n;; Subsequent arguments are tabular of the form\n;; - ACTION   (a tag that states what the action is)\n;; - BINDINGS (a set of key bindings bound to the intent)\n;; - IMPLEMENTATION (the actual command that performs the action)\n\n;;  ACTION          BINDINGS                    IMPLEMENTATION\n(eta-bind [*]        \n  ::no-action       ()                          'e/no-action                  ;; can be nothing\n  ::which-key       (\"C-x C-h\" \"C-x h\")         'which-key-show-major-mode    ;; allow multi\n  ::main-menu       (\"C-p\" \"M-p\" \"M-x\" \"ESC p\" \"ESC x\")   'counsel-M-x\n  ::quit            (\"ESC q\" \"M-q\")             'save-buffers-kill-terminal\n  ::help-key        (\"ESC \u003cf1\u003e\")                'helpful-key\n  ::eval-elisp      (\"ESC l\")                   'eval-last-sexp)\n#+END_SRC\n\n*** ~eta-modal~\n\nIt's easier to think of this as using multimethods for major\nmodes. ~eta-modal-init~ is akin to ~defmulti~ while ~eta-modal~ is akin\nto ~defmethod~. This allows actiovs that will be consistent across\nmajor modes.\n\nFor example the default bindings in Eclipse are ~\u003cF8\u003e~ for build and\n~\u003cF6\u003e~ for debug. ~Build~ and ~Debug~ are actions that can be reassigned\nkey-bindings. Whether one is writing ~java~, ~c++~ or any other\nlanguage, these actions are the same although the underlying\nimplementation might be very different.\n\nThis type of standardisation can now be applied to one's Emacs setup.\n\n\n#+BEGIN_SRC emacs-lisp\n;; ACTION              BINDINGS              INTERACTIVE PARAMS\n(eta-modal-init []\n  ::mode-menu          (\"\u003cf8\u003e\")              ()\n  ::eval-cursor        (\"C-e\")               (\"P\")\n  ::eval-cursor-alt    (\"C-x p\" \"C-x C-p\")   (\"P\")\n  ::eval-file          (\"C-x x\" \"C-x C-x\")   ())\n  \n;;... then later on ...\n\n;; elisp mode\n(eta-modal [::lisp   lisp-interaction-mode]\n  ::eval-cursor     'eval-last-sexp\n  ::eval-file       'e/eval-buffer\n  ::eval-cursor-alt 'pp-macroexpand-last-sexp)\n\n;; org mode\n(eta-modal [::org    org-mode]\n  ::eval-cursor     'org-ctrl-c-ctrl-c\n  ::eval-cursor-alt 'e/org-babel-tangle-block\n  ::mode-connect    'org-babel-tangle\n  ::eval-file       nil)\n\n;; elisp mode\n(eta-modal [::clojure  cider-mode]\n  ::eval-cursor     'cider-eval-last-sexp\n  ::eval-file       'cider-eval-buffer\n  ::eval-cursor-alt 'cider-macroexpand-last-sexp)\n  \n;; ... and so on ...\n#+END_SRC\n\n* Concept\n\n~eta~ provides a indirection layer between the bindings and the\nimplementation so that the intent of the user can be stated.\n\n#+BEGIN_SRC md.graph\nBINDINGS -\u003e [ACTION or INTENT] -\u003e IMPLEMENTATION\n#+END_SRC\n\nThis leads to better organisation a cleaner binding definition and\ngives the user a bit more control over where the bindings are\nplaced. It makes migrating away from older libraries much less\npainful.\n\nAnother features is the ability to have multiple keybindings for a\ngiven action. This is extremely useful in a lot of situations:\n\n- allow access to a commonly used feature at various hand positions\n- when minor modes override one binding, the feature is still\n  available via another set of shortcuts.\n\n* Similar Libraries\n\nThese are current libraries that attempt to solve the same problem:\n\n- [[https://github.com/jwiegley/use-package/blob/master/bind-key.el][Bind Key]] is the go to binding library shipped as part of\n  ~use-package~. ~eta~ is essentially offerring a more conventient\n  interface for ~bind-key~).\n- [[https://github.com/jerrypnz/major-mode-hydra.el][Major Mode Hydra]] is a multimethod for only the one action. In this\n  case, a user can define a ~major-mode-hydra~ key that brings up the\n  hydra menu for the mode.\n  - This library is backed by ~pretty-hydra~. ~pretty-hydra~ and ~eta~\n    are used extensively in [[https://github.com/zcaudate/etude/blob/master/etude/core/etude-core-lisp.el#L37-L72][etude]] for modal menus (effectively\n    emulatinig what Major Mode Hydra provides).\n\n- [[https://github.com/noctuid/general.el][General]] does something similar.\n- [[https://github.com/countvajhula/rigpa][Rigpa]] This project is quite recent, very interesting and offers a framework for the user to build around as opposed to eta's whatever goes approach.\n\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzcaudate%2Feta","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzcaudate%2Feta","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzcaudate%2Feta/lists"}