Re: Columnar package list style (patch included)
On 2016-03-04 15:31, Julian Andres Klode wrote:
On Wed, Mar 02, 2016 at 11:56:09PM +0100, Christian Blichmann wrote:
[...]
A patch formatted with git format-patch is a great idea.
Done. My git-fu is weak.
Comments:
diff --git a/apt-private/private-cmndline.cc
b/apt-private/private-cmndline.cc
index 8290859..406f9ba 100644
--- a/apt-private/private-cmndline.cc
+++ b/apt-private/private-cmndline.cc
@@ -173,7 +173,8 @@ static bool
addArgumentsAPTGet(std::vector<CommandLine::Args> &Args, char const
addArg(0, "show-progress", "DpkgPM::Progress", 0);
addArg('f', "fix-broken", "APT::Get::Fix-Broken", 0);
addArg(0, "purge", "APT::Get::Purge", 0);
- addArg('V',"verbose-versions","APT::Get::Show-Versions",0);
+ addArg('V', "verbose-versions", "APT::Get::Show-Versions", 0);
+ addArg(0, "list-columns", "APT::Get::Show-Columns", 0);
list or show columns?
Done. It's now List-Columns.
[...]
diff --git a/apt-private/private-output.h
b/apt-private/private-output.h
index 8e4b50e..d99e2af 100644
--- a/apt-private/private-output.h
+++ b/apt-private/private-output.h
@@ -9,6 +9,7 @@
#include <fstream>
#include <string>
#include <iostream>
+#include <vector>
// forward declaration
class pkgCacheFile;
@@ -34,6 +35,8 @@ void ListSingleVersion(pkgCacheFile &CacheFile,
pkgRecords &records,
APT_PUBLIC void ShowBroken(std::ostream &out, CacheFile &Cache, bool
const Now);
APT_PUBLIC void ShowBroken(std::ostream &out, pkgCacheFile &Cache,
bool const Now);
+void ShowColumnarList(std::ostream &out, const
std::vector<std::string> &List, size_t Indent, size_t ScreenWidth);
Don't like columnar, but don't know why.
Done. Renamed to ShowWithColumns()
+
template<class Container, class PredicateC, class DisplayP, class
DisplayV> bool ShowList(std::ostream &out, std::string const &Title,
Container const &cont,
PredicateC Predicate,
@@ -43,7 +46,9 @@ template<class Container, class PredicateC, class
DisplayP, class DisplayV> bool
size_t const ScreenWidth = (::ScreenWidth > 3) ? ::ScreenWidth - 3
: 0;
int ScreenUsed = 0;
bool const ShowVersions =
_config->FindB("APT::Get::Show-Versions", false);
+ bool const ShowColumnar = _config->FindB("APT::Get::Show-Columns",
false);
columnar or columns?
Done. It's ListColumns now.
[...]
No changelog entries, we autogenerate them from git commit messages.
Done.
From 145006bf98a61a2b39e4787fbf26577dc0aac681 Mon Sep 17 00:00:00 2001
From: Christian Blichmann <christian@blichmann.eu>
Date: Tue, 1 Mar 2016 22:56:32 +0100
Subject: [PATCH] Add columnar output for package lists in the style of 'ls'
---
apt-private/private-cmndline.cc | 3 +-
apt-private/private-output.cc | 77 +++++++++++++++++++++++++++++++++++++++++
apt-private/private-output.h | 39 ++++++++++++++-------
doc/apt-get.8.xml | 6 ++++
4 files changed, 112 insertions(+), 13 deletions(-)
diff --git a/apt-private/private-cmndline.cc b/apt-private/private-cmndline.cc
index 8290859..eb8b57d 100644
--- a/apt-private/private-cmndline.cc
+++ b/apt-private/private-cmndline.cc
@@ -173,7 +173,8 @@ static bool addArgumentsAPTGet(std::vector<CommandLine::Args> &Args, char const
addArg(0, "show-progress", "DpkgPM::Progress", 0);
addArg('f', "fix-broken", "APT::Get::Fix-Broken", 0);
addArg(0, "purge", "APT::Get::Purge", 0);
- addArg('V',"verbose-versions","APT::Get::Show-Versions",0);
+ addArg('V', "verbose-versions", "APT::Get::Show-Versions", 0);
+ addArg(0, "list-columns", "APT::Get::List-Columns", 0);
addArg(0, "auto-remove", "APT::Get::AutomaticRemove", 0);
addArg(0, "reinstall", "APT::Get::ReInstall", 0);
addArg(0, "solver", "APT::Solver", CommandLine::HasArg);
diff --git a/apt-private/private-output.cc b/apt-private/private-output.cc
index 458d78d..9a9f277 100644
--- a/apt-private/private-output.cc
+++ b/apt-private/private-output.cc
@@ -24,6 +24,7 @@
#include <unistd.h>
#include <signal.h>
#include <sys/ioctl.h>
+#include <vector>
#include <sstream>
@@ -301,6 +302,82 @@ void ListSingleVersion(pkgCacheFile &CacheFile, pkgRecords &records, /*{{{*/
out << output;
}
/*}}}*/
+// ShowWithColumns - Show a list in the style of ls /*{{{*/
+// ---------------------------------------------------------------------
+/* This prints out a vector of strings with the given indent and in as
+ many columns as will fit the screen width.
+
+ The output looks like:
+ abiword debootstrap gir1.2-upowerglib-1.0
+ abiword-common dh-make google-chrome-beta
+ abiword-plugin-grammar dmeventd gstreamer1.0-clutter-3.0
+ binfmt-support dmsetup hostname
+ console-setup evolution-data-server iproute2
+ console-setup-linux evolution-data-server-common
+ coreutils ffmpeg
+ */
+struct columnInfo
+{
+ bool ValidLen;
+ size_t LineWidth;
+ vector<size_t> RemainingWidths;
+};
+void ShowWithColumns(ostream &out, vector<string> const &List, size_t Indent, size_t ScreenWidth)
+{
+ enum { MinColumnWidth = 2, ColumnSpace = 1 };
+
+ size_t const ListSize = List.size();
+ size_t const MaxScreenCols = (ScreenWidth - Indent) /
+ MinColumnWidth;
+ size_t const MaxNumCols = min(MaxScreenCols, ListSize);
+
+ vector<columnInfo> ColumnInfo(MaxNumCols);
+ for (size_t I = 0; I < MaxNumCols; ++I) {
+ ColumnInfo[I].ValidLen = true;
+ ColumnInfo[I].LineWidth = (I + 1) * MinColumnWidth;
+ ColumnInfo[I].RemainingWidths.resize(I + 1, MinColumnWidth);
+ }
+
+ for (size_t I = 0; I < ListSize; ++I) {
+ for (size_t J = 0; J < MaxNumCols; ++J) {
+ auto& Col = ColumnInfo[J];
+ if (!Col.ValidLen)
+ continue;
+
+ size_t Idx = I / ((ListSize + J) / (J + 1));
+ size_t RealColLen = List[I].size() + (Idx == J ? 0 : ColumnSpace);
+ if (Col.RemainingWidths[Idx] < RealColLen) {
+ Col.LineWidth += RealColLen - Col.RemainingWidths[Idx];
+ Col.RemainingWidths[Idx] = RealColLen;
+ Col.ValidLen = Col.LineWidth < ScreenWidth;
+ }
+ }
+ }
+ size_t NumCols = MaxNumCols;
+ while (NumCols > 1 && !ColumnInfo[NumCols - 1].ValidLen)
+ --NumCols;
+
+ size_t NumRows = ListSize / NumCols + (ListSize % NumCols != 0);
+ auto const &LineFormat = ColumnInfo[NumCols - 1];
+ for (size_t Row = 0; Row < NumRows; ++Row) {
+ size_t Col = 0;
+ size_t I = Row;
+ out << string(Indent, ' ');
+ while (true) {
+ out << List[I];
+
+ size_t CurLen = List[I].size();
+ size_t MaxLen = LineFormat.RemainingWidths[Col++];
+ I += NumRows;
+ if (I >= ListSize)
+ break;
+
+ out << string(MaxLen - CurLen, ' ');
+ }
+ out << endl;
+ }
+}
+ /*}}}*/
// ShowBroken - Debugging aide /*{{{*/
// ---------------------------------------------------------------------
/* This prints out the names of all the packages that are broken along
diff --git a/apt-private/private-output.h b/apt-private/private-output.h
index 8e4b50e..b366d12 100644
--- a/apt-private/private-output.h
+++ b/apt-private/private-output.h
@@ -9,6 +9,7 @@
#include <fstream>
#include <string>
#include <iostream>
+#include <vector>
// forward declaration
class pkgCacheFile;
@@ -34,6 +35,8 @@ void ListSingleVersion(pkgCacheFile &CacheFile, pkgRecords &records,
APT_PUBLIC void ShowBroken(std::ostream &out, CacheFile &Cache, bool const Now);
APT_PUBLIC void ShowBroken(std::ostream &out, pkgCacheFile &Cache, bool const Now);
+void ShowWithColumns(std::ostream &out, const std::vector<std::string> &List, size_t Indent, size_t ScreenWidth);
+
template<class Container, class PredicateC, class DisplayP, class DisplayV> bool ShowList(std::ostream &out, std::string const &Title,
Container const &cont,
PredicateC Predicate,
@@ -43,7 +46,9 @@ template<class Container, class PredicateC, class DisplayP, class DisplayV> bool
size_t const ScreenWidth = (::ScreenWidth > 3) ? ::ScreenWidth - 3 : 0;
int ScreenUsed = 0;
bool const ShowVersions = _config->FindB("APT::Get::Show-Versions", false);
+ bool const ListColumns = _config->FindB("APT::Get::List-Columns", false);
bool printedTitle = false;
+ std::vector<std::string> PackageList;
for (auto const &Pkg: cont)
{
@@ -66,24 +71,34 @@ template<class Container, class PredicateC, class DisplayP, class DisplayV> bool
else
{
std::string const PkgName = PkgDisplay(Pkg);
- if (ScreenUsed == 0 || (ScreenUsed + PkgName.length()) >= ScreenWidth)
- {
- out << std::endl << " ";
- ScreenUsed = 0;
- }
- else if (ScreenUsed != 0)
- {
- out << " ";
- ++ScreenUsed;
+ if (ListColumns)
+ PackageList.push_back(PkgName);
+ else {
+ if (ScreenUsed == 0 || (ScreenUsed + PkgName.length()) >= ScreenWidth)
+ {
+ out << std::endl << " ";
+ ScreenUsed = 0;
+ }
+ else if (ScreenUsed != 0)
+ {
+ out << " ";
+ ++ScreenUsed;
+ }
+ out << PkgName;
+ ScreenUsed += PkgName.length();
}
- out << PkgName;
- ScreenUsed += PkgName.length();
}
}
if (printedTitle == true)
{
- out << std::endl;
+ if (ListColumns)
+ {
+ out << std::endl;
+ ShowWithColumns(out, PackageList, 2, ScreenWidth);
+ }
+ else
+ out << std::endl;
return false;
}
return true;
diff --git a/doc/apt-get.8.xml b/doc/apt-get.8.xml
index 60fa46f..dae9557 100644
--- a/doc/apt-get.8.xml
+++ b/doc/apt-get.8.xml
@@ -368,6 +368,12 @@
Configuration Item: <literal>APT::Get::Show-Versions</literal>.</para></listitem>
</varlistentry>
+ <varlistentry><term><option>--list-columns</option></term>
+ <listitem><para>Display package lists in columnar format; prints package lists in the
+ style of the "ls" command.
+ Configuration Item: <literal>APT::Get::List-Columns</literal>.</para></listitem>
+ </varlistentry>
+
<varlistentry><term><option>-a</option></term>
<term><option>--host-architecture</option></term>
<listitem><para>This option controls the architecture packages are built for
--
2.7.0
Reply to: