sublimehq/sublime_text

Wrong tab size detection on vanilla install

evandrocoan opened this issue · 4 comments

Wrong tab size detection on vanilla install

The tab is being recognized on some files as 2 spaces, instead of 4 spaces (default). It is happening on the vanilla/clean Sublime Text 3.

Related thread:

  1. #23819 Why there is a tab size detection if I am able to set tab_size to 4?

Expected behavior

Here is how the files are being correctly recognized:

image

Actual behavior

On his image the problem happens. We are seeing the indentation guides as 2 spaces, instead of 4 spaces as on the above file on Expected behavior.

image

Steps to reproduce

  1. Put this text on a Sublime Text vanilla install, and that is it. You will see the problem.
function x = my_roots( coeficientes_do_polinomio )

    passo_atual_de_iteracao = 1;
    grau_do_polinomio       = length( coeficientes_do_polinomio ) - 1

    # Salvamos o valor original do polinômio para o processo de purificação.
    polinomio_original         = coeficientes_do_polinomio
    grau_do_polinomio_original = grau_do_polinomio

    while grau_do_polinomio > 0

        xi( passo_atual_de_iteracao ) = fLocaliza( grau_do_polinomio, coeficientes_do_polinomio )

        [ x(passo_atual_de_iteracao), M(passo_atual_de_iteracao) ] = fNewtonPolinomios( grau_do_polinomio, coeficientes_do_polinomio, )

        # Redução de grau pela raiz x, M vezes.
        # Criar um função de redução de grau, que receba retorne o novo para continuar o processo.
        [ grau_do_polinomio, coeficientes_do_polinomio ] = reduzirGrauDoPolinomio(
                                                                                   grau_do_polinomio,
                                                                                   coeficientes_do_polinomio,
                                                                                   x( passo_atual_de_iteracao ),
                                                                                   M( passo_atual_de_iteracao )
                                                                                 )

    end
end

Environment

  • Operating system and version:
    • Windows ...
    • Mac OS ...
    • Linux ...
  • Sublime Text:
    • Build 3126

Looks like it is because of the lines between reduzirGrauDoPolinomio( and the closing ).

You can debug by looking at Packages/Default/detect_indentation.py.

Yes, it is:

spaces_list:  [4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 83, 83, 83, 83, 81, 4]
same_indent 1:  [8, 8, 8, 8, 8]
same_indent 1:  []
same_indent 1:  []
same_indent 1:  []
same_indent 1:  [4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 4]
same_indent 1:  [81]
same_indent 1:  [4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 4]
same_indent 2:  [8, 8, 8, 8, 8, 81]
same_indent 2:  []
same_indent 2:  [4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 81, 4]
same_indent 2:  [4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 83, 83, 83, 83, 81, 4]
set('tab_size', indent):  2

For now I do not have time to fix this.
From where come this evidence = [1.0, 1.0, 0.8, 0.9, 0.8, 0.9, 0.9, 0.95, 1.0]?

The evidence is compared against my last list:

same_indent 2:  [4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 83, 83, 83, 83, 81, 4]

And it is triggering the indentation settings to 2 spaces:

set('tab_size', indent):  2

This is the debugging code.

import sublime
import sublime_plugin


