How I can use tabs instead spaces for emacs ruby-mode? - ruby

I try to use tabs instead spaces in emacs with ruby-mode, but I can't do it. There is my fragment from my emacs dot-file
(setq-default indent-tabs-mode t)
(setq-default tab-width 2)
but it doesn't works, I guess this have trouble by reason ruby-mode. And how I can fix it?
sorry for my bad English

I don't write Ruby code, so don't know about the ruby-mode in particular. But it seems that you need to wrap your setting by a hook to the ruby-mode. How about trying this?
(add-hook 'ruby-mode-hook
(lambda ()
(setq indent-tabs-mode t)
(setq tab-width 2)))

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.

Why is it that these prog-mode keybindings aren't working in emacs-lisp-mode?

I have a couple lines in my Emacs setup:
;; swap defaults
(define-key prog-mode-map (kbd "RET") 'newline-and-indent)
(define-key prog-mode-map (kbd "C-j") 'newline)
This works as expected in the couple of other programming modes that I tried. But in the Emacs Lisp mode, RET was still bound to newline and C-j was still bound to newline-and-indent. I still observed this confusing behavior even after moving the keybinding code to the very beginning of my Emacs initialization. If I create separate keybinding statements for Emacs Lisp's mode, I don't have any problems.
;; swap defaults for most programming modes
(define-key prog-mode-map (kbd "RET") 'newline-and-indent)
(define-key prog-mode-map (kbd "C-j") 'newline)
;; swap defaults in Emacs Lisp mode too
(define-key emacs-lisp-mode-map (kbd "RET") 'newline-and-indent)
(define-key emacs-lisp-mode-map (kbd "C-j") 'newline)
Why is this? If it matters, I'm using Emacs 24.3 on OS X 10.8.3.
P.S. I recently learned about electric-indent-mode, which probably accomplishes something very similar to these keybindings. However, the mystery still stands.
Look at the definition of emacs-lisp-mode-map in lisp-modes.el:
(defvar emacs-lisp-mode-map
(let ((map (make-sparse-keymap "Emacs-Lisp"))
(menu-map (make-sparse-keymap "Emacs-Lisp"))
(lint-map (make-sparse-keymap))
(prof-map (make-sparse-keymap))
(tracing-map (make-sparse-keymap)))
(set-keymap-parent map lisp-mode-shared-map)
…
map))
The key is the set-keymap-parent call. Though Emacs Lisp Mode inherits from Prog Mode, its keymap does not inherit from prog-mode-map, but from another keymap defined in lisp-modes.el:
(defvar lisp-mode-shared-map
(let ((map (make-sparse-keymap)))
(define-key map "\e\C-q" 'indent-sexp)
(define-key map "\177" 'backward-delete-char-untabify)
map)
"Keymap for commands shared by all sorts of Lisp modes.")
This keymap also does not inherit from prog-mode-map, so bindings in prog-mode-map do indeed not have any effect in Emacs Lisp Mode.
This is arguably a bug in Emacs.
Update: I wrote to the mailing list.
Update 2: The corresponding bug report
Update 3: The bug has been fixed. In a current snapshot build your key bindings should work as expected. As a work around for earlier builds of Emacs you can use the following snippet in your init.el:
(unless (keymap-parent lisp-mode-shared-map)
(set-keymap-parent lisp-mode-shared-map prog-mode-map))
Now lisp-mode-shared-map will inherit from prog-mode-map, effectively replicating the bug fix.

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.

Setting mode through a function in Emacs Lisp

I have the following code in my .emacs file, which works as you'd expect:
;; Ruby
(global-font-lock-mode 1)
(autoload 'ruby-mode "ruby-mode" "Ruby editing mode." t)
(setq auto-mode-alist (cons '("\\.rb$" . ruby-mode) auto-mode-alist))
(setq auto-mode-alist (cons '("\\.rsel$" . ruby-mode) auto-mode-alist))
(setq auto-mode-alist (cons '("\\.rhtml$" . html-mode) auto-mode-alist))
(setq auto-mode-alist (cons '("\\.erb$" . html-mode) auto-mode-alist))
(setq auto-mode-alist (cons '("\\.prawn$" . html-mode) auto-mode-alist))
(setq auto-mode-alist (cons '("Rakefile$" . ruby-mode) auto-mode-alist))
However, my attempts to DRY it up a bit fail:
(defun set-mode-for-filename-patterns (mode filename-pattern-list)
(mapcar
(lambda (filename-pattern)
(setq
auto-mode-alist
(cons '(filename-pattern . mode) auto-mode-alist)))
filename-pattern-list))
;; Ruby
(global-font-lock-mode 1)
(autoload 'ruby-mode "ruby-mode" "Ruby editing mode." t)
(set-mode-for-filename-patterns
ruby-mode
'("\\.rb$"
"\\.rsel$"
"\\.rhtml$"
"\\.erb$"
"\\.prawn$"
"Rakefile$"
"Gemfile$"))
... with the following error:
Debugger entered--Lisp error: (void-variable ruby-mode)
(set-mode-for-filename-patterns ruby-mode (quote ("\\.rb$" "\\.rsel$" "\\.rhtml$" "\\.erb$" "\\.prawn$" "Rakefile$" "Gemfile$")))
eval-buffer(#<buffer *load*> nil "/home/duncan/.emacs" nil t) ; Reading at buffer position 1768
load-with-code-conversion("/home/duncan/.emacs" "/home/duncan/.emacs" t t)
load("~/.emacs" t t)
#[nil "\205\264
I'm a bit confused here ... in particular, I don't understand how ruby-mode is void & so can't be passed to a function, but can be consed into a pair?
Any pointers (heh) would be greatly appreciated.
In the form:
(cons '("\\.rb$" . ruby-mode) ...
ruby-mode is part of a quoted list. That means it is read as a symbol name, not evaluated as a variable. In other words, Emacs sees it as the symbol ruby-mode and accepts it as is.
In the form:
(set-mode-for-filename-patterns
ruby-mode
'("\\.rb$"
"\\.rsel$"
...
ruby-mode is not quoted, and so is read as the argument to a function. Function arguments are evaluated. Which means Emacs reads ruby-mode, recognizes it as a symbol, and tries to evaluate it. Evaluating a symbol means looking for the value that it points to, which in this case doesn't exist.
EDIT:
Your function still doesn't work, there's another problem. You've used a quoted list inside set-mode-for-filename-patterns. This works fine in your original code:
(setq auto-mode-alist (cons '("\\.rb$" . ruby-mode) auto-mode-alist))
as you are in effect manually supplying the value for filename-pattern and mode. Inside your function, you need these symbols to be evaluated, which doesn't happen when they're quoted! The result is that instead of adding each different string from your list to auto-mode-alist, you get the symbol filename-pattern instead.
To fix this, you need to recognize that the '(filename-pattern . mode) is meant to produce a cons cell with the values of filename-pattern and mode. Which we can produce with (cons filename-pattern mode). So the corrected function would be:
(defun set-mode-for-filename-patterns (mode filename-pattern-list)
(mapcar
(lambda (filename-pattern)
(setq
auto-mode-alist
(cons (cons filename-pattern mode) auto-mode-alist)))
filename-pattern-list))
And the corrected function call is:
(set-mode-for-filename-patterns
'ruby-mode
'("\\.rb$"
"\\.rsel$"
"\\.rhtml$"
"\\.erb$"
"\\.prawn$"
"Rakefile$"
"Gemfile$"))
Look here:
(setq auto-mode-alist (cons '("\\.rb$" . ruby-mode) auto-mode-alist))
----------------------------^
This is a quote which means you prevent the evaluation of the next
form, thus '("\\.rb$" . ruby-mode) is equivalent to (cons '"hello"
'ruby-mode).
But when you call the function set-mode-for-filename-patterns the
arguments are first evaluate then their result is passed to the
function. That's why evaluation (set-mode-for-filename-patterns
ruby-mode ..) raise an error, because the emacs-lisp interpreter tries
to evaluate ruby-mode as a variable, but ruby-mode has no value in
this context hence the error (void-variable ruby-mode). What you
want here, is to pass the symbol ruby-mode so you have to quote it
like this (set-mode-for-filename-patterns 'ruby-mode ...)
Note that you could have set a value to ruby-mode mode with let.
(let ((ruby-mode 'ruby-mode))
(set-mode-for-filename-patterns ruby-mode ...))
Here when the argument the form (set-...) is evaluated it evaluates
ruby-mode and can find a value for it (which is the symbol
ruby-mode) and then pass it to the function.
I think set-mode-for-filename-patterns is an interesting function. I'm going to add it to my config but use a more optimized implementation.
The implementations here all add one item to the auto-mode-alist variable for each file suffix. Emacs searches this list every time it finds a file. So the shorter the auto-mode-alist, the faster Emacs will find files.
This version is probably slower at startup but faster when finding files:
(defun set-mode-for-filename-patterns (mode filename-pattern-list)
(push (cons (regexp-opt filename-pattern-list) mode)
auto-mode-alist))`
This will work with the the same call:
(set-mode-for-filename-patterns
'ruby-mode
'("\\.rb$"
"\\.rsel$"
"\\.rhtml$"
"\\.erb$"
"\\.prawn$"
"Rakefile$"
"Gemfile$"))
If you look at the value of auto-mode-alist you'll see that many of the built-in modes use regexps for the same performance reason.
BTW, I advise that you just trust regexp-opt to do the right thing. The regexps it makes are pretty hard on the eye (and brain).

suppress additional braces in emacs electric mode

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.

Resources