[Aptitude-svn-commit] r3666 - in branches/aptitude-0.3/aptitude: . doc/en src src/cmdline src/vscreen/config

Daniel Burrows dburrows at costa.debian.org
Sun Jul 24 07:36:19 UTC 2005


Author: dburrows
Date: Sun Jul 24 07:36:14 2005
New Revision: 3666

Modified:
   branches/aptitude-0.3/aptitude/ChangeLog
   branches/aptitude-0.3/aptitude/doc/en/aptitude.xml
   branches/aptitude-0.3/aptitude/src/cmdline/cmdline_search.cc
   branches/aptitude-0.3/aptitude/src/pkg_columnizer.cc
   branches/aptitude-0.3/aptitude/src/pkg_item.cc
   branches/aptitude-0.3/aptitude/src/pkg_item_with_subtree.h
   branches/aptitude-0.3/aptitude/src/pkg_ver_item.cc
   branches/aptitude-0.3/aptitude/src/pkg_view.cc
   branches/aptitude-0.3/aptitude/src/vscreen/config/column_definition.cc
   branches/aptitude-0.3/aptitude/src/vscreen/config/column_definition.h
Log:
Add support for passing parameters to the column formatting algorithm.

Modified: branches/aptitude-0.3/aptitude/ChangeLog
==============================================================================
--- branches/aptitude-0.3/aptitude/ChangeLog	(original)
+++ branches/aptitude-0.3/aptitude/ChangeLog	Sun Jul 24 07:36:14 2005
@@ -1,5 +1,9 @@
 2005-07-23  Daniel Burrows  <dburrows at debian.org>
 
+	* doc/en/aptitude.xml, src/cmdline/cmdline_search.cc, src/pkg_columnizer.cc, src/pkg_item_width_subtree.h, src/vscreen/config/column_definitions.cc, src/vscreen/config/column_definitions.h:
+
+	  Add support for parametric column formatting.
+
 	* src/generic/matchers.cc, src/generic/matchers.h:
 
 	  Move implementation of ~pkg_matcher to the .cc file,

Modified: branches/aptitude-0.3/aptitude/doc/en/aptitude.xml
==============================================================================
--- branches/aptitude-0.3/aptitude/doc/en/aptitude.xml	(original)
+++ branches/aptitude-0.3/aptitude/doc/en/aptitude.xml	Sun Jul 24 07:36:14 2005
@@ -3782,7 +3782,12 @@
 	    identifying the escape; for instance,
 	    <literal>%20V</literal> generates the <link
 	    linkend='formatCandVer'>candidate version</link> of the
-	    package, 20 characters wide.
+	    package, 20 characters wide.  Placing a question mark
+	    (<literal>?</literal>) between the <literal>%</literal>
+	    and the character identifying the escape causes the
+	    column's <quote>basic</quote> width to vary depending on
+	    its content.  Note that the resulting columns might not
+	    line up vertically!
 	  </para>
 
 	  <para>
@@ -3800,6 +3805,12 @@
 	  </para>
 
 	  <para>
+	    In summary, the syntax of a <literal>%</literal>-escape is:
+	  </para>
+
+	  <synopsis><literal>%</literal><optional><replaceable>width</replaceable></optional><optional><literal>?</literal></optional><replaceable>code</replaceable><optional><literal>#</literal></optional></synopsis>
+
+	  <para>
 	    The configuration variables <literal><link
 	    linkend='configPackage-Display-Format'>Aptitude::UI::Package-Display-Format</link></literal>,
 	    <literal><link
@@ -3845,6 +3856,23 @@
 	    </seglistitem>
 
 	    <seglistitem>
