Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/zk-phi/git-complete

Yet another completion engine powered by "git grep"
https://github.com/zk-phi/git-complete

emacs

Last synced: about 2 months ago
JSON representation

Yet another completion engine powered by "git grep"

Awesome Lists containing this project

README

        

* git-complete.el

Yet another completion engine powered by =git grep=

=git grep= を使った補完エンジン

** Description

=git-complete= provides an interactive command which, when invoked,
scans the current git project with =git grep= and suggests what you
may want to insert.

[[screencast.gif]]

=git-complete= CAN:

- complete *not just a symbol but the whole idiom* if appropreate,
unlike other completion engines (rather like snippet engines)

- be used as an "omni (smart) completion" engine, i.e. =git-complete=
tries to suggest expressions you may want to insert next, according
to the context, *even when you don't remember it*, by grepping your
project (class methods after a class name, typical argument for a
function, for examples)

- be used with *no per-language configurations or dictionaries*,
unlike snippet engines or omni-completion engines

=git-complete= CAN'T:

- complete expressions which has not been used in the git project yet

- start completion automatically, since it's a bit time-consuming to
grep over the project (especially for the first invokation)

- be 100% accurate, since =git-complete= has no knowledge about the
language you are coding in

EXTRA FEATURES:

- "autopair"
- =git-complete= (optionally) tries to keep the parentheses balanced
by inserting or merging some parens if appropreate

- DWIM newline insertion
- =git-complete= tries to insert newline after completion if you may
want so

*** See also:

The =git grep= idea is taken from =auto-programming.el= by hitode909.

https://github.com/hitode909/emacs-auto-programming

- Atom version: =atom-auto-programming= by the author of
=auto-programming.el=
- https://github.com/hitode909/atom-auto-programming

- Vim version: =vim-auto-programming= by haya14busa
- https://github.com/haya14busa/vim-auto-programming

** Quickstart
*** Installation

