miss_hit icon indicating copy to clipboard operation
miss_hit copied to clipboard

special indenting for functions without end

Open fangq opened this issue 1 year ago • 11 comments

Describe the solution you'd like

This is a follow up to a previous issue #255. I would like to control the indentation of the docstring (the contiguous block of comments right below a function definition).

The current default setting is

function res = myfun(a, b, c)
    %
    % res = myfun(a, b, c)
    % help info
    %
    statement1;
    statement2;
    ...
end

I am wondering if the following is possible - if yes, how to achieve this? if not, would be nice to have a flag to control this doc string indentation

function res = myfun(a, b, c)
%
% res = myfun(a, b, c)
% help info
%
    statement1;
    statement2;
    ...
end

What kind of feature is this?

  • New feature in MISS_HIT

Your MATLAB/Octave environment

  • both MATLAB and Octave, all versions

MISS_HIT component affected Choose one or more of the below:

  • Style checker

fangq avatar Apr 09 '23 20:04 fangq

Now that is just ugly, why'd you want to do that? :) Are there some other tools that expect it to be like that?

florianschanda avatar Apr 12 '23 08:04 florianschanda

yes, I agree. I wonder if I can update this ticket to request a refined style to #255?

in #255, I did not make it clear using the word "top-level" functions. What I really meant was the top-most (or main) function in each .m file, not all the subfunctions in the same unit. For example, my desired output looks like the following

function output=mainfun(input)
%
% docstring for mainfun
% copyright ...
% the main-function should be flattened without indentation 
%

statement1;
statement2;

%% -------- local functions -------

% comment for relatively short localfun 1
function output=localfun1(input)
    % local-functions, or functions with an "end" at the bottom should be indented
    statement1
    statement2
end

% comment for relatively short localfun 2
function output=localfun2(input)
    % short comment on 
    statement1
    statement2
end

essentially, my goal is to have access to two formatting features

  1. decide to indent a function (main, or local, or nested) or not depending on the presence of the matching end tag of the function
  2. (optionally) control the indentation of the doc-string of the main-function (top-most function) of a unit.

let me know if you see these make sense - I am happy to update the ticket to reflect the desired formats.

fangq avatar Apr 19 '23 18:04 fangq

OK, thank you for the concrete example. I will see what I can do, but I am not getting a lot of time to work on MH these days; so it may take a while.

florianschanda avatar Apr 20 '23 07:04 florianschanda

@fangq your test contains a syntax error as far as I am aware (missing end for the main function defined in the file). I don't have access to a matlab right now; can you confirm that you don't expect this to work?

florianschanda avatar May 16 '23 13:05 florianschanda

With indent_function_file_body: false the fixed file looks like this:

function output = mainfun(input)
%
% docstring for mainfun
% copyright ...
% the main-function should be flattened without indentation
%

statement1;
statement2;

%% -------- local functions -------

% comment for relatively short localfun 1
function output = localfun1(input)
    % local-functions, or functions with an "end" at the bottom should be indented
    statement1;
    statement2;
end

% comment for relatively short localfun 2
function output = localfun2(input)
    % short comment on
    statement1;
    statement2;
end

end

Isn't that exactly what you already need?

florianschanda avatar May 16 '23 13:05 florianschanda

@fangq I have added a test + config file that shows you can get precisely what you wrote above.

https://github.com/florianschanda/miss_hit/tree/master/tests/style/issue_265_alternative_indent

I am closing the ticket, but if I missed something please re-open! Sorry for not doing this sooner.

florianschanda avatar May 16 '23 13:05 florianschanda

@fangq your test contains a syntax error as far as I am aware (missing end for the main function defined in the file). I don't have access to a matlab right now; can you confirm that you don't expect this to work?

thanks a lot for working on this feature!

@florianschanda, MATLAB function does not require the closing end tag to end a function. This applies to both the primary function in a .m file, as well as local or nested functions embedded in the main unit.

your test result looks fine to me. if the primary function does have a matching end, the two flushed end statements at the bottom look a bit awkward, but in a way this is what the user ask for and they should anticipate that.

a slightly more intuitive approach is to use the presence of the ending end -statement to decide whether to remove a function indent or not. But the current flag's name will not entirely reflect that.

fangq avatar May 16 '23 21:05 fangq

I didn't know the final end could be missing. I will add support for that.

florianschanda avatar May 18 '23 09:05 florianschanda

just to provide more info: if a function's end is omitted in a unit, all local function must also omit it. one can not mix functions with and without ending end.

so, both the following forms are acceptable, and they are equivalent

function mainfun
  statements;
end %end of mainfun

function localfun1
  statements;
end %end of localfun1

function localfun2
  statements;
end %end of localfun2
function mainfun
statements;

function localfun1
statements;

function localfun2
statements;

the above two forms are for local functions, it is different from the example code in your test, which is nested function, see their differences in https://www.mathworks.com/help/matlab/matlab_prog/types-of-functions.html

for nested functions, one must explicitly write end for both the parent function and the nested ones, for example

function mainfun
    statements;

    function nestedfun1
        statements;
    end %end of nestedfun1

    function nestedfun2
        statements;
    end %end of nestedfun2
end %end of mainfun

both local and nested functions can appear in the same unit - in such a case, all end must present.

function output=mainfun(input)
    output=localfun(nestedfun1(input));

    function output=nestedfun1(input)
        output=input;
    end %end of nestedfun1
end %end of mainfun

function output=localfun(input)
  output=input;
end %end of localfun1

fangq avatar May 19 '23 01:05 fangq

in a way, matlab's traditional indentation setting, which the indent_function_file_body: false was trying to mimic, was largely for formatting the end-omitting local functions as in the below form.

function mainfun
statements;

function localfun1
statements;

function localfun2
statements;

when the end tag does present, the flushed end/end does look a bit awkward.

end
end

would it be possible to use the following logic:

when indent_function_file_body: false is set

  1. when function end is present (meaning that all functions have end), indent_function_file_body: false only controls the docstring, and leave the code still indented
  2. when function end is omitted (meaning that all functions omit it), indent_function_file_body: false controls both the docstring and the code - therefore, both the function help info section and the code are flush (as in upstream matlab functions)

fangq avatar May 19 '23 01:05 fangq

This in this case (all or no ends) then it already works. I was super worried I missed a case ;)

florianschanda avatar May 19 '23 07:05 florianschanda