+	      <seg><literal>%#<replaceable>number</replaceable></literal></seg>
+	      <seg>Parameter Replacement</seg>
+	      <seg>Variable</seg>
+	      <seg>No</seg>
+	      <seg>No</seg>
+	      <seg>
+		In some circumstances, a display format string will
+		have <quote>parameters</quote>: for instance, in the
+		command-line <literal>search</literal>, the groups
+		matched by the search are used as parameters when
+		displaying the result.  This format code will be
+		replaced by the parameter indicated by
+		<replaceable>number</replaceable>.
+	      </seg>
+	    </seglistitem>
+
+	    <seglistitem>
 	      <seg><literal>%a</literal></seg>
 	      <seg>Action Flag</seg>
 	      <seg>1</seg>

Modified: branches/aptitude-0.3/aptitude/src/cmdline/cmdline_search.cc
==============================================================================
--- branches/aptitude-0.3/aptitude/src/cmdline/cmdline_search.cc	(original)
+++ branches/aptitude-0.3/aptitude/src/cmdline/cmdline_search.cc	Sun Jul 24 07:36:14 2005
@@ -21,6 +21,33 @@
 #include <apt-pkg/error.h>
 #include <apt-pkg/strutl.h>
 
+using namespace std;
+
+class search_result_parameters : public column_parameters
+{
+  pkg_match_result *r;
+public:
+  search_result_parameters(pkg_match_result *_r)
+    :r(_r)
+  {
+  }
+
+  ~search_result_parameters()
+  {
+    delete r;
+  }
+
+  int param_count()
+  {
+    return r->num_groups();
+  }
+
+  wstring get_param(int n)
+  {
+    return transcode(r->group(n));
+  }
+};
+
 // compare...uses the candidate version of each package.
 class compare
 {
@@ -28,18 +55,19 @@
 public:
   compare(pkg_sortpolicy *_s):s(_s) {}
 
-  bool operator()(pkgCache::PkgIterator a, pkgCache::PkgIterator b)
+  bool operator()(const pair<pkgCache::PkgIterator, pkg_match_result *> &a,
+		  const pair<pkgCache::PkgIterator, pkg_match_result *> &b)
   {
-    pkgCache::VerIterator av=(*apt_cache_file)[a].CandidateVerIter(*apt_cache_file);
-    pkgCache::VerIterator bv=(*apt_cache_file)[b].CandidateVerIter(*apt_cache_file);
+    pkgCache::VerIterator av=(*apt_cache_file)[a.first].CandidateVerIter(*apt_cache_file);
+    pkgCache::VerIterator bv=(*apt_cache_file)[b.first].CandidateVerIter(*apt_cache_file);
 
-    return s->compare(a, av, b, bv)<0;
+    return s->compare(a.first, av, b.first, bv)<0;
   }
 };
 
 // FIXME: apt-cache does lots of tricks to make this fast.  Should I?
 int cmdline_search(int argc, char *argv[], const char *status_fname,
-		   string display_format, string width, std::string sort)
+		   string display_format, string width, string sort)
 {
   int real_width=-1;
 
@@ -64,7 +92,7 @@
       real_width=tmp;
     }
 
-  std::wstring wdisplay_format;
+  wstring wdisplay_format;
 
   if(!transcode(display_format.c_str(), wdisplay_format))
     {
@@ -101,7 +129,7 @@
       return -1;
     }
 
-  std::vector<pkg_matcher *> matchers;
+  vector<pkg_matcher *> matchers;
 
   for(int i=1; i<argc; ++i)
     {
@@ -123,25 +151,38 @@
       matchers.push_back(m);
     }
 
