diary

Text-based journaling program
git clone https://git.in0rdr.ch/diary.git
Log | Files | Refs | README | LICENSE

commit 8420712317f8c340d146f8b20a8d720e8823bf17
parent ed467795aaa78361b19d771bed959ec49fdc354b
Author: Andreas Gruhler <agruhl@gmx.ch>
Date:   Sun,  7 Feb 2021 14:16:55 +0100

Reorder options and precedence example

This commit reorders the options and arguments in the help texts:
* version
* help
* dir
* editor
* fmt
* range
* weekday

Further, it provides an example on variable precedence. The precedence
is roughly defined as follows:
1. Default values in the source code
2. Config file
3. Environment variables
4. Option arguments
5. Non-option argument

To make this order consistent for the weekday value derived from the
glibc locale, the commit includes an additional check for the $LANG
environment variable.

Diffstat:
MREADME.md | 51+++++++++++++++++++++++++++++++++++++++------------
Mdiary.1 | 121+++++++++++++++++++++++++++++++++++++++++++++++++------------------------------
Mdiary.c | 76+++++++++++++++++++++++++++++++++++++++++-----------------------------------
3 files changed, 156 insertions(+), 92 deletions(-)

diff --git a/README.md b/README.md @@ -75,28 +75,55 @@ Note: for *BSD users run gmake. The [`diary.cfg`](./diary.cfg) configuration file can optionally be used to persist diary configuration. To install the sample from this repository: ```bash -mkdir -p ~/.config/diary -cp diary.cfg ~/.config/diary/ +mkdir -p ${XDG_CONFIG_HOME:-~/.config}/diary +cp diary.cfg ${XDG_CONFIG_HOME:-~/.config}/diary/ ``` -The file `~/.config/diary/diary.cfg` should adhere to a basic `key = value` format. Lines can be commented with the special characters `#` or `;`. The following configuration keys are currently supported: +The file `${XDG_CONFIG_HOME:-~/.config}/diary/diary.cfg` should adhere to a basic `key = value` format. Lines can be commented with the special characters `#` or `;`. The following configuration keys are currently supported: | Command Line Option | Config Key | Example Config Value | Default Config Value | Description | | --- | --- | --- | --- | --- | | `--dir`, `-d`, or first non-option argument | `dir` | ~/diary | n/a | Diary directory. Path that holds the journal text files. If unset, defaults to environment variable `$DIARY_DIR`.| -| `--range` or `-r` | `range` | 10 | 1 | Number of years to show before/after todays date | -| `--weekday` or `-w` | `weekday` | 0 | 1 | First weekday, `0` = Sunday, `1` = Monday, ..., `6` = Saturday. Use `0` to display week beginning at Sunday ("S-M-T-W-T-F-S"), or `1` for "M-T-W-T-F-S-S" (default) | -| `--fmt` or `-f` | `fmt` | %d_%b_%y | %Y-%m-%d | Date format and file name for the files inside the `dir`. For the format specifiers, see [`man strftime`](https://man7.org/linux/man-pages/man3/strftime.3.html). Be careful: If you change this, you might no longer find your existing diary entries, because the diary assumes to find the journal files under another file name. Hence, a change in FMT shows an empty diary, at first. Rename all files in the DIARY_DIR to migrate to a new FMT. | | `--editor` or `-e` | `editor` | "vim" | "" | Editor to open journal files with. If unset, defaults to environment variable `$EDITOR`. If no editor is provided, the diary is opened read-only. | +| `--fmt` or `-f` | `fmt` | %d_%b_%y | %Y-%m-%d | Date format and file name for the files inside the `dir`. For the format specifiers, see [`man strftime`](https://man7.org/linux/man-pages/man3/strftime.3.html). Be careful: If you change this, you might no longer find your existing diary entries, because the diary assumes to find the journal files under another file name. Hence, a change in FMT shows an empty diary, at first. Rename all files in the DIARY_DIR to migrate to a new FMT. | +| `--range` or `-r` | `range` | 10 | 1 | Number of years to show before/after todays date | +| `--weekday` or `-w` | `weekday` | 0 | 1 | First weekday, `0` = Sunday, `1` = Monday, ..., `6` = Saturday. Use `0` to display week beginning at Sunday ("S-M-T-W-T-F-S"), or `1` for "M-T-W-T-F-S-S". If `glibc` is installed, the first day of the week is derived from the current locale setting (`$LANG`, see `man locale`). Without `glibc`, the first weekday defaults to 1 (Monday), unless specified otherwise with this option. | ## Precedence Rules <a name="precedence_rules"></a> -The variable defaults, for instance, for the variables `EDITOR` and `DIARY_DIR`, are populated with values in the following order: +The default variables, for instance, for the configuration variables `editor`, `dir` and `weekday`, are populated with values in the following order: 1. No default for `DIARY_DIR`. Defaults for `range`, `weekday`, `fmt` and `editor` are provided in [diary.h](diary.h) * If `EDITOR` is unset and no editor is provided in the config file or via the `-e` option, the diary works read-only. Journal files cannot be opened. * If `DIARY_DIR` is not provided, the diary won't open. -2. **Config file** (empty default for `CONFIG.editor`, no default for `CONFIG.dir`) -3. **Environment** variables `$DIARY_DIR` / `$EDITOR` -4. **Option arguments** `-d` / `-e` -5. First non-option argument is interpreted as `DIARY_DIR` -\ No newline at end of file +2. **Config file** (empty default for `editor`, no default for `dir`) +3. **Environment** variables `$DIARY_DIR`, `$EDITOR` and `$LANG` for locale (`weekday`) +4. **Option arguments** `-d` / `-e` / `-w` +5. First non-option argument is interpreted as `DIARY_DIR` + +### Precedence Example: Locale and First Day of Week + +If glibc is installed, the first weekday defaults to the locale defined in the current shell environment (`$LANG`, see `man locale`), unless specified otherwise via the `--wekday` / `-w` command line options. For example: + +```bash +# start with weekday=3(Wed), overrule any other configuration value +$ diary -w3 + +# start with glibc derived weekday=1, regardless of 'weekday' in config file +$ LANG=de_CH diary + +# if glibc is installed, start with glibc derived base date (weekday=0) +$ LANG= diary + +# disable environment variable, default to value from config file +$ unset LANG + +# start with 'weekday' default from config file, if available +$ diary + +# remove config file +$ rm ${XDG_CONFIG_HOME:-~/.config}/diary/diary.cfg + +# start with 'weekday' default value from source code (1=Mon) +$ diary +``` +\ No newline at end of file diff --git a/diary.1 b/diary.1 @@ -22,23 +22,53 @@ Show diary help text \fB\-d\fR, \fB\-\-dir\fR=\fI\,DIARY_DIR\/\fR Diary storage directory DIARY_DIR .TP -\fB\-r\fR, \fB\-\-range\fR=\fI\,RANGE\/\fR -RANGE is the number of years to show before/after todays date -.TP -\fB\-f\fR, \fB\-\-date_weekday\fR=\fI\,DAY\/\fR -First day of the week. DAY is an integer in range (0..6), -interpreted as 0 = Sun, 1 = Mon, ..., 6 = Sat +\fB\-e\fR, \fB\-\-editor\fR=\fI\,EDITOR\/\fR +EDITOR is the text editor used for opening the journal files. .TP \fB\-f\fR, \fB\-\-fmt\fR=\fI\,FMT\/\fR FMT is a custom date and file format. Change with care, because the diary reads and writes to files with file name FMT. The new FMT is only applied to newly saved entries. Existing entries with the old FMT are not automatically migrated to the new FMT and do not show up with a new FMT -specifier. Consequently, a change in FMT shows an empty diary, at first. +specifier. Consequently, a change in FMT shows an empty diary at first. Rename all files in the DIARY_DIR to migrate to a new FMT. .TP -\fB\-e\fR, \fB\-\-editor\fR=\fI\,EDITOR\/\fR -EDITOR is the text editor used for opening the journal files. +\fB\-r\fR, \fB\-\-range\fR=\fI\,RANGE\/\fR +RANGE is the number of years to show before/after todays date. Defaults to 1 year. +.TP +\fB\-f\fR, \fB\-\-weekday\fR=\fI\,DAY\/\fR +First day of the week. DAY is an integer in range (0..6), interpreted as 0 = Sun, +1 = Mon, ..., 6 = Sat. If glibc is installed, the first day of the week is derived +from the current locale setting ('$LANG', see man locale). Without glibc, the +first weekday defaults to 1 (Monday), unless specified otherwise with this option. + +.SH NAVIGATION +Navigation is done using the following vim-inspired keyboard shortcuts: + +.TS +tab(|); +l l. +Key(s) | Action +====== | ====== +k, up | go backward by 1 week +j, down | go forward by 1 week +h, left | go backward by 1 day +l, right | go forward by 1 day +J | go forward by 1 month +K | go backward by 1 month + +e, enter | edit current entry +d, x | delete current entry +q | quit the program + +N | go to the previous journal entry +n | go to the next journal entry +g | go to the first journal entry +G | go to the last journal entry + +t | jump to today +s | jump to specific day +.TE .SH ENVIRONMENT @@ -46,13 +76,16 @@ EDITOR is the text editor used for opening the journal files. If this variable is set to a directory that can be opened, .B diary will use it to store diary files. Diary files are simple text files named -after their date, formatted like FMT (see '-f'/'--fmt' options and +after their date, formatted according to FMT (see '-f'/'--fmt' options and 'fmt' config key). The format defaults to "%Y-%m-%d", which is "YYYY-MM-DD" (see man strftime). All other files different from FMT are ignored. .IP EDITOR The program used to edit journal entries. +.IP LANG +The default locale used to display the first day of the week. + .SH ARGUMENTS If the argument \fIDIRECTORY\fR is given, diary files are read from and @@ -73,7 +106,7 @@ The diary.cfg configuration file can optionally be used to persist diary configu Create default config location: .nf - $ mkdir -p ~/.config/diary + $ mkdir -p ${XDG_CONFIG_HOME:-~/.config}/diary .fi Install an example config file with defaults: @@ -88,42 +121,14 @@ Install an example config file with defaults: # Date and file format, change with care fmt = %Y-%m-%d # Editor to open journal files with - editor = ""' | sed 's/^[[:space:]]*//' > ~/.config/diary/diary.cfg + editor = ""' | sed 's/^[[:space:]]*//' > ${XDG_CONFIG_HOME:-~/.config}/diary/diary.cfg .fi -Use characters '#' or ';' for commenting lines. - -.SH NAVIGATION -Navigation is done using the following vim-inspired keyboard shortcuts: - -.TS -tab(|); -l l. -Key(s) | Action -====== | ====== -k, up | go backward by 1 week -j, down | go forward by 1 week -h, left | go backward by 1 day -l, right | go forward by 1 day -J | go forward by 1 month -K | go backward by 1 month - -e, enter | edit current entry -d, x | delete current entry -q | quit the program - -N | go to the previous journal entry -n | go to the next journal entry -g | go to the first journal entry -G | go to the last journal entry - -t | jump to today -s | jump to specific day -.TE +Use the '#' or ';' characters to comment lines. .SH PRECEDENCE RULES -The variable defaults, for instance, for the variables 'EDITOR' and 'DIARY_DIR', are populated with values in the following order: +The default variables, for instance, for the configuration variables 'editor', 'dir' and 'weekday', are populated with values in the following order: .TP 1. @@ -138,12 +143,12 @@ won't open. 2. .B Config file -(empty default for 'CONFIG.editor', no default for 'CONFIG.dir') +(empty default for 'editor', no default for 'dir') .TP 3. .B Environment -variables '$DIARY_DIR' / '$EDITOR' +variables '$DIARY_DIR', '$EDITOR' and '$LANG' for locale ('weekday') .TP 4. .B @@ -151,11 +156,37 @@ Option arguments, see section .B OPTIONS -'-d' / '-e' .TP 5. First non-option argument \fIDIRECTORY\fR is interpreted as 'DIARY_DIR' +.SH PRECEDENCE EXAMPLE: LOCALE AND FIRST DAY OF WEEK +If glibc is installed, the first weekday defaults to the locale defined in the current shell +environment ($LANG, see man locale), unless specified otherwise via the '--wekday'/'-w'. + +.nf + # start with weekday=3(Wed), overrule any other configuration value + $ diary -w3 + + # start with glibc derived weekday=1, regardless of 'weekday' in config file + $ LANG=de_CH diary + + # if glibc is installed, start with glibc derived base date (weekday=0) + $ LANG= diary + + # disable environment variable, default to value from config file + $ unset LANG + + # start with 'weekday' default from config file, if available + $ diary + + # remove config file + $ rm ${XDG_CONFIG_HOME:-~/.config}/diary/diary.cfg + + # start with 'weekday' default value from source code (1=Mon) + $ diary +.fi + .SH DEVELOPMENT All source code is available in this github repository: <https://github.com/in0rdr/diary/>. Contributions are always welcome! diff --git a/diary.c b/diary.c @@ -342,10 +342,10 @@ void usage() { printf(" -v, --version : Print diary version\n"); printf(" -h, --help : Show diary help text\n"); printf(" -d, --dir DIARY_DIR : Diary storage directory DIARY_DIR\n"); + printf(" -e, --editor EDITOR : Editor to open journal files with\n"); + printf(" -f, --fmt FMT : Date and file format, change with care\n"); printf(" -r, --range RANGE : RANGE is the number of years to show before/after today's date\n"); printf(" -w, --weekday DAY : First day of the week, 0 = Sun, 1 = Mon, ..., 6 = Sat\n"); - printf(" -f, --fmt FMT : Date and file format, change with care\n"); - printf(" -e, --editor EDITOR : Editor to open journal files with\n"); printf("\n"); printf("Full docs and keyboard shortcuts: DIARY(1)\n"); printf("or online via: <https://github.com/in0rdr/diary>\n"); @@ -358,37 +358,6 @@ int main(int argc, char** argv) { char* config_file_path; chtype atrs; - #ifdef __GNU_LIBRARY__ - // references: locale(5) and util-linux's cal.c - // get the base date, 8-digit integer (YYYYMMDD) returned as char * - #ifdef _NL_TIME_WEEK_1STDAY - unsigned long d = (uintptr_t) nl_langinfo(_NL_TIME_WEEK_1STDAY); - // reference: https://sourceware.org/glibc/wiki/Locales - // assign a static date value 19971130 (a Sunday) - #else - unsigned long d = 19971130; - #endif - struct tm base = { - .tm_sec = 0, - .tm_min = 0, - .tm_hour = 0, - .tm_mday = d % 100, - .tm_mon = (d / 100) % 100 - 1, - .tm_year = d / (100 * 100) - 1900 - }; - mktime(&base); - // weekday is base date's day of the week offset by (_NL_TIME_FIRST_WEEKDAY - 1) - #ifdef __linux__ - CONFIG.weekday = (base.tm_wday + *nl_langinfo(_NL_TIME_FIRST_WEEKDAY) - 1) % 7; - #elif defined __MACH__ - CFIndex first_day_of_week; - CFCalendarRef currentCalendar = CFCalendarCopyCurrent(); - first_day_of_week = CFCalendarGetFirstWeekday(currentCalendar); - CFRelease(currentCalendar); - CONFIG.weekday = (base.tm_wday + first_day_of_week - 1) % 7; - #endif - #endif - // the diary directory defaults to the diary_dir specified in the config file config_home = getenv("XDG_CONFIG_HOME"); if (config_home == NULL) config_home = XDG_CONFIG_HOME_FALLBACK; @@ -414,6 +383,43 @@ int main(int argc, char** argv) { strcpy(CONFIG.editor, env_var); } + // get locale from environment variable LANG + // https://www.gnu.org/software/gettext/manual/html_node/Locale-Environment-Variables.html + env_var = getenv("LANG"); + if (env_var != NULL) { + // if available, overwrite the editor with the environments locale + #ifdef __GNU_LIBRARY__ + // references: locale(5) and util-linux's cal.c + // get the base date, 8-digit integer (YYYYMMDD) returned as char * + #ifdef _NL_TIME_WEEK_1STDAY + unsigned long d = (uintptr_t) nl_langinfo(_NL_TIME_WEEK_1STDAY); + // reference: https://sourceware.org/glibc/wiki/Locales + // assign a static date value 19971130 (a Sunday) + #else + unsigned long d = 19971130; + #endif + struct tm base = { + .tm_sec = 0, + .tm_min = 0, + .tm_hour = 0, + .tm_mday = d % 100, + .tm_mon = (d / 100) % 100 - 1, + .tm_year = d / (100 * 100) - 1900 + }; + mktime(&base); + // weekday is base date's day of the week offset by (_NL_TIME_FIRST_WEEKDAY - 1) + #ifdef __linux__ + CONFIG.weekday = (base.tm_wday + *nl_langinfo(_NL_TIME_FIRST_WEEKDAY) - 1) % 7; + #elif defined __MACH__ + CFIndex first_day_of_week; + CFCalendarRef currentCalendar = CFCalendarCopyCurrent(); + first_day_of_week = CFCalendarGetFirstWeekday(currentCalendar); + CFRelease(currentCalendar); + CONFIG.weekday = (base.tm_wday + first_day_of_week - 1) % 7; + #endif + #endif + } + // get the diary directory via argument, this takes precedence over env/config if (argc < 2) { if (CONFIG.dir == NULL) { @@ -430,10 +436,10 @@ int main(int argc, char** argv) { { "version", no_argument, 0, 'v' }, { "help", no_argument, 0, 'h' }, { "dir", required_argument, 0, 'd' }, + { "editor", required_argument, 0, 'e' }, + { "fmt", required_argument, 0, 'f' }, { "range", required_argument, 0, 'r' }, { "weekday", required_argument, 0, 'w' }, - { "fmt", required_argument, 0, 'f' }, - { "editor", required_argument, 0, 'e' }, { 0, 0, 0, 0 } };