~bayindirh/nudge

4a527595454a217b6c3fe1a1d431bc3176175190 — Hakan Bayindir 7 months ago 0196967
refactor: Rewrite applyFlags to work correctly.

- refactor: Rewrite applyFlags function to set only provided flags.
- fix: Use flag.Visit() to get a list of set flags.

This version uses flag.Visit() to extract set flags into an array, and iterates the flags in that array to set what’s provided in the first place.

NOTE: This is a v0 code, and is VeryAlpha at this point. The code will be revised. DO NOT USE!
2 files changed, 60 insertions(+), 41 deletions(-)

M CHANGELOG.md
M src/nudge.go
M CHANGELOG.md => CHANGELOG.md +5 -0
@@ 2,6 2,11 @@

**Note:** Please add newest entries on top. Use ISO date format YYYY-MM-DD and markdown formatting.

## 2023-07-25

- refactor: Rewrite `applyFlags` function to set only provided flags.
- fix: Use `flag.Visit()` to get a list of set flags.

## 2023-07-15

- refactor: Remove verbosity settings related plumbing from code. Will use logging level only.

M src/nudge.go => src/nudge.go +55 -41
@@ 200,8 200,6 @@ func readAndApplyConfiguration(configurationFilePath *string, runtimeConfigurati
			runtimeConfiguration.logLevel = viper.GetString("logging.log_level")
			logger.Debugf("Logging level is found and set to %s.", runtimeConfiguration.logLevel)
		}

		// TODO: Get logging level and process the data.
	}
}