-  vector<pkgCache::PkgIterator> output;
+  vector<pair<pkgCache::PkgIterator, pkg_match_result *> > output;
   for(pkgCache::PkgIterator pkg=(*apt_cache_file)->PkgBegin();
       !pkg.end(); ++pkg)
     {
-      for(std::vector<pkg_matcher *>::iterator m=matchers.begin();
+      for(vector<pkg_matcher *>::iterator m=matchers.begin();
 	  m!=matchers.end(); ++m)
-	if((*m)->matches(pkg, (*apt_cache_file)[pkg].CandidateVerIter(*apt_cache_file)))
-	  output.push_back(pkg);
+	{
+	  pkg_match_result *r=(*m)->get_match(pkg, (*apt_cache_file)[pkg].CandidateVerIter(*apt_cache_file));
+
+	  if(r != NULL)
+	    output.push_back(pair<pkgCache::PkgIterator, pkg_match_result *>(pkg, r));
+	}
     }
 
   std::sort(output.begin(), output.end(), comp);
 
-  for(vector<pkgCache::PkgIterator>::iterator i=output.begin();
+  for(vector<pair<pkgCache::PkgIterator, pkg_match_result *> >::iterator i=output.begin();
       i!=output.end(); ++i)
-    printf("%ls\n",
-	   pkg_item::pkg_columnizer(*i,
-				    i->VersionList(),
-				    *columns,
-				    0).layout_columns(real_width==-1?screen_width:real_width).c_str());
+    {
+      column_parameters *p=new search_result_parameters(i->second);
+
+      printf("%ls\n",
+	     pkg_item::pkg_columnizer(i->first,
+				      i->first.VersionList(),
+				      *columns,
+				      0).layout_columns(real_width==-1?screen_width:real_width,
+							*p).c_str());
+
+      // Note that this deletes the whole result, so we can't re-use
+      // the list.
+      delete p;
+    }
 
   delete columns;
 

Modified: branches/aptitude-0.3/aptitude/src/pkg_columnizer.cc
==============================================================================
--- branches/aptitude-0.3/aptitude/src/pkg_columnizer.cc	(original)
+++ branches/aptitude-0.3/aptitude/src/pkg_columnizer.cc	Sun Jul 24 07:36:14 2005
@@ -666,7 +666,7 @@
 	  if(!columns)
 	    {
 	      _error->Warning(_("Internal error: Default column string is unparsable"));
-	      columns->push_back(column_definition(pkg_columnizer::name, pkg_columnizer::defaults[pkg_columnizer::name].width, true, true));
+	      columns->push_back(column_definition(column_definition::COLUMN_GENERATED, pkg_columnizer::name, pkg_columnizer::defaults[pkg_columnizer::name].width, true, true, false));
 	    }
 	}
     }
@@ -676,5 +676,6 @@
 {
   setup_columns();
 
-  return pkg_genheaders(*columns).layout_columns(width);
+  empty_column_parameters p;
+  return pkg_genheaders(*columns).layout_columns(width, p);
 }

Modified: branches/aptitude-0.3/aptitude/src/pkg_item.cc
==============================================================================
--- branches/aptitude-0.3/aptitude/src/pkg_item.cc	(original)
+++ branches/aptitude-0.3/aptitude/src/pkg_item.cc	Sun Jul 24 07:36:14 2005
@@ -297,7 +297,8 @@
   win->getmaxyx(height, width);
   pkg_columnizer::setup_columns();
 
-  wstring disp=pkg_columnizer(package, visible_version(), pkg_columnizer::get_columns(), basex).layout_columns(width);
+  empty_column_parameters p;
+  wstring disp=pkg_columnizer(package, visible_version(), pkg_columnizer::get_columns(), basex).layout_columns(width, p);
   win->mvaddnstr(y, 0, disp.c_str(), width);
 }
 

Modified: branches/aptitude-0.3/aptitude/src/pkg_item_with_subtree.h
==============================================================================
--- branches/aptitude-0.3/aptitude/src/pkg_item_with_subtree.h	(original)
+++ branches/aptitude-0.3/aptitude/src/pkg_item_with_subtree.h	Sun Jul 24 07:36:14 2005
@@ -81,12 +81,14 @@
     win->getmaxyx(height, width);
     pkg_columnizer::setup_columns();
 
