Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement a 'generate getter/setter' for a Java Class in emacs?

Tags:

java

emacs

Sometimes I miss the laziness of using an IDE that let me just write the attribute of a Java class and then let the IDE generate the required getter/setter.

Can Emacs do this?

Currently I just copy paste a pair of getter/setter form the previous line, and then copy paste and modify it. It's simple, but yet, make coding a little bit funnier :)

like image 442
swdev Avatar asked Feb 14 '11 08:02

swdev


2 Answers

You asked specifically about generating a getter/setter pair. And you can write elisp to do this. But it may be interesting to look into a more general solution.

To solve this generally, I use ya-snippet . The name refers to "Yet Another Snippet package", so you can be sure the problem has been solved before. But I found ya-snippet to be the most useful, simple, and capable solution, for my needs.

For a property with a getter/setter, I type

prop<TAB>

...and I get a template that I can then fill in, like a form. I specify the name of the property, and everything else is generated. Very nice, easy.

enter image description here

This works for any micro-pattern you commonly use in code. I have snippets for a singleton, constructor, for loops, switch statements, try/catch, and so on.

The key with ya-snippet is there is no elisp code to write. Basically I just provide the text for the template, and it works. This is the ya-snippet code for the getter/setter snippet you see above:

# name : getter/setter property ... { ... }
# key: prop
# --
private ${1:Type} _${2:Name};
public ${1:Type} get$2 {
    ${3://get impl}
}
public void set$2($1 value) {
    ${4://set impl}
}

Everything above the "# --" is metadata for the snip. The "key" is the most important bit of that metadata - it is the short sequence that can be expanded. The name is shown on the yasnippet menu. The stuff below the # -- line is the expansion code. It includes several fill-in fields.

YAsnippet works for any programming mode in emacs (java, php, c#, python, etc) and it works for other text modes too.

like image 200
Cheeso Avatar answered Sep 20 '22 18:09

Cheeso


I'm using yasnippet as well, but this is a better snippet, imho:

# -*- mode: snippet -*-
# name: property
# key: r
# --
private ${1:T} ${2:value};
public $1 get${2:$(capitalize text)}() { return $2; }
public void set${2:$(capitalize text)}($1 $2) { this.$2 = $2; }
 $0

This code, for instance is generated in 10 keystrokes (r, C-o, Long, C-o, id, C-o):

private Long id;
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }

I recommend binding yas/expand to C-o and not TAB to avoid clashes with e.g. auto-complete. I have this setup:

(global-set-key "\C-o" 'open-line-or-yas)
(defun open-line-or-yas ()
  (interactive)
  (cond ((and (looking-back " ") (looking-at "[\s\n}]+"))
     (insert "\n\n")
     (indent-according-to-mode)
     (previous-line)
     (indent-according-to-mode))
    ((expand-abbrev))
    (t 
     (setq *yas-invokation-point* (point))
     (yas/next-field-or-maybe-expand-1))))
(defun yas/next-field-or-maybe-expand-1 ()
  (interactive)
  (let ((yas/fallback-behavior 'return-nil))
    (unless (yas/expand)
      (yas/next-field))))

Note (expand-abbrev) somewhere inside this code. It allows me to expand e.g. bis to BufferedInputStream when I define:

(define-abbrev-table 'java-mode-abbrev-table
  '(
    ("bb" "ByteBuffer" nil 1)
    ("bis" "BufferedInputStream" nil 1)
    %...
))
like image 26
abo-abo Avatar answered Sep 20 '22 18:09

abo-abo