1
0
mirror of https://github.com/minio/mc.git synced 2025-11-12 01:02:26 +03:00
Files
mc/pkg/console/console.go
Harshavardhana 3caee383f0 Migrate to govendor to avoid limitations of godep
- over the course of a project history every maintainer needs to update
  its dependency packages, the problem essentially with godep is manipulating
  GOPATH - this manipulation leads to static objects created at different locations
  which end up conflicting with the overall functionality of golang.

  This also leads to broken builds on many platforms. There is no easier way out of
  this other than asking users to do 'godep restore' all the time which perhaps as
  a practice doesn't sound clean, also has its own set of problems.

- govendor on the other hand is a right tool but a stop gap tool until we wait for
  golangs official 1.5 version which fixes this vendoring issue once and for all.

- govendor makes sure that the import paths are re-written instead of manipulating
  GOPATH.

  This has advantages
    - no more compiled objects being referenced in GOPATH and build time GOPATH
      manging which leads to conflicts.
    - proper import paths referencing the exact package a project is dependent on.

  govendor is simple and provides the minimal necessary tooling to achieve this.

  For now this is the right solution.
2015-08-12 19:04:16 -07:00

475 lines
12 KiB
Go

/*
* 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 (
"fmt"
"os"
"sync"
"path/filepath"
"github.com/minio/mc/internal/github.com/fatih/color"
"github.com/minio/mc/internal/github.com/mattn/go-isatty"
"github.com/minio/mc/internal/github.com/minio/minio/pkg/probe"
"github.com/minio/mc/internal/github.com/shiena/ansicolor"
)
// NoDebugPrint defines if the input should be printed in debug or not. By default it's set to true.
var NoDebugPrint = true
// IsTesting this flag indicates if IsExited should be set or not, false by default
var IsTesting = false
// IsExited sets this boolean value if Fatal is called instead of os.Exit(1)
var IsExited = 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
JSON *color.Color
Bar *color.Color
PrintC *color.Color
Print *color.Color
}
var (
mutex = &sync.RWMutex{}
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...)
return
}
// PrintC prints a message with color
PrintC = func(data ...interface{}) {
print(themesDB[currThemeName].PrintC, data...)
return
}
// Printf prints a formatted message
Printf = func(f string, data ...interface{}) {
printf(themesDB[currThemeName].Print, f, data...)
return
}
// Println prints a message with a newline
Println = func(data ...interface{}) {
println(themesDB[currThemeName].Print, data...)
}
// Fatal print a error message and exit
Fatal = func(data ...interface{}) {
print(themesDB[currThemeName].Fatal, data...)
if !IsTesting {
os.Exit(1)
}
defer func() {
IsExited = true
}()
return
}
// Fatalf print a error message with a format specified and exit
Fatalf = func(f string, data ...interface{}) {
printf(themesDB[currThemeName].Fatal, f, data...)
if !IsTesting {
os.Exit(1)
}
defer func() {
IsExited = true
}()
return
}
// Fatalln print a error message with a new line and exit
Fatalln = func(data ...interface{}) {
println(themesDB[currThemeName].Fatal, data...)
if !IsTesting {
os.Exit(1)
}
defer func() {
IsExited = true
}()
return
}
// Error prints a error message
Error = func(data ...interface{}) {
if IsTesting {
defer func() {
IsExited = true
}()
}
print(themesDB[currThemeName].Error, data...)
return
}
// Errorf print a error message with a format specified
Errorf = func(f string, data ...interface{}) {
if IsTesting {
defer func() {
IsExited = true
}()
}
printf(themesDB[currThemeName].Error, f, data...)
return
}
// Errorln prints a error message with a new line
Errorln = func(data ...interface{}) {
if IsTesting {
defer func() {
IsExited = true
}()
}
println(themesDB[currThemeName].Error, data...)
return
}
// Info prints a informational message
Info = func(data ...interface{}) {
print(themesDB[currThemeName].Info, data...)
return
}
// Infof prints a informational message in custom format
Infof = func(f string, data ...interface{}) {
printf(themesDB[currThemeName].Info, f, data...)
return
}
// Infoln prints a informational message with a new line
Infoln = func(data ...interface{}) {
println(themesDB[currThemeName].Info, data...)
return
}
// Debug prints a debug message without a new line
// Debug prints a debug message
Debug = func(data ...interface{}) {
if !NoDebugPrint {
print(themesDB[currThemeName].Debug, data...)
}
}
// Debugf prints a debug message with a new line
Debugf = func(f string, data ...interface{}) {
if !NoDebugPrint {
printf(themesDB[currThemeName].Debug, f, data...)
}
}
// Debugln prints a debug message with a new line
Debugln = func(data ...interface{}) {
if !NoDebugPrint {
println(themesDB[currThemeName].Debug, data...)
}
}
// Time helper to print Time theme
Time = func(format string, data ...interface{}) string {
if isatty.IsTerminal(os.Stdout.Fd()) {
return themesDB[currThemeName].Time.SprintfFunc()(format, 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...)
}
// JSON helper to print json strings
JSON = func(format string, data ...interface{}) string {
if isatty.IsTerminal(os.Stdout.Fd()) {
return themesDB[currThemeName].JSON.SprintfFunc()(format, data...)
}
return fmt.Sprintf(format, 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{}) {
mutex.Lock()
defer mutex.Unlock()
switch c {
case themesDB[currThemeName].Debug:
output := color.Output
color.Output = stderrColoredOutput
if isatty.IsTerminal(os.Stderr.Fd()) {
c.Print(ProgramName() + ": <DEBUG> ")
c.Print(a...)
} else {
fmt.Fprint(color.Output, ProgramName()+": <DEBUG> ")
fmt.Fprint(color.Output, a...)
}
color.Output = output
case themesDB[currThemeName].Fatal:
fallthrough
case themesDB[currThemeName].Error:
output := color.Output
color.Output = stderrColoredOutput
if isatty.IsTerminal(os.Stderr.Fd()) {
c.Print(ProgramName() + ": <ERROR> ")
c.Print(a...)
} else {
fmt.Fprint(color.Output, ProgramName()+": <ERROR> ")
fmt.Fprint(color.Output, a...)
}
color.Output = output
case themesDB[currThemeName].Info:
if isatty.IsTerminal(os.Stdout.Fd()) {
c.Print(ProgramName() + ": ")
c.Print(a...)
} else {
fmt.Fprint(color.Output, ProgramName()+": ")
fmt.Fprint(color.Output, a...)
}
default:
if isatty.IsTerminal(os.Stdout.Fd()) {
c.Print(a...)
} else {
fmt.Fprint(color.Output, a...)
}
}
}
// printf - same as print with a new line
printf = func(c *color.Color, f string, a ...interface{}) {
mutex.Lock()
defer mutex.Unlock()
switch c {
case themesDB[currThemeName].Debug:
output := color.Output
color.Output = stderrColoredOutput
if isatty.IsTerminal(os.Stderr.Fd()) {
c.Print(ProgramName() + ": <DEBUG> ")
c.Printf(f, a...)
} else {
fmt.Fprint(color.Output, ProgramName()+": <DEBUG> ")
fmt.Fprintf(color.Output, f, a...)
}
color.Output = output
case themesDB[currThemeName].Fatal:
fallthrough
case themesDB[currThemeName].Error:
output := color.Output
color.Output = stderrColoredOutput
if isatty.IsTerminal(os.Stderr.Fd()) {
c.Print(ProgramName() + ": <ERROR> ")
c.Printf(f, a...)
} else {
fmt.Fprint(color.Output, ProgramName()+": <ERROR> ")
fmt.Fprintf(color.Output, f, a...)
}
color.Output = output
case themesDB[currThemeName].Info:
if isatty.IsTerminal(os.Stdout.Fd()) {
c.Print(ProgramName() + ": ")
c.Printf(f, a...)
} else {
fmt.Fprint(color.Output, ProgramName()+": ")
fmt.Fprintf(color.Output, f, a...)
}
default:
if isatty.IsTerminal(os.Stdout.Fd()) {
c.Printf(f, a...)
} else {
fmt.Fprintf(color.Output, f, a...)
}
}
}
// println - same as print with a new line
println = func(c *color.Color, a ...interface{}) {
mutex.Lock()
defer mutex.Unlock()
switch c {
case themesDB[currThemeName].Debug:
output := color.Output
color.Output = stderrColoredOutput
if isatty.IsTerminal(os.Stderr.Fd()) {
c.Print(ProgramName() + ": <DEBUG> ")
c.Println(a...)
} else {
fmt.Fprint(color.Output, ProgramName()+": <DEBUG> ")
fmt.Fprintln(color.Output, a...)
}
color.Output = output
case themesDB[currThemeName].Fatal:
fallthrough
case themesDB[currThemeName].Error:
output := color.Output
color.Output = stderrColoredOutput
if isatty.IsTerminal(os.Stderr.Fd()) {
c.Print(ProgramName() + ": <ERROR> ")
c.Println(a...)
} else {
fmt.Fprint(color.Output, ProgramName()+": <ERROR> ")
fmt.Fprintln(color.Output, a...)
}
color.Output = output
case themesDB[currThemeName].Info:
if isatty.IsTerminal(os.Stdout.Fd()) {
c.Print(ProgramName() + ": ")
c.Println(a...)
} else {
fmt.Fprint(color.Output, ProgramName()+": ")
fmt.Fprintln(color.Output, a...)
}
default:
if isatty.IsTerminal(os.Stdout.Fd()) {
c.Println(a...)
} else {
fmt.Fprintln(color.Output, a...)
}
}
}
)
// Lock console
func Lock() {
mutex.Lock()
}
// Unlock locked console
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))
}
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
}
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])
return progName
}