summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md13
-rw-r--r--TODO11
-rw-r--r--config.mk2
-rw-r--r--gramscii.156
-rw-r--r--gramscii.c114
5 files changed, 180 insertions, 16 deletions
diff --git a/README.md b/README.md
index 2d6fe84..f23c2a0 100644
--- a/README.md
+++ b/README.md
@@ -74,3 +74,16 @@ intellectual, a philosopher, and an artist, and maintained that societal
changes are only possible when a class exerts intellectual and moral
leadership over its contemporaries. So just get rid of all your shiny
iPointless things and come back to reality.
+
+COPYING
+=======
+
+`gramscii` is written and maintained by Vincenzo 'KatolaZ' Nicosia
+<katolaz@freaknet.org>. You can use, modify and/or redistribute it under
+the terms of the GNU General Public Licence, either version 3 of the
+License or, at your option, any later version.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
diff --git a/TODO b/TODO
index 32af33c..f6087c7 100644
--- a/TODO
+++ b/TODO
@@ -1,14 +1,13 @@
+ optimize redraws (redraw only the modified rectangle)
- change screen management (i.e., dynamic array of lines)
-- add action multiplier (e.g., "7h" moves left by 7 cols)
-- add scripting mode option ("-s"?)
- add screen geometry option (-g 25x80?)
- read file at point
+ - read output of command (!)
- use [ENTER] to exit from text insert
- maybe move "text" mode to "t"
- implement ellipse
-- parse control characters
- - parse arrows (text-mode will allow movements as well)
++ parse control characters
+ + parse arrows (text-mode will allow movements as well)
- (?) implement CTRL+G as abort (aside ESC)
- add crop command (c)
- remove extra blanks until EOL when saving to file
@@ -23,7 +22,9 @@
- allow scrolling (both vertical and horizontal)
- catch SIGWINCH and react appropriately (after scroll is
enabled)
-- auto-arrow 'A' (automatic end-char)
+* add action multiplier (e.g., "7h" moves left by 7 cols)
+* add scripting mode option ("-s"?)
+* auto-arrow 'A' (automatic end-char)
* move configs in config.h
* get screen geometry
* allow the use of [ENTER] to confirm arrow, boxes (useful
diff --git a/config.mk b/config.mk
index f06b872..c801aca 100644
--- a/config.mk
+++ b/config.mk
@@ -3,4 +3,4 @@ BINDIR = ${PREFIX}/bin
MANDIR = ${PREFIX}/share/man
CFLAGS = -O3 -std=c90 -pedantic -Wall
-##CC = cc
+CC = cc
diff --git a/gramscii.1 b/gramscii.1
index 82c2fb3..c7f5c2f 100644
--- a/gramscii.1
+++ b/gramscii.1
@@ -4,6 +4,9 @@ gramscii \- simple editor for ASCII box diagrams
.SH SYNOPSIS
.PP
gramscii
+.RI [-s]
+.RI [-h]
+.RI [file ...]
.PP
.SH DESCRIPTION
.PP
@@ -11,6 +14,18 @@ gramscii is a simple interactive editor to create ASCII box-and-arrows
diagrams. It uses vi-like keybindings for drawing and editing boxes,
arrows, and text.
.PP
+.SH OPTIONS
+.TP 5m
+.BI -s
+Start gramscii in script-mode. In this mode the screen is set to 25 rows
+by 80 columns, no status bar is present, drawings and cursor movements
+are not shown, and the state of the screen is dumped to stdout when the
+program ends. With this flag, gramscii can be used in a pipeline,
+getting commands from stdin (or from a file) and making its output
+available for further processing.
+.TP
+.BI -h
+Print short usage unstructions and exit.
.SH COMMANDS
gramscii is a visual modal editor. Commands are associated to
keystrokes, and keystrokes have different meaning in different modes.
@@ -97,7 +112,9 @@ move the cursor right by 1 column
.PP
gramscii accepts also the uppercase commands
.B H, J, K, L,
-which will move in the corresponding direction by 5 units at a time.
+which will move in the corresponding direction by a LONG_STEP number of
+units at a time (defaults to 5, change LONG_STEP in config.h as you
+wish).
.TP 5m
.BI g
Initiate a global positioning command (go). These are two-letter
@@ -152,8 +169,35 @@ Typing
.BI g
followed by any character that is not listed above has no effect on the
cursor.
+.SS MULTIPLIERS
+Simple cursor movement commands (hjklHJKL) can be preceded by a number
+that acts as a multiplier. For instance, the command:
+.PP
+.RS
+14h
+.PP
.RE
-
+will move the cursor by 14 steps to the left. Similarily, the command:
+.PP
+.RS
+7J
+.PP
+.RE
+will move the cursor by 7 LONG_STEPs rows down (with the default
+LONG_STEP equal to 5, this will correspond to 35 rows down).
+.PP
+Multipliers can be used whenever a movement command is legal, i.e. in
+move, box, arrox, visual, and erase mode. So for instance the sequence:
+.RS
+ggb13l18jb
+.PP
+.RE
+will draw a 18x13 box whose top-left corner coincides with the top-left
+corner of the screen.
+.PP
+Multipliers are ignored by global positioning commands (i.e., those
+starting with
+.B g)
.SS MODES
The currently supported modes are:
.B move,
@@ -233,6 +277,14 @@ styles. See
.B STYLES
below for more information.
.TP 7m
+.BI A
+Exactly as
+.BI a
+toggles
+.B arrow
+mode, but the end point marker is automatically set according to the
+direction of the arrow.
+.TP 7m
.BI x
Toggle
.B erase
diff --git a/gramscii.c b/gramscii.c
index 4152b96..3bed08b 100644
--- a/gramscii.c
+++ b/gramscii.c
@@ -27,6 +27,7 @@
#include <signal.h>
#include <string.h>
#include <sys/ioctl.h>
+#include <ctype.h>
#include "config.h"
@@ -80,6 +81,7 @@ int dir;
int x;
int y;
int step;
+int mult;
int force_new;
char cursor;
char corner;
@@ -101,6 +103,7 @@ char fname[256];
char visual;
char silent;
+char autoend;
char *argv0;
@@ -147,6 +150,20 @@ char* state_str(){
return "ERR";
}
+char get_mark(char dir){
+ switch(dir){
+ case DIR_U:
+ return '^';
+ case DIR_D:
+ return 'v';
+ case DIR_L:
+ return '<';
+ case DIR_R:
+ return '>';
+ }
+ return '>';
+}
+
void status_bar(){
@@ -355,26 +372,78 @@ void handle_goto(){
show_cursor();
}
-int move_around(char c){
+int get_escape(FILE *fc){
+ char c[4];
+
+ c[0] = fgetc(fc);
+ if (c[0] == '['){
+ c[1] = fgetc(fc);
+ switch(c[1]){
+ case 'D':
+ dir = DIR_L;
+ x -= step;
+ break;
+ case 'B':
+ dir = DIR_D;
+ y += step;
+ break;
+ case 'A':
+ dir = DIR_U;
+ y -= step;
+ break;
+ case 'C':
+ dir = DIR_R;
+ x += step;
+ break;
+ }
+ return 1;
+ }
+ else{
+ ungetc(c[0], fc);
+ return 0;
+ }
+
+}
+
+
+int move_around(char c, FILE *fc){
+
+ if (isdigit(c)){
+ if (mult)
+ mult *=10;
+ mult += c - '0';
+ return 0;
+ }
switch(c){
+ case 27: /* control sequence? */
+ c = get_escape(fc);
+ break;
case 'H': step = LONG_STEP;/** FALLTHROUGH **/
case 'h':
dir = DIR_L;
+ if (mult)
+ step *= mult;
x -= step;
break;
case 'J': step = LONG_STEP;/** FALLTHROUGH **/
case 'j':
+ if (mult)
+ step *= mult;
dir = DIR_D;
y += step;
break;
case 'K': step = LONG_STEP;/** FALLTHROUGH **/
case 'k':
+ if (mult)
+ step *= mult;
dir = DIR_U;
y -= step;
break;
case 'L': step = LONG_STEP;/** FALLTHROUGH **/
case 'l':
+ if (mult)
+ step *= mult;
dir = DIR_R;
x += step;
break;
@@ -384,6 +453,7 @@ int move_around(char c){
default:
return 0;
}
+ mult = 0;
return c;
}
@@ -535,7 +605,7 @@ void get_box(FILE *fc){
while((c=fgetc(fc))!=EOF && c != 27 && c!= 'b' && c != '\n'){
if (change_style(c))
goto update_box;
- if (!move_around(c))
+ if (!move_around(c, fc))
continue;
check_bound();
redraw();
@@ -589,7 +659,12 @@ void draw_arrow(int x, int y, char *a, int a_len, int fix){
/* f(x,y,mark_end);*/
cur_dir = a[i];
}
- f(x,y,mark_end);
+ if (autoend){
+ if (cur_dir != DIR_N)
+ f(x,y, get_mark(cur_dir));
+ }
+ else
+ f(x,y,mark_end);
show_cursor();
}
@@ -613,7 +688,7 @@ void get_arrow(FILE *fc){
while((c=fgetc(fc))!=EOF && c != 27 && c!= 'a' && c != '\n'){
if (change_style(c))
goto update_arrow;
- if (!move_around(c))
+ if (!move_around(c, fc))
continue;
check_bound();
/* FIXME: if we are out of bound, do nothing? */
@@ -664,7 +739,7 @@ void delete(FILE *fc){
status_bar();
show_cursor();
while((c=fgetc(fc))!=EOF && c!=27 && c!= 'x' && c != '\n'){
- if (!move_around(c)) continue;
+ if (!move_around(c, fc)) continue;
check_bound();
do_delete(orig_x, orig_y);
step = 1;
@@ -758,7 +833,7 @@ void visual_box(FILE *fc){
set_video(VIDEO_REV);
draw_box(x,y,NOFIX);
while((c=fgetc(fc))!=EOF && c != 27 && c!= 'v' && c != '\n'){
- if (!move_around(c)) switch(c){
+ if (!move_around(c, fc)) switch(c){
case 'f':/* fill */
f = get_key(fc, "fill char: "); /** FALLTHROUGH **/
case 'x':/* erase */
@@ -842,7 +917,7 @@ void commands(FILE *fc){
char c;
while((c=fgetc(fc))!=EOF){
- if (!change_style(c) && !move_around(c)){
+ if (!change_style(c) && !move_around(c, fc)){
switch(c){
case 'i':
state = TEXT;
@@ -855,9 +930,11 @@ void commands(FILE *fc){
state = BOX;
get_box(fc);
break;
+ case 'A': autoend=1;
case 'a':
state = ARROW;
get_arrow(fc);
+ autoend = 0;
break;
case 'W':
force_new = 1;/** FALLTHROUGH **/
@@ -897,17 +974,38 @@ void commands(FILE *fc){
}
+void usage(){
+ fprintf(stderr, "Usage: %s [-s] [-h] [file ...]\n", argv0);
+ exit(1);
+}
+
int main(int argc, char *argv[]){
+ FILE *fc;
ARGBEGIN {
case 's':
silent = 1;
break;
+ case 'h': /* FALLTHROUGH */
+ default:
+ usage();
} ARGEND;
init();
-
+ while (argc){
+ fc = fopen(argv[0], "r");
+ if (fc == NULL){
+ fprintf(stderr, "Error opening file %s\n", argv[0]);
+ }
+ else {
+ commands(fc);
+ fclose(fc);
+ redraw();
+ }
+ argv++;
+ argc--;
+ }
commands(stdin);
cleanup(0);
return 0;