commit c51d624e68e3487772398aaf9ce1f0f7a43099e5
parent 8f4179b5965065c23a44e64921a8e7edf1a5277c
Author: Ed van Bruggen <edvb54@gmail.com>
Date: Fri, 24 Mar 2017 20:39:08 -0700
Add -t option to list tags
If tag is given after option it shows all notes with that tag. If no tag
is given then the tags are simply listed. A tag is defined as words before
a colon. Also cleaned up util.c and moved specific string functions back
to nt.c
Diffstat:
README.md | | | 12 | ++++++++++-- |
nt.1 | | | 12 | ++++++++++-- |
nt.c | | | 140 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------- |
util.c | | | 92 | ------------------------------------------------------------------------------- |
util.h | | | 4 | ---- |
5 files changed, 138 insertions(+), 122 deletions(-)
diff --git a/README.md b/README.md
@@ -2,11 +2,16 @@
## SYNOPSIS
-`nt` [**-Dlvy**] [**-f** *FILE*] [**-e** *NOTE*] [**-d** *NOTE*] [**-s** *SEARCH*] [**-n** *NUM* | **-NUM**] [*NOTE* ...]
+`nt` [**-Dlvy**] [**-f** *FILE*] [**-e** *NOTE*] [**-d** *NOTE*] [**-s** *SEARCH*] [**-t** [*TAG*]] [**-n** *NUM* | **-NUM**] [*NOTE* ...]
## DESCRIPTION
-Simple note taker for the command line.
+Simple note taker for the command line. To take a note simply run the command
+with the new note as arguments or from stdin. The note will be saved to a plain
+text file with each line being a note. The file is saved to the file either
+specified with **-f** or in the default one from `config.h`. Notes can have tags
+by prefixing the note with a tag followed by a colon. For example a note
+`chores: take out trash` will have the tag `chores`.
## OPTIONS
@@ -31,6 +36,9 @@ Simple note taker for the command line.
**-s** *SEARCH*
Search for pattern *SEARCH* in notes
+**-t** [*TAG*]
+ Search for *TAG* in notes, list all tags if no *TAG* is given
+
**-v**
Print version info and exit
diff --git a/nt.1 b/nt.1
@@ -4,10 +4,15 @@
nt \- simple note taker
.SH SYNOPSIS
.PP
-\fB\fCnt\fR [\fB\-Dlvy\fP] [\fB\-f\fP \fIFILE\fP] [\fB\-e\fP \fINOTE\fP] [\fB\-d\fP \fINOTE\fP] [\fB\-s\fP \fISEARCH\fP] [\fB\-n\fP \fINUM\fP | \fB\-NUM\fP] [\fINOTE\fP ...]
+\fB\fCnt\fR [\fB\-Dlvy\fP] [\fB\-f\fP \fIFILE\fP] [\fB\-e\fP \fINOTE\fP] [\fB\-d\fP \fINOTE\fP] [\fB\-s\fP \fISEARCH\fP] [\fB\-t\fP [\fITAG\fP]] [\fB\-n\fP \fINUM\fP | \fB\-NUM\fP] [\fINOTE\fP ...]
.SH DESCRIPTION
.PP
-Simple note taker for the command line.
+Simple note taker for the command line. To take a note simply run the command
+with the new note as arguments or from stdin. The note will be saved to a plain
+text file with each line being a note. The file is saved to the file either
+specified with \fB\-f\fP or in the default one from \fB\fCconfig.h\fR\&. Notes can have tags
+by prefixing the note with a tag followed by a colon. For example a note
+\fB\fCchores: take out trash\fR will have the tag \fB\fCchores\fR\&.
.SH OPTIONS
.PP
\fB\-d\fP \fINOTE\fP
@@ -31,6 +36,9 @@ Simple note taker for the command line.
\fB\-s\fP \fISEARCH\fP
Search for pattern \fISEARCH\fP in notes
.PP
+\fB\-t\fP [\fITAG\fP]
+ Search for \fITAG\fP in notes, list all tags if no \fITAG\fP is given
+.PP
\fB\-v\fP
Print version info and exit
.PP
diff --git a/nt.c b/nt.c
@@ -1,4 +1,5 @@
/* See LICENSE file for copyright and license details. */
+#include <ctype.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
@@ -19,8 +20,13 @@ typedef struct Note {
} Note;
/* functions */
-int confirm(const char *msg, ...);
void linkadd(char *str);
+int confirm(const char *msg, ...);
+char *get_tag(char *str);
+
+char *strconcat(char **s, int c);
+char *strtrim(char *s);
+int strinlist(char *str, char **list, int listc);
void nt_del(void);
void nt_del_all(void);
@@ -47,25 +53,6 @@ int lsnum;
#include "config.h"
-/* prompt user if no -y option to confirm action */
-int
-confirm(const char *msg, ...)
-{
- if (yes) return 1;
-
- char input = 'n';
- va_list ap;
-
- va_start(ap, msg);
- printf("%s: ", argv0);
- vprintf(msg, ap);
- printf("? [y/N] ");
- va_end(ap);
- scanf("%c", &input);
-
- return (input == 'y' || input == 'Y') ? 1 : 0;
-}
-
/* add str to Note linked list */
void
linkadd(char *str)
@@ -93,7 +80,91 @@ linkadd(char *str)
cur->str = estrdup(str);
cur->next = NULL;
tail = cur;
+}
+
+/* prompt user if no -y option to confirm action */
+int
+confirm(const char *msg, ...)
+{
+ if (yes) return 1;
+
+ char input = 'n';
+ va_list ap;
+
+ va_start(ap, msg);
+ printf("%s: ", argv0);
+ vprintf(msg, ap);
+ printf("? [y/N] ");
+ va_end(ap);
+ scanf("%c", &input);
+
+ return (input == 'y' || input == 'Y') ? 1 : 0;
+}
+
+/* return just tag from str */
+char *
+get_tag(char *str)
+{
+ if (!str) die("get_tag: given null pointer");
+ char *tag = estrdup(str);
+ strtok(tag, ":");
+ return tag;
+}
+
+/* compress array of strings to single string */
+char *
+strconcat(char **s, int c)
+{
+ if (!s) die("strconcat: given null pointer");
+
+ int len, i;
+ char *ret;
+
+ for (i = 0; i < c; i++)
+ len += strlen(s[i]) + 1;
+ ret = ecalloc(len, sizeof(char));
+
+ strcpy(ret, s[0]);
+ strcat(ret, " ");
+ for (i = 1; i < c; i++) {
+ strcat(ret, s[i]);
+ strcat(ret, " ");
+ }
+
+ return ret;
+}
+
+/* remove tailing or leading white space from s */
+char *
+strtrim(char *s)
+{
+ char *end;
+
+ /* trim leading space */
+ while (isspace((unsigned char)*s)) s++;
+
+ if (*s == 0) /* all spaces? */
+ return s;
+ /* trim trailing space */
+ end = s + strlen(s) - 1;
+ while (end > s && isspace((unsigned char)*end)) end--;
+
+ /* write new null terminator */
+ *(end+1) = 0;
+
+ return s;
+}
+
+/* return if str is in the list */
+int
+strinlist(char *str, char **list, int listc)
+{
+ int i;
+ for (i = 0; i < listc; i++)
+ if (strcmp(str, list[i]) == 0)
+ return 1;
+ return 0;
}
/* delete oldest matching note from notes */
@@ -190,6 +261,28 @@ nt_search(void)
die("%s: search: '%s' not found", argv0, sub);
}
+/* list all tags or all notes with a given tag */
+void
+nt_tag(void)
+{
+ Note *cur = head;
+ char **tag = ecalloc(1, sizeof(char*));
+ int tagc = 0, i;
+
+ for (; cur; cur = cur->next, tagc++) {
+ tag = erealloc(tag, (tagc+2) * sizeof(char*));
+ tag[tagc] = get_tag(cur->str);
+ if (strcmp(sub, "") == 0 && !strinlist(tag[tagc], tag, tagc))
+ printf("%s\n", tag[tagc]);
+ else if (strcmp(sub, tag[tagc]) == 0)
+ printf("%s\n", cur->str);
+ }
+
+ for (i = 0; i < tagc; i++)
+ free(tag[i]);
+ free(tag);
+}
+
/* create a new note */
void
nt_new(void)
@@ -244,7 +337,7 @@ void
usage(void)
{
die("usage: %s [-Dlvy] [-f FILE] [-e NOTE] [-d NOTE]\n"
- " [-s SEARCH] [-n NUM | -NUM] [NOTE ...]", argv0);
+ " [-s SEARCH] [-t [TAG]] [-n NUM | -NUM] [NOTE ...]", argv0);
}
int
@@ -283,6 +376,10 @@ main(int argc, char *argv[])
case 's':
mode = nt_search;
break;
+ case 't':
+ mode = nt_tag;
+ neednt = 0;
+ break;
case 'v':
printf("%s v%s\n", argv0, VERSION);
return 0;
@@ -306,5 +403,4 @@ main(int argc, char *argv[])
cleanup();
return 0;
-
}
diff --git a/util.c b/util.c
@@ -1,5 +1,4 @@
/* See LICENSE file for copyright and license details. */
-#include <ctype.h>
#include <assert.h>
#include <stdarg.h>
#include <stdio.h>
@@ -48,97 +47,6 @@ estrdup(char *s)
return s;
}
-char *
-strconcat(char **s, int c)
-{
- if (!s) die("strconcat: given null pointer");
-
- int len, i;
- char *ret;
-
- for (i = 0; i < c; i++)
- len += strlen(s[i]) + 1;
- ret = ecalloc(len, sizeof(char));
-
- strcpy(ret, s[0]);
- strcat(ret, " ");
- for (i = 1; i < c; i++) {
- strcat(ret, s[i]);
- strcat(ret, " ");
- }
-
- return ret;
-}
-
-/* split string s into muiltple strings by a_delim */
-char **
-strsplit(const char *s, const char a_delim, int *size)
-{
- if (!s) die("strsplit: given null pointer");
-
- char **ret = 0;
- size_t count = 0;
- char *last_delim = 0;
- char delim[2] = { a_delim, 0 }; /* converet a_delim into string for strtok */
- char *a_str = ecalloc(strlen(s)+1, sizeof(char));
- strcpy(a_str, s);
-
- /* count number of elements that will be extracted. */
- for (char *tmp = a_str; *tmp; tmp++)
- if (a_delim == *tmp) {
- count++;
- last_delim = tmp;
- }
-
- /* add space for trailing token. */
- count += last_delim < (a_str + strlen(a_str) - 1);
-
- /* add space for terminating null string so caller
- * knows where the list of returned strings ends. */
- count++;
-
- ret = ecalloc(count, sizeof(char*));
-
- if (ret) {
- size_t idx = 0;
- char *token = strtok(a_str, delim);
-
- while (token) {
- assert(idx < count);
- *(ret + idx++) = estrdup(token);
- token = strtok(0, delim);
- }
- assert(idx == count - 1);
- *(ret + idx) = 0;
- }
-
- free(a_str);
- *size = count - 1;
- return ret;
-}
-
-/* remove tailing or leading white space from s */
-char *
-strtrim(char *s)
-{
- char *end;
-
- /* trim leading space */
- while (isspace((unsigned char)*s)) s++;
-
- if (*s == 0) /* all spaces? */
- return s;
-
- /* trim trailing space */
- end = s + strlen(s) - 1;
- while (end > s && isspace((unsigned char)*end)) end--;
-
- /* write new null terminator */
- *(end+1) = 0;
-
- return s;
-}
-
void
die(const char *fmt, ...)
{
diff --git a/util.h b/util.h
@@ -10,8 +10,4 @@ void *emalloc(size_t size);
void *erealloc(void *p, size_t size);
char *estrdup(char *s);
-char *strconcat(char **s, int c);
-char **strsplit(const char *s, const char a_delim, int *size);
-char *strtrim(char *s);
-
void die(const char *errstr, ...);