LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
PrintAllowedConfiguration.cc
Go to the documentation of this file.
2 #include "cetlib/container_algorithms.h"
3 #include "cetlib/split_by_regex.h"
4 #include "cetlib/trim.h"
10 
11 #include <regex>
12 
13 using namespace fhicl::detail;
14 
15 namespace {
16 
17  std::regex const reNewLine{"\n"};
18 
19  inline bool
20  is_sequence_element(std::string const& k)
21  {
22  auto pos = k.find_last_of("]");
23  return pos != std::string::npos && pos == k.size() - 1;
24  }
25 
26  struct maybeName {
27 
28  maybeName(ParameterBase const& p, std::string const& ind)
29  : is_seq_elem{is_sequence_element(p.key())}, name{p.name()}, indent{ind}
30  {}
31 
32  bool is_seq_elem;
33  std::string name;
34  std::string indent;
35  };
36 
37  std::ostream&
38  operator<<(std::ostream& os, maybeName&& mn)
39  {
40  if (!mn.is_seq_elem) {
41  os << mn.indent << mn.name << ": ";
42  } else {
43  os << mn.indent;
44  }
45  return os;
46  }
47 
48  std::string
49  suffix(std::unordered_set<std::string>& keysWithCommas_,
50  std::unordered_set<std::string>& keysWithEllipses_,
51  std::string const& key,
52  std::string const& indent)
53  {
54  std::string result;
55  if (cet::search_all(keysWithCommas_, key)) {
56  keysWithCommas_.erase(key);
57  result += ",";
58  }
59  if (cet::search_all(keysWithEllipses_, key)) {
60  keysWithEllipses_.erase(key);
61  result.append("\n").append(indent).append("...");
62  }
63  return result;
64  }
65 
66  std::string
67  non_whitespace(std::string const& s, std::size_t const sz)
68  {
69 
70  // To support denoting optional tables, we sometimes print an
71  // indentation string that has only one character in it. But we
72  // don't want to print any extra whitespace. So we remove it
73  // here.
74  //
75  // We also ignore indents if the size is one -- i.e. the current
76  // state of the indent stack does not include any nested
77  // parameters, so there's no reason to include any prefixes that
78  // might be on the lowest-level indent (corresponding to sz == 1).
79 
80  return sz > 1 ? cet::trim_right_copy(s, " ") : "";
81  }
82 
83  auto
84  string_repeat(std::size_t const n, std::string const& s)
85  {
86  std::string result;
87  for (std::size_t i{}; i != n; ++i)
88  result += s;
89  return result;
90  }
91 }
92 
93 using namespace fhicl::detail;
94 
95 //======================================================================
96 
98  bool const showParents,
99  std::string const& prefix,
100  bool const stlf)
101  : buffer_{os}
102  , indent_{prefix}
104  , showParentsForFirstParam_{showParents}
105 {}
106 
108 
109 bool
111 {
112 
115 
116  if (!suppressFormat(p)) {
117 
118  if (p.is_conditional()) {
119  buffer_ << '\n';
120  indent_.modify_top("┌" + string_repeat(30, "─"));
121  buffer_ << non_whitespace(indent_(), indent_.size()) << '\n';
122  indent_.modify_top("│ ");
123  }
124 
125  if (!p.comment().empty()) {
126  if (!p.is_conditional())
127  buffer_ << non_whitespace(indent_(), indent_.size()) << '\n';
128  for (auto const& line : cet::split_by_regex(p.comment(), reNewLine))
129  buffer_ << indent_() << "## " << line << '\n';
130  }
131  }
132 
133  if (!is_sequence_element(p.key())) {
134  buffer_ << non_whitespace(indent_(), indent_.size()) << '\n';
135 
136  // In general, optional parameters cannot be template arguments to
137  // sequences. However, the implementation for 'TupleAs' uses
138  // OptionalTuple<...> as the holding type of the sequence
139  // elements. In the case where we have Sequence< TupleAs<> >, the
140  // TupleAs entries will be prefaced with '#', and we don't want
141  // that. Therefore, we modify the top indentation fragment only
142  // if the parameter is not a sequence element.
143 
144  if (p.is_optional()) {
145  if (p.is_conditional())
146  indent_.modify_top("│# ");
147  else
148  indent_.modify_top(" # ");
149  }
150  }
151 
154 
155  buffer_ << mps_.top().parent_names();
156 
157  return true;
158 }
159 
160 void
162 {
163  buffer_ << suffix(keysWithCommas_, keysWithEllipses_, p.key(), indent_());
164 
165  if (p.has_default() && p.parameter_type() == par_type::ATOM)
166  buffer_ << " # default";
167 
168  if (!suppressFormat(p)) {
169  if (p.is_conditional()) {
170  indent_.modify_top("└" + string_repeat(30, "─"));
171  buffer_ << '\n' << indent_();
172  indent_.modify_top(std::string(3, ' '));
173  } else if (p.is_optional()) {
174  indent_.modify_top(std::string(3, ' '));
175  }
176  }
177 
179  buffer_ << '\n' << mps_.top().closing_braces();
180  mps_.pop();
181 }
182 
183 //======================================================================
184 
185 void
187 {
188  buffer_ << maybeName{t, indent_()} << "{\n";
189  indent_.push();
190 }
191 
192 void
194 {
195  indent_.pop();
196  buffer_ << indent_() << "}";
197 }
198 
199 //======================================================================
200 
201 void
203 {
204  buffer_ << maybeName{s, indent_()} << "[\n";
205 
206  indent_.push();
207 
208  if (s.empty())
209  return;
210 
211  // We want the printout to look like this for sequences with
212  // defaults:
213  //
214  // list1: [
215  // 1, # default
216  // 2 # default
217  // ]
218  //
219  // And like this for vectors w/o defaults (has length 1):
220  //
221  // list2: [
222  // <int>,
223  // ...
224  // ]
225 
226  if (s.has_default() || (s.parameter_type() != par_type::SEQ_VECTOR)) {
227  for (std::size_t i{}; i != s.size() - 1; ++i)
228  keysWithCommas_.emplace(s.key() + "[" + std::to_string(i) + "]");
229  return;
230  }
231 
232  keysWithCommas_.emplace(s.key() + "[0]");
233  keysWithEllipses_.emplace(s.key() + "[0]");
234 }
235 
236 void
238 {
239  indent_.pop();
240  buffer_ << indent_() << "]";
241 }
242 
243 //======================================================================
244 
245 void
247 {
248  buffer_ << maybeName{a, indent_()} << a.stringified_value();
249 }
250 
251 //======================================================================
252 
253 void
255 {
256  buffer_ << maybeName{dp, indent_()} << "<< delegated >>";
257 }
bool empty() const noexcept
Definition: SequenceBase.h:28
bool is_sequence_element(std::string const &key)
std::size_t size() const noexcept
Definition: SequenceBase.h:33
void exit_sequence(SequenceBase const &) override
PrintAllowedConfiguration(std::ostream &os, bool const showParents=false, std::string const &prefix=std::string(3, ' '), bool const stlf=false)
void after_action(ParameterBase const &) override
void maybeReleaseTopLevelParameter(ParameterBase const &p)
void modify_top(std::string const &s)
Definition: Indentation.h:36
bool before_action(ParameterBase const &) override
decltype(auto) constexpr to_string(T &&obj)
ADL-aware version of std::to_string.
std::string stringified_value() const
Definition: AtomBase.h:18
par_type parameter_type() const
std::string indent(std::size_t const i)
std::string const & name() const
std::string const & key() const
Definition: ParameterBase.cc:6
void enter_sequence(SequenceBase const &) override
void delegated_parameter(DelegateBase const &) override
void cacheTopLevelParameter(ParameterBase const &p)
Char_t n[5]
std::string const & comment() const
std::ostream & operator<<(std::ostream &os, TableBase const &t)
Definition: TableBase.cc:139