| // Copyright 2017-2020 The Verible Authors. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #include "common/formatting/unwrapped_line.h" |
| |
| #include <algorithm> |
| #include <iostream> |
| #include <iterator> |
| #include <map> |
| #include <sstream> |
| #include <string> |
| #include <vector> |
| |
| #include "absl/strings/str_cat.h" |
| #include "absl/strings/str_join.h" |
| #include "common/formatting/format_token.h" |
| #include "common/strings/display_utils.h" |
| #include "common/text/tree_utils.h" |
| #include "common/util/container_iterator_range.h" |
| #include "common/util/spacer.h" |
| |
| namespace verible { |
| |
| std::ostream& operator<<(std::ostream& stream, PartitionPolicyEnum p) { |
| switch (p) { |
| case PartitionPolicyEnum::kUninitialized: |
| return stream << "uninitialized"; |
| case PartitionPolicyEnum::kAlwaysExpand: |
| return stream << "always-expand"; |
| case PartitionPolicyEnum::kFitOnLineElseExpand: |
| return stream << "fit-else-expand"; |
| case PartitionPolicyEnum::kTabularAlignment: |
| return stream << "tabular-alignment"; |
| case PartitionPolicyEnum::kAlreadyFormatted: |
| return stream << "already-formatted"; |
| case PartitionPolicyEnum::kInline: |
| return stream << "inline"; |
| case PartitionPolicyEnum::kAppendFittingSubPartitions: |
| return stream << "append-fitting-sub-partitions"; |
| case PartitionPolicyEnum::kJuxtaposition: |
| return stream << "juxtaposition"; |
| case PartitionPolicyEnum::kStack: |
| return stream << "stack"; |
| case PartitionPolicyEnum::kWrap: |
| return stream << "wrap"; |
| case PartitionPolicyEnum::kJuxtapositionOrIndentedStack: |
| return stream << "juxtaposition-or-indented-stack"; |
| } |
| LOG(FATAL) << "Unknown partition policy " << int(p); |
| } |
| |
| static void TokenFormatter(std::string* out, const PreFormatToken& token, |
| bool verbose) { |
| if (verbose) { |
| std::ostringstream oss; |
| token.before.CompactNotation(oss); |
| absl::StrAppend(out, oss.str()); |
| } |
| absl::StrAppend(out, token.Text()); |
| } |
| |
| void UnwrappedLine::SetIndentationSpaces(int spaces) { |
| CHECK_GE(spaces, 0); |
| indentation_spaces_ = spaces; |
| } |
| |
| void UnwrappedLine::DefaultOriginPrinter(std::ostream& stream, |
| const verible::Symbol* symbol) { |
| static constexpr int kContextLimit = 25; |
| stream << '"' << AutoTruncate{StringSpanOfSymbol(*symbol), kContextLimit} |
| << '"'; |
| } |
| |
| std::ostream* UnwrappedLine::AsCode( |
| std::ostream* stream, bool verbose, |
| const OriginPrinterFunction& origin_printer) const { |
| *stream << Spacer(indentation_spaces_, kIndentationMarker) << '[' |
| << absl::StrJoin(tokens_, " ", |
| [=](std::string* out, const PreFormatToken& token) { |
| TokenFormatter(out, token, verbose); |
| }) |
| << "], policy: " << partition_policy_; |
| if (origin_ != nullptr) { |
| *stream << ", (origin: "; |
| origin_printer(*stream, origin_); |
| *stream << ")"; |
| } |
| return stream; |
| } |
| |
| std::ostream& operator<<(std::ostream& stream, const UnwrappedLine& line) { |
| return *line.AsCode(&stream); |
| } |
| |
| FormattedExcerpt::FormattedExcerpt(const UnwrappedLine& uwline) |
| : indentation_spaces_(uwline.IndentationSpaces()) { |
| tokens_.reserve(uwline.Size()); |
| // Convert working PreFormatTokens (computed from wrap optimization) into |
| // decision-bound representation. |
| const auto range = uwline.TokensRange(); |
| std::transform(range.begin(), range.end(), std::back_inserter(tokens_), |
| [](const PreFormatToken& t) { return FormattedToken(t); }); |
| } |
| |
| std::ostream& FormattedExcerpt::FormattedText( |
| std::ostream& stream, bool indent, |
| const std::function<bool(const TokenInfo&)>& include_token_p) const { |
| if (tokens_.empty()) return stream; |
| // Let caller print the preceding/trailing newline. |
| if (indent) { |
| if (tokens_.front().before.action != SpacingDecision::Preserve) { |
| stream << Spacer(IndentationSpaces()); |
| } |
| } |
| // We do not want the indentation before the first token, if it was |
| // already handled separately. |
| const auto& front = tokens_.front(); |
| if (include_token_p(*front.token)) { |
| VLOG(2) << "action: " << front.before.action; |
| switch (front.before.action) { |
| case SpacingDecision::Align: |
| // When aligning tokens, the first token might be further indented. |
| stream << Spacer(front.before.spaces) << front.token->text(); |
| break; |
| default: |
| stream << front.token->text(); |
| } |
| } |
| for (const auto& ftoken : |
| verible::make_range(tokens_.begin() + 1, tokens_.end())) { |
| if (include_token_p(*ftoken.token)) stream << ftoken; |
| } |
| return stream; |
| } |
| |
| std::ostream& operator<<(std::ostream& stream, |
| const FormattedExcerpt& excerpt) { |
| return excerpt.FormattedText(stream, true); |
| } |
| |
| std::string FormattedExcerpt::Render() const { |
| std::ostringstream stream; |
| FormattedText(stream, true); |
| return stream.str(); |
| } |
| |
| } // namespace verible |