davidvarga / MBeautifier

MBeautifier is a MATLAB source code formatter, beautifier. It can be used directly in the MATLAB Editor and it is configurable.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Add option to run without opening the MATLAB editor

cszczepaniak opened this issue · comments

I use this as part of a pre-commit git hook and also sometimes in large batches of files, so it would be nice to have the option of passing in a filename and have the formatter run without opening the editor for performance reasons. A couple of possibilities for the calling syntax:

An optional parameter:
MBeautify.formatFile('someFile.m', 'someFile.m', 'UseEditor', false);

An optional positional argument:
MBeautify.formatFile('someFile.m', 'someFile.m', '--no-editor');

A new method:
MBeautify.formatFileSilently('someFile.m', 'someFile.m');

This feature would be awesome! Then I could integrate it in my CI pipeline.

The only problem is that I am using the smart indent feature provided by the undocumented API of the MATLAB Editor. I don't know if there was a way to use the underlying implementation without opening the Editor physically.

Personally I did not find one which does not mean that there isn't any (on other issues others helped me out on some undocumentes magic from Mathworks ... :) ).
If anyone can find a way to do so, it is a trivial implementation to have it integrated.

Other possibility to re-implement the smart indent functionality and drop the usage of the one provided by the editor.

Other possibility to re-implement the smart indent functionality and drop the usage of the one provided by the editor.

This would help a lot in making this nice toolbox Octave-compatible, which would be great for people that cannot (or doesn't want) to pay a Matlab license. But I understand it won't be easy and fast to implement.

Not sure how MBeautifier works today, but it sounds like this feature would essentially require a scanner/parser that can tokenize the code and create a full blown AST. Certainly no small task.

Played around a bit just for fun and ended up with the following script featuring a poor man's tokenizer:

clear all;
close all;
file = fullfile(pwd, 'mylittletestfunction.m');
document = matlab.desktop.editor.openDocument(file);
lines = splitlines(document.Text);

layer = 0;
layer_next = 0;
ind = '    ';
delimiters = {' ','\f','\n','\r','\t','\v', '(', ')', '[', ']', '{', '}' };
keywords = { 'function', 'class', 'if', 'for', 'while' };

for linect = 1:numel(lines)

    layer = layer_next;

    % remove existing indentation and whitespace
    lines{linect} = strtrim(lines{linect});

    % split line in words
    words = split(lines{linect}, delimiters);

    % ignore empty lines and comments
    if ((length(lines{linect}) ~= 0) && (lines{linect}(1) ~= '%'))
        % find keywords and adjust indent
        for wordct = 1:numel(words)
            % look for keywords that increase indent
            if (sum(strcmp(words{wordct}, keywords)))
                layer_next = layer_next + 1;
            end

            % look for end that decreases the indent
            if (sum(strcmp(words{wordct}, { 'end', 'end;' })))
                if (wordct == 1)
                    % end at the beginning decreases indent of this line
                    layer = layer - 1;
                end
                % inline end may alter the indent of the next line
                layer_next = layer_next - 1;
            end
        end
    end

    % add correct indentation
    for ict = 1:layer
        lines{linect} = [ ind, lines{linect} ];
    end
end

complete = join(lines, newline);
document.Text = complete{1};
document.save();

The script assumes that there is a file called mylittlefunction.m in the same directory, of course.

At least simple scripts can processed correctly. Naturally, different keywords are missing and it needs thorough testing but maybe we can come up with something.

At the risk of spamming in every ticket here; writing a fully working MATLAB lexer is an insane activity. Please refer to this for my analysis on this, if you want to know more: https://github.com/florianschanda/miss_hit/blob/master/LEXING_ISSUES.md

commented

I use this as part of a pre-commit git hook

Is it possible to support it by https://pre-commit.com/? It can be integrated to CI/CD of https://pre-commit.ci/. Currently pre-commit doesn't support octave/matlab directly.

@Freed-Wu there is MISS_HIT integration into pre-commit as described here https://florianschanda.github.io/miss_hit/configuration.html