Skip to content

Latest commit

 

History

History
367 lines (260 loc) · 9.66 KB

Readme.org

File metadata and controls

367 lines (260 loc) · 9.66 KB

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

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:

  • 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(<MyComponent />);
    import React from 'react';
    export default class extends React.Component {
    import ReactDOM from 'react-dom';
        ReactDOM.render(<AnotherComponent />);
    ...
        
  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(<MyComponent />);
    import React from 'react';
    export default class extends React.Component {
    import ReactDOM from 'react-dom';
        ReactDOM.render(<AnotherComponent />);
    ...
        
  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(<MyComponent />);
    from 'react';
    .Component {
    DOM from 'react-dom';
    DOM.render(<AnotherComponent />);
    ...
        
  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(<MyComponent />) 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",|)