Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Notepad++ Automatic Detection of Python Tabs or Spaces

I normally write code with tabs but many python libraries use spaces. Is there any way for Notepad++ to automatically detect how the file is formatted and have it automatically switch to using spaces when the file is already formatted that way?

BTW, I know there was already an SO question on how to change Notepad++'s tab format. But it would be better if it automatically changed based on the current file's formatting.

like image 621
speedplane Avatar asked Apr 03 '12 02:04

speedplane


People also ask

How do I set Notepad ++ to use spaces instead of tabs?

For anyone who follows: Go to: Preferences, Language, over on the right there is a “Tab Settings” list box, below that is a “Change to space”. Put a check in that box.

How do you fix inconsistent use of tabs and spaces in indentation error in Python?

The Python "TabError: inconsistent use of tabs and spaces in indentation" occurs when we mix tabs and spaces in the same code block. To solve the error, remove the spacing and only use tabs or spaces, but don't mix the two in the same code block.

How do I indent Python code in Notepad ++?

Goto Settings -> Preferences -> Language -> Tab Settings -> Select Python -> Uncheck (Default Value) and make sure that the 'Replace by space' is selected with 4 as the count. Next, goto Settings -> Preferences -> Auto-Completion -> Enable Auto-Indent (if it's not already enabled)

Can you mix tabs and spaces in Python?

Never mix tabs and spaces. The most popular way of indenting Python is with spaces only. The second-most popular way is with tabs only. Code indented with a mixture of tabs and spaces should be converted to using spaces exclusively.


2 Answers

If you install the "Python Script" plugin for Notepad++, you can write code to automatically switch between tabs and spaces.

Here's how:

  1. In the menu: Plugins -> Python Script -> Configuration, and set Initialization to ATSTARTUP. When Notepad++ starts, the startup.py script will run.

  2. Find startup.py and edit it. On my PC its path is c:\Program Files\Notepad++\plugins\PythonScript\scripts\startup.py, add the following code to startup.py.

The function buffer_active() is called every time when you switch tab, and guess_tab() checks whether the text is using tab indent or not. You can show the Python console to debug the code.

def guess_tab(text):
    count = 0
    for line in text.split("\n"):
        indents = line[:len(line)-len(line.lstrip())]
        if "\t" in indents:
            count += 1
    if count > 5: 
        return True
    else:
        return False

def buffer_active(arg):
    editor.setBackSpaceUnIndents(True)
    use_tab = guess_tab(editor.getText())
    editor.setUseTabs(use_tab)
    sys.stderr.write( "setUseTabs %s\n" % use_tab )

notepad.clearCallbacks([NOTIFICATION.BUFFERACTIVATED])    
notepad.callback(buffer_active, [NOTIFICATION.BUFFERACTIVATED])

This is only an example, feel free to make guess_tab() better yourself, maybe use a global dict to cache the result and speedup the callback function.

like image 189
HYRY Avatar answered Oct 27 '22 00:10

HYRY


Here is an improved version based on HYRY's answer :

  • Works on the startup tab (when you launch notepad++ to open a file)
  • Doesn't need a minimal amount of rows to trigger indentation detection. Indentation guess is based on the first encountered indented line.
  • Keeps indentation defaults when indentation cannot be detected
  • Very efficient, doesn't slow down Notepad++ when opening big files (tested on a 220 MB file, indentation detection takes only < 300 ms)

Available for download here : https://gist.github.com/vincepare/8a204172d959defb2122

import re
import time

def indent_guess_tab(text):
    for line in text.split("\n"):
        pattern = re.compile("^( {4,}|\t)")
        match = pattern.match(line)
        if (match):
            return True if ("\t" in match.group(1)) else False

def indent_auto_detect(arg):
    start = time.clock()

    # Get text sample
    maxLen = 500000
    len = editor.getTextLength()
    len = len if len < maxLen else maxLen
    sample = editor.getTextRange(0, len)

    # Indent set
    current_use_tab = editor.getUseTabs()
    use_tab = indent_guess_tab(sample)

    if (use_tab != None and use_tab != current_use_tab):
        console.write("Indent use tab switch (%s => %s)\n" % (current_use_tab, use_tab))
        editor.setUseTabs(use_tab)

    end = time.clock()
    console.write("Indentation detection took %s ms\n" % (round((end-start)*1000, 3)))

notepad.clearCallbacks([NOTIFICATION.BUFFERACTIVATED, NOTIFICATION.READY])    
notepad.callback(indent_auto_detect, [NOTIFICATION.BUFFERACTIVATED])
notepad.callback(indent_auto_detect, [NOTIFICATION.READY])
console.write("Automatic indentation detection started\n")
indent_auto_detect(None)
like image 24
Vince Avatar answered Oct 27 '22 01:10

Vince