@@ 210,7 208,7 @@ func readAndApplyConfiguration(configurationFilePath *string, runtimeConfigurati
// Cue Lord of the Rings from Blind Guardian.
func initFlags(notificationToSend *Notification, flagStorage *FlagStorage, logger *zap.SugaredLogger) {
	// In this initial version, we only handle some of the features. Rest will be handled later.
	// Values are sent to flagStorage, because we'll apply them after parsing the config file. 
	// Values are sent to flagStorage, because we'll apply them after parsing the config file.
	flag.StringVar(&flagStorage.device, "devices", notificationToSend.device, "List of devices to be notified. Separate multiple devices with ','.")
	flag.IntVar(&flagStorage.priority, "priority", notificationToSend.priority, "Adjust notification priority. Between -2 and 2. (default "+strconv.Itoa(notificationToSend.priority)+")")
	flag.StringVar(&flagStorage.sound, "sound", notificationToSend.sound, "Set notification sound.")


@@ 245,49 243,55 @@ func initFlags(notificationToSend *Notification, flagStorage *FlagStorage, logge
}

// This function simply copies relevant flags to runtime configuration and notification to send.
func applyFlags(flagStorage *FlagStorage, runtimeConfiguration *RuntimeConfiguration, notificationToSend *Notification, logger zap.SugaredLogger) {
func applyFlags(setFlags *[]string, flagStorage *FlagStorage, runtimeConfiguration *RuntimeConfiguration, notificationToSend *Notification, logger zap.SugaredLogger) {
	// TODO: Revise this function and add proper comments.
	logger.Debugf("Starting to apply flags to runtime configuration.")
	// This is left as a check, to see whether we can approach flag module globally.
	logger.Debugf("Flag parse status is %s.", flag.Parsed())
	
	// The only way to see whether a flag is set or not is to use flag.Lookup() function.
	// It returns the data structure if flag is present, and nil if the flag is not set.
	if flag.Lookup("devices") != nil {
		notificationToSend.device = flagStorage.device
		logger.Debugf("Recipient devices are set to %s.", notificationToSend.device)
	}
	
	if flag.Lookup("priority") != nil {
		notificationToSend.priority = flagStorage.priority
		logger.Debugf("Notification priority is changed to %d.", notificationToSend.priority)
	}
	
	if flag.Lookup("sound") != nil {
		notificationToSend.sound = flagStorage.sound
		logger.Debugf("Notification sound is changed to %s.", notificationToSend.sound)
	}
	
	if flag.Lookup("title") != nil {
		notificationToSend.title = flagStorage.title
		logger.Debugf("Notification title is changed to %s.", notificationToSend.title)
	}
	
	if flag.Lookup("url") != nil {
		notificationToSend.url = flagStorage.url
		logger.Debugf("Notification attached URL is set to %s.", notificationToSend.url)
	}
	
	if flag.Lookup("url_title") != nil {
		notificationToSend.urlTitle = flagStorage.urlTitle
		logger.Debugf("Notification attached URL will be shown as %s.", notificationToSend.urlTitle)
	}

	if flag.Lookup("dryrun") != nil {
		runtimeConfiguration.dryrun = flagStorage.dryrun
		logger.Debugf("Dry run mode is set to %s.", runtimeConfiguration.dryrun)
	// FIXME: Prettify this output.
	logger.Debugf("The set flags are %s.", setFlags)

	for _, flagValue := range *setFlags {
		logger.Debugf("Working on flag %s.", flagValue)

		switch flagValue {
		case "devices":
			notificationToSend.device = flagStorage.device
			logger.Debugf("Recipient devices are set to %s.", notificationToSend.device)
		case "priority":
			notificationToSend.priority = flagStorage.priority
			logger.Debugf("Notification priority is changed to %d.", notificationToSend.priority)
		case "sound":
			notificationToSend.sound = flagStorage.sound
			logger.Debugf("Notification sound is changed to %s.", notificationToSend.sound)
		case "title":
			notificationToSend.title = flagStorage.title
			logger.Debugf("Notification title is changed to %s.", notificationToSend.title)
		case "url":
			notificationToSend.url = flagStorage.url
			logger.Debugf("Notification attached URL is set to %s.", notificationToSend.url)
		case "url_title":
			notificationToSend.urlTitle = flagStorage.urlTitle
			logger.Debugf("Notification attached URL will be shown as %s.", notificationToSend.urlTitle)
		case "dryrun":
			runtimeConfiguration.dryrun = flagStorage.dryrun
			logger.Debugf("Dry run mode is set to %s.", runtimeConfiguration.dryrun)
		case "log_level":
			runtimeConfiguration.logLevel = flagStorage.logLevel
			logger.Debugf("Logging level is set to %s.", runtimeConfiguration.logLevel)
		case "config_path":
			logger.Debugf("Ignoring flag %s. Handled elsewhere.", flagValue)
		case "version":
			logger.Debugf("Ignoring flag %s. Handled elsewhere.", flagValue)
		default:
			logger.Warnf("Unhandled flag %s. Ignoring.", flagValue)
		}
	}
	
	// Skipped configPath, because it's handled in readAndApplyConfiguration.
	// Skipped versionRequested, because it's handled in main() directly.

	logger.Debugf("Application of flags is completed, returning.")
}

// This function checks configuration sanity when called, and creates warnings or errors depending on the situation.


@@ 387,6 391,9 @@ func main() {
	var notificationToSend Notification
	var validConfigurationOptions ValidConfigurationOptions

	// Since there's no easy way to check whether a flag is set, I need a list of set flags.
	var setFlags []string

	// TODO: Prettify logger with some stylistic configuration here.
	// Relevant documentation is here: https://pkg.go.dev/go.uber.org/zap#hdr-Configuring_Zap



@@ 433,7 440,14 @@ func main() {

	// To be able to satisfy Defaults -> Configuration -> Flags chain,
	// I need to apply the options got from flags to Runtime Configuration at this point.
	applyFlags(&flagStorage, &runtimeConfiguration, &notificationToSend, *sugaredLogger)
	// However I need to get the list of set flags from Flag. Since only visit() allows me
	// to do it, I need to use this anonymous function to make this work.
	flag.Visit(func(setFlag *flag.Flag) {
		setFlags = append(setFlags, setFlag.Name)
	})

	// Then I can apply the set flags.
	applyFlags(&setFlags, &flagStorage, &runtimeConfiguration, &notificationToSend, *sugaredLogger)

	// Check whether our version is asked or not.
	// Version info shall always return clean.