Commit b0a7bdf6 authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by facebook-github-bot-0

stripLeftMargin

Summary:
[Folly] `stripLeftMargin`.

So you can do:

    TEST(MyClass, doSomethingWithString) {
      //  Multiline string literal is indented properly inside the test case
      //  instead of being aligned all the way to the left, which would make
      //  the test case read poorly.
      auto input = folly::stripLeftMargin(R"TEXT(
        first line
        second line
        third line
      )TEXT");
      auto expected = //...
      auto actual = MyClass::doSomethingWithString(input);
      EXPECT_EQ(expected, actual);
    }

Reviewed By: markisaa

Differential Revision: D2909736

fb-gh-sync-id: ebb07da05e1a788535064cfcd9e07f617a007800
shipit-source-id: ebb07da05e1a788535064cfcd9e07f617a007800
parent 5e5cf95a
/*
* Copyright 2015 Facebook, Inc.
* Copyright 2016 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -16,6 +16,7 @@
#include <folly/String.h>
#include <boost/regex.hpp>
#include <folly/Format.h>
#include <folly/ScopeGuard.h>
......@@ -548,6 +549,25 @@ size_t hexDumpLine(const void* ptr, size_t offset, size_t size,
} // namespace detail
std::string stripLeftMargin(std::string s) {
using namespace boost;
static const auto kPre = regex(R"(\A[ \t]*\n)");
static const auto kPost = regex(R"([ \t]+\z)");
static const auto kScan = regex(R"(^[ \t]*(?=\S))");
s = regex_replace(s, kPre, "");
s = regex_replace(s, kPost, "");
const auto sentinel = std::numeric_limits<size_t>::max();
auto indent = sentinel;
sregex_iterator it(s.cbegin(), s.cend(), kScan);
sregex_iterator itend;
for (; it != itend; ++it) {
indent = std::min<size_t>(indent, it->length());
}
indent = indent == sentinel ? 0 : indent;
s = regex_replace(s, regex(sformat(R"(^[ \t]{{0,{0}}})", indent)), "");
return s;
}
} // namespace folly
#ifdef FOLLY_DEFINED_DMGL
......
/*
* Copyright 2015 Facebook, Inc.
* Copyright 2016 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -580,6 +580,17 @@ inline StringPiece skipWhitespace(StringPiece sp) {
return ltrimWhitespace(sp);
}
/**
* Strips the leading and the trailing whitespace-only lines. Then looks for
* the least indented non-whitespace-only line and removes its amount of
* leading whitespace from every line. Assumes leading whitespace is either all
* spaces or all tabs.
*
* Purpose: including a multiline string literal in source code, indented to
* the level expected from context.
*/
std::string stripLeftMargin(std::string s);
/**
* Fast, in-place lowercasing of ASCII alphabetic characters in strings.
* Leaves all other characters unchanged, including those with the 0x80
......
/*
* Copyright 2015 Facebook, Inc.
* Copyright 2016 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -16,6 +16,7 @@
#include <folly/String.h>
#include <boost/regex.hpp>
#include <gtest/gtest.h>
using namespace folly;
......@@ -1131,6 +1132,112 @@ TEST(String, whitespace) {
EXPECT_EQ("", rtrimWhitespace("\r "));
}
TEST(String, stripLeftMargin_empty) {
auto input = R"TEXT(
)TEXT";
auto expected = "";
EXPECT_EQ(expected, stripLeftMargin(input));
}
TEST(String, stripLeftMargin_one_line) {
auto input = R"TEXT(
hi there bob!
)TEXT";
auto expected = "hi there bob!\n";
EXPECT_EQ(expected, stripLeftMargin(input));
}
TEST(String, stripLeftMargin_two_lines) {
auto input = R"TEXT(
hi there bob!
nice weather today!
)TEXT";
auto expected = "hi there bob!\nnice weather today!\n";
EXPECT_EQ(expected, stripLeftMargin(input));
}
TEST(String, stripLeftMargin_three_lines_uneven) {
auto input = R"TEXT(
hi there bob!
nice weather today!
so long!
)TEXT";
auto expected = " hi there bob!\nnice weather today!\n so long!\n";
EXPECT_EQ(expected, stripLeftMargin(input));
}
TEST(String, stripLeftMargin_preceding_blank_lines) {
auto input = R"TEXT(
hi there bob!
)TEXT";
auto expected = "\n\nhi there bob!\n";
EXPECT_EQ(expected, stripLeftMargin(input));
}
TEST(String, stripLeftMargin_succeeding_blank_lines) {
auto input = R"TEXT(
hi there bob!
)TEXT";
auto expected = "hi there bob!\n\n\n";
EXPECT_EQ(expected, stripLeftMargin(input));
}
TEST(String, stripLeftMargin_interstitial_undented_whiteline) {
// using ~ as a marker
string input = R"TEXT(
hi there bob!
~
so long!
)TEXT";
input = boost::regex_replace(input, boost::regex(" +~"), "");
EXPECT_EQ("\n hi there bob!\n\n so long!\n ", input);
auto expected = "hi there bob!\n\nso long!\n";
EXPECT_EQ(expected, stripLeftMargin(input));
}
TEST(String, stripLeftMargin_interstitial_dedented_whiteline) {
// using ~ as a marker
string input = R"TEXT(
hi there bob!
~
so long!
)TEXT";
input = boost::regex_replace(input, boost::regex("~"), "");
EXPECT_EQ("\n hi there bob!\n \n so long!\n ", input);
auto expected = "hi there bob!\n\nso long!\n";
EXPECT_EQ(expected, stripLeftMargin(input));
}
TEST(String, stripLeftMargin_interstitial_equidented_whiteline) {
// using ~ as a marker
string input = R"TEXT(
hi there bob!
~
so long!
)TEXT";
input = boost::regex_replace(input, boost::regex("~"), "");
EXPECT_EQ("\n hi there bob!\n \n so long!\n ", input);
auto expected = "hi there bob!\n\nso long!\n";
EXPECT_EQ(expected, stripLeftMargin(input));
}
TEST(String, stripLeftMargin_interstitial_indented_whiteline) {
// using ~ as a marker
string input = R"TEXT(
hi there bob!
~
so long!
)TEXT";
input = boost::regex_replace(input, boost::regex("~"), "");
EXPECT_EQ("\n hi there bob!\n \n so long!\n ", input);
auto expected = "hi there bob!\n \nso long!\n";
EXPECT_EQ(expected, stripLeftMargin(input));
}
const folly::StringPiece kTestUTF8 = "This is \U0001F602 stuff!";
TEST(UTF8StringPiece, valid_utf8) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment