Emacs ruby symbol word completion - ruby

Quite often I define a ruby symbol (eg. :some_value), then I want to create a method with the same name def some_value.
Unfortunately, the autocompletion(M + /) for the second occurrence of some_value string does not work, being slightly different (:some_value vs some_value).
How can I setup emacs to handle such events?

Assuming that M-/ is bound to dabbrev-expand, you can configure dabbrev-mode to ignore certain prefixes when expanding strings. To make a single colon a prefix to be ignored, type
M-x customize-group
and then
dabbrev
This will take you to the customization page for dabbrev-mode. Go to the point Dabbrev Abbrev Skip Leading Regexp and click on Value menu. From the menu, pick "Regexp".
Now you see a textfield labeled "Regexp: " next to the value menu in which you enter a single colon.
:
Then click on the button State in the next line and choose the value "Save for Future Sessions".

First, my results! I typed :some_crazy_symbol in my model. On a newline, I typed def so, hit M-/ twice, and ended up with
def some_crazy_symbol
end
(Rinari supplied the end.)
I got this to work quite well by using hippie-expand. If you want to test it out, bind hippie-expand to M-/ like so:
(global-set-key (kbd "M-/") 'hippie-expand)
Heres' the documentation. Hippie expand works by trying out a number of different expansions on the current point. These expansions are stored in the hippie-expand-try-functions-list variable. On my system (and be default), this variable is set to:
(try-complete-file-name-partially try-complete-file-name try-expand-all-abbrevs try-expand-list try-expand-line try-expand-dabbrev try-expand-dabbrev-all-buffers try-expand-dabbrev-from-kill try-complete-lisp-symbol-partially try-complete-lisp-symbol)
The minibuffer readout showed that this particular expansion was accomplished using the try-expand-dabbrev function.

Not a direct answer to your question, but you should get more intelligent Ruby autocompletion by using auto complete mode paired with rsense.

If Dabbrev Abbrev Skip Leading Regexp and hippie-expand doesn't do exactly what you want and you've got some elisp skills, you could create a custom function for hippie-expand.
See the section about "substring expansion" on the hippie-expand page on the emacs-wiki. There's a function you could use there you could tailor to customize..
Substring Expansion
When doing lisp programming standard dabbrev is less useful, because Emacs has no namespaces, so in a package symbols begin with the same prefix, therefore the same prefix has to be typed again and again if one wants to complete symbols from the package. As with IswitchBuffers it is much more effective if a unique substring can be typed to get to the desired symbol.
Dabbrev offers nothing in this regard, so I turned to Hippie Expand which I had never used before.
Here’s a function based on hippie expand dabbrev expansion which performs substring expansion:
(defun try-my-dabbrev-substring (old)
(let ((old-fun (symbol-function 'he-dabbrev-search)))
(fset 'he-dabbrev-search (symbol-function 'my-dabbrev-substring-search))
(unwind-protect
(try-expand-dabbrev old)
(fset 'he-dabbrev-search old-fun))))
(defun my-dabbrev-substring-search (pattern &optional reverse limit)
(let ((result ())
(regpat (cond ((not hippie-expand-dabbrev-as-symbol)
(concat (regexp-quote pattern) "\\sw+"))
((eq (char-syntax (aref pattern 0)) ?_)
(concat (regexp-quote pattern) "\\(\\sw\\|\\s_\\)+"))
(t
(concat (regexp-quote pattern)
"\\(\\sw\\|\\s_\\)+")))))
(while (and (not result)
(if reverse
(re-search-backward regpat limit t)
(re-search-forward regpat limit t)))
(setq result (buffer-substring-no-properties (save-excursion
(goto-char (match-beginning 0))
(skip-syntax-backward "w_")
(point))
(match-end 0)))
(if (he-string-member result he-tried-table t)
(setq result nil))) ; ignore if bad prefix or already in table
result))

I figured I'd share the solution I came up with that works for hippie-expand.
To summarize:
(defun hippie-expand-ruby-symbols (orig-fun &rest args)
(if (eq major-mode 'ruby-mode)
(let ((table (make-syntax-table ruby-mode-syntax-table)))
(modify-syntax-entry ?: "." table)
(with-syntax-table table (apply orig-fun args)))
(apply orig-fun args)))
(advice-add 'hippie-expand :around #'hippie-expand-ruby-symbols)
hippie-expand will expand symbols in ruby-mode when : is considered a punctuation character, so this advice creates a temporary syntax table where : is a punctuation character and calls hippie-expand with it.

Related

More macro woes

I am still having some troubles with this concept. The key paragraph in the r7rs standard is:
"Identifiers that appear in the template but are not pattern
variables or the identifier ellipsis are inserted into the output as literal identifiers. If a literal identifier is inserted as a
free identifier then it refers to the binding of that identifier
within whose scope the instance of syntax-rules appears.
If a literal identifier is inserted as a bound identifier then
it is in effect renamed to prevent inadvertent captures of
free identifiers."
By "bound identifier" am I right that it means any argument to a lambda, a top-level define or a syntax definition ie. define-syntax, let-syntax or let-rec-syntax? (I think I could handle internal defines with a trick at compile time converting them to lambdas.)
By "free identifier" does it mean any other identifier that presumably is defined beforehand with a "bound identifier" expression?
I wonder about the output of code like this:
(define x 42)
(define-syntax double syntax-rules ()
((_) ((lambda () (+ x x)))))
(set! x 3)
(double)
Should the result be 84 or 6?
What about this:
(define x 42)
(define-syntax double syntax-rules ()
((_) ((lambda () (+ x x)))))
(define (proc)
(define x 3)
(double))
(proc)
Am I right to suppose that since define-syntax occurs at top-level, all its free references refer to top-level variables that may or may not exist at the point of definition. So to avoid collisions with local variables at the point of use, we should rename the outputted free reference, say append a '%' to the name (and disallow the user to create symbols with % in them). As well as duplicate the reference to the top-level variable, this time with the % added.
If a macro is defined in some form of nested scope (with let-syntax or let-rec-syntax) this is even trickier if it refers to scoped variables. When there is a use of the macro it will have to expand these references to their form at point of definition of the macro rather than point of use. So I'm guessing the best way is expand it naturally and scan the result for lambdas, if it finds one, rename its arguments at point of definition, as the r7rs suggests. But what about references internal to this lambda, should we change these as well? This seems obvious but was not explicitly stated in the standard.
Also I'm still not sure whether it is best to have a separate expansion phase separate from the compiler, or to interweave expanding macros with compiling code.
Thanks, and excuse me if I've missed something obviously, relatively new to this.
Steve
In your first example, properly written:
(define x 42)
(define-syntax double
(syntax-rules ()
( (_) ((lambda () (+ x x))) ) ))
(set! x 3)
(double)
the only possibility is 6 as there is only one variable called x.
In your second example, properly written:
(define x 42)
(define-syntax double
(syntax-rules ()
((_) ((lambda () (+ x x))) )))
(define (proc)
(define x 3)
(double))
(proc)
the hygienic nature of the Scheme macro system prevents capture of the unrelated local x, so the result is 84.
In general, identifiers (like your x) within syntax-rules refer to what they lexically refer to (the global x in your case). And that binding will be preserved because of hygiene. Because of hygiene you do not have to worry about unintended capture.
Thanks, I think I understand... I still wonder how in certain advanced circumstances hygiene is achieved, eg. the following:
(define (myproc x)
(let-syntax ((double (syntax-rules ()
((double) (+ x x)))))
((lambda (x) (double)) 3)))
(myproc 42)
The site comes up with 84 rather than 6. I wonder how this (correct) referential transparency is achieved just by renaming. The transformer output does not bind new variables, yet still when it expands on line 4, we have to find a way to get to the desired x rather than the most recent.
The best way I can think of is simply rename every time a lambda argument or definition shadows another, ie. keep appending %1, %2 etc... macro outputs will have their exact versions named (eg. x%1) while references to identifiers simply have their unadorned name x and the correct variable is found at compile time.
Thanks, I hope for any clarification.
Steve

Can syntax parameters be used to replace syntax?

I'm trying to use syntax parameters in order to inject new syntax where I need it to be injected. The result of this is then used in other syntax.
However, it's not working as I expect it to. Here's a minimal working example:
(require racket/stxparam)
(require (for-syntax racket/stxparam))
;; declare parameter to be replaced with code
(define-syntax-parameter placeholder
(lambda (stx)
(raise-syntax-error
(syntax-e stx)
"can only be used inside declare-many-commands")))
;; this is just to print what 'arg' looks like
(define-syntax (print-syntax stx)
(syntax-case stx ()
[(_ arg)
#'(displayln 'arg)]))
;; this is the top-level entity invoked to produce many commands
(define-syntax-rule (declare-many-commands cmds)
(begin
(let ([X 10])
(syntax-parameterize
([placeholder (make-rename-transformer #'X)])
cmds))
(let ([X 20])
(syntax-parameterize
([placeholder (make-rename-transformer #'X)])
cmds))))
(declare-many-commands
(print-syntax placeholder))
What I would like to get as result when running this is:
10
20
but what I get is:
placeholder
placeholder
EDIT:
Posted a new question to refine the problem: Injecting syntax at compile time using Racket's syntax parameters?
The problem here is that your print-syntax macro quotes its input, and inputs to macro transformers are unexpanded syntax. This means that the expansion of (print-syntax placeholder) will always be (displayln 'placeholder), and no macroexpansion ever occurs under quote, so the placeholder binding in scope is irrelevant.
If you want to use the syntax parameter, you need to actually produce a reference to the placeholder binding. In this case, you just need to remove the use of quote. You could change print-syntax to (displayln arg), but at that point, there’s really no reason for print-syntax to be a macro, since it’s equivalent to the displayln function. Just use that instead:
(declare-many-commands
(displayln placeholder))
This will print 10 and 20 as you expect.
It’s possible you really do want the quote, and I don’t understand your question. In that case, though, I think it’s difficult for me to understand what you’re getting at without some additional context.

How to turn off standard osx text editing bindings in emacs on OSX

I want to not have any standard osx text editing bindings available in emacs anymore. I'm using standard gnu emacs. leaving only the "old school" emacs commands. In other words: no more command+c for copy, no command+z for undo, etc. Is there some way to do this without explicitly rebinding each key combination? I tried googling for a way to do this but did not find anything.
These key bindings are defined here, in ns-win.el.
There seems to be no simple way to unbind all of them. You could copy all of those key bindings from ns-win.el into the scratch buffer. They look like this:
(define-key global-map [?\s-,] 'customize)
Then hit C-M-% for query-replace-regexp, type ^(define-key global-map \(.*\) '.*)$ as the search expression and (global-unset-key \1) as the replacement, turning those key bindings into:
(global-unset-key [?\s-,])
Then, select them all and type M-x eval-region.
In Emacs in OS X, the default setup is that the CMD key is bound to the SUPER qualifier, and the a number of keys like S-x, S-c, and S-v are bound to commands to minic the normal OS functions. The OPTION key is bound to META. Unfortunately, the basic setup doesn't allow you to type characters that normally would require the OPTION key, like "|" and "\".
The following will bind CMD to meta and make OPTION available for normal character composition.
(if (boundp 'ns-command-modifier)
(setq ns-command-modifier 'meta))
(if (boundp 'ns-option-modifier)
(setq ns-option-modifier nil))
The keybindings I find objectionable are the bindings to SUPER aka command. To disable these binding, though not all the NS bindings made:
File global-unset-all-super-key.el:
(defun global-unset-all-super-key ()
"Will unset any single key in global keymap that has the super
modifier."
(let ((km (current-global-map)))
(while km
(let ((maybe-event (and (listp (car km))
(caar km))))
(if (and (eventp maybe-event) ; Also filters maybe-event when
; nil because (car km) was not a list.
(memq 'super (event-modifiers maybe-event)))
(global-unset-key (vector maybe-event))))
(setq km (cdr km)))))
(provide 'global-unset-all-super-key)
Place global-unset-all-super-key.el in the Emacs lisp load path and add the following to init.el or .emacs:
;; Remove default super bindings on Mac systems.
;; Do this early, before any mappings are added.
(when (string-equal system-type "darwin")
(require 'global-unset-all-super-key)
(global-unset-all-super-key))

Dereference variable inside list

Is it possible to dereference a variable contained inside a list, to obtain its value? For example:
(define one 1)
(define two 2)
(define list '(one two))
(display (list-ref list 0))
Here list-ref references to one, and display shows one in letters. Could instead one dereference to the value contained by the homonym variable?
Eval can definitely solve this problem... but like most situations where eval is applicable, it's a large and dangerous hammer.
Matthew Flatt's blog post on this topic has become the go-to explanation:
http://blog.racket-lang.org/2011/10/on-eval-in-dynamic-languages-generally.html
Here's how you might do it without eval in Racket. Stripping away the cruft, "dict-ref" can find a named
element (or elements) in an "association list".
#lang racket
(define data
'((one 1)
(two 2)))
(define wanted-list '(two one))
;; evaluates to '((2) (1)):
(for/list ([wanted wanted-list])
(dict-ref data wanted))
That's happening because the quoted list contains two symbols, one and two. Try the following:
(display (eval (list-ref list 0)))
To resolve that symbol.

Converting this untabify on-save hook for emacs to work with espresso-mode (or all modes)

I found this snippet to add to my .emacs that will, on save, strip out tabs and replace them with spaces (to help my files play nicely with everyone else on the team who uses spaces).
Unfortunately, my lisp and emacs lisp chops are not very strong. It seems to be this snippet will work only for the java major mode - how can I get this to work with espresso-mode?
(defun java-mode-untabify ()
(save-excursion
(goto-char (point-min))
(while (re-search-forward "[ \t]+$" nil t)
(delete-region (match-beginning 0) (match-end 0)))
(goto-char (point-min))
(if (search-forward "\t" nil t)
(untabify (1- (point)) (point-max))))
nil)
(add-hook 'java-mode-hook
(lambda ()
(add-hook 'write-contents-hooks 'java-mode-untabify nil 'local)))
I have following code in my .emacs that works for me:
;; untabify some modes
(setq alexott/untabify-modes '(haskell-mode emacs-lisp-mode lisp-mode scheme-mode
erlang-mode clojure-mode))
(defun alexott/untabify-hook ()
(when (member major-mode alexott/untabify-modes)
(untabify (point-min) (point-max))))
(add-hook 'before-save-hook 'alexott/untabify-hook)
you can add espresso-mode into list of modes, for which untabify will perfomed, by changing list in alexott/untabify-modes variable following way:
(setq alexott/untabify-modes '(haskell-mode emacs-lisp-mode lisp-mode scheme-mode
erlang-mode clojure-mode espresso-mode))
The snippet you have here will work for any text file. There isn't anything Java specific about it besides the fact that it is named java-mode-untabify. The only thing you should need to do is duplicate that add-hook call and change the hook name to espresso-mode-hook, or whatever the correct hook is for espresso-mode. Although I might suggest you change the name of the function to something that reflects the fact that it is not Java specific. Something like cleanup-whitespace-in-buffer, or whatever you like.
(defun cleanup-whitespace-in-buffer () ; <- more appropriate name
(save-excursion
(goto-char (point-min))
(while (re-search-forward "[ \t]+$" nil t)
(delete-region (match-beginning 0) (match-end 0)))
(goto-char (point-min))
(if (search-forward "\t" nil t)
(untabify (1- (point)) (point-max))))
nil)
(add-hook 'espresso-mode-hook ; <- you can actually add this to any hook
(lambda ()
(add-hook 'write-contents-hooks 'cleanup-whitespace-in-buffer nil 'local)))
CAVEAT:
I just modified the snippet you posted. I'm not on a machine with Emacs right now, so I haven't tested any of this.
The cleanup-whitespace-in-buffer function simply deletes any trailing whitespace from every line in the file, then converts non-trailing tabs into spaces. The call to add-hook creates an anonymous function (a lambda) that will be called whenever the hook is run. This anonymous function arranges for cleanup-whitespace-in-buffer to be run in a buffer before it is saved.
I really like Alex Ott's answer a lot better since it is much more flexible. It sets up a function that is run whenever ANY buffer is saved. It checks to see if the buffer being saved has a mode that is in the list of specified modes and, if so, untabifies the buffer before saving. It doesn't remove trailing white space, but you could easily change the (untabify (point-min) (point-max)) call into (cleanup-whitespace-in-buffer) if you want that behavior. This allows you to easily add other modes that will have their files preprocessed before saving. It even works if, for some reason, your mode doesn't have a hook associated with it. His method is better than what I suggested. I simply posted this answer in the interests of clarifying how your snippet works since you said you feel a little week in Emacs Lisp.

Resources