|
|
@ -7,6 +7,7 @@ package mop |
|
|
|
import ( |
|
|
|
import ( |
|
|
|
`bytes` |
|
|
|
`bytes` |
|
|
|
`fmt` |
|
|
|
`fmt` |
|
|
|
|
|
|
|
`reflect` |
|
|
|
`regexp` |
|
|
|
`regexp` |
|
|
|
`strings` |
|
|
|
`strings` |
|
|
|
`text/template` |
|
|
|
`text/template` |
|
|
@ -17,7 +18,9 @@ const TotalColumns = 15 |
|
|
|
|
|
|
|
|
|
|
|
type Column struct { |
|
|
|
type Column struct { |
|
|
|
width int |
|
|
|
width int |
|
|
|
|
|
|
|
name string |
|
|
|
title string |
|
|
|
title string |
|
|
|
|
|
|
|
formatter func(string)string |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
type Layout struct { |
|
|
|
type Layout struct { |
|
|
@ -30,21 +33,21 @@ type Layout struct { |
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
func (self *Layout) Initialize() *Layout { |
|
|
|
func (self *Layout) Initialize() *Layout { |
|
|
|
self.columns = []Column{ |
|
|
|
self.columns = []Column{ |
|
|
|
{ -7, `Ticker` }, |
|
|
|
{ -7, `Ticker`, `Ticker`, nil }, |
|
|
|
{ 10, `Last` }, |
|
|
|
{ 10, `LastTrade`, `Last`, currency }, |
|
|
|
{ 10, `Change` }, |
|
|
|
{ 10, `Change`, `Change`, currency }, |
|
|
|
{ 10, `Change%` }, |
|
|
|
{ 10, `ChangePct`, `Change%`, last }, |
|
|
|
{ 10, `Open` }, |
|
|
|
{ 10, `Open`, `Open`, currency }, |
|
|
|
{ 10, `Low` }, |
|
|
|
{ 10, `Low`, `Low`, currency }, |
|
|
|
{ 10, `High` }, |
|
|
|
{ 10, `High`, `High`, currency }, |
|
|
|
{ 10, `52w Low` }, |
|
|
|
{ 10, `Low52`, `52w Low`, currency }, |
|
|
|
{ 10, `52w High` }, |
|
|
|
{ 10, `High52`, `52w High`, currency }, |
|
|
|
{ 11, `Volume` }, |
|
|
|
{ 11, `Volume`, `Volume`, nil }, |
|
|
|
{ 11, `AvgVolume` }, |
|
|
|
{ 11, `AvgVolume`, `AvgVolume`, nil }, |
|
|
|
{ 9, `P/E` }, |
|
|
|
{ 9, `PeRatio`, `P/E`, blank }, |
|
|
|
{ 9, `Dividend` }, |
|
|
|
{ 9, `Dividend`, `Dividend`, blank_currency }, |
|
|
|
{ 9, `Yield` }, |
|
|
|
{ 9, `Yield`, `Yield`, percent }, |
|
|
|
{ 11, `MktCap` }, |
|
|
|
{ 11, `MarketCap`, `MktCap`, currency }, |
|
|
|
} |
|
|
|
} |
|
|
|
self.regex = regexp.MustCompile(`(\.\d+)[MB]?$`) |
|
|
|
self.regex = regexp.MustCompile(`(\.\d+)[MB]?$`) |
|
|
|
self.market_template = build_market_template() |
|
|
|
self.market_template = build_market_template() |
|
|
@ -107,24 +110,27 @@ func (self *Layout) Header(profile *Profile) string { |
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
func (self *Layout) prettify(quotes *Quotes) []Stock { |
|
|
|
func (self *Layout) prettify(quotes *Quotes) []Stock { |
|
|
|
pretty := make([]Stock, len(quotes.stocks)) |
|
|
|
pretty := make([]Stock, len(quotes.stocks)) |
|
|
|
|
|
|
|
//
|
|
|
|
for i, q := range quotes.stocks { |
|
|
|
// Iterate over the list of stocks and properly format all its columns.
|
|
|
|
pretty[i].Ticker = self.pad(q.Ticker, 0) |
|
|
|
//
|
|
|
|
pretty[i].LastTrade = self.pad(currency(q.LastTrade), 1) |
|
|
|
for i, stock := range quotes.stocks { |
|
|
|
pretty[i].Change = self.pad(currency(q.Change), 2) |
|
|
|
pretty[i].Advancing = stock.Advancing |
|
|
|
pretty[i].ChangePct = self.pad(last(q.ChangePct), 3) |
|
|
|
//
|
|
|
|
pretty[i].Open = self.pad(currency(q.Open), 4) |
|
|
|
// Iterate over the list of stock columns. For each column name:
|
|
|
|
pretty[i].Low = self.pad(currency(q.Low), 5) |
|
|
|
// - Get current column value.
|
|
|
|
pretty[i].High = self.pad(currency(q.High), 6) |
|
|
|
// - If the column has the formatter method then call it.
|
|
|
|
pretty[i].Low52 = self.pad(currency(q.Low52), 7) |
|
|
|
// - Set the column value padding it to the given width.
|
|
|
|
pretty[i].High52 = self.pad(currency(q.High52), 8) |
|
|
|
//
|
|
|
|
pretty[i].Volume = self.pad(q.Volume, 9) |
|
|
|
for _,column := range self.columns { |
|
|
|
pretty[i].AvgVolume = self.pad(q.AvgVolume, 10) |
|
|
|
// ex. value = stock.Change
|
|
|
|
pretty[i].PeRatio = self.pad(blank(q.PeRatioX), 11) |
|
|
|
value := reflect.ValueOf(&stock).Elem().FieldByName(column.name).String() |
|
|
|
pretty[i].Dividend = self.pad(blank_currency(q.Dividend), 12) |
|
|
|
if column.formatter != nil { |
|
|
|
pretty[i].Yield = self.pad(percent(q.Yield), 13) |
|
|
|
// ex. value = currency(value)
|
|
|
|
pretty[i].MarketCap = self.pad(currency(q.MarketCapX), 14) |
|
|
|
value = column.formatter(value) |
|
|
|
pretty[i].Advancing = q.Advancing |
|
|
|
} |
|
|
|
|
|
|
|
// ex. pretty[i].Change = self.pad(value, 10)
|
|
|
|
|
|
|
|
reflect.ValueOf(&pretty[i]).Elem().FieldByName(column.name).SetString(self.pad(value, column.width)) |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
profile := quotes.profile |
|
|
|
profile := quotes.profile |
|
|
@ -141,7 +147,7 @@ func (self *Layout) prettify(quotes *Quotes) []Stock { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
func (self *Layout) pad(str string, col int) string { |
|
|
|
func (self *Layout) pad(str string, width int) string { |
|
|
|
match := self.regex.FindStringSubmatch(str) |
|
|
|
match := self.regex.FindStringSubmatch(str) |
|
|
|
if len(match) > 0 { |
|
|
|
if len(match) > 0 { |
|
|
|
switch len(match[1]) { |
|
|
|
switch len(match[1]) { |
|
|
@ -152,7 +158,7 @@ func (self *Layout) pad(str string, col int) string { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return fmt.Sprintf(`%*s`, self.columns[col].width, str) |
|
|
|
return fmt.Sprintf(`%*s`, width, str) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|