Skip to content

Commit

Permalink
main: introduce colprint API
Browse files Browse the repository at this point in the history
ctags has many --list-* options. colprint helps to implement the options.
The column widths are dynamically calculated.

Signed-off-by: Masatake YAMATO <yamato@redhat.com>
  • Loading branch information
masatake committed Jun 20, 2017
1 parent 9052128 commit ad9b42b
Show file tree
Hide file tree
Showing 13 changed files with 367 additions and 1 deletion.
2 changes: 2 additions & 0 deletions dictfiles/GENERATED-src-main.list
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ close
cmd
cmdline
cnf
colprint
column
combine
comment
common
Expand Down
1 change: 1 addition & 0 deletions dictfiles/c-syntax.list
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
endif
ifdef
ifndef
2 changes: 2 additions & 0 deletions dictfiles/english.list
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
merchantability
readonly
splitter
whitespace
whitespaces
5 changes: 5 additions & 0 deletions dictfiles/libc.list
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
boolean
fprintf
fputc
fputs
isalnum
isalpha
isdigit
Expand All @@ -9,6 +11,9 @@ isxdigit
printf
putc
puts
qsort
stdarg
strcat
strchr
strcmp
va
7 changes: 7 additions & 0 deletions dictfiles/local-vars.list
Original file line number Diff line number Diff line change
@@ -1,22 +1,29 @@
# Local variables
ap
buf
dev
dictfile
dirs
downcase
dup
ffile
fn
fname
foldcase
funcmap
iname
indx
input0
langs
len
msg
mydict
oname
optname
slist
submode
subtag
tokeninfo
uuid
vcol
vstr
1 change: 0 additions & 1 deletion dictfiles/misc.list
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ travis
unix
vg
vs2013
whitespace
www
xno
xyes
290 changes: 290 additions & 0 deletions main/colprint.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,290 @@
/*
* Copyright (c) 2017 Masatake YAMATO
*
* This source code is released for free distribution under the terms of the
* GNU General Public License version 2 or (at your option) any later version.
*
*/
#include "general.h" /* must always come first */

#include "colprint.h"
#include "ptrarray.h"
#include "routines.h"
#include "strlist.h"
#include "vstring.h"

#include <stdarg.h>
#include <stdio.h>
#include <string.h>


enum colprintJustification {
COLPRINT_LEFT, /* L:... */
COLPRINT_RIGHT, /* R:... */
COLPRINT_LAST,
};

struct colprintHeaderColumn {
vString *value;
enum colprintJustification justification;
unsigned int maxWidth;
bool needPrefix;
};

struct colprintTable {
ptrArray *header;
ptrArray *lines;
};

static void fillWithWhitespaces (int i, FILE *fp)
{
while (i-- > 0)
{
fputc(' ', fp);
}
}

static struct colprintHeaderColumn * colprintHeaderColumnNew (const char* spec)
{
int offset = 2;
struct colprintHeaderColumn *headerCol = xCalloc (1, struct colprintHeaderColumn);

if (strstr(spec, "L:") == spec)
headerCol->justification = COLPRINT_LEFT;
else if (strstr(spec, "R:") == spec)
headerCol->justification = COLPRINT_RIGHT;
else
{
headerCol->justification = COLPRINT_LEFT;
offset = 0;
}

headerCol->value = vStringNewInit(spec + offset);
headerCol->maxWidth = vStringLength(headerCol->value);
return headerCol;
}

static void colprintHeaderColumnDelete (struct colprintHeaderColumn * headerCol)
{
vStringDelete (headerCol->value);
eFree (headerCol);
}

struct colprintTable *colprintTableNew (const char* columnHeader, ... /* NULL TERMINATED */)
{
char *tmp;
va_list ap;
struct colprintTable *table;
struct colprintHeaderColumn *headerCol;


table = xCalloc (1, struct colprintTable);
table->header = ptrArrayNew ((ptrArrayDeleteFunc)colprintHeaderColumnDelete);
table->lines = ptrArrayNew ((ptrArrayDeleteFunc)stringListDelete);

headerCol = colprintHeaderColumnNew(columnHeader);
ptrArrayAdd (table->header, headerCol);

va_start(ap, columnHeader);
while (1)
{
tmp = va_arg(ap, char*);
if (tmp)
{
headerCol = colprintHeaderColumnNew(tmp);
ptrArrayAdd (table->header, headerCol);
}
else
break;
}
va_end(ap);

struct colprintHeaderColumn *last_col = ptrArrayLast (table->header);
if (last_col)
last_col->justification = COLPRINT_LAST;

return table;
}

void colprintTableDelete (struct colprintTable *table)
{
ptrArrayDelete(table->header);
table->header = NULL;

ptrArrayDelete(table->lines);
table->header = NULL;

eFree (table);
}

static void colprintColumnPrintGeneric (vString *column, struct colprintHeaderColumn *spec, bool machinable, FILE *fp)
{
int maxWidth = spec->maxWidth + (spec->needPrefix? 1: 0);

if ((column == spec->value) && (spec->needPrefix))
{
fputc('#', fp);
maxWidth--;
}

if (machinable)
{
fputs (vStringValue (column), fp);
if (spec->justification != COLPRINT_LAST)
fputc ('\t', fp);
}
else
{
int padLen = maxWidth - vStringLength (column);
if (spec->justification == COLPRINT_LEFT
|| spec->justification == COLPRINT_LAST)
{
fputs (vStringValue (column), fp);
if (spec->justification != COLPRINT_LAST)
{
fillWithWhitespaces (padLen, fp);
fputc (' ', fp);
}
}
else
{
fillWithWhitespaces (padLen, fp);
fputs (vStringValue (column), fp);
fputc (' ', fp);
}
}
}

