Version 9 (modified by manualwiki, 12 years ago) (diff) |
---|
Scriptable RefactorErl interface
ris is similar to ri, with the following basic ideas:
- results are always returned via the function return value.
- no mandatory standard output.
- function arguments are as general as possible and may contain semantic queries (which are evaluated first).
- you can also input a semantic query via atoms instead of strings to ease escaping.
- operations are composable (i.e., continue one where another has left off) - queries and refactorings can go back and forth.
- you can perform a series of batch refactorings in a single step by selecting multiple entities at once.
File manipulations
% Here an entity is returned, which can be used later. Added = ris:add_byname("path/to/mymod.erl"). ... % Readd the file. ReAdded = ris:add(Added).
It is possible to drop files from the database:
ris:drop('mods[name==mymod]'). % or % 'Added' is the previous entity. ris:drop(Added).
Refactorings
Transformations are listed in refactoring functionalities. Here is the list of transformations that you can use via this interface:
- eliminate/1: Eliminates the given variable(s). (eliminate variable).
- extfun/2, extract/2: This is the extract function transformation.
- inline/1: Inlines the given function(s), or macro(s). (inline function, inline macro).
% Move every unexported function to another_module and move it back: ris:move( ris:move("mods[name=='mymod'] .fun[exported==false]", "other_mod"), "mymod").
- rename/2: Renames variable, function, record, record field, macro, header file or module file.
ris:rename("mods[name=='mymod'].fun[name=='Colour']", "Color").
Operators
The result of the queries can be combined with the following set operators:
- intersect: The following example takes the intersection of the files included by the two modules.
ris:q({"mods[name==mod1].includes", intersect, "mods[name==mod2].includes"}).
- union: The union set operation. (Example: same as above, just substitute 'intersect' with 'union')
- minus: The substraction set operation. (Example: same as above, just substitute 'intersect' with 'minus')
- Sequence: Queries can be sequenced to continue a query from where another has left off. The execution works on arbitrarily long starting and continuation sequences (i.e., not just a single element). The following examples are correct, and can be used from ris:
% Language elements can be written via atoms or via strings. The dot is optional. ris:q([mods, funs]). ris:q([mods, .funs]). ris:q(["mods", "funs"]). % Filters can be sequenced. ris:q(['mods', '[name==a]']). % Statistics can be sequenced. ris:q(['mods', '.fun', '.arity', ':sum']). ris:q(["mods", "funs", "arity", ":avg"]).
Sequences can be constructed not only between queries parts, but between a basic ris command and query parts, too. This example first adds the module from file 'mymodule.erl'. The add call returns the entities loaded. A semantic query aggregate of a list works by executing the first query (or in this case, specifying a starting entity), and then running the next query in the chain (in this case getting the name of files included by the add call).
ris:q([ris:add_byname("mymodule.erl"),".includes.name"]).
Textual display
Use ris:show/1 to stringify entities. ris:show/2 does the same while accepting additional options already known for ri:q/3. Use the respective ris:print/1 and ris:print/2 functions for screen and file output.
ris:print(ris:q("mods.fun")).
The following gives the same result set, but written to the given file and annotated with line numbers. (Note that you could also manually write the output of ris:show/1 to a file.)
ris:print(ris:q("mods.fun"), [{out,"funs.txt"}, linenum]).