This program converts glob files' tabs to spaces. There is a special case to ignore content inside triple back ticks.

Example usage is ./tab_2_spaces.py *.md

Main Concern: Can I write the while loop better?

#!/usr/bin/env python3
This program is used to convert markdown file's tab indentations to 2 spaces.

import argparse
from pathlib import Path
import os
import io
import itertools
from multiprocessing import Pool

_TAB_2_SPACE = "  "

def fix_indent(filename):
    with io.open(filename, mode="r", encoding="utf-8") as h:
        text = h.read()

    lines = text.splitlines(True)
    c = len(lines)
    i = 0

    # Replace tab to spaces
    while i < c:
        line = lines[i]

        if line.startswith("```"):
            i += 1
            while i < c:
                if lines[i].startswith("```"):
                i += 1
        elif line.startswith("\t"):
            lines[i] = line.replace("\t", _TAB_2_SPACE)

        i += 1

    with io.open(filename, mode="w", encoding="utf-8") as h:

def main():
    parser = argparse.ArgumentParser(description="Fix indent")
        "files", metavar="N", type=str, nargs="+", help="List of files to scan"

    args = parser.parse_args()
    all_files = tuple(
                (filename for filename in Path().glob("**/" + file_))
                for file_ in args.files

    with Pool(2) as process_pool:
        process_pool.map(fix_indent, all_files)

if __name__ == "__main__":

1 Answer 1


A lot of the code in your while loop can be replaced with a for loop using enumerate() and a toggled boolean.

You should be able to replace your code from c = len(lines) (line 21) down through your entire while loop with:

skip = False
for index, line in enumerate(lines):
    if line.startswith("```"):
        skip = not skip
        if not skip:
            if line.startswith("\t"):
                lines[index] = line.replace("\t", _TAB_2_SPACE)

I can't test this right now, so please let me know if you run in to any problems with this implementation.

  • \$\begingroup\$ You can merge else and if to an elif 🤔and next if with an and. \$\endgroup\$
    – JaDogg
    Commented Sep 10, 2019 at 10:00
  • 2
    \$\begingroup\$ elif not skip and line.startswith("\t"): \$\endgroup\$
    – JaDogg
    Commented Sep 10, 2019 at 10:03
  • \$\begingroup\$ @bhathiya-perera I felt that my implementation was easier to read so I chose not to condense it, but you are correct. \$\endgroup\$ Commented Sep 10, 2019 at 17:14
  • 1
    \$\begingroup\$ Indeed. It's far better than the Java like Python I've written above. :) \$\endgroup\$
    – JaDogg
    Commented Sep 10, 2019 at 20:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.