#+begin_src emacs-lisp
(require 'git-complete)
#+end_src

and (optionally) bind some keys.

#+begin_src emacs-lisp
(global-set-key (kbd "C-c C-c") 'git-complete)
#+end_src

You may also invoke git-complete with =M-x git-complete=.

Note that you also need to install =git= if it's not installed yet.

*** Examples

(Consider "|" as the cursor in following examples)

- after a part of a package name:

#+begin_src perl
SHA|
#+end_src

git-complete completes the import statement.

#+begin_src perl
use Digest::SHA;
|
#+end_src

- after a constructor:

#+begin_src javascript
var foo = moment().|
#+end_src

git-complete suggests method names frequently used in your project.

#+begin_src javascript
var foo = moment().format(|
#+end_src

and =M-x git-complete= (again) suggests typical arguments to the
method frequently used in your project.

#+begin_src javascript
var foo = moment().format("YYYY-MM-DD HH:mm:ss"|
#+end_src

- after a newline:

#+begin_src perl
use strict;
|
#+end_src

suggests next line which usually follows the line =use strict;= in
your project.

#+begin_src perl
use strict;
use warnings;
|
#+end_src

** Customizations

- =git-complete-enable-autopair= : either git-complete should keep the
parenthesis balance during completion

- =git-complete-ignore-case= : either to use =--ignore-case= option or
not when git grepping

- =git-complete-grep-function= : function used to grep over the
repo. git-complete by default uses =git grep= but you may tell
git-complete to use =rg= instead by setting this variable to
='git-complete-ripgrep=

See "How it works" section for the options below:

- =git-complete-threshold=
- =git-complete-whole-line-completion-threshold=
- =git-complete-next-line-completion-threshold=
- =git-complete-repeat-completion=

** How it works

There are three methods to collect completions:

- whole current-line completion
- omni current-line completion
- omni next-line completion

User is prompted to select one of the completions, and the selected
completion is inserted to the buffer in different ways according to
its type.

*** Completion collection
**** Whole current-line completion

example:

: React| * consider | as the cursor

1. Collect lines with "React" in your git repo, by =git grep=-ing with
"React"

: $ git grep -F -h "React"
: import React from 'react';
: export default class extends React.Component {
: export default class extends React.Component {
: import React from 'react';
: export default class extends React.Component {
: import React from 'react';
: import ReactDOM from 'react-dom';
: export default class extends React.Component {
: ReactDOM.render();
: import React from 'react';
: export default class extends React.Component {
: import ReactDOM from 'react-dom';
: ReactDOM.render();
: ...

2. If some identical lines appear "frequently" (as defined by
=git-complete-whole-line-completion-threshold=), they are added to
the completions list, as "whole-line" completions.

: | | frequency | type |
: +-------------------------------------------------+-----------+------------|
: | export default class extends React.Component{\n | 60% | whole-line |
: | import React from 'react';\n | 30% | whole-line |
: | ... | ... | ... |

**** Omni current-line completion

example:

: React| * consider | as the cursor

1. Collect lines with "React" in your git repo, by =git grep=-ing with
"React"

: $ git grep -F -h "React"
: import React from 'react';
: export default class extends React.Component {
: export default class extends React.Component {
: import React from 'react';
: export default class extends React.Component {
: import React from 'react';
: import ReactDOM from 'react-dom';
: export default class extends React.Component {
: ReactDOM.render();
: import React from 'react';
: export default class extends React.Component {
: import ReactDOM from 'react-dom';
: ReactDOM.render();
: ...

2. Trim each lines found in 1. as follows:

- Find the query string ("React" in this case) inside the line and
remove characters before the query and the query itself.

- If the line has more close parens than open parens, remove
characters after the innermost matching close paren.

: from 'react';
: .Component {
: .Component {
: from 'react';
: .Component {
: from 'react';
: DOM from 'react-dom';
: .Component {
: DOM.render();
: from 'react';
: .Component {
: DOM from 'react-dom';
: DOM.render();
: ...

3. If some identical idioms appear "frequently" (as defined in
=git-complete-threshold=) at the beginning of the lines, add the
idioms to the completions list as "omni" completions.

: | | frequency | type |
: +-------------------------+-----------+------|
: | .Component {\n | 60% | omni |
: | from 'react';\n | 30% | omni |
: | DOM from 'react-dom';\n | 5% | omni |
: | DOM.render(< | 5% | omni |
: | ... | ... | ... |

Note that =DOM.render(<= is added to the list but
=DOM.render()= is not, since it does not appear
"frequently".

4. If no completions are found, shorten the query by one subword
(configurable via =git-cmopletion-omni-completion-type=) from the
beginning and =git grep= again, then back to the step 3. .

example:

: var foo = bar(MyClass.|

The query =var foo = bar(MyClass.= is too specific to find some
"frequent" idioms, thus shortened to =foo = bar(MyClass.=,
=bar(MyClass.= then =MyClass.= which may give some "frequent"
idioms: method names of the class =MyClass=.

When the query is shortened, all completions will be type of
"omni", since the step 2. is skipped.

**** Omni next-line completion

example:

: use strict;
: |

1. Collect lines next to =use strict;= in your git repo, by grepping
with =use strict;=

: > git grep -F -h -A1 "use strict;"
: use strict;
: sub foo {
: --
: use strict;
: use warnings;
: --
: use strict;
: use warnings;
: --
: use strict;
: sub bar {
: --
: use strict;
: use utf8;
: --
: ...

2. Find identical lines as like the step 2. of "Whole current-line
completion", according to
=git-complete-next-line-completion-threshold=

: | | frequency | type |
: +-----------------+-----------+------|
: | use warnings;\n | 80% | omni |
: | use utf8;\n | 20% | omni |
: | ... | ... | ... |

3. If no completions are found, shorten the query and repeat like the
step 3 of "Omni current-line completion".

*** Completion insertion
**** Whole-line completion

example:

: React|

when you select a "whole-line" completion like below:

: export default class extends React.Component {\n

then

1. Delete all characters in the current line

: |

2. Insert the completion

: export default class extends React.Component {
: |

3. Add some close parens as needed (if "autopair" feature is not disabled)

: export default class extends React.Component {
: |
: }

**** Omni completion

example:

: var foo = moment().format|

when you select a "omni" completion like below:

: ("YYYY-MM-DD HH:mm:ss",

then

1. Insert the completion after the cursor

: var foo = moment().format("YYYY-MM-DD HH:mm:ss",|

2. Add some close parens as needed (if "autopair" feature is not
disabled) after the cursor

: var foo = moment().format("YYYY-MM-DD HH:mm:ss",|)