nt

Unnamed repository; edit this file 'description' to name the repository.
git clone git://edryd.org/nt
Log | Files | Refs | LICENSE

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, ...);