1
0
mirror of https://github.com/minio/mc.git synced 2025-11-13 12:22:45 +03:00

Merge themes as settable from outside console, add a default theme as well.

This commit is contained in:
Harshavardhana
2015-08-19 22:29:28 -07:00
parent ec372eb47a
commit cf5290ad74
10 changed files with 94 additions and 297 deletions

View File

@@ -16,13 +16,7 @@
package main
import (
"fmt"
"strings"
"github.com/minio/mc/internal/github.com/minio/cli"
"github.com/minio/mc/pkg/console"
)
import "github.com/minio/mc/internal/github.com/minio/cli"
// Collection of mc commands currently supported are
var commands = []cli.Command{}
@@ -47,21 +41,6 @@ var (
Usage: "Mimic operating system toolchain behavior wherever it makes sense",
}
themeFlag = cli.StringFlag{
Name: "theme",
Value: console.GetDefaultThemeName(),
Usage: fmt.Sprintf("Choose a console theme from this list [%s]", func() string {
keys := []string{}
for _, themeName := range console.GetThemeNames() {
if console.GetThemeName() == themeName {
themeName = "*" + themeName + "*"
}
keys = append(keys, themeName)
}
return strings.Join(keys, ", ")
}()),
}
jsonFlag = cli.BoolFlag{
Name: "json",
Usage: "Enable json formatted output",

View File

@@ -18,6 +18,7 @@ package main
import (
"encoding/json"
"fmt"
"github.com/minio/mc/pkg/console"
)
@@ -33,13 +34,13 @@ type ContentMessage struct {
// String string printer for Content metadata
func (c ContentMessage) String() string {
if !globalJSONFlag {
message := console.Time("[%s] ", c.Time)
message = message + console.Size("%6s ", c.Size)
message := console.Colorize("Time", fmt.Sprintf("[%s] ", c.Time))
message = message + console.Colorize("Size", fmt.Sprintf("%6s ", c.Size))
message = func() string {
if c.Filetype == "folder" {
return message + console.Dir("%s", c.Name)
return message + console.Colorize("Dir", fmt.Sprintf("%s", c.Name))
}
return message + console.File("%s", c.Name)
return message + console.Colorize("File", fmt.Sprintf("%s", c.Name))
}()
return message + "\n"
}

10
main.go
View File

@@ -78,18 +78,9 @@ func registerBefore(ctx *cli.Context) error {
globalMimicFlag = ctx.GlobalBool("mimic")
globalDebugFlag = ctx.GlobalBool("debug")
globalJSONFlag = ctx.GlobalBool("json")
themeName := ctx.GlobalString("theme")
if globalDebugFlag {
console.NoDebugPrint = false
}
if console.IsValidTheme(themeName) != true {
console.Errorf("Invalid theme, please choose from the following list: %s.\n", console.GetThemeNames())
return errInvalidTheme{Theme: themeName}
}
if err := console.SetTheme(themeName); err != nil {
errorIf(err, "Unable to set theme")
}
verifyMCRuntime()
@@ -128,7 +119,6 @@ func registerApp() *cli.App {
registerFlag(configFlag) // path to config folder
registerFlag(quietFlag) // suppress console output
registerFlag(mimicFlag) // OS toolchain mimic
registerFlag(themeFlag) // console theme flag
registerFlag(jsonFlag) // json formatted output
registerFlag(debugFlag) // enable debugging output

2
pb.go
View File

@@ -156,7 +156,7 @@ func newCpBar() barSend {
bar.NotPrint = true
bar.ShowSpeed = true
bar.Callback = func(s string) {
console.Bar("\r" + s)
console.Colorize("Bar", ("\r" + s))
}
switch runtime.GOOS {
case "linux":

View File

@@ -41,21 +41,21 @@ var IsExited = false
// IsError sets this boolean value if Error is called when IsTesting is enabled
var IsError = false
// Theme holds console color scheme
type Theme struct {
Fatal *color.Color
Error *color.Color
Info *color.Color
Debug *color.Color
Size *color.Color
Time *color.Color
File *color.Color
Dir *color.Color
Command *color.Color
SessionID *color.Color
Bar *color.Color
PrintC *color.Color
Print *color.Color
// Theme default map
var Theme = map[string]*color.Color{
"Debug": color.New(color.FgWhite, color.Faint, color.Italic),
"Fatal": color.New(color.FgRed, color.Italic, color.Bold),
"Error": color.New(color.FgYellow, color.Italic),
"Info": color.New(color.FgGreen, color.Bold),
"File": color.New(color.FgWhite),
"Dir": color.New(color.FgCyan, color.Bold),
"Command": color.New(color.FgWhite, color.Bold),
"SessionID": color.New(color.FgYellow, color.Bold),
"Size": color.New(color.FgYellow),
"Time": color.New(color.FgGreen),
"Bar": color.New(color.FgGreen, color.Bold),
"Print": color.New(),
"PrintC": color.New(color.FgGreen, color.Bold),
}
var (
@@ -63,47 +63,33 @@ var (
stderrColoredOutput = ansicolor.NewAnsiColorWriter(os.Stderr)
// themesDB contains supported list of Themes
themesDB = map[string]Theme{
"minimal": MiniTheme,
"nocolor": NoColorTheme,
"white": WhiteTheme,
}
// currTheme is current theme
currThemeName = GetDefaultThemeName()
// Bar print progress bar
Bar = func(data ...interface{}) {
print(themesDB[currThemeName].Bar, data...)
}
// Print prints a message
Print = func(data ...interface{}) {
print(themesDB[currThemeName].Print, data...)
consolePrint("Print", Theme["Print"], data...)
return
}
// PrintC prints a message with color
PrintC = func(data ...interface{}) {
print(themesDB[currThemeName].PrintC, data...)
consolePrint("PrintC", Theme["PrintC"], data...)
return
}
// Printf prints a formatted message
Printf = func(f string, data ...interface{}) {
printf(themesDB[currThemeName].Print, f, data...)
Printf = func(format string, data ...interface{}) {
consolePrintf("Print", Theme["Print"], format, data...)
return
}
// Println prints a message with a newline
Println = func(data ...interface{}) {
println(themesDB[currThemeName].Print, data...)
consolePrintln("Print", Theme["Print"], data...)
return
}
// Fatal print a error message and exit
Fatal = func(data ...interface{}) {
print(themesDB[currThemeName].Fatal, data...)
consolePrint("Fatal", Theme["Fatal"], data...)
if !IsTesting {
os.Exit(1)
}
@@ -114,8 +100,8 @@ var (
}
// Fatalf print a error message with a format specified and exit
Fatalf = func(f string, data ...interface{}) {
printf(themesDB[currThemeName].Fatal, f, data...)
Fatalf = func(format string, data ...interface{}) {
consolePrintf("Fatal", Theme["Fatal"], format, data...)
if !IsTesting {
os.Exit(1)
}
@@ -127,7 +113,7 @@ var (
// Fatalln print a error message with a new line and exit
Fatalln = func(data ...interface{}) {
println(themesDB[currThemeName].Fatal, data...)
consolePrintln("Fatal", Theme["Fatal"], data...)
if !IsTesting {
os.Exit(1)
}
@@ -144,18 +130,18 @@ var (
IsError = true
}()
}
print(themesDB[currThemeName].Error, data...)
consolePrint("Error", Theme["Error"], data...)
return
}
// Errorf print a error message with a format specified
Errorf = func(f string, data ...interface{}) {
Errorf = func(format string, data ...interface{}) {
if IsTesting {
defer func() {
IsError = true
}()
}
printf(themesDB[currThemeName].Error, f, data...)
consolePrintf("Error", Theme["Error"], format, data...)
return
}
@@ -166,25 +152,25 @@ var (
IsError = true
}()
}
println(themesDB[currThemeName].Error, data...)
consolePrintln("Error", Theme["Error"], data...)
return
}
// Info prints a informational message
Info = func(data ...interface{}) {
print(themesDB[currThemeName].Info, data...)
consolePrint("Info", Theme["Info"], data...)
return
}
// Infof prints a informational message in custom format
Infof = func(f string, data ...interface{}) {
printf(themesDB[currThemeName].Info, f, data...)
Infof = func(format string, data ...interface{}) {
consolePrintf("Info", Theme["Info"], format, data...)
return
}
// Infoln prints a informational message with a new line
Infoln = func(data ...interface{}) {
println(themesDB[currThemeName].Info, data...)
consolePrintln("Info", Theme["Info"], data...)
return
}
@@ -192,82 +178,41 @@ var (
// Debug prints a debug message
Debug = func(data ...interface{}) {
if !NoDebugPrint {
print(themesDB[currThemeName].Debug, data...)
consolePrint("Debug", Theme["Debug"], data...)
}
}
// Debugf prints a debug message with a new line
Debugf = func(f string, data ...interface{}) {
Debugf = func(format string, data ...interface{}) {
if !NoDebugPrint {
printf(themesDB[currThemeName].Debug, f, data...)
consolePrintf("Debug", Theme["Debug"], format, data...)
}
}
// Debugln prints a debug message with a new line
Debugln = func(data ...interface{}) {
if !NoDebugPrint {
println(themesDB[currThemeName].Debug, data...)
consolePrintln("Debug", Theme["Debug"], data...)
}
}
// Time helper to print Time theme
Time = func(format string, data ...interface{}) string {
Colorize = func(tag string, data interface{}) string {
if isatty.IsTerminal(os.Stdout.Fd()) {
return themesDB[currThemeName].Time.SprintfFunc()(format, data...)
return Theme[tag].SprintFunc()(data)
}
return fmt.Sprintf(format, data...)
}
// Size helper to print Size theme
Size = func(format string, data ...interface{}) string {
if isatty.IsTerminal(os.Stdout.Fd()) {
return themesDB[currThemeName].Size.SprintfFunc()(format, data...)
}
return fmt.Sprintf(format, data...)
}
// File helper to print File theme
File = func(format string, data ...interface{}) string {
if isatty.IsTerminal(os.Stdout.Fd()) {
return themesDB[currThemeName].File.SprintfFunc()(format, data...)
}
return fmt.Sprintf(format, data...)
}
// Dir helper to print Dir theme
Dir = func(format string, data ...interface{}) string {
if isatty.IsTerminal(os.Stdout.Fd()) {
return themesDB[currThemeName].Dir.SprintfFunc()(format, data...)
}
return fmt.Sprintf(format, data...)
}
// Command helper to print command theme
Command = func(format string, data ...interface{}) string {
if isatty.IsTerminal(os.Stdout.Fd()) {
return themesDB[currThemeName].Command.SprintfFunc()(format, data...)
}
return fmt.Sprintf(format, data...)
}
// SessionID helper to print sessionid theme
SessionID = func(format string, data ...interface{}) string {
if isatty.IsTerminal(os.Stdout.Fd()) {
return themesDB[currThemeName].SessionID.SprintfFunc()(format, data...)
}
return fmt.Sprintf(format, data...)
return fmt.Sprint(data)
}
)
var (
// wrap around standard fmt functions
// print prints a message prefixed with message type and program name
print = func(c *color.Color, a ...interface{}) {
// consolePrint prints a message prefixed with message type and program name
consolePrint = func(tag string, c *color.Color, a ...interface{}) {
mutex.Lock()
defer mutex.Unlock()
switch c {
case themesDB[currThemeName].Debug:
switch tag {
case "Debug":
output := color.Output
color.Output = stderrColoredOutput
if isatty.IsTerminal(os.Stderr.Fd()) {
@@ -278,9 +223,9 @@ var (
fmt.Fprint(color.Output, a...)
}
color.Output = output
case themesDB[currThemeName].Fatal:
case "Fatal":
fallthrough
case themesDB[currThemeName].Error:
case "Error":
output := color.Output
color.Output = stderrColoredOutput
if isatty.IsTerminal(os.Stderr.Fd()) {
@@ -291,7 +236,7 @@ var (
fmt.Fprint(color.Output, a...)
}
color.Output = output
case themesDB[currThemeName].Info:
case "Info":
if isatty.IsTerminal(os.Stdout.Fd()) {
c.Print(ProgramName() + ": ")
c.Print(a...)
@@ -308,60 +253,60 @@ var (
}
}
// printf - same as print with a new line
printf = func(c *color.Color, f string, a ...interface{}) {
// consolePrintf - same as print with a new line
consolePrintf = func(tag string, c *color.Color, format string, a ...interface{}) {
mutex.Lock()
defer mutex.Unlock()
switch c {
case themesDB[currThemeName].Debug:
switch tag {
case "Debug":
output := color.Output
color.Output = stderrColoredOutput
if isatty.IsTerminal(os.Stderr.Fd()) {
c.Print(ProgramName() + ": <DEBUG> ")
c.Printf(f, a...)
c.Printf(format, a...)
} else {
fmt.Fprint(color.Output, ProgramName()+": <DEBUG> ")
fmt.Fprintf(color.Output, f, a...)
fmt.Fprintf(color.Output, format, a...)
}
color.Output = output
case themesDB[currThemeName].Fatal:
case "Fatal":
fallthrough
case themesDB[currThemeName].Error:
case "Error":
output := color.Output
color.Output = stderrColoredOutput
if isatty.IsTerminal(os.Stderr.Fd()) {
c.Print(ProgramName() + ": <ERROR> ")
c.Printf(f, a...)
c.Printf(format, a...)
} else {
fmt.Fprint(color.Output, ProgramName()+": <ERROR> ")
fmt.Fprintf(color.Output, f, a...)
fmt.Fprintf(color.Output, format, a...)
}
color.Output = output
case themesDB[currThemeName].Info:
case "Info":
if isatty.IsTerminal(os.Stdout.Fd()) {
c.Print(ProgramName() + ": ")
c.Printf(f, a...)
c.Printf(format, a...)
} else {
fmt.Fprint(color.Output, ProgramName()+": ")
fmt.Fprintf(color.Output, f, a...)
fmt.Fprintf(color.Output, format, a...)
}
default:
if isatty.IsTerminal(os.Stdout.Fd()) {
c.Printf(f, a...)
c.Printf(format, a...)
} else {
fmt.Fprintf(color.Output, f, a...)
fmt.Fprintf(color.Output, format, a...)
}
}
}
// println - same as print with a new line
println = func(c *color.Color, a ...interface{}) {
// consolePrintln - same as print with a new line
consolePrintln = func(tag string, c *color.Color, a ...interface{}) {
mutex.Lock()
defer mutex.Unlock()
switch c {
case themesDB[currThemeName].Debug:
switch tag {
case "Debug":
output := color.Output
color.Output = stderrColoredOutput
if isatty.IsTerminal(os.Stderr.Fd()) {
@@ -372,9 +317,9 @@ var (
fmt.Fprintln(color.Output, a...)
}
color.Output = output
case themesDB[currThemeName].Fatal:
case "Fatal":
fallthrough
case themesDB[currThemeName].Error:
case "Error":
output := color.Output
color.Output = stderrColoredOutput
if isatty.IsTerminal(os.Stderr.Fd()) {
@@ -385,7 +330,7 @@ var (
fmt.Fprintln(color.Output, a...)
}
color.Output = output
case themesDB[currThemeName].Info:
case "Info":
if isatty.IsTerminal(os.Stdout.Fd()) {
c.Print(ProgramName() + ": ")
c.Println(a...)
@@ -413,54 +358,17 @@ func Unlock() {
mutex.Unlock()
}
// SetTheme sets a color theme
func SetTheme(themeName string) *probe.Error {
if !IsValidTheme(themeName) {
return probe.NewError(fmt.Errorf("Unsupported theme name [%s]", themeName))
}
// SetCustomTheme sets a color theme
func SetCustomTheme(theme map[string]*color.Color) *probe.Error {
mutex.Lock()
// Just another additional precaution to completely disable color.
// Color theme is also necessary, because it does other useful things like exit-on-fatal..
switch currThemeName {
case "nocolor":
color.NoColor = true
default:
color.NoColor = false
defer mutex.Unlock()
// add new theme
for k, v := range theme {
Theme[k] = v
}
currThemeName = themeName
mutex.Unlock()
return nil
}
// GetThemeName returns currently set theme name
func GetThemeName() string {
return currThemeName
}
// GetDefaultThemeName returns the default theme
func GetDefaultThemeName() string {
return "minimal"
}
// GetThemeNames returns currently supported list of themes
func GetThemeNames() (themeNames []string) {
for themeName := range themesDB {
themeNames = append(themeNames, themeName)
}
return themeNames
}
// IsValidTheme returns true if "themeName" is currently supported
func IsValidTheme(themeName string) bool {
_, ok := themesDB[themeName]
return ok
}
// ProgramName - return the name of the executable program
func ProgramName() string {
_, progName := filepath.Split(os.Args[0])

View File

@@ -19,6 +19,7 @@ package console
import (
"testing"
"github.com/minio/mc/internal/github.com/fatih/color"
. "github.com/minio/mc/internal/gopkg.in/check.v1"
)
@@ -29,14 +30,8 @@ type MySuite struct{}
var _ = Suite(&MySuite{})
func (s *MySuite) TestSetTheme(c *C) {
err := SetTheme("nocolor")
err := SetCustomTheme(map[string]*color.Color{"unknown": new(color.Color)})
c.Assert(err, IsNil)
c.Assert(GetThemeName(), Equals, "nocolor")
err = SetTheme("unknown")
c.Assert(err, Not(IsNil))
c.Assert(GetThemeName(), Equals, "nocolor")
}
func (s *MySuite) TestDefaultTheme(c *C) {
c.Assert(GetDefaultThemeName(), Equals, "minimal")
_, ok := Theme["unknown"]
c.Assert(ok, Equals, true)
}

View File

@@ -1,70 +0,0 @@
/*
* Minio Client (C) 2015 Minio, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package console
import "github.com/minio/mc/internal/github.com/fatih/color"
// MiniTheme - Minio's default color theme
var MiniTheme = Theme{
Debug: (color.New(color.FgWhite, color.Faint, color.Italic)),
Fatal: (color.New(color.FgRed, color.Italic, color.Bold)),
Error: (color.New(color.FgYellow, color.Italic)),
Info: (color.New(color.FgGreen, color.Bold)),
File: (color.New(color.FgWhite)),
Dir: (color.New(color.FgCyan, color.Bold)),
Command: (color.New(color.FgWhite, color.Bold)),
SessionID: (color.New(color.FgYellow, color.Bold)),
Size: (color.New(color.FgYellow)),
Time: (color.New(color.FgGreen)),
Bar: (color.New(color.FgGreen, color.Bold)),
PrintC: (color.New(color.FgGreen, color.Bold)),
Print: (color.New()),
}
// WhiteTheme - All white color theme
var WhiteTheme = Theme{
Debug: (color.New(color.FgWhite, color.Faint, color.Italic)),
Fatal: (color.New(color.FgWhite, color.Bold, color.Italic)),
Error: (color.New(color.FgWhite, color.Bold, color.Italic)),
Info: (color.New(color.FgWhite, color.Bold)),
File: (color.New(color.FgWhite, color.Bold)),
Dir: (color.New(color.FgWhite, color.Bold)),
Command: (color.New(color.FgWhite, color.Bold)),
SessionID: (color.New(color.FgWhite, color.Bold)),
Size: (color.New(color.FgWhite, color.Bold)),
Time: (color.New(color.FgWhite, color.Bold)),
Bar: (color.New(color.FgWhite, color.Bold)),
PrintC: (color.New(color.FgWhite, color.Bold)),
Print: (color.New()),
}
// NoColorTheme - Disables color theme
var NoColorTheme = Theme{
Debug: new(color.Color),
Fatal: new(color.Color),
Error: new(color.Color),
Info: new(color.Color),
File: new(color.Color),
Dir: new(color.Color),
Command: new(color.Color),
SessionID: new(color.Color),
Size: new(color.Color),
Time: new(color.Color),
Bar: new(color.Color),
PrintC: new(color.Color),
Print: new(color.Color),
}

View File

@@ -18,6 +18,7 @@ package main
import (
"encoding/json"
"fmt"
"strings"
"github.com/minio/mc/pkg/console"
@@ -33,9 +34,9 @@ type SessionJSONMessage struct {
func (s sessionV2) String() string {
if !globalJSONFlag {
message := console.SessionID("%s -> ", s.SessionID)
message = message + console.Time("[%s]", s.Header.When.Local().Format(printDate))
message = message + console.Command(" %s %s", s.Header.CommandType, strings.Join(s.Header.CommandArgs, " "))
message := console.Colorize("SessionID", fmt.Sprintf("%s -> ", s.SessionID))
message = message + console.Colorize("Time", fmt.Sprintf("[%s]", s.Header.When.Local().Format(printDate)))
message = message + console.Colorize("Command", fmt.Sprintf(" %s %s", s.Header.CommandType, strings.Join(s.Header.CommandArgs, " ")))
return message + "\n"
}
sessionMesage := SessionJSONMessage{

View File

@@ -17,6 +17,7 @@
package main
import (
"fmt"
"os"
"path/filepath"
"regexp"
@@ -41,9 +42,9 @@ type sessionV1 struct {
}
func (s sessionV1) String() string {
message := console.Time("[%s] ", s.Started.Local().Format(printDate))
message = message + console.SessionID("%s", s.SessionID)
message = message + console.Command(" [%s %s]", s.CommandType, strings.Join(s.URLs, " "))
message := console.Colorize("Time", fmt.Sprintf("[%s] ", s.Started.Local().Format(printDate)))
message = message + console.Colorize("SessionID", fmt.Sprintf("%s", s.SessionID))
message = message + console.Colorize("Command", fmt.Sprintf(" [%s %s]", s.CommandType, strings.Join(s.URLs, " ")))
return message
}

View File

@@ -122,14 +122,6 @@ func (e errInvalidTarget) Error() string {
return "Invalid target " + e.URL
}
type errInvalidTheme struct {
Theme string
}
func (e errInvalidTheme) Error() string {
return "Theme " + e.Theme + " is not supported."
}
type errTargetIsNotDir errInvalidURL
func (e errTargetIsNotDir) Error() string {