Allow for merging data files when reloading

This allows for merging the (unsaved) items with the items from the data
files when invoking the reload operation. To this end, an external merge
tool (defaults to vimdiff) is used.

Signed-off-by: Lukas Fleischer <calcurse@cryptocrack.de>
This commit is contained in:
Lukas Fleischer 2014-07-16 23:22:36 +02:00
parent e93030befb
commit 5aec540895
6 changed files with 97 additions and 18 deletions

View File

@ -707,8 +707,8 @@ int parse_args(int argc, char **argv)
io_load_app();
io_load_todo();
io_import_data(IO_IMPORT_ICAL, ifile);
io_save_apts();
io_save_todo();
io_save_apts(path_apts);
io_save_todo(path_todo);
non_interactive = 1;
}
if (xflag) {

View File

@ -256,11 +256,54 @@ static inline void key_generic_save(void)
static inline void key_generic_reload(void)
{
if (io_get_modified() && status_ask_bool(_("By reloading items, you "
"will lose any unsaved modifications. "
"Continue?")) != 1) {
wins_update(FLAG_STA);
return;
if (io_get_modified()) {
const char *msg_um_prefix =
_("There are unsaved modifications:");
const char *msg_um_discard = _("(d)iscard");
const char *msg_um_merge = _("(m)erge");
const char *msg_um_keep = _("(k)eep and cancel");
const char *msg_um_choice = _("[dmk]");
char msg_um_asktype[BUFSIZ];
snprintf(msg_um_asktype, BUFSIZ, "%s %s, %s, %s",
msg_um_prefix, msg_um_discard, msg_um_merge,
msg_um_keep);
char *path_apts_backup, *path_todo_backup;
const char *backup_ext = ".sav";
switch (status_ask_choice(msg_um_asktype, msg_um_choice, 3)) {
case 1:
break;
case 2:
path_apts_backup = xmalloc(strlen(path_apts) +
strlen(backup_ext) + 1);
path_todo_backup = xmalloc(strlen(path_todo) +
strlen(backup_ext) + 1);
sprintf(path_apts_backup, "%s%s", path_apts,
backup_ext);
sprintf(path_todo_backup, "%s%s", path_todo,
backup_ext);
io_save_mutex_lock();
io_save_apts(path_apts_backup);
io_save_todo(path_todo_backup);
io_save_mutex_unlock();
wins_launch_external2(path_apts, path_apts_backup,
conf.mergetool);
wins_launch_external2(path_todo, path_todo_backup,
conf.mergetool);
xfree(path_apts_backup);
xfree(path_todo_backup);
break;
case 3:
/* FALLTHROUGH */
default:
wins_update(FLAG_STA);
return;
}
}
/* Reinitialize data structures. */

View File

@ -103,8 +103,9 @@
#define DPID_PATH DIR_NAME DPID_PATH_NAME
#define NOTES_DIR DIR_NAME NOTES_DIR_NAME
#define DEFAULT_EDITOR "vi"
#define DEFAULT_PAGER "less"
#define DEFAULT_EDITOR "vi"
#define DEFAULT_PAGER "less"
#define DEFAULT_MERGETOOL "vimdiff"
#define ATTR_FALSE 0
#define ATTR_TRUE 1
@ -259,6 +260,7 @@ struct conf {
unsigned progress_bar;
const char *editor;
const char *pager;
const char *mergetool;
char output_datefmt[BUFSIZ]; /* format for displaying date */
int input_datefmt; /* format for reading date */
};
@ -753,8 +755,10 @@ void ical_export_data(FILE *);
unsigned io_fprintln(const char *, const char *, ...);
void io_init(const char *, const char *);
void io_extract_data(char *, const char *, int);
unsigned io_save_apts(void);
unsigned io_save_todo(void);
void io_save_mutex_lock(void);
void io_save_mutex_unlock(void);
unsigned io_save_apts(const char *);
unsigned io_save_todo(const char *);
unsigned io_save_keys(void);
void io_save_cal(enum save_display);
void io_load_app(void);
@ -1121,6 +1125,7 @@ void wins_reset(void);
void wins_prepare_external(void);
void wins_unprepare_external(void);
void wins_launch_external(const char *, const char *);
void wins_launch_external2(const char *, const char *, const char *);
void wins_status_bar(void);
void wins_erase_status_bar(void);
void wins_other_status_page(int);

View File

@ -319,12 +319,22 @@ void io_extract_data(char *dst_data, const char *org, int len)
static pthread_mutex_t io_save_mutex = PTHREAD_MUTEX_INITIALIZER;
void io_save_mutex_lock(void)
{
pthread_mutex_lock(&io_save_mutex);
}
void io_save_mutex_unlock(void)
{
pthread_mutex_unlock(&io_save_mutex);
}
/*
* Save the apts data file, which contains the
* appointments first, and then the events.
* Recursive items are written first.
*/
unsigned io_save_apts(void)
unsigned io_save_apts(const char *aptsfile)
{
llist_item_t *i;
FILE *fp;
@ -332,7 +342,7 @@ unsigned io_save_apts(void)
if (read_only)
return 1;
if ((fp = fopen(path_apts, "w")) == NULL)
if ((fp = fopen(aptsfile, "w")) == NULL)
return 0;
recur_save_data(fp);
@ -356,7 +366,7 @@ unsigned io_save_apts(void)
}
/* Save the todo data file. */
unsigned io_save_todo(void)
unsigned io_save_todo(const char *todofile)
{
llist_item_t *i;
FILE *fp;
@ -364,7 +374,7 @@ unsigned io_save_todo(void)
if (read_only)
return 1;
if ((fp = fopen(path_todo, "w")) == NULL)
if ((fp = fopen(todofile, "w")) == NULL)
return 0;
LLIST_FOREACH(&todolist, i) {
@ -419,12 +429,12 @@ void io_save_cal(enum save_display display)
if (show_bar)
progress_bar(PROGRESS_BAR_SAVE, PROGRESS_BAR_TODO);
if (!io_save_todo())
if (!io_save_todo(path_todo))
ERROR_MSG("%s", access_pb);
if (show_bar)
progress_bar(PROGRESS_BAR_SAVE, PROGRESS_BAR_APTS);
if (!io_save_apts())
if (!io_save_apts(path_apts))
ERROR_MSG("%s", access_pb);
if (show_bar)

View File

@ -126,7 +126,7 @@ struct dmon_conf dmon;
*/
void vars_init(void)
{
const char *ed, *pg;
const char *ed, *pg, *mt;
/* Variables for user configuration */
conf.confirm_quit = 1;
@ -159,6 +159,11 @@ void vars_init(void)
pg = DEFAULT_PAGER;
conf.pager = pg;
mt = getenv("MERGETOOL");
if (mt == NULL || mt[0] == '\0')
mt = DEFAULT_MERGETOOL;
conf.mergetool = mt;
wins_set_layout(1);
ui_calendar_set_first_day_of_week(MONDAY);

View File

@ -611,6 +611,22 @@ void wins_launch_external(const char *file, const char *cmd)
wins_unprepare_external();
}
/*
* While inside interactive mode, launch the external command cmd on the given
* two files.
*/
void wins_launch_external2(const char *file1, const char *file2,
const char *cmd)
{
const char *arg[] = { cmd, file1, file2, NULL };
int pid;
wins_prepare_external();
if ((pid = shell_exec(NULL, NULL, *arg, arg)))
child_wait(NULL, NULL, pid);
wins_unprepare_external();
}
#define NB_CAL_CMDS 28 /* number of commands while in cal view */
#define NB_APP_CMDS 33 /* same thing while in appointment view */
#define NB_TOD_CMDS 32 /* same thing while in todo view */