+    empty_column_parameters p;
+
     std::wstring disp=pkg_with_subtree_columnizer(vs_subtree<child, sorter>::get_expanded(),
 						  hierarchical,
 						  get_package(),
 						  visible_version(),
 						  pkg_columnizer::get_columns(),
-						  basex).layout_columns(width);
+						  basex).layout_columns(width, p);
     win->mvaddnstr(y, 0, disp, width);
   }
 

Modified: branches/aptitude-0.3/aptitude/src/pkg_ver_item.cc
==============================================================================
--- branches/aptitude-0.3/aptitude/src/pkg_ver_item.cc	(original)
+++ branches/aptitude-0.3/aptitude/src/pkg_ver_item.cc	Sun Jul 24 07:36:14 2005
@@ -518,10 +518,11 @@
   win->getmaxyx(height, width);
   pkg_item::pkg_columnizer::setup_columns();
 
+  empty_column_parameters p;
   wstring disp=pkg_ver_columnizer(version,
 				  show_pkg_name,
 				  pkg_item::pkg_columnizer::get_columns(),
-				  basex).layout_columns(width);
+				  basex).layout_columns(width, p);
   win->mvaddnstr(y, 0, disp.c_str(), width);
 }
 

Modified: branches/aptitude-0.3/aptitude/src/pkg_view.cc
==============================================================================
--- branches/aptitude-0.3/aptitude/src/pkg_view.cc	(original)
+++ branches/aptitude-0.3/aptitude/src/pkg_view.cc	Sun Jul 24 07:36:14 2005
@@ -112,7 +112,8 @@
 	    ver=pkgCache::VerIterator(*apt_cache_file);
 	  }
 
-	set_text(pkg_item::pkg_columnizer(pkg, ver, *columns, 0).layout_columns(getmaxx()));
+	empty_column_parameters p;
+	set_text(pkg_item::pkg_columnizer(pkg, ver, *columns, 0).layout_columns(getmaxx(), p));
       }
     else
       set_text("");

Modified: branches/aptitude-0.3/aptitude/src/vscreen/config/column_definition.cc
==============================================================================
--- branches/aptitude-0.3/aptitude/src/vscreen/config/column_definition.cc	(original)
+++ branches/aptitude-0.3/aptitude/src/vscreen/config/column_definition.cc	Sun Jul 24 07:36:14 2005
@@ -27,11 +27,27 @@
 
 using namespace std;
 
+column_parameters::~column_parameters()
+{
+}
+
+int empty_column_parameters::param_count()
+{
+  return 0;
+}
+
+wstring empty_column_parameters::get_param(int n)
+{
+  abort();
+}
+
 column_generator::~column_generator()
 {
 }
 
-column_definition_list *parse_columns(wstring config, column_parser_func parser, column_type_defaults *defaults)
+column_definition_list *parse_columns(wstring config,
+				      column_parser_func parser,
+				      column_type_defaults *defaults)
 {
   column_definition_list *rval=new column_definition_list;
 
@@ -63,12 +79,7 @@
 		}
 	    }
 
-	  rval->push_back(column_definition(-1,
-					    wcswidth(de_backslashified.c_str(),
-						     de_backslashified.size()),
-					    false,
-					    false,
-					    de_backslashified));
+	  rval->push_back(column_definition(de_backslashified, false, false));
 	}
 
       if(firstbreak!=config.npos)
