@@ -927,12 +927,86 @@ unsigned char Editline::BufferEndCommand(int ch) {
927927static void
928928PrintCompletion (FILE *output_file,
929929 llvm::ArrayRef<CompletionResult::Completion> results,
930- size_t max_len) {
930+ size_t max_completion_length, size_t max_length) {
931+ constexpr size_t ellipsis_length = 3 ;
932+ constexpr size_t padding_length = 8 ;
933+ constexpr size_t separator_length = 4 ;
934+
935+ const size_t description_col =
936+ std::min (max_completion_length + padding_length, max_length);
937+
931938 for (const CompletionResult::Completion &c : results) {
932- fprintf (output_file, " \t %-*s" , (int )max_len, c.GetCompletion ().c_str ());
933- if (!c.GetDescription ().empty ())
934- fprintf (output_file, " -- %s" , c.GetDescription ().c_str ());
935- fprintf (output_file, " \n " );
939+ if (c.GetCompletion ().empty ())
940+ continue ;
941+
942+ // Print the leading padding.
943+ fprintf (output_file, " " );
944+
945+ // Print the completion with trailing padding to the description column if
946+ // that fits on the screen. Otherwise print whatever fits on the screen
947+ // followed by ellipsis.
948+ const size_t completion_length = c.GetCompletion ().size ();
949+ if (padding_length + completion_length < max_length) {
950+ fprintf (output_file, " %-*s" ,
951+ static_cast <int >(description_col - padding_length),
952+ c.GetCompletion ().c_str ());
953+ } else {
954+ // If the completion doesn't fit on the screen, print ellipsis and don't
955+ // bother with the description.
956+ fprintf (output_file, " %.*s...\n " ,
957+ static_cast <int >(max_length - padding_length - ellipsis_length),
958+ c.GetCompletion ().c_str ());
959+ continue ;
960+ }
961+
962+ // If we don't have a description, or we don't have enough space left to
963+ // print the separator followed by the ellipsis, we're done.
964+ if (c.GetDescription ().empty () ||
965+ description_col + separator_length + ellipsis_length >= max_length) {
966+ fprintf (output_file, " \n " );
967+ continue ;
968+ }
969+
970+ // Print the separator.
971+ fprintf (output_file, " -- " );
972+
973+ // Descriptions can contain newlines. We want to print them below each
974+ // other, aligned after the separator. For example, foo has a
975+ // two-line description:
976+ //
977+ // foo -- Something that fits on the line.
978+ // More information below.
979+ //
980+ // However, as soon as a line exceed the available screen width and
981+ // print ellipsis, we don't print the next line. For example, foo has a
982+ // three-line description:
983+ //
984+ // foo -- Something that fits on the line.
985+ // Something much longer that doesn't fit...
986+ //
987+ // Because we had to print ellipsis on line two, we don't print the
988+ // third line.
989+ bool first = true ;
990+ for (llvm::StringRef line : llvm::split (c.GetDescription (), ' \n ' )) {
991+ if (line.empty ())
992+ break ;
993+ if (!first)
994+ fprintf (output_file, " %*s" ,
995+ static_cast <int >(description_col + separator_length), " " );
996+
997+ first = false ;
998+ const size_t position = description_col + separator_length;
999+ const size_t description_length = line.size ();
1000+ if (position + description_length < max_length) {
1001+ fprintf (output_file, " %.*s\n " , static_cast <int >(description_length),
1002+ line.data ());
1003+ } else {
1004+ fprintf (output_file, " %.*s...\n " ,
1005+ static_cast <int >(max_length - position - ellipsis_length),
1006+ line.data ());
1007+ continue ;
1008+ }
1009+ }
9361010 }
9371011}
9381012
@@ -953,7 +1027,8 @@ void Editline::DisplayCompletions(
9531027 const size_t max_len = longest->GetCompletion ().size ();
9541028
9551029 if (results.size () < page_size) {
956- PrintCompletion (editline.m_output_file , results, max_len);
1030+ PrintCompletion (editline.m_output_file , results, max_len,
1031+ editline.GetTerminalWidth ());
9571032 return ;
9581033 }
9591034
@@ -963,7 +1038,7 @@ void Editline::DisplayCompletions(
9631038 size_t next_size = all ? remaining : std::min (page_size, remaining);
9641039
9651040 PrintCompletion (editline.m_output_file , results.slice (cur_pos, next_size),
966- max_len);
1041+ max_len, editline. GetTerminalWidth () );
9671042
9681043 cur_pos += next_size;
9691044
0 commit comments