cmd_flag.v

2.4 KB · raw

1//! `koh flag` — mark a save unsafe, clear the mark, or list what is marked.2//!3//! A flag is an event, not a column: save records are write-once, and clearing4//! a flag is itself an event, so flagging stays undoable and syncs like5//! everything else.67module cli89import json210import src.events11import src.fmt12import src.history13import src.storage1415pub fn cmd_flag(raw []string) int {16	args := parse('flag', raw, Options{17		values: ['reason']18		flags:  ['clear', 'json']19	}) or { return usage_error(err.msg()) }20	store := open_store() or { return refuse(args.json(), err.msg()) }21	defer {22		store.close()23	}24	if args.positional.len == 0 && !args.flag('clear') {25		return list_flags(store, args)26	}27	id := args.positional_at(0)28	if id == '' {29		return usage_error('flag needs a save ID, or nothing at all to list flagged saves')30	}31	save := history.resolve(store, id) or { return refuse(args.json(), err.msg()) }32	if args.flag('clear') {33		events.clear_flag(store, save.id) or { return refuse(args.json(), err.msg()) }34		if args.json() {35			emit_json(json2.encode(FlagJson{36				save_id: save.id37				flagged: false38				reason:  ''39			}))40			return 041		}42		ok('cleared the flag on [${save.id}]')43		return 044	}45	reason := args.value('reason')46	events.flag(store, save.id, reason) or { return refuse(args.json(), err.msg()) }47	if args.json() {48		emit_json(json2.encode(FlagJson{49			save_id: save.id50			flagged: true51			reason:  reason52		}))53		return 054	}55	ok('flagged [${save.id}]${if reason != '' { ' — ${reason}' } else { '' }}')56	return 057}5859fn list_flags(store &storage.Store, args Args) int {60	flags := events.latest_flags(store) or { return refuse(args.json(), err.msg()) }61	mut flagged := []FlagJson{}62	for save_id, state in flags {63		if !state.flagged {64			continue65		}66		flagged << FlagJson{67			save_id: save_id68			flagged: true69			reason:  state.reason70		}71	}72	flagged.sort(a.save_id < b.save_id)73	if args.json() {74		emit_json(json2.encode(FlagListJson{75			flagged: flagged76		}))77		return 078	}79	if flagged.len == 0 {80		ok('nothing is flagged')81		return 082	}83	for entry in flagged {84		save := history.by_id(store, entry.save_id) or { continue }85		mut line := '  ${fmt.amber('⚑')} ${fmt.dim('[' + save.id + ']')} ${fmt.stamp(save.created_at)}  ${save.message}'86		if entry.reason != '' {87			line += '  ${fmt.dim(entry.reason)}'88		}89		println(line)90	}91	return 092}9394struct FlagJson {95	save_id string96	flagged bool97	reason  string98}99100struct FlagListJson {101	flagged []FlagJson102}