== RefactorErl Console Interface == After start up you can use the ri module to interact easily with the tool. With this you can add files/directories to the database, run semantic queries, create backups, or even do transformations. == General help == Help can be acquired in ri with {{{ ri:help(). }}} or even shorter as {{{ ri:h(). }}} This function lists several topics, on which further help is available as {{{ ri:h(Topic). }}} If the name of a function is known, specic help can be acquired by adding an _h postfix to the name. For example, help for the function add is available as {{{ ri:add_h() }}} == Compiling the tool == The tool can be recompiled by invoking {{{ ri:build(). }}} This function can also take a list of build parameters. This feature is mostly used through development. Note that this function tries to compile the C++ files as well, if these were not compiled before. So if you want to prevent this, then you have to specify the no_nif additional parameter to the function. So in this case the recompilation looks like this: {{{ ri:build(no_nif). }}} == Managing files == You can add files to the RefactorErl database by calling the add function with either a filename as a string or a module name as an atom. Note that in the latter case, "ri" defaults to the current working directory (which you may work around by including a path in your singe-quoted atom). If you specify a directory instead of a regular filename, then it will be recursively traversed. You may just as well give a list of atoms or strings to add more files at once. All of the following example commands would add the same le: {{{ cd(dir), ri:add(modname). ri:add('dir/modname'). ri:add(['dir/modname']). ri:add("dir/modname.erl"). ri:add("/current/dir/modname.erl"). }}} The module displays the progression of loading. Removing files from the database is similarly easy and also recursive, except for one difference. As the system by the time you want to remove a module must know the exact location of the said, you need not restrict yourself to dropping a module relative to the current directory, but must in exchange use real module names that do not contain path delimiters. The following will equally work: {{{ ri:drop(modname). ri:drop([modname]). ri:drop("dir/modname.erl"). ri:drop("/current/dir/modname.erl"). }}} Modules can be loaded as applications, but the base of your library has to be set before: {{{ ri:addenv(appbase, "path/to/my/applib"). }}} You can check the already given application base directories: {{{ ri:envs(). }}} Let's see an example: {{{ (refactorerl@localhost)18> ri:envs(). output = original appbase = "/usr/local/lib/erlang/lib" (refactorerl@localhost)19> ri:add(usr, synatx_tools). Application synatx_tools not found under usr not_found (refactorerl@localhost)20> ri:add(usr, syntax_tools). Adding: /usr/local/lib/erlang/lib/syntax_tools-1.6.7.1/src ... }}} You can also set include directories to your include files using: {{{ ri:addenv(include, "path/to/my/include"). }}} It is possible to delete the defined environment variables: {{{ ri:delenv(include). }}} Loaded files can be saved using {{{ ri:save(Filename). }}} For convenience, both the filenames and the directory names can be given as atoms as well as strings. The list of loaded files can be obtained by calling {{{ ri:ls(). }}} This call also displays the status of the loaded files (error or no_error). If the module m is loaded, {{{ ri:ls(m). }}} will give information about the functions, records and macros in the file. The contents of a file can be listed by {{{ ri:cat(m). }}} Loading BEAM files. Usually, Erlang source files (having the extension .erl) are loaded into RefactorErl. In addition, RefactorErl is also capable of loading compiled .beam files. {{{ ri:add("compiled.beam"). }}} Note that this feature is applicable only to those .beam files that were compiled with the debug_info option. Also note that the resulting file will be pretty printed by RefactorErl. == Using transformations == Transformations can be called using their abbreviated names, and the list of required parameters. These commands are listed in [[RefactoringSteps|refactoring functionalities]]. There is another way to call a transormation. This way let the user to choose: user want to specify all of arguments or not. There are lots of cases when the user can not specify all of the required arguments. In this case the tool can help the user with interactions. The tool ask questions and the user has to answer it to specify the missing arguments. The interactions also work if there is some problem with the given arguments. == Manipulating the graph == You can reset RefactorErl by invoking {{{ ri:reset(). }}} This will remove all loaded files. This function should be called if the graph gets corrupted. You can add a checkpoint using {{{ ri:backup(). }}} If the transformations you have performed are not satisfactory, you can go back to the previous checkpoint using {{{ ri:undo(). }}} If you use NIF, then it is little different:[[BR]] You can create backups with '''ri:backup/0''' or '''ri:backup/1''' and you can load these backups with '''ri:restore/1'''. When execute a transformation a backup will be created, which name differs from the ordinary backups, and the '''ri:undo/0''' function will restore that. == Inspecting the graph == You can draw the semantic representation graph of RefactorErl by calling {{{ ri:graph(). }}} This function produces a .dot file (by default, graph.dot, although this can be customised), which can be transformed to several visual formats using Graphviz. One of these transformations is available from RefactorErl for convenience: {{{ ri:svg(). }}} The representation can be ltered: {{{ ri:svg(OutFile, Filter). }}} where Filter is one of the following:[[BR]] all: default, all edges except environmental ones are shown syn: only syntactic edges are shown sem: only semantic edges are shown lex: only lexical edges are shown all_env: all edges are shown, no ltering ctx: context related edges are shown not_lex: all edges except lexical ones are shown dataflow: dataflow related edges are shown a list of the above: shows the union of the designated subgraphs == Using queries == Queries 6 can be invoked by either {{{ ri:q(Query). }}} or {{{ ri:q(Module, Regexp, Query). }}} The former is applicable when a query starts generally, such as {{{ ri:q("mods.funs.name"). }}} For those queries that begin from a selected position (these queries start with "@" when used from Emacs), the second variant is required. As the console cannot mark a position, the first and the second component indicate the starting point for the query. The following example shows how to get all the variables used in the body of the function f/2 from the module m. {{{ ri:q(m, "f\\\\(X, Y\\\\)", "@fun.var"). }}} Additional options can be given to a semantic query in a proplist as the last argument. The following arguments are currently recognized: {out,FileName} - write the textual output of a query to a file linenum - prepends match sites with le and line number information similar to grep -n. The following example outputs all dened functions with line numbers to a file named result.txt. {{{ ri:q("mods.funs",[linenum,{out,"result.txt"}]). }}}