{"action":"created","issue":{"url":"https://api.github.com/repos/haskell/haskell-mode/issues/1133","repository_url":"https://api.github.com/repos/haskell/haskell-mode","labels_url":"https://api.github.com/repos/haskell/haskell-mode/issues/1133/labels{/name}","comments_url":"https://api.github.com/repos/haskell/haskell-mode/issues/1133/comments","events_url":"https://api.github.com/repos/haskell/haskell-mode/issues/1133/events","html_url":"https://github.com/haskell/haskell-mode/issues/1133","id":131477874,"number":1133,"title":"Implement electric comma, semicolon, etc","user":{"login":"gracjan","id":917978,"avatar_url":"https://avatars.githubusercontent.com/u/917978?v=3","gravatar_id":"","url":"https://api.github.com/users/gracjan","html_url":"https://github.com/gracjan","followers_url":"https://api.github.com/users/gracjan/followers","following_url":"https://api.github.com/users/gracjan/following{/other_user}","gists_url":"https://api.github.com/users/gracjan/gists{/gist_id}","starred_url":"https://api.github.com/users/gracjan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gracjan/subscriptions","organizations_url":"https://api.github.com/users/gracjan/orgs","repos_url":"https://api.github.com/users/gracjan/repos","events_url":"https://api.github.com/users/gracjan/events{/privacy}","received_events_url":"https://api.github.com/users/gracjan/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/haskell/haskell-mode/labels/indentation","name":"indentation","color":"bfe5bf"},{"url":"https://api.github.com/repos/haskell/haskell-mode/labels/well-defined-task","name":"well-defined-task","color":"009800"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":13,"created_at":"2016-02-04T21:22:03Z","updated_at":"2016-03-04T22:58:52Z","closed_at":null,"body":"`haskell-indentation` reacts to a couple of characters, most notably comma and semicolonbut also other chars.\r\n\r\nImplement function that can be used in `post-command-hook` that will:\r\n- [ ] check if there is exactly one character on the line\r\n- [ ] check if there is only one indentation position returned from `haskell-indentation-find-indentations`\r\n- [ ] do the indentation if both are true\r\n- [ ] connect this function to `,;` and `=|` and `)}]`\r\n\r\nMore info:\r\nhttp://www.gnu.org/software/emacs/manual/html_node/ccmode/Electric-Keys.html"},"comment":{"url":"https://api.github.com/repos/haskell/haskell-mode/issues/comments/192511836","html_url":"https://github.com/haskell/haskell-mode/issues/1133#issuecomment-192511836","issue_url":"https://api.github.com/repos/haskell/haskell-mode/issues/1133","id":192511836,"user":{"login":"fice-t","id":13156601,"avatar_url":"https://avatars.githubusercontent.com/u/13156601?v=3","gravatar_id":"","url":"https://api.github.com/users/fice-t","html_url":"https://github.com/fice-t","followers_url":"https://api.github.com/users/fice-t/followers","following_url":"https://api.github.com/users/fice-t/following{/other_user}","gists_url":"https://api.github.com/users/fice-t/gists{/gist_id}","starred_url":"https://api.github.com/users/fice-t/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/fice-t/subscriptions","organizations_url":"https://api.github.com/users/fice-t/orgs","repos_url":"https://api.github.com/users/fice-t/repos","events_url":"https://api.github.com/users/fice-t/events{/privacy}","received_events_url":"https://api.github.com/users/fice-t/received_events","type":"User","site_admin":false},"created_at":"2016-03-04T22:58:52Z","updated_at":"2016-03-04T22:58:52Z","body":"Yeah, I think so. The below does just that:\r\n\r\n```elisp\r\n\r\n(defun haskell-electric-command (char)\r\n  (let ((only-char? (string-empty-p (string-trim-left (thing-at-point 'line t))))\r\n        (electric? (if (listp haskell-use-electric-keys)\r\n                            (memq char haskell-use-electric-keys)\r\n                          haskell-use-electric-keys)))\r\n    (insert char)\r\n    (when (and only-char?\r\n               electric?\r\n               (= 1 (length (save-excursion\r\n                              (move-to-column (haskell-indentation-current-indentation))\r\n                              (haskell-indentation-find-indentations)))))\r\n      (indent-according-to-mode))))\r\n\r\n(defcustom haskell-use-electric-keys t\r\n  \"If t, various special keys will be 'electric'. If a list, only the\r\nspecial characters present in the list will be 'electric'.\"\r\n  :group 'haskell-indentation\r\n  :type '(choice boolean (repeat character)))\r\n\r\n(defmacro define-haskell-electric-keys (names)\r\n  `(progn\r\n     ,@(cl-loop for (name . char) in names\r\n                for func-name = (intern (concat \"haskell-electric-\" name))\r\n                collect `(defun ,func-name ()\r\n                           ,(format \"Automatically indent when typing '%c' when:\r\n1) There is no other character on the current line.\r\n2) There is only one possible indentation position.\r\n3) The variable `haskell-use-electric-keys' is either t or, if it's a list, '%c' is in it.\"\r\n                                    char\r\n                                    char)\r\n                           (interactive)\r\n                           (haskell-electric-command ,char))\r\n                into functions\r\n                collect `(define-key haskell-mode-map\r\n                           ,(char-to-string char) #',func-name)\r\n                into define-keys\r\n                finally (return (append functions define-keys)))))\r\n\r\n(define-haskell-electric-keys ((\"comma\" . ?,) (\"semicolon\" . ?\\;)\r\n                               (\"equals\" . ?=) (\"pipe\" . ?|)\r\n                               (\"end-paren\" . ?\\)) (\"end-brace\" . ?})\r\n                               (\"end-bracket\" . ?\\])))\r\n```\r\n\r\n`haskell-electric-command` is basically the same as the above except it handles the input of the character as well.\r\n\r\n`define-haskell-electric-keys` is a macro that both creates the `defun`s for the electric keys and their keybindings. So it will create `haskell-electric-comma` and in `haskell-mode-map` bind it to `,`, and so on."}}