ctrl+shift+p filters: :st2 :st3 :win :osx :linux
Browse

Auto​Aligner

Sublime Text plugin for automatic code alignment.

Details

Installs

  • Total 30K
  • Win 18K
  • OS X 6K
  • Linux 5K
Jul 16 Jul 15 Jul 14 Jul 13 Jul 12 Jul 11 Jul 10 Jul 9 Jul 8 Jul 7 Jul 6 Jul 5 Jul 4 Jul 3 Jul 2 Jul 1 Jun 30 Jun 29 Jun 28 Jun 27 Jun 26 Jun 25 Jun 24 Jun 23 Jun 22 Jun 21 Jun 20 Jun 19 Jun 18 Jun 17 Jun 16 Jun 15 Jun 14 Jun 13 Jun 12 Jun 11 Jun 10 Jun 9 Jun 8 Jun 7 Jun 6 Jun 5 Jun 4 Jun 3 Jun 2 Jun 1
Windows 15 11 14 17 15 15 12 16 3 10 9 13 17 13 12 7 4 12 24 21 10 12 5 5 13 21 18 18 18 9 3 13 13 15 8 6 3 5 12 11 11 7 23 7 7 13
OS X 5 2 0 1 3 1 1 1 2 2 3 3 3 5 1 4 2 3 5 1 1 5 1 1 2 2 2 4 3 2 4 9 2 3 3 3 1 2 6 1 2 3 2 2 1 2
Linux 1 1 3 3 5 6 0 3 0 1 1 2 4 0 6 1 2 1 3 1 8 2 0 5 2 2 1 2 2 2 0 1 7 2 5 2 1 2 4 1 3 5 6 4 0 2

Readme

Source
raw.​githubusercontent.​com

Aligner Build Status

Sublime Text plugin for automatic code alignment.

This project is a tool for automatic code alignment. Formatting source code so that similar syntactic structures are arranged one above the other is often used to improve readability.

First of all, for convenience, the lines of code are split into tokens having a generic type. For example, the identifiers have type :id, and the brackets have type :bracket. The project implemented a type hierarchy, which simplifies the setup. It is defined in heirarchy.rb.

Each type must match the regular expression that recognizes token of this type. Moreover, the sequence of regular expressions must follow the hierarchy. That is more general regular expressions are used later. This sequence is described in the class TypeData, the file staff.rb.

To achieve maximum flexibility and independence of the type of language in which the source code is written, parser of the context-free grammars is implemented.

It works in conjunction with the algorithm based on dynamic programming, which finds matching having a maximum weight of two arrays of tokens.

The grammar in BNF is in file grammar.rb. Grammar should be designed so that if the rule of convolution can be applied, it should be applied, otherwise any sequence of tokens should still be correct.

Here is the example of grammar:

@@grammar.add_rule(:main, [:expr    ], [:reducible]);
@@grammar.add_rule(:expr, [:expr, :p], [:reducible]);
@@grammar.add_rule(:expr, [:p       ], [:reducible]);
t1 = [:expr, TokenTemplate.new(['=']), :expr]
@@grammar.add_rule(:expr, t1)
@@grammar.add_rule(:p, [:t], [:reducible])
@@grammar.add_rule(:t, [TokenTemplate.new(:id)], [:reducible]);

This grammar defines the assignment operation. The first argument to the procedure of adding rules - nonterminal. :main - axiom of the grammar. The second argument is the rule itself. It may consist of nonterminals and templates of tokens. A template can define a valid token type, a specific value, and excluded values.

Grammar shown corresponds to the following recorded in the canonical Backus–Naur form:

main ::= expr
expr ::= expr p | p | expr '=' expr
p    ::= t
t    ::= <any identifier>

Flag :reducible indicates that this rule has no effect on meta-expression being fitted. Meta-expression is an array of tokens, which also contains other meta-expression. Each level of the obtained tree structure is compared in the matching process only with the corresponding level of the other meta-expression. Consider the example: “ f(a, b + c ) f( b + c, a)

and

f(a , b + c) f(b + c, a )

When using the grammar, the program causes the alignment of the second type,
in spite of the fact that different function arguments are similar in spelling.
Such behavior is, of course, leads to improvement of readability.

To maximize the quality for each language you need to write its own grammar.

## Examples of work

From

@@types_inheritance[:space] = nil; @@types_inheritance[:quote] = nil; @@types_inheritance[:regexp] = nil; @@types_inheritance[:id] = nil; @@types_inheritance[:spchar] = nil;

To

@@types_inheritance[:space ] = nil; @@types_inheritance[:quote ] = nil; @@types_inheritance[:regexp] = nil; @@types_inheritance[:id ] = nil; @@types_inheritance[:spchar] = nil;

---

From

switch (state)
{
case State.QLD: city = "Brisbane”; break; case State.WA: city = “Perth”; break;
case State.NSW: city = “Sydney”; break;
default: city = “???”; break;
}

To

switch (state)
{ case State.QLD:city = “Brisbane”; break; case State.WA :city = “Perth” ; break; case State.NSW:city = “Sydney” ; break; default :city = “???” ; break; }

##Learning

Due to the fact that different people are accustomed to different ways of setting padding between tokens,
you must use the simplest method of fine-tuning.
The project implements a method of learning. The input is properly formatted string.
The resulting information is aggregated and used in the future for proper indenting.

There are 2 types of training: minimum and maximum indents.

Training starts with the command `ruby learner_test.rb <lang_type>`.
It is not required by default.
The resulting information is stored in files `max_by_type_<lang_type>.dat` and `min_by_type_<lang_type>.dat`.

##Installation

First of all, make sure that your system has a ruby interpreter `ver. >= 1.9`.
In Ubuntu you can use following command:

sudo apt-get install ruby

To install the plugin, clone it to your Siblime Text 2/3 Package directory with following command:

cd ~/.config/sublime-text-3/Packages git clone https://github.com/generall/aligner.git AutoAligner

Or you may install it with Package Control using name `AutoAligner`.

Default hotkey for alignment is: `["ctrl+k","ctrl+a"]`.

##Prospection

Here is a list of things that have to be improved.

* Automatic detection of similar lines for fully automated code alignment.
* Customization for different languages.
    * extended grammar
    * extended set of types of token
    * Customized languages:
        * C
        * java
* Extended machine learning for alignment decision
    * experiments with Markov chain learing
* to be continued...

## The expected course of action to add the grammar.

In file `staff.rb` add new regexp array by following pattern:

@@regexp_array[:new_grammar_name] = [ # [, , , , , ] [/'(.|['])*'/ , :quote , true , 0.1, 0, 1], … ]

Add BNF to file `grammar.rb`.