Created
October 27, 2021 19:41
-
-
Save jcarlosroldan/c7e65ec9cae879c3bd73db762b551c26 to your computer and use it in GitHub Desktop.
Convert the files in a directory from space-indented to tab indented detecting the indentation level automatically
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
''' TABBER: Because spaces suck | |
This script will recursively convert all files in its directory from space indented to tab indented. | |
It will detect the number of spaces used for indentation and transform them into tabbed files. | |
Usage: | |
1. Copy the directory you want to convert and put this file inside. If you're brave enough, skip the | |
copying part. | |
2. Review the EXTENSIONS and IGNORE_FILES values. | |
3. Run it. | |
4. Review the errors if any, and run it again. | |
''' | |
from math import gcd | |
from os import listdir | |
from os.path import isdir, join | |
from re import findall, match | |
EXTENSIONS = 'txt', 'json', 'js', 'yaml', 'vue', 'editorconfig', 'md', 'gitignore' | |
IGNORE_FILES = 'node_modules', '.vscode', '.git', 'package-lock.json' | |
def tabulate(base='.'): | |
for file in listdir(base): | |
if file in IGNORE_FILES: continue | |
path = join(base, file) | |
if isdir(path): | |
tabulate(path) | |
elif any(path.endswith(ext) for ext in EXTENSIONS): | |
with open(path, 'r', encoding='utf-8') as fp: | |
content = fp.read() | |
space_starts = findall(r'\n( +)[^\s]', content) | |
tab_starts = findall(r'\n(\t+)[^\s]', content) | |
if len(space_starts) and len(tab_starts): | |
print('%s\n\tSkipped due to mixed spaces and tabs' % path) | |
continue | |
if not len(space_starts): continue | |
space_starts = list({len(s) for s in space_starts if s is not None}) | |
tab_size = space_starts[0] | |
for length in space_starts[1:]: | |
tab_size = gcd(length, tab_size) | |
if tab_size == 1: | |
print('%s\n\tSkipped due to inconsistent spacing of lengths: %s' % (path, ', '.join(sorted(space_starts)))) | |
res = '' | |
previous_indentation = -1 | |
for n, line in enumerate(content.split('\n')): | |
if not len(line): | |
res += '\n' | |
continue | |
indentation = match(r'^ +', line) | |
indentation = len(indentation.group()) // tab_size if indentation is not None else 0 | |
if abs(previous_indentation - indentation) > 1: | |
print('%s\n\tSkipped due to inconsistent line indentation on line %d' % (path, n)) | |
break | |
res += indentation * '\t' + line.lstrip(' ') + '\n' | |
previous_indentation = indentation | |
else: | |
with open(path, 'w', encoding='utf-8') as fp: | |
fp.write(res.rstrip()) | |
if __name__ == '__main__': | |
tabulate() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment