<div dir="ltr"><br><br><div class="gmail_quote"><div dir="ltr">On Tue, Dec 6, 2016 at 10:31 AM Greg Clayton <<a href="mailto:gclayton@apple.com">gclayton@apple.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><br class="gmail_msg"><br class="gmail_msg">
<br class="gmail_msg">
It should be a formatter option for collections to allow you to print out different ranges. If I have a target and a target knows how to print the process and the process knows how to print the threads and the threads know how to print the stack frames, it doesn't mean I always want to see everything. Sounds like we can easily control this in the llvm::formatv case with extra formatting options:<br class="gmail_msg">
<br class="gmail_msg">
This might print just a summary of the target:<br class="gmail_msg">
<br class="gmail_msg">
llvm::formatv("{0}", target);<br class="gmail_msg">
<br class="gmail_msg">
This might print the target and info about the process:<br class="gmail_msg">
<br class="gmail_msg">
llvm::formatv("{0;process}", target);<br class="gmail_msg">
<br class="gmail_msg">
The question becomes, can we then forward arguments into the "Process" logger to control if the threads are displayed?<br class="gmail_msg">
<br class="gmail_msg">
llvm::formatv("{0;process{threads{frames}}}", target);<br class="gmail_msg">
<br class="gmail_msg">
This would allow recursive formatters to be called with specified arguments. Just a thought, but if we are going to delve into recursive formatters, we might need to think about that.<br class="gmail_msg"></blockquote><div><br></div><div>A formatter can literally do anything with the style string.  So for example, suppose you have formatters defined for Process and Thread.  each of these ultimately boils down to a function:</div><div><br></div><div>void format(llvm::raw_ostream &Out, const Process &P, StringRef Style); </div><div>void format(llvm::raw_ostream &Out, const Thread &P, StringRef Style); <br></div><div><br></div><div>We implement each of these, so Process can define its own Style language, as can Target, as can Thread.  We can come up with something better than this, but say for the sake of illustration Thread's style string worked like this: If empty, print thread id, otherwise treat each alphabetic character as representing a "code" of what to print.  P = process, T = thread id, N = thread name.  So "P - T - N" would print the process id, then the thread id, then the thread name, separated by dashes.</div><div><br></div><div>Now suppose you want to print a process.  If style string is empty, it prints only the process id, otherwise if it equals T then it prints the first thread, or if it equals T* it prints all threads.  T or T* can optionally be followed by arguments to forward to the thread in square brackets.  So you could have:</div><div><br></div><div>formatv("Process {0;P - T*[N]}", process);</div><div><br></div><div>There's obviously a balance between flexibility and conciseness, but I guess that's no different than C++.  It's as flexible as you could possibly need, sometimes to the point of allowing you to make bad design decisions :)</div><div><br></div><div>In the beginning probably best to just define some simple formatters that don't do anything recursive, and then some obvious patterns might start to fall out and we can refine the styles we support for all of the various LLDB types.</div></div></div>