White = "\033[97m"
)
+// Set colours strings to ""
func NotInteractive() {
Reset = ""
Red = ""
White = ""
}
+// Reset colours strings to their values
func Interactive() {
Reset = "\033[0m"
Red = "\033[31m"
import "database/sql"
+/*
+To commit or rollback a transaction:
+
+ - If err is nil, tx is committed;
+ - If err is not nil, tx is rolled back.
+
+Parameters:
+
+ - tx *sql.Tx;
+ - err error.
+
+Returns:
+
+ - err error: an error generated by tx.Commit or by tx.Rollback.
+*/
func CommitTx(tx *sql.Tx, err error) (_ error) {
if err == nil {
err = tx.Commit()
} else {
- tx.Rollback()
+ err = tx.Rollback()
}
return AppendError(err)
"os/exec"
)
+/*
+To run an editor on the terminal.
+
+Editor merely runs the editor program (param editorPath) by passing as first parameter a file path (param path)
+
+Parameters:
+
+ - editorPath string: the path to the editor binary;
+ - path string: the path to wich the edited file will be saved.
+
+Returns:
+
+ - err error: an error if exec.Command.Run shoud generate one.
+*/
func Editor(editorPath string, path string) (err error) {
editor := exec.Command(editorPath, path)
editor.Stdin = os.Stdin
"runtime"
)
+// Mypanic
+// If err is not nil logs a FATAL error message
func Mypanic(err error) {
if err == nil {
return
Logf(FATAL, "%v", err)
}
+/*
+Takes a funcion `f` that might return an error, a void function `pre`, a void function `post`
+
+It is supposed to be used to handle deferred function calls that returns an error without ugly sintax such as:
+
+ defer func() {
+ err := fp.Close()
+
+ if err != nil {
+ panic(err)
+ }
+ }()
+
+Using Deferrable:
+
+ defer Deferrable(fp.Close, nil, nil)
+
+What it does:
+
+ - If pre is not nil, executes pre();
+ - Executes f() and panic (using Mypanic) if `f` result is not nil;
+ - If does not panic and post is not nil, executes post.
+*/
func Deferrable(f func() error, pre func(), post func()) {
if pre != nil {
pre()
}
}
+// Appends to error the funcion in wich the error has been generated
func AppendError(err error) error {
if err == nil {
return nil
return fmt.Errorf("%s: %v", fileName, err)
}
+// Returns the third to last function on the stack
+// Should be used only in AppendError
func trace() (receipts []string) {
var p = make([]uintptr, 10)
runtime.Callers(2, p)
"os/exec"
)
+// Show a message on the terminal via less by executing
+// echo {string} piped through less.
+// The string is generated using Printf-like format and arguments
func Lessf(format string, args ...interface{}) error {
str := fmt.Sprintf(format, args...)
return less(str)
}
+// Show the string `str` on the terminal via less by executing
+// echo {str} piped through less
func less(str string) (err error) {
echo := exec.Command("echo", str)
echo.Stdin = os.Stdin
type LogLevel int
const (
- FATAL LogLevel = (1 << iota) >> 1
- ERROR
- WARNING
- INFO
- VERBOSE
+ FATAL LogLevel = (1 << iota) >> 1 // To log an error and exit
+ ERROR // To log and error
+ WARNING // To log a warning
+ INFO // To log some information
+ VERBOSE // To log some detailed information (meant to debug)
)
+// Maps log levels to strings
var levelToString = map[LogLevel]string{
FATAL: " FATAL ",
ERROR: " ERROR ",
VERBOSE: "VERBOSE",
}
+// Maps log levels to colours
func getLevelColor(level LogLevel) string {
switch level {
case FATAL:
return Gray
}
+// To log synchronously
var logGuard *sync.Mutex = &sync.Mutex{}
-var MaximumLevel LogLevel = WARNING
+// Minimum level to log
+// If it is WARNING, INFO and VERBOSE are not logged
+// If it is ERROR, WARNING, INFO and WARNING are not logged
+// ... and so on ...
+var MinimumLevel LogLevel = WARNING
+
+// Log a message with a specific log level; Format and args are Printf-like
func Logf(level LogLevel, format string, args ...interface{}) {
logGuard.Lock()
defer logGuard.Unlock()
- if level > MaximumLevel {
+ if level > MinimumLevel {
return
}
return format
}
+// Log a message on *testing.T with a specific log level; Format and args are Printf-like
func Tlogf(t *testing.T, level LogLevel, format string, args ...interface{}) {
logGuard.Lock()
defer logGuard.Unlock()
"reflect"
)
+// Represent an object method, callable by invoking F and passing the very same
+// parameters that would be passed to that object method (which means NOT the receiver)
type Method struct {
to reflect.Method
numIn int
return
}
+// Retuns the numer of parameters that F expects
func (m *Method) NumIn() int {
return m.numIn
}
+/*
+Takes an integer `i` and retuns the i-th parameter kind that F would expect.
+
+Note that F do take as parameters the object method's parameters but NOT the method receiver
+*/
func (m *Method) ParamKind(i int) reflect.Kind {
return m.to.Type.In(i + 1).Kind()
}
}
}
+// Giveng an obj interface{}, returns a *Method from that obj.
+// GetMethod seeks a method that has name equal to name + suffix.
+// `suffix` might just be an empty string.
func GetMethod(obj interface{}, name string, suffix string) *Method {
to := reflect.TypeOf(obj)
vo := reflect.ValueOf(obj)
return nil
}
+// Giveng an obj interface{}, returns an interface{} which is a propery value of that onj.
+// GetProperty seeks a property that has name equal to name + suffix.
+// `suffix` might just be an empty string.
func GetProperty(obj interface{}, name string, suffix string, tags ...string) interface{} {
to := reflect.TypeOf(obj)
vo := reflect.ValueOf(obj)
RUnlock()
}
+/*
+Lock a lockable and retun a funcion to unlock the lockable.
+
+The meaning is to avoid ugly syntax such as:
+
+ mu.Lock()
+ defer mu.Unlock()
+
+Which became:
+
+ defer Monitor(mu)()
+*/
func Monitor(mu lockable) func() {
mu.Lock()
return func() {
}
}
+/*
+Lock a rlockable and retun a funcion to unlock the rlockable.
+
+The meaning is to avoid ugly syntax such as:
+
+ mu.RLock()
+ defer mu.RUnlock()
+
+Which became:
+
+ defer RMonitor(mu)()
+*/
func RMonitor(mu rlockable) func() {
mu.RLock()
return func() {
var syncIoGuard = &sync.Mutex{}
+// Fprintf but synced
func Fprintf(fp io.Writer, format string, args ...any) {
defer Monitor(syncIoGuard)()
fmt.Fprint(fp, format, args)
}
+// Printf but synced
func Printf(format string, args ...any) {
defer Monitor(syncIoGuard)()