summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosias <justjosias@tutanota.com>2020-04-22 13:37:23 +0300
committerJosias <justjosias@tutanota.com>2020-04-22 13:37:23 +0300
commitf79b58016e1757164e5e3f3e4d7a0b9533981e8d (patch)
treed9a8f5f77d4bce7955bb9ef8dfdcb87a6e059cb8
parent3140ef2a51699ebb8399bb94962148b87c4ef8cf (diff)
Use enTangleD for literate programming
-rw-r--r--Makefile14
-rw-r--r--README.md8
-rw-r--r--rccat.c42
-rw-r--r--rccat.md197
4 files changed, 216 insertions, 45 deletions
diff --git a/Makefile b/Makefile
index c8758ba..3a1e308 100644
--- a/Makefile
+++ b/Makefile
@@ -2,25 +2,13 @@ PREFIX ?= /usr/local
INSTALL ?= install
INSTALL_PROGRAM ?= $(INSTALL)
-ifneq "$(DESTDIR)" ""
- PREFIX = $(DESTDIR)
-endif
-
all: build
-
build:
$(CC) -o rccat rccat.c
-run:
- ./rccat
clean:
$(RM) rccat
-install: rccat
- #$(PRE_INSTALL)
+install:
$(INSTALL_PROGRAM) -d $(PREFIX)/bin
-
- #$(NORMAL_INSTALL)
$(INSTALL_PROGRAM) -m755 rccat $(PREFIX)/bin
-
uninstall:
- #$(NORMAL_UNINSTALL)
$(RM) $(PREFIX)/bin/rccat
diff --git a/README.md b/README.md
index cc102f9..74e2f5c 100644
--- a/README.md
+++ b/README.md
@@ -2,13 +2,17 @@
A cat-like tool to make printing files into the terminal a little more interesting.
+I have now revised the program with literate programming with [enTangleD](https://entangled.github.io). It has been an interesting experience, and now you can easily read the source code of the program in [rccat.md](rccat.md).
+
+The generated files are also pushed (`rccat.c` and `Makefile`), so you don't need enTangleD to be able to use it.
+
## Usage
First compile with `make`.
Then use it like, `rccat FILENAME`.
-## Roadmap
+## TODO
- [x] Support multiple files
- [ ] Implement basic options (including -v and -h)
@@ -16,4 +20,4 @@ Then use it like, `rccat FILENAME`.
## Contributing
-This is not a serious project, and I am using this to help me to learn C. But corrections for my errors are welcome.
+This is not a serious project, and I am using this to help me to learn C (and now literate programming). But corrections for my errors are welcome.
diff --git a/rccat.c b/rccat.c
index 0fed002..2963758 100644
--- a/rccat.c
+++ b/rccat.c
@@ -3,7 +3,7 @@
#include <string.h>
#include <time.h>
#include <unistd.h>
-
+#define BUF_SIZE 10
#define KNRM "\x1B[0m"
#define KRED "\x1B[31m"
#define KGRN "\x1B[32m"
@@ -15,19 +15,13 @@
const char *colors[7] = {KNRM, KRED, KGRN, KYEL, KBLU, KMAG, KCYN};
-typedef struct config {
- int end;
-} config;
-
int lastcolor = 0;
void printColors(char *text)
{
- // If the output is piped, the colors don't make much sense
if (!(isatty(STDOUT_FILENO))) {
printf("%s", text);
return;
}
- // Normal operation
if (text) {
for (int i = 0; i < strlen(text); ++i) {
int color = 0;
@@ -35,48 +29,36 @@ void printColors(char *text)
color = rand() % 6;
} while (color == lastcolor);
lastcolor = color;
- // for the future
- //if (text[i] == '\n')
- // printf("$");
printf("%s%c", colors[color], text[i]);
}
}
- printf("%s", KWHT); // reset to default colors
+ printf("%s", KWHT);
}
-
-const int BUF_SIZE = 10;
-
int main(int argc, char *argv[])
{
srand(time(NULL));
-
- char buffer[10] = {""};
+ char buffer[BUF_SIZE] = {""};
for (int i = 0; i < argc; ++i) {
if (strcmp(argv[i], "-") == 0 || argc == 1) {
- while (fgets(buffer, BUF_SIZE, stdin) != NULL) {
- printColors(buffer);
- }
- clearerr(stdin);
+
} else if (i >= 1) {
FILE *fp;
fp = fopen(argv[i], "r");
-
- if (fp) {
- size_t got;
- while ((got = fread(buffer, 1, BUF_SIZE -1, fp))) {
- buffer[got] = '\0';
+ if (!(fp)) {
+ fprintf(stderr, "rccat: %s: no such file or directory.\n", argv[i]);
+ }
+ size_t got;
+ while ((got = fread(buffer, 1, BUF_SIZE -1, fp))) {
+ buffer[got] = '\0';
printColors(buffer);
}
printf("%s", KWHT);
if (ferror(fp))
fprintf(stderr, "Error: can't read %s\n", argv[1]);
- fclose(fp);
- } else {
- fprintf(stderr, "rccat: %s: no such file or directory.\n", argv[1]);
- }
+ fclose(fp);
}
}
- return 0;
+ return EXIT_SUCCESS;
}
diff --git a/rccat.md b/rccat.md
new file mode 100644
index 0000000..69520b8
--- /dev/null
+++ b/rccat.md
@@ -0,0 +1,197 @@
+# rccat
+
+This program will provide a `cat`-like utility for printing text from a file to `stdout`. Except that output will be randomly colorized.
+
+Thus the name: Randomly Colored Cat.
+
+Here is the basic structure of the program:
+
+``` {.c file=rccat.c}
+<<includes>>
+<<constants>>
+
+<<colors-function>>
+<<main-function>>
+```
+
+Now for the includes:
+
+``` {.c #includes}
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+```
+
+`unistd.h`, `stdlib.h`, and `time.h` are required for randomness, `stdio.h` for `printf`, and `string.h` for `strcmp` and `strlen`.
+
+Some constants that will be the same throughout the program:
+``` {.c #constants}
+#define BUF_SIZE 10
+<<colors>>
+```
+
+Now the colors:
+
+``` {.c #colors}
+#define KNRM "\x1B[0m"
+#define KRED "\x1B[31m"
+#define KGRN "\x1B[32m"
+#define KYEL "\x1B[33m"
+#define KBLU "\x1B[34m"
+#define KMAG "\x1B[35m"
+#define KCYN "\x1B[36m"
+#define KWHT "\x1B[37m"
+
+const char *colors[7] = {KNRM, KRED, KGRN, KYEL, KBLU, KMAG, KCYN};
+```
+
+These are all the codes for the colors we want, and an array to order them nicely to randomly index them.
+
+## Print Colors
+
+``` {.c #colors-function}
+int lastcolor = 0;
+void printColors(char *text)
+{
+ <<notty>>
+ if (text) {
+ <<normal>>
+ }
+ <<reset>>
+}
+```
+
+If the output is piped (and thus isn't a tty), the colors don't make much sense.
+``` {.c #notty}
+if (!(isatty(STDOUT_FILENO))) {
+ printf("%s", text);
+ return;
+}
+```
+
+Go through the text character by character and print it with a random color between 0 and 6 (the index of colors). It also makes sure that the color is not the same as the last one.
+``` {.c #normal}
+for (int i = 0; i < strlen(text); ++i) {
+ int color = 0;
+ do {
+ color = rand() % 6;
+ } while (color == lastcolor);
+ lastcolor = color;
+ printf("%s%c", colors[color], text[i]);
+}
+```
+
+Now we have to reset the terminal to the normal colors.
+``` {.c #reset}
+printf("%s", KWHT);
+```
+
+## Main
+
+The main function that every C program must have.
+
+``` {.c #main-function}
+int main(int argc, char *argv[])
+{
+ <<main-body>>
+
+ return EXIT_SUCCESS;
+}
+```
+
+Initialize random and buffer, and loop through the arguments.
+``` {.c #main-body}
+srand(time(NULL));
+char buffer[BUF_SIZE] = {""};
+
+for (int i = 0; i < argc; ++i) {
+ <<parse-arg>>
+}
+```
+
+Determine whether or not the argument is `-`. If so, get the input from `stdin` instead of a file. In addition, it should not try to read the file from `argv[0]`, since that is itself.
+``` {.c #parse-arg}
+if (strcmp(argv[i], "-") == 0 || argc == 1) {
+ <<print-from-stdin>>
+} else if (i >= 1) {
+ <<open-file>>
+ <<read-file>>
+ <<close-file>>
+}
+```
+
+``` {.c #read-file}
+size_t got;
+while ((got = fread(buffer, 1, BUF_SIZE -1, fp))) {
+ buffer[got] = '\0';
+ printColors(buffer);
+ }
+ printf("%s", KWHT);
+ if (ferror(fp))
+ fprintf(stderr, "Error: can't read %s\n", argv[1]);
+```
+
+Prepare a file pointer and make sure the file exists. If not, write an error to `stderr`.
+``` {.c #open-file}
+FILE *fp;
+fp = fopen(argv[i], "r");
+if (!(fp)) {
+ fprintf(stderr, "rccat: %s: no such file or directory.\n", argv[i]);
+}
+```
+
+``` {.c #close-file}
+fclose(fp);
+```
+
+## Building
+
+To compile with your C compiler directly, you can use `gcc -o rccat rccat.c`, but that isn't as useful as a Makefile.
+
+The complete Makefile:
+
+``` {.make file=Makefile}
+PREFIX ?= /usr/local
+INSTALL ?= install
+INSTALL_PROGRAM ?= $(INSTALL)
+
+<<make-all>>
+<<make-build>>
+<<make-clean>>
+<<make-install>>
+<<make-uninstall>>
+```
+
+`PREFIX` determines where you want the program to be installed when `make install` is run.
+
+If you just want to run `make`, it automatically calls build.
+``` {.make #make-all}
+all: build
+```
+
+Compiling the program with your C compiler.
+``` {.make #make-build}
+build:
+ $(CC) -o rccat rccat.c
+```
+
+A simple way to delete the `rccat` file, and any other generated files (in the future).
+``` {.make #make-clean}
+clean:
+ $(RM) rccat
+```
+
+Install the program to `PREFIX` (as mentioned above). It first prepares the install and then copies over the file to `PREFIX/bin`.
+``` {.make #make-install}
+install:
+ $(INSTALL_PROGRAM) -d $(PREFIX)/bin
+ $(INSTALL_PROGRAM) -m755 rccat $(PREFIX)/bin
+```
+
+Uninstall the program from `PREFIX/bin`.
+``` {.make #make-uninstall}
+uninstall:
+ $(RM) $(PREFIX)/bin/rccat
+```