1// +build go1.3
2
3// Copyright 2013 com authors
4//
5// Licensed under the Apache License, Version 2.0 (the "License"): you may
6// not use this file except in compliance with the License. You may obtain
7// a copy of the License at
8//
9//     http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14// License for the specific language governing permissions and limitations
15// under the License.
16
17// Package com is an open source project for commonly used functions for the Go programming language.
18package com
19
20import (
21	"bytes"
22	"fmt"
23	"os/exec"
24	"runtime"
25	"strings"
26)
27
28// ExecCmdDirBytes executes system command in given directory
29// and return stdout, stderr in bytes type, along with possible error.
30func ExecCmdDirBytes(dir, cmdName string, args ...string) ([]byte, []byte, error) {
31	bufOut := new(bytes.Buffer)
32	bufErr := new(bytes.Buffer)
33
34	cmd := exec.Command(cmdName, args...)
35	cmd.Dir = dir
36	cmd.Stdout = bufOut
37	cmd.Stderr = bufErr
38
39	err := cmd.Run()
40	return bufOut.Bytes(), bufErr.Bytes(), err
41}
42
43// ExecCmdBytes executes system command
44// and return stdout, stderr in bytes type, along with possible error.
45func ExecCmdBytes(cmdName string, args ...string) ([]byte, []byte, error) {
46	return ExecCmdDirBytes("", cmdName, args...)
47}
48
49// ExecCmdDir executes system command in given directory
50// and return stdout, stderr in string type, along with possible error.
51func ExecCmdDir(dir, cmdName string, args ...string) (string, string, error) {
52	bufOut, bufErr, err := ExecCmdDirBytes(dir, cmdName, args...)
53	return string(bufOut), string(bufErr), err
54}
55
56// ExecCmd executes system command
57// and return stdout, stderr in string type, along with possible error.
58func ExecCmd(cmdName string, args ...string) (string, string, error) {
59	return ExecCmdDir("", cmdName, args...)
60}
61
62// _________        .__                 .____
63// \_   ___ \  ____ |  |   ___________  |    |    ____   ____
64// /    \  \/ /  _ \|  |  /  _ \_  __ \ |    |   /  _ \ / ___\
65// \     \___(  <_> )  |_(  <_> )  | \/ |    |__(  <_> ) /_/  >
66//  \______  /\____/|____/\____/|__|    |_______ \____/\___  /
67//         \/                                   \/    /_____/
68
69// Color number constants.
70const (
71	Gray = uint8(iota + 90)
72	Red
73	Green
74	Yellow
75	Blue
76	Magenta
77	//NRed      = uint8(31) // Normal
78	EndColor = "\033[0m"
79)
80
81// getColorLevel returns colored level string by given level.
82func getColorLevel(level string) string {
83	level = strings.ToUpper(level)
84	switch level {
85	case "TRAC":
86		return fmt.Sprintf("\033[%dm%s\033[0m", Blue, level)
87	case "ERRO":
88		return fmt.Sprintf("\033[%dm%s\033[0m", Red, level)
89	case "WARN":
90		return fmt.Sprintf("\033[%dm%s\033[0m", Magenta, level)
91	case "SUCC":
92		return fmt.Sprintf("\033[%dm%s\033[0m", Green, level)
93	default:
94		return level
95	}
96}
97
98// ColorLogS colors log and return colored content.
99// Log format: <level> <content [highlight][path]> [ error ].
100// Level: TRAC -> blue; ERRO -> red; WARN -> Magenta; SUCC -> green; others -> default.
101// Content: default; path: yellow; error -> red.
102// Level has to be surrounded by "[" and "]".
103// Highlights have to be surrounded by "# " and " #"(space), "#" will be deleted.
104// Paths have to be surrounded by "( " and " )"(space).
105// Errors have to be surrounded by "[ " and " ]"(space).
106// Note: it hasn't support windows yet, contribute is welcome.
107func ColorLogS(format string, a ...interface{}) string {
108	log := fmt.Sprintf(format, a...)
109
110	var clog string
111
112	if runtime.GOOS != "windows" {
113		// Level.
114		i := strings.Index(log, "]")
115		if log[0] == '[' && i > -1 {
116			clog += "[" + getColorLevel(log[1:i]) + "]"
117		}
118
119		log = log[i+1:]
120
121		// Error.
122		log = strings.Replace(log, "[ ", fmt.Sprintf("[\033[%dm", Red), -1)
123		log = strings.Replace(log, " ]", EndColor+"]", -1)
124
125		// Path.
126		log = strings.Replace(log, "( ", fmt.Sprintf("(\033[%dm", Yellow), -1)
127		log = strings.Replace(log, " )", EndColor+")", -1)
128
129		// Highlights.
130		log = strings.Replace(log, "# ", fmt.Sprintf("\033[%dm", Gray), -1)
131		log = strings.Replace(log, " #", EndColor, -1)
132
133	} else {
134		// Level.
135		i := strings.Index(log, "]")
136		if log[0] == '[' && i > -1 {
137			clog += "[" + log[1:i] + "]"
138		}
139
140		log = log[i+1:]
141
142		// Error.
143		log = strings.Replace(log, "[ ", "[", -1)
144		log = strings.Replace(log, " ]", "]", -1)
145
146		// Path.
147		log = strings.Replace(log, "( ", "(", -1)
148		log = strings.Replace(log, " )", ")", -1)
149
150		// Highlights.
151		log = strings.Replace(log, "# ", "", -1)
152		log = strings.Replace(log, " #", "", -1)
153	}
154	return clog + log
155}
156
157// ColorLog prints colored log to stdout.
158// See color rules in function 'ColorLogS'.
159func ColorLog(format string, a ...interface{}) {
160	fmt.Print(ColorLogS(format, a...))
161}
162