@@ -76,7 +87,7 @@
 	  if(config[firstbreak]==L'#')
 	    {
 	      if(rval->empty())
-		rval->push_back(column_definition(-1, 0, true, L""));
+		rval->push_back(column_definition(L"", true, false));
 	      else
 		rval->back().expand=true;
 
@@ -85,6 +96,7 @@
 	  else if(config[firstbreak]==L'%')
 	    {
 	      int width=-1;
+	      bool dynamic_width=false;
 
 	      firstbreak++;
 
@@ -100,8 +112,11 @@
 		  unsigned long val;
 
 		  wstring tocvt=L"";
-		  while(iswdigit(config[firstbreak]) && firstbreak<config.size()-1)
-		    tocvt+=config[firstbreak++];
+		  while(firstbreak < config.size() && iswdigit(config[firstbreak]))
+		    {
+		      tocvt+=config[firstbreak];
+		      ++firstbreak;
+		    }
 
 		  if(firstbreak==config.size())
 		    {
@@ -122,15 +137,74 @@
 		  width=val;
 		}
 
+	      if(config[firstbreak]==L'?')
+		{
+		  ++firstbreak;
+		  dynamic_width=true;
+		}
+
 	      if(config[firstbreak]==L'%')
-		rval->push_back(column_definition(-1,
-						  1,
-						  false,
-						  false,
-						  L"%"));
+		{
+		  rval->push_back(column_definition(L"%",
+						    false,
+						    false));
+		  ++firstbreak;
+		}
+	      else if(config[firstbreak]==L'#')
+		// Parameter substitution is introduced by %[nn]#:
+		{
+		  ++firstbreak;
+
+		  if(!iswdigit(config[firstbreak]))
+		    {
+		      _error->Error(_("Missing parameter number in format string"));
+		      delete rval;
+		      return NULL;
+		    }
+
+		  unsigned long val;
+
+		  wstring tocvt=L"";
+		  while(firstbreak<config.size() && iswdigit(config[firstbreak]))
+		    {
+		      tocvt+=config[firstbreak];
+		      ++firstbreak;
+		    }
+
+		  wchar_t *endptr;
+		  val=wcstol(tocvt.c_str(), &endptr, 0);
+		  if(*endptr!=L'\0')
+		    {
+		      _error->Error(_("Bad number in format string: '%ls'"), tocvt.c_str());
+		      delete rval;
+		      return NULL;
+		    }
+
+		  if(val<1)
+		    {
+		      _error->Error(_("Parameter numbers must be 1 or greater, not %ld"), val);
+		      delete rval;
+		      return NULL;
+		    }
+
+		  // Default for parameters is to be dynamic.
+		  if(width == -1)
+		    {
+		      width=0;
+		      dynamic_width=true;
+		    }
+
+		  rval->push_back(column_definition(column_definition::COLUMN_PARAM,
+						    val-1,
+						    width,
+						    false,
+						    false,
+						    dynamic_width));
+		}
 	      else
 		{
 		  int itemtype=parser(config[firstbreak]);
+		  ++firstbreak;
 
 		  if(itemtype==-1)
 		    {
@@ -143,13 +217,13 @@
 		  if(width==-1)
 		    width=defaults[itemtype].width;
 
-		  rval->push_back(column_definition(itemtype,
+		  rval->push_back(column_definition(column_definition::COLUMN_GENERATED,
+						    itemtype,
 						    width,
 						    defaults[itemtype].expand,
 						    defaults[itemtype].shrink,
-						    L""));
+						    dynamic_width));
 		}
-	      firstbreak++;
 	    }
 	  start=firstbreak;
 	}
@@ -157,7 +231,8 @@
   return rval;
 }
 
-wstring column_generator::layout_columns(unsigned int width)
+wstring column_generator::layout_columns(unsigned int width,
+					 column_parameters &p)
 {
   layout l;
 
@@ -165,11 +240,36 @@
       j!=columns.end();
       j++)
     {
-      if(j->type==-1)
-	l.push_back(column(column_disposition(j->arg, 0), j->width,
-			   j->expand, j->shrink));
+      column_disposition disp(L"", 0);
+      unsigned int width;
+
+      if(j->type == column_definition::COLUMN_LITERAL)
+	{
+	  disp = column_disposition(j->arg, 0);
+	  width = wcswidth(j->arg.c_str(), j->arg.size());
+	}
       else
-	l.push_back(column(setup_column(j->type), j->width, j->expand, j->shrink));
+	{
+	  assert(j->type == column_definition::COLUMN_GENERATED ||
+		 j->type == column_definition::COLUMN_PARAM);
+
+	  if(j->type == column_definition::COLUMN_GENERATED)
+	    disp = setup_column(j->ival);
+	  else
+	    {
+	      if(p.param_count() <= j->ival)
+		disp = column_disposition(_("Bad format parameter"), 0);
+	      else
+		disp = column_disposition(p.get_param(j->ival), 0);
+	    }
+
+	  if(j->dynamic_size)
+	    width = wcswidth(disp.text.c_str(), disp.text.size());
+	  else
+	    width = j->width;
+	}
+
+      l.push_back(column(disp, width, j->expand, j->shrink));
     }
 
   return columnify(l, width);