static void colprintHeaderColumnPrint (struct colprintHeaderColumn *headerCol, bool machinable, FILE* fp)
{
colprintColumnPrintGeneric (headerCol->value, headerCol, machinable, fp);
}

static void colprintHeaderPrint (ptrArray *header, int startFrom, bool withHeader, bool machinable, FILE *fp)
{
unsigned int i;

if (!withHeader)
return;

for (i = startFrom; i < ptrArrayCount(header); i++)
{
struct colprintHeaderColumn *headerCol = ptrArrayItem (header, i);
colprintHeaderColumnPrint (headerCol, machinable, fp);
}
fputc('\n', fp);
}

static void colprintLinePrint (stringList *line, int startFrom, ptrArray *header, bool machinable, FILE *fp)
{
unsigned int i;

for (i = startFrom; i < stringListCount (line); i++)
{
vString *value = stringListItem(line, i);
struct colprintHeaderColumn *spec = ptrArrayItem (header, i);
colprintColumnPrintGeneric(value, spec, machinable, fp);
}
}
static void colprintLinesPrint (ptrArray *lines, int startFrom, ptrArray *header, bool machinable, FILE *fp)
{
unsigned int i;

for (i = 0; i < ptrArrayCount (lines); i++)
{
stringList *line = ptrArrayItem (lines, i);
colprintLinePrint (line, startFrom, header, machinable, fp);
fputc('\n', fp);
}
}

static void colprintUpdateMaxWidths (ptrArray *header, ptrArray *lines, unsigned int startFrom)
{
for (unsigned int c = 0; c < ptrArrayCount(header); c++)
{
struct colprintHeaderColumn *spec = ptrArrayItem (header, c);

if (c == startFrom)
spec->needPrefix = true;
else
spec->needPrefix = false;
}

for (unsigned int c = 0; c < ptrArrayCount(header); c++)
{
struct colprintHeaderColumn *spec = ptrArrayItem (header, c);

for (unsigned int l = 0; l < ptrArrayCount(lines); l++)
{
struct colprintLine *line = ptrArrayItem(lines, l);
vString *column = ptrArrayItem((ptrArray *)line, c);
if (spec->maxWidth < vStringLength(column))
spec->maxWidth = vStringLength(column);
}
}
}

void colprintTablePrint (struct colprintTable *table, unsigned int startFrom, bool withHeader, bool machinable, FILE *fp)
{
colprintUpdateMaxWidths (table->header, table->lines, startFrom);

colprintHeaderPrint (table->header, startFrom, withHeader, machinable, fp);
colprintLinesPrint (table->lines, startFrom, table->header, machinable, fp);
}

void colprintTableSort (struct colprintTable *table, int (* compareFn) (struct colprintLine *, struct colprintLine *))
{
ptrArraySort (table->lines, (int (*) (const void *, const void *))compareFn);
}

struct colprintLine *colprintTableGetNewLine (struct colprintTable *table)
{
stringList *line = stringListNew ();

ptrArrayAdd (table->lines, line);
return (struct colprintLine *)line;
}

static void colprintLineAppendColumn (struct colprintLine *line, vString *column)
{
stringList *slist = (stringList *)line;
stringListAdd (slist, column);
}

void colprintLineAppendColumnCString (struct colprintLine *line, const char *column)
{
vString* vcol = vStringNewInit (column? column: "");
colprintLineAppendColumn (line, vcol);
}

void colprintLineAppendColumnVString (struct colprintLine *line, vString* column)
{
colprintLineAppendColumnCString(line, vStringValue (column));
}

void colprintLineAppendColumnChar (struct colprintLine *line, char column)
{
vString* vcol = vStringNew ();
vStringPut (vcol, column);
colprintLineAppendColumn (line, vcol);
}

void colprintLineAppendColumnInt (struct colprintLine *line, unsigned int column)
{
char buf[12];

snprintf(buf, 12, "%d", column);
colprintLineAppendColumnCString (line, buf);
}

const char *colprintLineGetColumn (struct colprintLine *line, unsigned int column)
{
stringList *slist = (stringList *)line;
if (column <= stringListCount(slist))
{
vString *vstr = stringListItem (slist, column);
return vStringValue (vstr);
}
else
return NULL;
}
31 changes: 31 additions & 0 deletions main/colprint.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright (c) 2017 Masatake YAMATO
*
* This source code is released for free distribution under the terms of the
* GNU General Public License version 2 or (at your option) any later version.
*
*/
#ifndef CTAGS_MAIN_COLPRINT_H
#define CTAGS_MAIN_COLPRINT_H

#include "general.h"
#include <stdio.h>

struct colprintTable;
struct colprintLine;

/* Each column must have a prefix for specifying justification: "L:" or "R:". */
struct colprintTable *colprintTableNew (const char* columnHeader, ... /* NULL TERMINATED */);
void colprintTableDelete (struct colprintTable *table);
void colprintTablePrint (struct colprintTable *table, unsigned int startFrom, bool withHeader, bool machinable, FILE *fp);
void colprintTableSort (struct colprintTable *table, int (* compareFn) (struct colprintLine *, struct colprintLine *));

struct colprintLine *colprintTableGetNewLine (struct colprintTable *table);

void colprintLineAppendColumnCString (struct colprintLine *line, const char* column);
void colprintLineAppendColumnChar (struct colprintLine *line, char column);
void colprintLineAppendColumnInt (struct colprintLine *line, unsigned int column);

const char *colprintLineGetColumn (struct colprintLine *line, unsigned int column);

#endif /* CTAGS_MAIN_COLPRINT_H */
Loading

0 comments on commit ad9b42b

Please sign in to comment.