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"
DWIM newline insertion
*** 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=
Vim version: =vim-auto-programming= by haya14busa
** Quickstart *** Installation
(require 'git-complete)
and (optionally) bind some keys.
(global-set-key (kbd "C-c C-c") 'git-complete)
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:
SHA|
git-complete completes the import statement.
use Digest::SHA; |
after a constructor:
var foo = moment().|
git-complete suggests method names frequently used in your project.
var foo = moment().format(|
and =M-x git-complete= (again) suggests typical arguments to the method frequently used in your project.
var foo = moment().format("YYYY-MM-DD HH:mm:ss"|
after a newline:
use strict; |
suggests next line which usually follows the line =use strict;= in your project.
use strict; use warnings; |
** 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:
** How it works
There are three methods to collect completions:
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
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(
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
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(
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(
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(
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; : |
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; : -- : ...
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 | : | ... | ... | ... |
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
Delete all characters in the current line
: |
Insert the completion
: export default class extends React.Component { : |
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
Insert the completion after the cursor
: var foo = moment().format("YYYY-MM-DD HH:mm:ss",|
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",|)