Modified: branches/aptitude-0.3/aptitude/src/vscreen/config/column_definition.h
==============================================================================
--- branches/aptitude-0.3/aptitude/src/vscreen/config/column_definition.h	(original)
+++ branches/aptitude-0.3/aptitude/src/vscreen/config/column_definition.h	Sun Jul 24 07:36:14 2005
@@ -45,24 +45,67 @@
 
 #include "../columnify.h"
 
+/** Defined the default settings for a particular column type. */
 struct column_type_defaults
 {
   unsigned int width;
   bool expand, shrink;
 };
-// Defines the default values for a given type
 
+/** Abstraction of the parameters passed into the layout process. */
+class column_parameters
+{
+public:
+  virtual int param_count()=0;
+  virtual std::wstring get_param(int n)=0;
+
+  virtual ~column_parameters();
+};
+
+/** An empty list of parameters. */
+class empty_column_parameters : public column_parameters
+{
+public:
+  int param_count();
+  std::wstring get_param(int n);
+};
+
+/** Defines how a single column is to be generated. */
 struct column_definition
 {
-  int type;
+  // A literal column is taken from a literal string passed as a
+  // parameter.  A generated one is created by calling a virtual
+  // method.  A parameterized column is taken from a column_parameters
+  // object passed into the layout method.
+  enum column_type {COLUMN_LITERAL, COLUMN_GENERATED, COLUMN_PARAM};
+  column_type type;
+
+  // For parametric columns, this is the parameter number;
+  // for generated ones, it's the type of column:
+  int ival;
+
+  // For literal columns only:
+  std::wstring arg;
+
+  // For generated or parametric columns:
   unsigned int width;
-  bool expand, shrink;
+  bool expand:1, shrink:1;
 
-  std::wstring arg; // For plain-text columns, this is the column contents
+  // For generated or parametric columns.  If \b true, "width"
+  // will be ignored and the true width of the incoming string will
+  // be given to the layout algorithm.
+  bool dynamic_size:1;
+
+  column_definition(const std::wstring &_arg, bool _expand, bool _shrink)
+    :type(COLUMN_LITERAL), arg(_arg), expand(_expand), shrink(_shrink)
+  {
+  }
 
-  column_definition(int _type, int _width, bool _expand, bool _shrink,
-		    std::wstring _arg=L"")
-    :type(_type), width(_width), expand(_expand), shrink(_shrink), arg(_arg)
+  column_definition(column_type _type,
+		    int _ival, int _width, bool _expand, bool _shrink,
+		    bool _dynamic_size)
+    :type(_type), ival(_ival), width(_width),
+     expand(_expand), shrink(_shrink), dynamic_size(_dynamic_size)
   {
     assert(_width>=0);
   }
@@ -85,9 +128,9 @@
 
   virtual ~column_generator();
 
-  std::wstring layout_columns(unsigned int width);
-  // Lays out the columns into, well, columns.  startlocs is a list of where
-  // the definable groups start -- it should have ngroups entries.
+  std::wstring layout_columns(unsigned int width,
+			      column_parameters &p);
+  // Lays out the columns into columns.
 };
 
 column_definition_list *parse_columns(std::wstring config,



More information about the Aptitude-svn-commit mailing list