suppress additional braces in emacs electric mode - ruby

I started using ruby-electric-mode. I like it except that I am used to closing open brackets myself (the other pairing are still useful to me). How can I make emacs suppress additional brackets when I type in the closing brackets myself? I now am manually deleting the auto-magically inserted bracket every time.
Thanks in advance,
Raghu.

It sounds like what you want is for the } to either jump to the (already inserted) }, or to simply insert a } and delete the } that was inserted earlier by the electric mode.
This code should do what you want, the choice of what to do on } is toggled by the variable my-ruby-close-brace-goto-close.
;; assuming
;; (require 'ruby)
;; (require 'ruby-electric)
(defvar my-ruby-close-brace-goto-close t
"Non-nill indicates to move point to the next }, otherwise insert }
and delete the following }.")
(defun my-ruby-close-brace ()
"replacement for ruby-electric-brace for the close brace"
(interactive)
(let ((p (point)))
(if my-ruby-close-brace-goto-close
(unless (search-forward "}" nil t)
(message "No close brace found")
(insert "}"))
(insert "}")
(save-excursion (if (search-forward "}" nil t)
(delete-char -1))))))
(define-key ruby-mode-map "}" 'my-ruby-close-brace)

It is a “customizable” setting. Run M-x customize-variable (ESCx if you do not have a Meta key) and customize ruby-electric-expand-delimiters-list.
Uncheck “Everything” and check only the ones you want to be automatically inserted. Be sure to also “Save for Future Sessions”.
If you decide that you mostly like the automatic insertions but that there are some places where you want to turn it off for a single keystroke, then use C-q (Control-q) before an open paren/bracket/brace/quote to suppress the automatic insertion of the closing mark.

Ran into the same issue. The solution I found is to:
Use autopair, which does exactly what you want. Make sure you install it.
Enable ruby-electric-mode but only for | because the rest is already taken care of.
This leads to the following code in your .emacs file:
(use-package autopair
:config (autopair-global-mode)
)
(use-package ruby-electric-mode
:init
(setq ruby-electric-expand-delimiters-list (quote (124)))
)
(add-hook 'ruby-mode-hook 'ruby-electric-mode)
This code uses use-package package, make sure you installed it (M-X list-packages, then find use-package, then i on the line, then x and restart emacs).
Also, that might interest people visiting this thread. I added this code to skip closing delimiters with TAB, it helps jumping over them. Comment out the while lines (and adjust )) to have a single TAB jump over all closing delimiters (taken from emacs board discussion):
(use-package bind-key)
(defun special-tab ()
"Wrapper for tab key invocation.
If point is just before a close delimiter, skip forward until
there is no closed delimiter in front of point. Otherwise, invoke
normal tab command for current mode.
Must be bound to <tab> using bind-key* macro from bind-key package.
Note, this function will not be called if `override-global-mode' is
turned off."
(interactive)
(defun next-char-delims (delims)
(let ((char (and (not (equal (point) (point-max)))
(string (char-after (point))))))
(when char (member char delims))))
(let ((open '("'" "\"" ")" "]" "}" "|")))
(if (next-char-delims open)
(progn (forward-char 1))
;;(while (next-char-delims open)
;; (forward-char 1)))
(call-interactively (key-binding (kbd "TAB"))))))
(if (macrop 'bind-key*)
(bind-key* (kbd "<tab>") 'special-tab)
(user-error "Must have bind-key from use-package.el to use special-tab function"))
This time, you need the bind-key package for this snippet to work.

Related

Emacs: How to enable highlighting breakpoints in a text terminal (emacs -nw)

Emacs doesn't show breakpoints in text mode.
I tried integrating the suggestions here and here, but failed (I am not a lisp programmer).
I tried:
(require 'gdb-mi)
(setq default-text-properties '(foo 1111))
(defun set_breakpt_cmds ()
"set breakpoint and indicate on editor"
(interactive)
(gud-break)
(gdb-put-breakpoint-icon "false" (get-text-property 1 'foo)))
(global-set-key (kbd "<f12>") 'set_breakpt_cmds)
The resulting error is
Wrong number of arguments: (lambda (arg) "Set breakpoint at current line." (interactive "p") (if (not gud-running) (gud-call "dbstop \
at %l in %f" arg))), 0
Note: A similar issue is this (following this). However the solution there doesn't fit me because I would like to be able to call the fix from .emacs file. This way it is easier to duplicate my emacs configuration when I setup a new linux box.
Thanks
The error you get comes from the fact that gud-break expects an argument (which isn't used), so just use (gud-break 1).
The message reads as follow:
the error is of kind wrong number of arguments
when calling (lambda (arg) ...) (where we see that exactly one argument is expected)
and it was called with 0 arguments.

elisp parse output of asynchronous shell command

I have a simple elisp interactive function that I use to launch a Clojure repl.
(defun boot-repl ()
(interactive)
(shell-command "boot repl wait &"))
It opens an *Async Shell Command* buffer, and after a while the following text appears :
nREPL server started on port 59795 on host 127.0.0.1 - nrepl://127.0.0.1:59795
Implicit target dir is deprecated, please use
the target task instead. Set BOOT_EMIT_TARGET=no to disable implicit
target dir.
I would like to monitor the output of this command to be able to parse the port ("59795" in this example).
Even just the first line (in the case without warnings) would be alright.
This way I could be able to use another command to connect to the Clojure REPL waiting for me.
I cannot use shell-command-to-string as the command does not return and it blocks emacs forever (boot repl wait is supposed to last for my whole programming session, possibly more).
There may be something easy to do with cider also, but I haven't found it.
So, how do I parse the result of an asynchronous bash command in Elisp ?
Alternatively, how can I set-up Cider to launch this REPL for my and connect to it ?
To answer the question directly, you can definitely parse the output of an asyncronous shell command, using start-process and set-process-filter:
(let ((proc (start-process "find" "find" "find"
(expand-file-name "~") "-name" "*el")))
(set-process-filter proc (lambda (proc line)
(message "process output: %s" line))))
(Docs for filter function)
However, note that line above is not necessarily a line, and may include multiple lines or broken lines. Your filter is called whenever the process or emacs decides to flush some ouput:
...
/home/user/gopath/src/github.com/gongo/json-reformat/test/json-reformat-test.el
/home/user/gopath/src/github.com/gongo/json-reformat/test/test-
process output: helper.el
In your case, this could mean that your port number might be broken into two separate process-filter calls.
To fix this, we can introduce a line-buffering and line-splitting wrapper, which calls your filter for each process output line:
(defun process-filter-line-buffer (real-filter)
(let ((cum-string-sym (gensym "proc-filter-buff"))
(newline (string-to-char "\n"))
(string-indexof (lambda (string char start)
(loop for i from start below (length string)
thereis (and (eq char (aref string i))
i)))))
(set cum-string-sym "")
`(lambda (proc string)
(setf string (concat ,cum-string-sym string))
(let ((start 0) new-start)
(while (setf new-start
(funcall ,string-indexof string ,newline start))
;;does not include newline
(funcall ,real-filter proc (substring string start new-start))
(setf start (1+ new-start)));;past newline
(setf ,cum-string-sym (substring string start))))))
Then, you can safely expect your lines to be whole:
(let* ((test-output "\nREPL server started on port 59795 on host 127.0.0.1 - \nrepl://127.0.0.1:59795 Implicit target dir is deprecated, please use the target task instead. Set BOOT_EMIT_TARGET=no to disable implicit target dir.")
(proc (start-process "echo-test" "echo-test" "echo" test-output)))
(set-process-filter proc (process-filter-line-buffer
(lambda (proc line)
(when (string-match
"REPL server started on port \\([0-9]+\\)"
line)
(let ((port (match-string 1 line)))
;;take whatever action here with PORT
(message "port found: %s" port)))))))
Finally, I'm not familiar with cider but this kind of low-level work probably belongs in an inferior-type mode and has probably already been solved.
shell-command
allows to name optional output- and error-buffers. Than the error should appear inside the latter and not clutter the output any more.
A better answer to the other one I provided is to simply use cider as you suggested:
(progn
(package-refresh-contents)
(package-install 'cider)
(cider-jack-in))

How can I test an interactive function in emacs?

I'm the maintainer of an Emacs package whose entire purpose is related to user interaction. Whenever I make a change to the code, I have to test it out manually to see if it works. It would be nice if I could do some automated testing, but I have no idea how to simulate user input in the way that would be required to do so. Is there any way to run an interactive function that will prompt the user and then respond to that prompt with simulated typing (including key combinations like C-j)?
New: I have reimplemented my with-simulated-input macro using execute-kbd-macro, so it now works in batch mode as well. You can view the new implementation here.
Original answer:
I found the answer in a question on the Emacs SX site. Basically, you have to put the desired sequence of keys into unread-command-events after converting it to the proper format. For example:
(let ((unread-command-events (listify-key-sequence (kbd "blu RET"))))
(ido-completing-read "Select a color: " '("yellow" "blue")))
Properly returns "blue".
One thing to be careful about is that you have to make sure that your key sequence will definitely terminate the interactive part of the command, or else the command will continue waiting for input. One way to ensure termination is to append "C-g" to the key sequence, which will abort the command if it hasn't finished by the time it gets to the end of the key sequence. If the command does finish, then any unused input will be discarded when the let-binding goes out of scope, so the C-g event will not signal an error. So a more proper test might be:
;; Runs successfully
(condition-case nil
(let ((unread-command-events (listify-key-sequence (kbd "blu RET C-g"))))
(ido-completing-read "Select a color: " '("yellow" "blue")))
(quit (error "Reached end of `unread-command-events' without terminating")))
;; Throws an error
(condition-case nil
(let ((unread-command-events (listify-key-sequence (kbd "blu C-g"))))
(ido-completing-read "Select a color: " '("yellow" "blue")))
(quit (error "Reached end of `unread-command-events' without terminating")))
An important caveat to this approach is that despite allowing you to run an interactive function completely non-interactively, it will not work in a batch-mode emacs session, presumably because emacs doesn't process keyboard input at all in batch mode.
You can make use of execute-kbd-macro and ERT. I have a very simple implementation in my test file.
The tests actually look very neat - almost as if I was pressing the keys interactively:
(ert-deftest ivy-read ()
(should (equal
(ivy-with '(ivy-read "pattern: " '("blue" "yellow"))
"C-m")
"blue"))
(should (equal
(ivy-with '(ivy-read "pattern: " '("blue" "yellow"))
"y C-m")
"yellow"))
(should (equal
(ivy-with '(ivy-read "pattern: " '("blue" "yellow"))
"y DEL b C-m")
"blue"))
(should (equal
(ivy-with '(ivy-read "pattern: " '("blue" "yellow"))
"z C-m")
"z")))

Use z (jump around) in Emacs to find directories

Z is a popular shell tool for jumping around commonly used directories. It uses "frecency" as a metric for determining which directory you intend to jump to based on keyword completions. So if I commonly cd to ~/.ssh, I can z ssh to jump there.
My question is how can I get the same functionality to work inside Emacs? That is, I want to be able to use ido-find-file or something similar but only have to type a few characters to jump to the directory I intended. Hopefully the solution can incorporate z itself so it makes use of the frecency metric already recorded by z.
I used z once but then I found fasd, which is inspired by autojump, z or v, and which I found much more powerful, if I remember well it is because:
it not only finds directories but also files
it can cd a result or use mplayer or your editor or another command
the completion is better, specially for zsh (again, if I remember well). The thing is, I constantly use the d alias to change directories.
Anyway, there's an emacs package to find files with it: https://github.com/steckerhalter/emacs-fasd
That's cool, but it isn't as interactive as I would like.
edit: then I had to update the package and:
(setq fasd-enable-initial-prompt nil) ;; don't ask for first query but fire fuzzy completion straight away.
There's a still a use case that isn't filled:
How to use fasd (or autojump or z) with completion in an emacs shell ?
I often use emacs' shell-mode. When I use my favorite alias d, it works, but I don't have completion at all. Here, zsh's completion is clearly missing. So I would like to use ido completion, for instance. I wrote a little function which you can easily adapt for z:
edit: finished the command and added ido completion triggered by TAB. Now type d (d followed by a space). If it keeps changing and if I manage to create a minor mode I'll post the link to my gitlab repo.
edit: I created a mode for this feature: https://gitlab.com/emacs-stuff/fasd-shell/tree/master
;; Use the fasd command line utility to change recently visited directories and more.
(defun fasd-get-path-list (pattern)
"call fasd with pattern and return the list of possibilities"
(s-split "\n" (s-trim (shell-command-to-string (format "fasd -l -R %s" pattern))))
)
(defun fasd ()
"If current shell command is `d something' call fasd"
(interactive)
(let* ((user-input (buffer-substring-no-properties (comint-line-beginning-position)
(point-max))))
(if (and (string= (substring user-input 0 2) "d ")) ;; todo: mapping to use something else than d and change directory.
(progn
;; get what is after "d "
(setq fasd-pattern (buffer-substring-no-properties (+ (comint-line-beginning-position) 2) (point-max)))
(setq fasd-command (concat "cd " (ido-completing-read "cd to: " (fasd-get-path-list fasd-pattern))))
(comint-kill-input)
(insert fasd-command)
(comint-send-input)
))))
;; Use TAB as in normal shell. Now we have even better completion than in zsh !
(define-key shell-mode-map (kbd "<tab>") 'fasd) ;; works like a charm :)
As a side note, I don't use it very often because I open shells in the directory of the current buffer with shell-here and shell-pop (a drop-down terminal like guake for gnome).
Within a project, I find projectile (Projectile) mode to be really helpful.
I use the standard keybindings C-p f or M-x projectile-find-file.
It does fuzzy matching on filenames and filters on recently used files.

Emacs equivalent to VIM's `%`?

In VIM, One can use % to indicate the current filename when invoking a shell command. Can Anyone point Me in the direction of documentation showing what the equivalent is in emacs?
There isn't one. But this is Emacs! So here:
(defun my-shell-command-on-current-file (command &optional output-buffer error-buffer)
"Run a shell command on the current file (or marked dired files).
In the shell command, the file(s) will be substituted wherever a '%' is."
(interactive (list (read-from-minibuffer "Shell command: "
nil nil nil 'shell-command-history)
current-prefix-arg
shell-command-default-error-buffer))
(cond ((buffer-file-name)
(setq command (replace-regexp-in-string "%" (buffer-file-name) command nil t)))
((and (equal major-mode 'dired-mode) (save-excursion (dired-move-to-filename)))
(setq command (replace-regexp-in-string "%" (mapconcat 'identity (dired-get-marked-files) " ") command nil t))))
(shell-command command output-buffer error-buffer))
(global-set-key (kbd "M-!") 'my-shell-command-on-current-file)
You can use this whenever the minibuffer expects you to type something (caveat: does not work with ido, but obviously you can always get out of that with e.g. C-x C-f). You can also use it in regular buffers.
(defun insert-filename-or-buffername (&optional arg)
"If the buffer has a file, insert the base name of that file.
Otherwise insert the buffer name. With prefix argument, insert the full file name."
(interactive "P")
(let* ((buffer (window-buffer (minibuffer-selected-window)))
(file-path-maybe (buffer-file-name buffer)))
(insert (if file-path-maybe
(if arg
file-path-maybe
(file-name-nondirectory file-path-maybe))
(buffer-name buffer)))))
(define-key minibuffer-local-map (kbd "C-c f") 'insert-filename-or-buffername)
in my case, using the emacs 24 gui version from homebrew.... I see the filename as the 3rd item in from the bottom left corner of the (minor)-mode-bar, just above the mini-buffer.
To see where i am, using ido-mode i just do C-x C-f No config needed there.

Resources