class DetectIndentationCommand(sublime_plugin.TextCommand):
    """Examines the contents of the buffer to determine the indentation settings."""

    def run(self, edit, show_message=True, threshold=10):
        sample = self.view.substr(sublime.Region(0, min(self.view.size(), 2**14)))

        starts_with_tab = 0
        spaces_list = []
        indented_lines = 0

        for line in sample.split("\n"):
            print( line )
            if not line:
                continue
            if line[0] == "\t":
                starts_with_tab += 1
                indented_lines += 1
            elif line.startswith(' '):
                print( 'On line.startswith space...' )
                spaces = 0
                for ch in line:
                    if ch == ' ':
                        spaces += 1
                        #print( 'spaces += 1: %d', spaces )
                    else:
                        break
                if spaces > 1 and spaces != len(line):
                    indented_lines += 1
                    print( 'indented_lines += 1: %d', indented_lines )
                    spaces_list.append(spaces)
                    print( 'spaces_list.append(spaces): %d', spaces )

        evidence = [1.0, 1.0, 0.8, 0.9, 0.8, 0.9, 0.9, 0.95, 1.0]

        print( 'spaces_list: ', spaces_list )

        if indented_lines >= threshold:
            if len(spaces_list) > starts_with_tab:
                for indent in range(8, 1, -1):
                    same_indent = list(filter(lambda x: x % indent == 0, spaces_list))
                    print( 'same_indent 1: ', same_indent )

                    if len(same_indent) >= evidence[indent] * len(spaces_list):
                        if show_message:
                            sublime.status_message(
                                "Detect Indentation: Setting indentation to " +
                                str(indent) + " spaces")
                        self.view.settings().set('translate_tabs_to_spaces', True)
                        self.view.settings().set('tab_size', indent)
                        print( "set('tab_size', indent): ", indent )
                        return

                for indent in range(8, 1, -2):
                    same_indent = list(filter(lambda x: x % indent == 0 or x % indent == 1, spaces_list))
                    print( 'same_indent 2: ', same_indent )

                    if len(same_indent) >= evidence[indent] * len(spaces_list):
                        if show_message:
                            sublime.status_message(
                                "Detect Indentation: Setting indentation to " +
                                str(indent) + " spaces")
                        self.view.settings().set('translate_tabs_to_spaces', True)
                        self.view.settings().set('tab_size', indent)
                        print( "set('tab_size', indent): ", indent )
                        return

            elif starts_with_tab >= 0.8 * indented_lines:
                if show_message:
                    sublime.status_message("Detect Indentation: Setting indentation to tabs")
                self.view.settings().set('translate_tabs_to_spaces', False)


class DetectIndentationEventListener(sublime_plugin.EventListener):
    def on_load(self, view):
        if view.settings().get('detect_indentation'):
            is_at_front = (view.window() is not None and view.window().active_view() == view)
            view.run_command('detect_indentation', {'show_message': is_at_front})

The smallest amount of code which triggers 2 spaces indent is:

        xi( passo_atual_de_iteracao ) = fLocaliza( grau_do_polinomio, coeficientes_do_polinomio )

        [ x(passo_atual_de_iteracao), M(passo_atual_de_iteracao) ] = fNewtonPolinomios( grau_do_polinomio, coeficientes_do_polinomio, )

        # Redução de grau pela raiz x, M vezes.
        # Criar um função de redução de grau, que receba retorne o novo para continuar o processo.
        [ grau_do_polinomio, coeficientes_do_polinomio ] = reduzirGrauDoPolinomio(
                                                                                   grau_do_polinomio,
                                                                                   coeficientes_do_polinomio,
                                                                                   x( passo_atual_de_iteracao ),
                                                                                   M( passo_atual_de_iteracao )
                                                                                 )

But just removing the last parenthesis, it correctly detect 4 spaces:

        xi( passo_atual_de_iteracao ) = fLocaliza( grau_do_polinomio, coeficientes_do_polinomio )

        [ x(passo_atual_de_iteracao), M(passo_atual_de_iteracao) ] = fNewtonPolinomios( grau_do_polinomio, coeficientes_do_polinomio, )

        # Redução de grau pela raiz x, M vezes.
        # Criar um função de redução de grau, que receba retorne o novo para continuar o processo.
        [ grau_do_polinomio, coeficientes_do_polinomio ] = reduzirGrauDoPolinomio(
                                                                                   grau_do_polinomio,
                                                                                   coeficientes_do_polinomio,
                                                                                   x( passo_atual_de_iteracao ),
                                                                                   M( passo_atual_de_iteracao )

it seems like it would be useful if the indentation detection was syntax aware, and thus could cope better with code created with "indent_to_bracket": true, set.

Fixed in Sublime Text 4.