summaryrefslogtreecommitdiff
path: root/src/tools/viewcsv.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/viewcsv.cpp')
-rw-r--r--src/tools/viewcsv.cpp868
1 files changed, 434 insertions, 434 deletions
diff --git a/src/tools/viewcsv.cpp b/src/tools/viewcsv.cpp
index 5009ea8..328cafc 100644
--- a/src/tools/viewcsv.cpp
+++ b/src/tools/viewcsv.cpp
@@ -20,33 +20,33 @@ using namespace Bu;
20class Options : public Bu::OptParser 20class Options : public Bu::OptParser
21{ 21{
22public: 22public:
23 Options( int argc, char *argv[] ) : 23 Options( int argc, char *argv[] ) :
24 bHeader( true ) 24 bHeader( true )
25 { 25 {
26 addOption( bHeader, "no-header", 26 addOption( bHeader, "no-header",
27 "Don't use the first line as a header row. This behaviour can " 27 "Don't use the first line as a header row. This behaviour can "
28 "also be toggled while running with 'h'." ); 28 "also be toggled while running with 'h'." );
29 setNonOption( slot( this, &Options::onNonOption ) ); 29 setNonOption( slot( this, &Options::onNonOption ) );
30 addHelpOption(); 30 addHelpOption();
31 31
32 setOverride( "no-header", "true" ); 32 setOverride( "no-header", "true" );
33 parse( argc, argv ); 33 parse( argc, argv );
34 } 34 }
35 35
36 virtual ~Options() 36 virtual ~Options()
37 { 37 {
38 } 38 }
39 39
40 int onNonOption( StrArray aParams ) 40 int onNonOption( StrArray aParams )
41 { 41 {
42 //sio << aParams << sio.nl; 42 //sio << aParams << sio.nl;
43 sFileIn = aParams[0]; 43 sFileIn = aParams[0];
44 44
45 return 0; 45 return 0;
46 } 46 }
47 47
48 Bu::String sFileIn; 48 Bu::String sFileIn;
49 bool bHeader; 49 bool bHeader;
50}; 50};
51 51
52typedef Bu::Array<StrArray> StrGrid; 52typedef Bu::Array<StrArray> StrGrid;
@@ -54,421 +54,421 @@ typedef Bu::Array<int> IntArray;
54class CsvDoc 54class CsvDoc
55{ 55{
56public: 56public:
57 CsvDoc() : 57 CsvDoc() :
58 iMaxCols( 0 ) 58 iMaxCols( 0 )
59 { 59 {
60 } 60 }
61 61
62 virtual ~CsvDoc() 62 virtual ~CsvDoc()
63 { 63 {
64 } 64 }
65 65
66 void addRow( StrArray aStr ) 66 void addRow( StrArray aStr )
67 { 67 {
68 sgData.append( aStr ); 68 sgData.append( aStr );
69 if( iMaxCols < aStr.getSize() ) 69 if( iMaxCols < aStr.getSize() )
70 iMaxCols = aStr.getSize(); 70 iMaxCols = aStr.getSize();
71 while( aWidths.getSize() < iMaxCols ) 71 while( aWidths.getSize() < iMaxCols )
72 { 72 {
73 aWidths.append( 0 ); 73 aWidths.append( 0 );
74 } 74 }
75 for( int j = 0; j < aStr.getSize(); j++ ) 75 for( int j = 0; j < aStr.getSize(); j++ )
76 { 76 {
77 if( aWidths[j] < aStr[j].getSize() ) 77 if( aWidths[j] < aStr[j].getSize() )
78 aWidths[j] = aStr[j].getSize(); 78 aWidths[j] = aStr[j].getSize();
79 } 79 }
80 } 80 }
81 81
82 int iMaxCols; 82 int iMaxCols;
83 StrGrid sgData; 83 StrGrid sgData;
84 IntArray aWidths; 84 IntArray aWidths;
85}; 85};
86 86
87class CsvView 87class CsvView
88{ 88{
89public: 89public:
90 CsvView( CsvDoc &doc ) : 90 CsvView( CsvDoc &doc ) :
91 doc( doc ), 91 doc( doc ),
92 iXOff( 0 ), 92 iXOff( 0 ),
93 iYOff( 0 ), 93 iYOff( 0 ),
94 bHeaderRow( false ) 94 bHeaderRow( false )
95 { 95 {
96 } 96 }
97 97
98 virtual ~CsvView() 98 virtual ~CsvView()
99 { 99 {
100 } 100 }
101 101
102 void render() 102 void render()
103 { 103 {
104 erase(); 104 erase();
105 int maxx, maxy; 105 int maxx, maxy;
106 getmaxyx( stdscr, maxy, maxx ); 106 getmaxyx( stdscr, maxy, maxx );
107 107
108 int iRows = buMin( (int)doc.sgData.getSize(), maxy-((bHeaderRow)?(4):(3)) ); 108 int iRows = buMin( (int)doc.sgData.getSize(), maxy-((bHeaderRow)?(4):(3)) );
109 int iCols = buMin( doc.iMaxCols, (int)maxx-1 ); 109 int iCols = buMin( doc.iMaxCols, (int)maxx-1 );
110 110
111 int iHdrHeight = 1; 111 int iHdrHeight = 1;
112 if( bHeaderRow ) 112 if( bHeaderRow )
113 iHdrHeight++; 113 iHdrHeight++;
114 114
115 // Draw the headers 115 // Draw the headers
116 for( int iRow = 0; iRow < iRows; iRow++ ) 116 for( int iRow = 0; iRow < iRows; iRow++ )
117 { 117 {
118 if( iRow+iYOff >= doc.sgData.getSize() ) 118 if( iRow+iYOff >= doc.sgData.getSize() )
119 break; 119 break;
120 char buf[6]; 120 char buf[6];
121 snprintf( buf, 6, "%5d", iRow+iYOff ); 121 snprintf( buf, 6, "%5d", iRow+iYOff );
122 mvaddnstr( iRow+iHdrHeight+1, 0, buf, 5 ); 122 mvaddnstr( iRow+iHdrHeight+1, 0, buf, 5 );
123 mvaddch( iRow+iHdrHeight+1, 6, ACS_VLINE ); 123 mvaddch( iRow+iHdrHeight+1, 6, ACS_VLINE );
124 } 124 }
125 int iXPos = 6; 125 int iXPos = 6;
126 try 126 try
127 { 127 {
128 for( int iCol = 0; iCol < iCols; iCol++ ) 128 for( int iCol = 0; iCol < iCols; iCol++ )
129 { 129 {
130 if( iXPos >= maxx ) 130 if( iXPos >= maxx )
131 break; 131 break;
132 int iWidth = buMin( doc.aWidths[iCol+iXOff], maxx-iXPos-1 ); 132 int iWidth = buMin( doc.aWidths[iCol+iXOff], maxx-iXPos-1 );
133 char buf[6]; 133 char buf[6];
134 snprintf( buf, 6, "%d", iCol+iXOff ); 134 snprintf( buf, 6, "%d", iCol+iXOff );
135 mvaddch( 0, iXPos, ACS_VLINE ); 135 mvaddch( 0, iXPos, ACS_VLINE );
136 mvaddch( iHdrHeight, iXPos, ACS_PLUS ); 136 mvaddch( iHdrHeight, iXPos, ACS_PLUS );
137 mvaddnstr( 0, iXPos+1, buf, 5 ); 137 mvaddnstr( 0, iXPos+1, buf, 5 );
138 if( bHeaderRow ) 138 if( bHeaderRow )
139 { 139 {
140 mvaddnstr( 140 mvaddnstr(
141 1, iXPos+1, doc.sgData[0][iCol+iXOff].getStr(), iWidth 141 1, iXPos+1, doc.sgData[0][iCol+iXOff].getStr(), iWidth
142 ); 142 );
143 mvaddch( 1, iXPos, ACS_VLINE ); 143 mvaddch( 1, iXPos, ACS_VLINE );
144 } 144 }
145 for( int j = 0; j < iWidth; j++ ) 145 for( int j = 0; j < iWidth; j++ )
146 { 146 {
147 mvaddch( iHdrHeight, iXPos+j+1, ACS_HLINE ); 147 mvaddch( iHdrHeight, iXPos+j+1, ACS_HLINE );
148 } 148 }
149 iXPos += iWidth+1; 149 iXPos += iWidth+1;
150 } 150 }
151 } 151 }
152 catch(...) { } 152 catch(...) { }
153 for( int j = 0; j < 6; j++ ) 153 for( int j = 0; j < 6; j++ )
154 { 154 {
155 mvaddch( iHdrHeight, j, ACS_HLINE ); 155 mvaddch( iHdrHeight, j, ACS_HLINE );
156 } 156 }
157 157
158 // Draw some data 158 // Draw some data
159 for( int iRow = 0; iRow < iRows; iRow++ ) 159 for( int iRow = 0; iRow < iRows; iRow++ )
160 { 160 {
161 try 161 try
162 { 162 {
163 int iXPos = 6; 163 int iXPos = 6;
164 for( int iCol = 0; iCol < iCols; iCol++ ) 164 for( int iCol = 0; iCol < iCols; iCol++ )
165 { 165 {
166 if( iXPos >= maxx ) 166 if( iXPos >= maxx )
167 break; 167 break;
168 int iWidth = buMin( doc.aWidths[iCol+iXOff], maxx-iXPos-1 ); 168 int iWidth = buMin( doc.aWidths[iCol+iXOff], maxx-iXPos-1 );
169 mvaddch( iRow+iHdrHeight+1, iXPos, ACS_VLINE ); 169 mvaddch( iRow+iHdrHeight+1, iXPos, ACS_VLINE );
170 mvaddnstr( iRow+iHdrHeight+1, iXPos+1, 170 mvaddnstr( iRow+iHdrHeight+1, iXPos+1,
171 doc.sgData[iRow+iYOff][iCol+iXOff].getStr(), iWidth ); 171 doc.sgData[iRow+iYOff][iCol+iXOff].getStr(), iWidth );
172 iXPos += iWidth+1; 172 iXPos += iWidth+1;
173 } 173 }
174 } catch(...) { } 174 } catch(...) { }
175 } 175 }
176 176
177 attron( A_REVERSE ); 177 attron( A_REVERSE );
178 for( int j = 0; j < maxx; j++ ) 178 for( int j = 0; j < maxx; j++ )
179 { 179 {
180 mvaddch( maxy-1, j, ' ' ); 180 mvaddch( maxy-1, j, ' ' );
181 } 181 }
182 mvaddstr( maxy-1, 1, "q) quit h) toggle header row" ); 182 mvaddstr( maxy-1, 1, "q) quit h) toggle header row" );
183 char buf[30]; 183 char buf[30];
184 int iWidth = sprintf( buf, "[%dx%ld]", 184 int iWidth = sprintf( buf, "[%dx%ld]",
185 doc.iMaxCols, doc.sgData.getSize() 185 doc.iMaxCols, doc.sgData.getSize()
186 ); 186 );
187 mvaddstr( maxy-1, maxx-iWidth-1, buf ); 187 mvaddstr( maxy-1, maxx-iWidth-1, buf );
188 attroff( A_REVERSE ); 188 attroff( A_REVERSE );
189 } 189 }
190 190
191 void move( int iX, int iY ) 191 void move( int iX, int iY )
192 { 192 {
193 iXOff += iX; 193 iXOff += iX;
194 iYOff += iY; 194 iYOff += iY;
195 if( iXOff < 0 ) 195 if( iXOff < 0 )
196 iXOff = 0; 196 iXOff = 0;
197 197
198 if( bHeaderRow ) 198 if( bHeaderRow )
199 { 199 {
200 if( iYOff < 1 ) 200 if( iYOff < 1 )
201 iYOff = 1; 201 iYOff = 1;
202 } 202 }
203 else 203 else
204 { 204 {
205 if( iYOff < 0 ) 205 if( iYOff < 0 )
206 iYOff = 0; 206 iYOff = 0;
207 } 207 }
208 208
209 if( iYOff >= doc.sgData.getSize() ) 209 if( iYOff >= doc.sgData.getSize() )
210 iYOff = doc.sgData.getSize()-1; 210 iYOff = doc.sgData.getSize()-1;
211 211
212 if( iXOff >= doc.iMaxCols ) 212 if( iXOff >= doc.iMaxCols )
213 iXOff = doc.iMaxCols-1; 213 iXOff = doc.iMaxCols-1;
214 } 214 }
215 215
216 void pageDown() 216 void pageDown()
217 { 217 {
218 int maxx, maxy; 218 int maxx, maxy;
219 getmaxyx( stdscr, maxy, maxx ); 219 getmaxyx( stdscr, maxy, maxx );
220 move( 0, maxy-((bHeaderRow)?(4):(3)) ); 220 move( 0, maxy-((bHeaderRow)?(4):(3)) );
221 } 221 }
222 222
223 void pageUp() 223 void pageUp()
224 { 224 {
225 int maxx, maxy; 225 int maxx, maxy;
226 getmaxyx( stdscr, maxy, maxx ); 226 getmaxyx( stdscr, maxy, maxx );
227 move( 0, -(maxy-((bHeaderRow)?(4):(3))) ); 227 move( 0, -(maxy-((bHeaderRow)?(4):(3))) );
228 } 228 }
229 229
230 void home() 230 void home()
231 { 231 {
232 iYOff = 0; 232 iYOff = 0;
233 if( bHeaderRow ) iYOff++; 233 if( bHeaderRow ) iYOff++;
234 } 234 }
235 235
236 void end() 236 void end()
237 { 237 {
238 iYOff = doc.sgData.getSize()-1; 238 iYOff = doc.sgData.getSize()-1;
239 } 239 }
240 240
241 void setHeaderRow( bool bOn ) 241 void setHeaderRow( bool bOn )
242 { 242 {
243 if( bHeaderRow == bOn ) 243 if( bHeaderRow == bOn )
244 return; 244 return;
245 245
246 bHeaderRow = bOn; 246 bHeaderRow = bOn;
247 move( 0, ((bOn)?(1):(-1)) ); 247 move( 0, ((bOn)?(1):(-1)) );
248 } 248 }
249 249
250 void toggleHeaderRow() 250 void toggleHeaderRow()
251 { 251 {
252 setHeaderRow( !bHeaderRow ); 252 setHeaderRow( !bHeaderRow );
253 } 253 }
254 254
255 Bu::String prompt( const Bu::String &sPrompt ) 255 Bu::String prompt( const Bu::String &sPrompt )
256 { 256 {
257 int maxx, maxy; 257 int maxx, maxy;
258 Bu::String sStr; 258 Bu::String sStr;
259 259
260 RegEx re( sPrompt ); 260 RegEx re( sPrompt );
261 261
262 curs_set( 1 ); 262 curs_set( 1 );
263 for(;;) 263 for(;;)
264 { 264 {
265 getmaxyx( stdscr, maxy, maxx ); 265 getmaxyx( stdscr, maxy, maxx );
266 for( int j = 0; j < maxx; j++ ) 266 for( int j = 0; j < maxx; j++ )
267 { 267 {
268 mvaddch( maxy-1, j, ' ' ); 268 mvaddch( maxy-1, j, ' ' );
269 } 269 }
270 mvaddstr( maxy-1, 0, sPrompt.getStr() ); 270 mvaddstr( maxy-1, 0, sPrompt.getStr() );
271 271
272 mvaddstr( maxy-1, sPrompt.getSize(), sStr.getStr() ); 272 mvaddstr( maxy-1, sPrompt.getSize(), sStr.getStr() );
273 273
274 int iCh = getch(); 274 int iCh = getch();
275 switch( iCh ) 275 switch( iCh )
276 { 276 {
277 case '\n': 277 case '\n':
278 case '\r': 278 case '\r':
279 case KEY_ENTER: 279 case KEY_ENTER:
280 curs_set( 0 ); 280 curs_set( 0 );
281 return sStr; 281 return sStr;
282 break; 282 break;
283 283
284 case KEY_BACKSPACE: 284 case KEY_BACKSPACE:
285 if( sStr.getSize() > 0 ) 285 if( sStr.getSize() > 0 )
286 sStr.resize( sStr.getSize()-1 ); 286 sStr.resize( sStr.getSize()-1 );
287 break; 287 break;
288 288
289 default: 289 default:
290 if( iCh < 127 ) 290 if( iCh < 127 )
291 sStr += (char)iCh; 291 sStr += (char)iCh;
292 break; 292 break;
293 } 293 }
294 } 294 }
295 } 295 }
296 296
297 void resetCaret() 297 void resetCaret()
298 { 298 {
299 sysCaret.reset(); 299 sysCaret.reset();
300 } 300 }
301 301
302 void findNext( const Bu::String &sTerm ) 302 void findNext( const Bu::String &sTerm )
303 { 303 {
304 RegEx re( sTerm ); 304 RegEx re( sTerm );
305 305
306 int y = sysCaret.iRow; 306 int y = sysCaret.iRow;
307 if( y < 0 ) 307 if( y < 0 )
308 y = 0; 308 y = 0;
309 int x = sysCaret.iCol+1; 309 int x = sysCaret.iCol+1;
310 for( ; y < doc.sgData.getSize(); y++ ) 310 for( ; y < doc.sgData.getSize(); y++ )
311 { 311 {
312 StrArray &aRow = doc.sgData[y]; 312 StrArray &aRow = doc.sgData[y];
313 for( ; x < aRow.getSize(); x++ ) 313 for( ; x < aRow.getSize(); x++ )
314 { 314 {
315 if( re.execute( aRow[x] ) ) //aRow[x].find( sTerm ) ) 315 if( re.execute( aRow[x] ) ) //aRow[x].find( sTerm ) )
316 { 316 {
317 sysCaret.iRow = y; 317 sysCaret.iRow = y;
318 sysCaret.iCol = x; 318 sysCaret.iCol = x;
319 scrollToCaret(); 319 scrollToCaret();
320 return; 320 return;
321 } 321 }
322 } 322 }
323 x = 0; 323 x = 0;
324 } 324 }
325 } 325 }
326 326
327 void scrollToCaret() 327 void scrollToCaret()
328 { 328 {
329 iXOff = sysCaret.iCol; 329 iXOff = sysCaret.iCol;
330 iYOff = sysCaret.iRow; 330 iYOff = sysCaret.iRow;
331 } 331 }
332 332
333 CsvDoc &doc; 333 CsvDoc &doc;
334 int iXOff; 334 int iXOff;
335 int iYOff; 335 int iYOff;
336 bool bHeaderRow; 336 bool bHeaderRow;
337 337
338 class Caret 338 class Caret
339 { 339 {
340 public: 340 public:
341 Caret() : 341 Caret() :
342 iRow( -1 ), 342 iRow( -1 ),
343 iCol( -1 ) 343 iCol( -1 )
344 { 344 {
345 } 345 }
346 346
347 virtual ~Caret() 347 virtual ~Caret()
348 { 348 {
349 } 349 }
350 350
351 351
352 void reset() 352 void reset()
353 { 353 {
354 iRow = iCol = -1; 354 iRow = iCol = -1;
355 } 355 }
356 356
357 bool isSet() 357 bool isSet()
358 { 358 {
359 if( iRow < 0 || iCol < 0 ) 359 if( iRow < 0 || iCol < 0 )
360 return false; 360 return false;
361 return true; 361 return true;
362 } 362 }
363 363
364 int iRow; 364 int iRow;
365 int iCol; 365 int iCol;
366 }; 366 };
367 367
368 Caret sysCaret; 368 Caret sysCaret;
369}; 369};
370 370
371int main( int argc, char *argv[] ) 371int main( int argc, char *argv[] )
372{ 372{
373 Options opt( argc, argv ); 373 Options opt( argc, argv );
374 374
375 if( !opt.sFileIn.isSet() ) 375 if( !opt.sFileIn.isSet() )
376 { 376 {
377 sio << "No file specified." << sio.nl; 377 sio << "No file specified." << sio.nl;
378 return 1; 378 return 1;
379 } 379 }
380 380
381 CsvDoc doc; 381 CsvDoc doc;
382 { 382 {
383 File fIn( opt.sFileIn, File::Read ); 383 File fIn( opt.sFileIn, File::Read );
384 NewLine nlIn( fIn ); 384 NewLine nlIn( fIn );
385 Buffer bIn( nlIn ); 385 Buffer bIn( nlIn );
386 CsvReader cr( bIn ); 386 CsvReader cr( bIn );
387 387
388 while( !fIn.isEos() ) 388 while( !fIn.isEos() )
389 { 389 {
390 StrArray sa = cr.readLine(); 390 StrArray sa = cr.readLine();
391 if( fIn.isEos() ) 391 if( fIn.isEos() )
392 break; 392 break;
393 doc.addRow( sa ); 393 doc.addRow( sa );
394 } 394 }
395 } 395 }
396 396
397 initscr(); 397 initscr();
398 cbreak(); 398 cbreak();
399 noecho(); 399 noecho();
400 nonl(); 400 nonl();
401 intrflush( stdscr, FALSE ); 401 intrflush( stdscr, FALSE );
402 keypad( stdscr, TRUE ); 402 keypad( stdscr, TRUE );
403 curs_set( 0 ); 403 curs_set( 0 );
404 404
405 CsvView view( doc ); 405 CsvView view( doc );
406 view.setHeaderRow( opt.bHeader ); 406 view.setHeaderRow( opt.bHeader );
407 407
408 Bu::String sSearchTerm; 408 Bu::String sSearchTerm;
409 409
410 bool bRun = true; 410 bool bRun = true;
411 do 411 do
412 { 412 {
413 view.render(); 413 view.render();
414 414
415 int ch = getch(); 415 int ch = getch();
416 switch( ch ) 416 switch( ch )
417 { 417 {
418 case 'q': 418 case 'q':
419 bRun = false; 419 bRun = false;
420 break; 420 break;
421 421
422 case KEY_DOWN: 422 case KEY_DOWN:
423 view.move( 0, 1 ); 423 view.move( 0, 1 );
424 break; 424 break;
425 425
426 case KEY_UP: 426 case KEY_UP:
427 view.move( 0, -1 ); 427 view.move( 0, -1 );
428 break; 428 break;
429 429
430 case KEY_LEFT: 430 case KEY_LEFT:
431 view.move( -1, 0 ); 431 view.move( -1, 0 );
432 break; 432 break;
433 433
434 case KEY_RIGHT: 434 case KEY_RIGHT:
435 view.move( 1, 0 ); 435 view.move( 1, 0 );
436 break; 436 break;
437 437
438 case KEY_NPAGE: 438 case KEY_NPAGE:
439 view.pageDown(); 439 view.pageDown();
440 break; 440 break;
441 441
442 case KEY_PPAGE: 442 case KEY_PPAGE:
443 view.pageUp(); 443 view.pageUp();
444 break; 444 break;
445 445
446 case KEY_HOME: 446 case KEY_HOME:
447 view.home(); 447 view.home();
448 break; 448 break;
449 449
450 case KEY_END: 450 case KEY_END:
451 view.end(); 451 view.end();
452 break; 452 break;
453 453
454 case '/': 454 case '/':
455 sSearchTerm = view.prompt("find: "); 455 sSearchTerm = view.prompt("find: ");
456 view.resetCaret(); 456 view.resetCaret();
457 view.findNext( sSearchTerm ); 457 view.findNext( sSearchTerm );
458 break; 458 break;
459 459
460 case 'n': 460 case 'n':
461 view.findNext( sSearchTerm ); 461 view.findNext( sSearchTerm );
462 break; 462 break;
463 463
464 case 'h': 464 case 'h':
465 view.toggleHeaderRow(); 465 view.toggleHeaderRow();
466 break; 466 break;
467 } 467 }
468 } while( bRun ); 468 } while( bRun );
469 469
470 endwin(); 470 endwin();
471 471
472 return 0; 472 return 0;
473} 473}
474 474