Repository: jesseduffield/lazygit
File: pkg/config/user_config_validation.go (Go)

Code before:
			var newPath string
			if len(path) == 0 {
				newPath = field.Name
			} else {
				newPath = fmt.Sprintf("%s.%s", path, field.Name)
			}
			if err := validateKeybindingsRecurse(newPath,
				value.FieldByName(field.Name).Interface()); err != nil {
				return err
			}
		}
	} else if value.Kind() == reflect.Slice {
		for i := 0; i < value.Len(); i++ {
			if err := validateKeybindingsRecurse(
				fmt.Sprintf("%s[%d]", path, i), value.Index(i).Interface()); err != nil {
				return err
			}
		}
	} else if value.Kind() == reflect.String {
		key := node.(string)
		if !isValidKeybindingKey(key) {
			return fmt.Errorf("Unrecognized key '%s' for keybinding '%s'. For permitted values see %s",
				strings.ToLower(key), path, constants.Links.Docs.CustomKeybindings)
		}
	} else {
		panic("Unexpected type")
	}
	return nil
}

func validateKeybindings(keybindingConfig KeybindingConfig) error {
	if err := validateKeybindingsRecurse("", keybindingConfig); err != nil {
		return err
	}

	if len(keybindingConfig.Universal.JumpToBlock) != 5 {
		return fmt.Errorf("keybinding.universal.jumpToBlock must have 5 elements; found %d.",
			len(keybindingConfig.Universal.JumpToBlock))
	}

	return nil
}

func validateCustomCommandKey(key string) error {
	if !isValidKeybindingKey(key) {
		return fmt.Errorf("Unrecognized key '%s' for custom command. For permitted values see %s",
			strings.ToLower(key), constants.Links.Docs.CustomKeybindings)
	}
	return nil
}


Review comment (bug):
Would adding the failed `node`, or `value` to this panic message be helpful? I'm not sure how possible it is for somebody to sneak other value types inside of here via wacky config.

Code after:
		for _, field := range reflect.VisibleFields(reflect.TypeOf(node)) {
			var newPath string
			if len(path) == 0 {
				newPath = field.Name
			} else {
				newPath = fmt.Sprintf("%s.%s", path, field.Name)
			}
			if err := validateKeybindingsRecurse(newPath,
				value.FieldByName(field.Name).Interface()); err != nil {
				return err
			}
		}
	} else if value.Kind() == reflect.Slice {
		for i := 0; i < value.Len(); i++ {
			if err := validateKeybindingsRecurse(
				fmt.Sprintf("%s[%d]", path, i), value.Index(i).Interface()); err != nil {
				return err
			}
		}
	} else if value.Kind() == reflect.String {
		key := node.(string)
		if !isValidKeybindingKey(key) {
			return fmt.Errorf("Unrecognized key '%s' for keybinding '%s'. For permitted values see %s",
				key, path, constants.Links.Docs.CustomKeybindings)
		}
	} else {
		log.Fatalf("Unexpected type for property '%s': %s", path, value.Kind())
	}
	return nil
}

func validateKeybindings(keybindingConfig KeybindingConfig) error {
	if err := validateKeybindingsRecurse("", keybindingConfig); err != nil {
		return err
	}

	if len(keybindingConfig.Universal.JumpToBlock) != 5 {
		return fmt.Errorf("keybinding.universal.jumpToBlock must have 5 elements; found %d.",
			len(keybindingConfig.Universal.JumpToBlock))
	}

	return nil
}

func validateCustomCommandKey(key string) error {
	if !isValidKeybindingKey(key) {
		return fmt.Errorf("Unrecognized key '%s' for custom command. For permitted values see %s",
			key, constants.Links.Docs.CustomKeybindings)
	}
	return nil
}