简体   繁体   中英

How to remove whitespaces from multiline string pass it to another program and then add back whitespaces?

Summary

I need to detect indentation level of the first line in multiline string passed to a script. Store it. Remove this indent from other lines. Pass the multiline string with removed indent level to another program (that I've figured how to do) add back indent to all lines in multiline string and print it to stdout (that I also know how to do).


To be specific I have a problem with vim and Python formatter YAPF. The way yapf works is that if python file is incorrect formatting would result in error.

So imagine this

def f():
   # imagine some very very long lines here that we want to reformat

If I would select this imagined lines in vim and then press gq (I've set formatprg=yapf ) vim would substitute this lines with a traceback of yapf which is no good of course. But If I would select the whole function it would do the job perfectly.

You can test this with

echo '   fooo = 1' | yapf

This would result in IndentationError While echo 'fooo = 1' | yapf echo 'fooo = 1' | yapf would work

So what I think is a very nice workaround is to remove indentation store the indent level of the first line, pass string without indentation to yapf somehow and then add indent to the result. The problem with this is I'd like this to be a one liner or close to that so that it could be stored directly in my vimrc. So python isn't a good match for that because I would need at least to import re package etc.

So I thought about perl.

The only problem is that I don't know perl much.

So for now my experiment looks like this

$a = "    foo = 1\n    bar = '1'";
my ($indent, $text) = $a =~ m/^(\s+)(.*)$/m;
$command = "echo " . $text;
$out = `$command`;
print "$out\n";
print "$text\n";

I will be glad for any help. Maybe there is more easy way to do this, I don't know.

Since you seem to be familiar with Python already I would recommend using itstextwrap module, which contains dedent and (in version 3.3 and later) indent functions that can do most of the job for you:

import re
from textwrap import dedent, indent

whitespace = re.compile('\s+')

test_string = '''    while True:
        pass'''

leading_whitespace = whitespace.match(test_string)

dedented_text = dedent(test_string)

# Do whatever you want with dedented_text

indented_text = indent(dedented_text, leading_whitespace.group(0))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM