Exemple #1
0
//doLiveGraph builds a graph in the terminal window that
//updates every graphUpdate seconds
//It will build up to maxGraphs graphs with one time-series
//per graph
func doLiveGraph(res *wavefront.QueryResponse, query *wavefront.Querying, period int64) {

	err := ui.Init()
	if err != nil {
		log.Fatal(err)
	}
	defer ui.Close()

	if maxGraphs > len(res.TimeSeries) {
		maxGraphs = len(res.TimeSeries)
	}

	var wDivisor, hDivisor int
	switch maxGraphs {
	case 1:
		wDivisor = 1
		hDivisor = 1
	case 2:
		wDivisor = 2
		hDivisor = 1
	case 3, 4:
		wDivisor = 2
		hDivisor = 2
	}

	height := ui.TermHeight() / hDivisor
	width := ui.TermWidth() / wDivisor
	xVals, yVals := calculateCoords(maxGraphs, ui.TermWidth()/wDivisor, ui.TermHeight()/hDivisor)
	graphs := buildGraphs(res, height, width, xVals, yVals)

	ui.Render(graphs...)
	ui.Handle("/sys/kbd/q", func(ui.Event) {
		// press q to quit
		ui.StopLoop()
	})

	ui.Handle("/sys/kbd/C-c", func(ui.Event) {
		// handle Ctrl + c combination
		ui.StopLoop()
	})

	ui.Handle("/timer/1s", func(e ui.Event) {
		query.SetEndTime(time.Now())
		query.SetStartTime(period)
		res, err := query.Execute()
		if err != nil {
			log.Fatal(err)
		}
		graphs := buildGraphs(res, height, width, xVals, yVals)
		ui.Render(graphs...)
	})

	ui.Loop()

}
Exemple #2
0
func readMessage(message *imap.MessageInfo) {
	set := new(imap.SeqSet)
	set.AddNum(message.Seq)
	cmd, err := imap.Wait(c.Fetch(set, BODY_PART_NAME))
	panicMaybe(err)

	reader, err := messageReader(cmd.Data[0].MessageInfo())
	panicMaybe(err)

	scanner := bufio.NewScanner(reader)
	var lines []string
	for scanner.Scan() {
		lines = append(lines, scanner.Text())
	}
	messageBodyStr := strings.Join(lines[:min(len(lines), ui.TermHeight()-2)], "\n")

	if len(messageBodyStr) <= 0 {
		LOG.Printf("Message body was empty or could not be retrieved: +%v\n", err)
		return
	}

	msgBox := ui.NewPar(messageBodyStr)
	msgBox.Border.Label = "Reading Message"
	msgBox.Height = ui.TermHeight()
	msgBox.Width = ui.TermWidth()
	msgBox.Y = 0
	ui.Render(msgBox)

	topLineIndex := 0

	redraw := make(chan bool)

	for {
		select {
		case e := <-ui.EventCh():
			switch e.Key {
			case ui.KeyArrowDown:
				topLineIndex = max(0, min(
					len(lines)-msgBox.Height/2,
					topLineIndex+1))
				go func() { redraw <- true }()
			case ui.KeyArrowUp:
				topLineIndex = max(0, topLineIndex-1)
				go func() { redraw <- true }()
			case ui.KeyEsc:
				// back to "list messages"
				return
			}
		case <-redraw:
			messageBodyStr = strings.Join(lines[topLineIndex+1:], "\n")
			msgBox.Text = messageBodyStr
			ui.Render(msgBox)
		}
	}
}
func (p *LabelListPage) Create() {
	ui.Clear()
	ls := ui.NewList()
	p.uiList = ls
	if p.statusBar == nil {
		p.statusBar = new(StatusBar)
	}
	if p.commandBar == nil {
		p.commandBar = commandBar
	}
	queryName := p.ActiveQuery.Name
	queryJQL := p.ActiveQuery.JQL
	p.labelCounts = countLabelsFromQuery(queryJQL)
	p.cachedResults = p.labelsAsSortedList()
	p.isPopulated = true
	p.displayLines = make([]string, len(p.cachedResults))
	ls.ItemFgColor = ui.ColorYellow
	ls.BorderLabel = fmt.Sprintf("Label view -- %s: %s", queryName, queryJQL)
	ls.Height = ui.TermHeight() - 2
	ls.Width = ui.TermWidth()
	ls.Y = 0
	p.statusBar.Create()
	p.commandBar.Create()
	p.Update()
}
Exemple #4
0
Fichier : ui.go Projet : mhoc/river
func BuildUI() {
	ui.Init()
	defer ui.Close()

	receiveBox := CreateReceiveBox()
	sendBox := CreateSendBox()
	ui.Body.AddRows(
		ui.NewRow(ui.NewCol(12, 0, receiveBox)),
		ui.NewRow(ui.NewCol(12, 0, sendBox)),
	)

	ui.Body.Align()
	ui.Render(ui.Body)

	ui.Handle("/sys/kbd/C-x", func(e ui.Event) {
		ui.StopLoop()
	})

	ui.Handle("/timer/1s", func(e ui.Event) {
		ReceiveBoxHeight = ui.TermHeight() - SendBoxHeight
		receiveBox.Height = ReceiveBoxHeight
		ui.Body.Align()
		ui.Render(ui.Body)
	})

	// Leaving this commented out for now
	// I'd like to get this method of screen refreshing working instead of the 1s method,
	// but this crashes on resize.
	// ui.Handle("/sys/wnd/resize", func(e ui.Event) {
	//   ui.Body.Align()
	//   ui.Render(ui.Body)
	// })

	ui.Loop()
}
func (p *TicketListPage) Create() {
	log.Debugf("TicketListPage.Create(): self:        %s (%p)", p.Id(), p)
	log.Debugf("TicketListPage.Create(): currentPage: %s (%p)", currentPage.Id(), currentPage)
	ui.Clear()
	ls := ui.NewList()
	p.uiList = ls
	if p.statusBar == nil {
		p.statusBar = new(StatusBar)
	}
	if p.commandBar == nil {
		p.commandBar = commandBar
	}
	query := p.ActiveQuery.JQL
	if sort := p.ActiveSort.JQL; sort != "" {
		re := regexp.MustCompile(`(?i)\s+ORDER\s+BY.+$`)
		query = re.ReplaceAllString(query, ``) + " " + sort
	}
	if len(p.cachedResults) == 0 {
		p.cachedResults = JiraQueryAsStrings(query, p.ActiveQuery.Template)
	}
	if p.selectedLine >= len(p.cachedResults) {
		p.selectedLine = len(p.cachedResults) - 1
	}
	p.displayLines = make([]string, len(p.cachedResults))
	ls.ItemFgColor = ui.ColorYellow
	ls.BorderLabel = fmt.Sprintf("%s: %s", p.ActiveQuery.Name, p.ActiveQuery.JQL)
	ls.Height = ui.TermHeight() - 2
	ls.Width = ui.TermWidth()
	ls.Y = 0
	p.statusBar.Create()
	p.commandBar.Create()
	p.Update()
}
Exemple #6
0
func (ed *Editor) resize() {
	termui.Body.Width = termui.TermWidth()

	ed.applets.Height = termui.TermHeight() - 2 + 1 // offset 1 for border
	ed.desc.Y = ed.locked.Y + ed.locked.Height - 1  // offset 1 for border
	ed.desc.Height = termui.TermHeight() - ed.desc.Y - 2
	ed.title.Y = termui.TermHeight() - 2

	ed.title.Width = termui.TermWidth() + 1                     // offset 1 for border
	ed.appinfo.Width = termui.TermWidth() - ed.appinfo.X + 1    // offset 1 for border
	ed.locked.Width = termui.TermWidth() - ed.applets.Width + 1 // offset 1 for border
	ed.desc.Width = termui.TermWidth() - ed.applets.Width + 1   // offset 1 for border
	ed.desc.WrapLength = ed.desc.Width

	termui.Render(ed.applets, ed.fields, ed.appinfo, ed.locked, ed.desc, ed.title)
}
Exemple #7
0
func (ui *tatui) initHomeLeft() {

	textURL := viper.GetString("url")
	if textURL == "" {
		textURL = "[Invalid URL, please check your config file](fg-red)"
	}

	p := termui.NewPar(`                            TEXT AND TAGS
            ----------------------------------------------
            ----------------------------------------------
                     |||                     |||
                     |||                     |||
                     |||         |||         |||
                     |||         |||         |||
                     |||                     |||
                     |||         |||         |||
                     |||         |||         |||
                     |||                     |||
                     |||                     |||

                       Tatcli Version: ` + internal.VERSION + `
                    https://github.com/ovh/tatcli
                TAT Engine: https://github.com/ovh/tat
								Current Tat Engine: ` + textURL + `
								Current config file: ` + internal.ConfigFile + `
 Shortcuts:
 - Ctrl + a to view all topics. Cmd /topics in send box
 - Ctrl + b to go back to messsages list, after selected a message
 - Ctrl + c clears filters and UI on current messages list
 - Ctrl + f to view favorites topics. Cmd /favorites
 - Ctrl + h to go back home. Cmd /home or /help
 - Ctrl + t hide or show top menu. Cmd /toggle-top
 - Ctrl + y hide or show actionbox menu. Cmd /toggle-bottom
 - Ctrl + o open current message on tatwebui with a browser. Cmd /open
	          Use option tatwebui-url in config file. See /set-tatwebui-url
 - Ctrl + p open links in current message with a browser. Cmd /open-links
 - Ctrl + j / Ctrl + k (for reverse action):
	    if mode run is enabled, set a msg from open to doing,
	        from doing to done from done to open.
	    if mode monitoring is enabled, set a msg from UP to AL,
	        from AL to UP.
 - Ctrl + q to quit. Cmd /quit
 - Ctrl + r to view unread topics. Cmd /unread
 - Ctrl + u display/hide usernames in messages list. Cmd /toggle-usernames
 - UP / Down to move into topics & messages list
 - UP / Down to navigate through history of action box
 - <tab> to go to next section on screen`)

	p.Height = termui.TermHeight() - uiHeightTop - uiHeightSend
	p.TextFgColor = termui.ColorWhite
	p.BorderTop = true
	p.BorderLeft = false
	p.BorderBottom = false
	ui.homeLeft = p
}
Exemple #8
0
func (p *CommandBar) Create() {
	ls := ui.NewList()
	p.uiList = ls
	ls.ItemFgColor = ui.ColorGreen
	ls.Border = false
	ls.Height = 1
	ls.Width = ui.TermWidth()
	ls.X = 0
	ls.Y = ui.TermHeight() - 1
	p.Update()
}
Exemple #9
0
func adjustDimensions() {
	termui.Body.Width = termui.TermWidth()
	height := termui.TermHeight()
	parMap["moveHistory"].Height = height - 23 - 4
	parMap["output"].Height = height - 23
	if height < 31 {
		parMap["board"].Height = height - 8
		parMap["moveHistory"].Height = 2
		parMap["output"].Height = 6
	}
}
func (p *TicketShowPage) Create() {
	log.Debugf("TicketShowPage.Create(): self:        %s (%p)", p.Id(), p)
	log.Debugf("TicketShowPage.Create(): currentPage: %s (%p)", currentPage.Id(), currentPage)
	p.opts = getJiraOpts()
	if p.TicketId == "" {
		p.TicketId = ticketListPage.GetSelectedTicketId()
	}
	if p.MaxWrapWidth == 0 {
		if m := p.opts["max_wrap"]; m != nil {
			p.MaxWrapWidth = uint(m.(int64))
		} else {
			p.MaxWrapWidth = defaultMaxWrapWidth
		}
	}
	ui.Clear()
	ls := ui.NewList()
	if p.statusBar == nil {
		p.statusBar = new(StatusBar)
	}
	if p.commandBar == nil {
		p.commandBar = commandBar
	}
	p.uiList = ls
	if p.Template == "" {
		if templateOpt := p.opts["template"]; templateOpt == nil {
			p.Template = "jira_ui_view"
		} else {
			p.Template = templateOpt.(string)
		}
	}
	innerWidth := uint(ui.TermWidth()) - 3
	if innerWidth < p.MaxWrapWidth {
		p.WrapWidth = innerWidth
	} else {
		p.WrapWidth = p.MaxWrapWidth
	}
	if p.apiBody == nil {
		p.apiBody, _ = FetchJiraTicket(p.TicketId)
	}
	p.cachedResults = WrapText(JiraTicketAsStrings(p.apiBody, p.Template), p.WrapWidth)
	p.displayLines = make([]string, len(p.cachedResults))
	if p.selectedLine >= len(p.cachedResults) {
		p.selectedLine = len(p.cachedResults) - 1
	}
	ls.ItemFgColor = ui.ColorYellow
	ls.Height = ui.TermHeight() - 2
	ls.Width = ui.TermWidth()
	ls.Border = true
	ls.BorderLabel = fmt.Sprintf("%s %s", p.TicketId, p.ticketTrailAsString())
	ls.Y = 0
	p.statusBar.Create()
	p.commandBar.Create()
	p.Update()
}
Exemple #11
0
func (p *StatusBar) Create() {
	ls := ui.NewList()
	p.uiList = ls
	ls.ItemFgColor = ui.ColorWhite
	ls.ItemBgColor = ui.ColorRed
	ls.Bg = ui.ColorRed
	ls.Border = false
	ls.Height = 1
	ls.Width = ui.TermWidth()
	ls.X = 0
	ls.Y = ui.TermHeight() - 2
	p.Update()
}
func (p *BaseListPage) Create() {
	ui.Clear()
	ls := ui.NewList()
	p.uiList = ls
	p.cachedResults = make([]string, 0)
	p.displayLines = make([]string, len(p.cachedResults))
	ls.ItemFgColor = ui.ColorYellow
	ls.BorderLabel = "Updating, please wait"
	ls.Height = ui.TermHeight()
	ls.Width = ui.TermWidth()
	ls.Y = 0
	p.Update()
}
Exemple #13
0
func (ui *tatui) initHomeRight() {
	p := termui.NewPar(`Action Box

  Keywords:
   - /help display this page
   - /me show information about you
   - /version to show tatcli and engine version

  On messages list:
   - /label eeeeee yourLabel to add a label on selected message
   - /unlabel yourLabel to remove label "yourLabel" on selected message
   - /voteup, /votedown, /unvoteup, /unvotedown to vote up or down, or remove vote
   - /task, /untask to add or remove selected message as a personal task
   - /like, /unlike to add or remove like on selected message
   - /filter label:labelA,labelB andtag:tag,tagb
   - /mode (run|monitoring): enable Ctrl + l shortcut, see on left side for help
   - /codereview splits screen into fours panes:
     label:OPENED label:APPROVED label:MERGED label:DECLINED
   - /monitoring splits screen into three panes: label:UP, label:AL, notlabel:AL,UP
     This is the same as two commands:
      - /split label:UP label:AL notlabel:AL,UP
      - /mode monitoring
   - /run <tag> splits screen into three panes: label:open, label:doing, label:done
     /run AA,BB is the same as two commands:
      - /split tag:AA,BB;label:open tag:AA,BB;label:doing tag:AA,BB;label:done
      - /mode run
   - /set-tatwebui-url <urlOfTatWebUI> sets tatwebui-url in tatcli config file. This
      url is used by Ctrl + o shortcut to open message with a tatwebui instance.
   - /split <criteria> splits screen with one section per criteria delimited by space, ex:
      /split label:labelA label:labelB label:labelC
      /split label:labelA,labelB andtag:tag,tagb
      /split tag:myTag;label:labelA,labelB andtag:tag,tagb;label:labelC
   - /save saves current filters in tatcli config file
   - /toggle-usernames displays or hides username in messages list

  For /split and /filter, see all parameters on https://github.com/ovh/tat#parameters

  On topics list, ex:
   - /filter topic:/Private/firstname.lastname
  			see all parameters on https://github.com/ovh/tat#parameters-4

`)

	p.Height = termui.TermHeight() - uiHeightTop - uiHeightSend
	p.TextFgColor = termui.ColorWhite
	p.BorderTop = true
	p.BorderLeft = false
	p.BorderRight = false
	p.BorderBottom = false
	ui.homeRight = p
}
func (p *BaseInputBox) Create() {
	ls := ui.NewList()
	var strs []string
	p.uiList = ls
	ls.Items = strs
	ls.ItemFgColor = ui.ColorGreen
	ls.BorderFg = ui.ColorRed
	ls.Height = 1
	ls.Width = 30
	ls.Overflow = "wrap"
	ls.X = ui.TermWidth()/2 - ls.Width/2
	ls.Y = ui.TermHeight()/2 - ls.Height/2
	p.Update()
}
func (p *PasswordInputBox) Create() {
	ls := ui.NewList()
	p.uiList = ls
	var strs []string
	ls.Items = strs
	ls.ItemFgColor = ui.ColorGreen
	ls.BorderLabel = "Enter Password:"
	ls.BorderFg = ui.ColorRed
	ls.Height = 3
	ls.Width = 30
	ls.X = ui.TermWidth()/2 - ls.Width/2
	ls.Y = ui.TermHeight()/2 - ls.Height/2
	p.Update()
}
Exemple #16
0
func refresh() {
	prompt.Text = promptMsg

	nreport := ui.TermHeight() - 13
	ls.Height = nreport
	if len(reportItems) > nreport*reportPage {
		// can seek to the page
		ls.Items = reportItems[nreport*reportPage : len(reportItems)]
	} else {
		ls.Items = []string{}
	}

	ui.Body.Align()
	ui.Render(ui.Body)
}
Exemple #17
0
func setupBody() {

	height := termui.TermHeight() - 23

	prompt := termui.NewPar("")
	prompt.Height = 1
	prompt.Border = false
	parMap["prompt"] = prompt

	input := termui.NewPar("")
	input.Height = 3
	input.BorderLabel = "Input"
	input.BorderFg = termui.ColorYellow
	parMap["input"] = input

	moveHistory := termui.NewPar("")
	moveHistory.Height = height - 4
	moveHistory.BorderLabel = "Move History"
	moveHistory.BorderFg = termui.ColorBlue
	parMap["moveHistory"] = moveHistory
	linesMap["moveHistory"] = NewLines()

	output := termui.NewPar("")
	output.Height = height
	output.BorderLabel = "Output"
	output.BorderFg = termui.ColorGreen
	parMap["output"] = output
	linesMap["output"] = NewLines()

	board := termui.NewPar("")
	board.Height = 23
	board.Width = 37
	board.BorderLabel = "Board"
	board.BorderFg = termui.ColorRed
	parMap["board"] = board

	// build layout
	termui.Body.AddRows(
		termui.NewRow(
			termui.NewCol(6, 0, parMap["prompt"], parMap["input"], parMap["moveHistory"]),
			termui.NewCol(6, 0, parMap["output"]),
		),
		termui.NewRow(
			termui.NewCol(12, 0, parMap["board"]),
		),
	)
	changeState(0)
}
Exemple #18
0
func showSubreddit(subredditName string) error {
	r := geddit.NewSession("r by /u/bnadland")

	submissions, err := r.SubredditSubmissions(subredditName, geddit.HotSubmissions, geddit.ListingOptions{})
	if err != nil {
		return err
	}

	isActive := true

	cursor := 3
	for isActive {

		entries := []string{}
		for i, submission := range submissions {
			entries = append(entries, fmt.Sprintf("%s %s", isActiveCursor(cursor, i), submission.Title))
		}

		ls := termui.NewList()
		ls.Items = entries
		ls.ItemFgColor = termui.ColorDefault
		ls.Border.Label = fmt.Sprintf("Subreddit: %s", subredditName)
		ls.Height = termui.TermHeight()
		ls.Width = termui.TermWidth()
		ls.Y = 0
		termui.Render(ls)
		event := <-termui.EventCh()
		if event.Type == termui.EventKey {
			switch event.Key {
			case termui.KeyArrowLeft:
				isActive = false
			case termui.KeyArrowDown:
				cursor = cursor + 1
				if cursor > len(submissions) {
					cursor = len(submissions)
				}
			case termui.KeyArrowUp:
				cursor = cursor - 1
				if cursor < 0 {
					cursor = 0
				}
			}
		}
	}
	return nil
}
Exemple #19
0
func main() {
	if len(os.Args) < 2 {
		log.Fatal("Usage: ", os.Args[0], " <sparkyfish server hostname/IP>[:port]")
	}

	dest := os.Args[1]
	i := last(dest, ':')
	if i < 0 {
		dest = fmt.Sprint(dest, ":7121")
	}

	// Initialize our screen
	err := termui.Init()
	if err != nil {
		panic(err)
	}

	if termui.TermWidth() < 60 || termui.TermHeight() < 28 {
		fmt.Println("sparkyfish needs a terminal window at least 60x28 to run.")
		os.Exit(1)
	}

	defer termui.Close()

	// 'q' quits the program
	termui.Handle("/sys/kbd/q", func(termui.Event) {
		termui.StopLoop()
	})
	// 'Q' also works
	termui.Handle("/sys/kbd/Q", func(termui.Event) {
		termui.StopLoop()
	})

	sc := newsparkyClient()
	sc.serverHostname = dest

	sc.prepareChannels()

	sc.wr = newwidgetRenderer()

	// Begin our tests
	go sc.runTestSequence()

	termui.Loop()
}
Exemple #20
0
func (ui *tatui) initMessage() {
	strs := []string{"[Loading...](fg-black,bg-white)"}

	ls := termui.NewList()
	ls.BorderTop, ls.BorderLeft, ls.BorderRight, ls.BorderBottom = true, false, false, false
	ls.Items = strs
	ls.ItemFgColor = termui.ColorWhite
	ls.BorderLabel = "Message"
	ls.Overflow = "wrap"
	ls.Width = 25
	ls.Y = 0
	ls.Height = termui.TermHeight() - uiHeightTop - uiHeightSend
	_, ok := ui.uilists[uiMessages][ui.selectedPaneMessages]
	if ok && ui.uilists[uiMessages][ui.selectedPaneMessages].position >= 0 && ui.uilists[uiMessages][ui.selectedPaneMessages].position < len(ui.currentListMessages[ui.selectedPaneMessages]) {
		ui.currentMessage = ui.currentListMessages[ui.selectedPaneMessages][ui.uilists[uiMessages][ui.selectedPaneMessages].position]
		ui.uilists[uiMessage][0] = &uilist{uiType: uiMessage, list: ls, position: 0, page: 0, update: ui.updateMessage}
	}
}
func (p *SortOrderPage) Create() {
	ls := ui.NewList()
	p.uiList = ls
	p.selectedLine = 0
	p.firstDisplayLine = 0
	if len(p.cachedResults) == 0 {
		p.cachedResults = getSorts()
		p.displayLines = make([]string, len(p.cachedResults))
	}
	ls.ItemFgColor = ui.ColorGreen
	ls.BorderLabel = "Sort By..."
	ls.BorderFg = ui.ColorRed
	ls.Height = 10
	ls.Width = 50
	ls.X = ui.TermWidth()/2 - ls.Width/2
	ls.Y = ui.TermHeight()/2 - ls.Height/2
	p.Update()
}
Exemple #22
0
func (ui *tatui) initMessages() {
	for k := range ui.currentFilterMessages[ui.currentTopic.Topic] {
		strs := []string{"[Loading...](fg-black,bg-white)"}
		ls := termui.NewList()
		ls.BorderTop, ls.BorderLeft, ls.BorderRight, ls.BorderBottom = true, false, false, false
		ls.Items = strs
		ls.ItemFgColor = termui.ColorWhite
		ls.BorderLabel = "Messages"
		ls.Width = 25
		ls.Y = 0
		ls.Height = (termui.TermHeight() - uiHeightTop - uiHeightSend) / len(ui.currentFilterMessages[ui.currentTopic.Topic])

		if _, ok := ui.uilists[uiMessages]; !ok {
			ui.uilists[uiMessages] = make(map[int]*uilist)
		}
		ui.uilists[uiMessages][k] = &uilist{uiType: uiMessages, list: ls, position: 0, page: 0, update: ui.updateMessages}
	}
	ui.applyLabelOnMsgPanes()
	ui.render()
}
Exemple #23
0
func (ui *tatui) showResult(cmdResult, result string) {
	ui.current = uiResult
	ui.send.BorderLabel = " ✎ Action"
	termui.Body.Rows = nil

	p := termui.NewPar(`Result of ` + cmdResult + `:
` + result + `
`)

	p.Height = termui.TermHeight() - uiHeightTop - uiHeightSend
	p.TextFgColor = termui.ColorWhite
	p.BorderTop = true

	ui.prepareTopMenu()
	termui.Body.AddRows(
		termui.NewRow(
			termui.NewCol(12, 0, p),
		),
	)
	ui.prepareSendRow()
	termui.Clear()
}
Exemple #24
0
func (ui *tatui) initTopics() {
	strs := []string{"[Loading...](fg-black,bg-white)"}

	ls := termui.NewList()
	ls.BorderTop, ls.BorderLeft, ls.BorderRight, ls.BorderBottom = true, false, false, false
	ls.Items = strs
	ls.ItemFgColor = termui.ColorWhite
	if ui.onlyFavorites == "true" {
		ls.BorderLabel = " ★ Favorites Topics ★ "
	} else if ui.onlyUnread {
		ls.BorderLabel = " ✉ Unread Topics ✉ "
	} else {
		ls.BorderLabel = " All Topics "
	}

	ls.Width = 25
	ls.Y = 0
	ls.Height = termui.TermHeight() - uiHeightTop - uiHeightSend

	m := make(map[int]*uilist)
	m[0] = &uilist{uiType: uiTopics, list: ls, position: 0, page: 0, update: ui.updateTopics}
	ui.uilists[uiTopics] = m
}
func (p *QueryPage) Create() {
	log.Debugf("QueryPage.Create(): self:        %s (%p)", p.Id(), p)
	log.Debugf("QueryPage.Create(): currentPage: %s (%p)", currentPage.Id(), currentPage)
	ui.Clear()
	ls := ui.NewList()
	p.uiList = ls
	if p.statusBar == nil {
		p.statusBar = new(StatusBar)
	}
	if p.commandBar == nil {
		p.commandBar = commandBar
	}
	p.cachedResults = getQueries()
	p.displayLines = make([]string, len(p.cachedResults))
	ls.ItemFgColor = ui.ColorYellow
	ls.BorderLabel = "Queries"
	ls.Height = ui.TermHeight() - 2
	ls.Width = ui.TermWidth()
	ls.Y = 0
	p.statusBar.Create()
	p.commandBar.Create()
	p.Update()
}
Exemple #26
0
func (p *HelpPage) Create() {
	ui.Clear()
	ls := ui.NewList()
	p.uiList = ls
	if p.statusBar == nil {
		p.statusBar = new(StatusBar)
	}
	if p.commandBar == nil {
		p.commandBar = commandBar
	}
	if len(p.cachedResults) == 0 {
		p.cachedResults = HelpTextAsStrings(nil, "jira_ui_help")
	}
	p.displayLines = make([]string, len(p.cachedResults))
	ls.ItemFgColor = ui.ColorYellow
	ls.BorderLabel = "Help"
	ls.Height = ui.TermHeight() - 2
	ls.Width = ui.TermWidth()
	ls.Y = 0
	p.statusBar.Create()
	p.commandBar.Create()
	p.Update()
}
Exemple #27
0
// Relayout recalculates widgets sizes and coords.
func (t *TermUISingle) Relayout() {
	tw, th := termui.TermWidth(), termui.TermHeight()
	h := th

	// First row: Title and Status pars
	firstRowH := 3
	t.Title.Height = firstRowH
	t.Title.Width = tw / 2
	if tw%2 == 1 {
		t.Title.Width++
	}
	t.Status.Height = firstRowH
	t.Status.Width = tw / 2
	t.Status.X = t.Title.X + t.Title.Width
	h -= firstRowH

	// Second row: lists
	secondRowH := 3
	num := len(t.Pars)
	parW := tw / num
	for i, par := range t.Pars {
		par.Y = th - h
		par.Width = parW
		par.Height = secondRowH
		par.X = i * parW
	}
	if num*parW < tw {
		t.Pars[num-1].Width = tw - ((num - 1) * parW)
	}
	h -= secondRowH

	// Third row: Sparklines
	t.Sparkline.Width = tw
	t.Sparkline.Height = h
	t.Sparkline.Y = th - h
}
Exemple #28
0
// monitor starts a terminal UI based monitoring tool for the requested metrics.
func monitor(ctx *cli.Context) {
	var (
		client comms.EthereumClient
		err    error
	)
	// Attach to an Ethereum node over IPC or RPC
	endpoint := ctx.String(monitorCommandAttachFlag.Name)
	if client, err = comms.ClientFromEndpoint(endpoint, codec.JSON); err != nil {
		utils.Fatalf("Unable to attach to geth node: %v", err)
	}
	defer client.Close()

	xeth := rpc.NewXeth(client)

	// Retrieve all the available metrics and resolve the user pattens
	metrics, err := retrieveMetrics(xeth)
	if err != nil {
		utils.Fatalf("Failed to retrieve system metrics: %v", err)
	}
	monitored := resolveMetrics(metrics, ctx.Args())
	if len(monitored) == 0 {
		list := expandMetrics(metrics, "")
		sort.Strings(list)

		if len(list) > 0 {
			utils.Fatalf("No metrics specified.\n\nAvailable:\n - %s", strings.Join(list, "\n - "))
		} else {
			utils.Fatalf("No metrics collected by geth (--%s).\n", utils.MetricsEnabledFlag.Name)
		}
	}
	sort.Strings(monitored)
	if cols := len(monitored) / ctx.Int(monitorCommandRowsFlag.Name); cols > 6 {
		utils.Fatalf("Requested metrics (%d) spans more that 6 columns:\n - %s", len(monitored), strings.Join(monitored, "\n - "))
	}
	// Create and configure the chart UI defaults
	if err := termui.Init(); err != nil {
		utils.Fatalf("Unable to initialize terminal UI: %v", err)
	}
	defer termui.Close()

	termui.UseTheme("helloworld")

	rows := len(monitored)
	if max := ctx.Int(monitorCommandRowsFlag.Name); rows > max {
		rows = max
	}
	cols := (len(monitored) + rows - 1) / rows
	for i := 0; i < rows; i++ {
		termui.Body.AddRows(termui.NewRow())
	}
	// Create each individual data chart
	footer := termui.NewPar("")
	footer.HasBorder = true
	footer.Height = 3

	charts := make([]*termui.LineChart, len(monitored))
	units := make([]int, len(monitored))
	data := make([][]float64, len(monitored))
	for i := 0; i < len(monitored); i++ {
		charts[i] = createChart((termui.TermHeight() - footer.Height) / rows)
		row := termui.Body.Rows[i%rows]
		row.Cols = append(row.Cols, termui.NewCol(12/cols, 0, charts[i]))
	}
	termui.Body.AddRows(termui.NewRow(termui.NewCol(12, 0, footer)))

	refreshCharts(xeth, monitored, data, units, charts, ctx, footer)
	termui.Body.Align()
	termui.Render(termui.Body)

	// Watch for various system events, and periodically refresh the charts
	refresh := time.Tick(time.Duration(ctx.Int(monitorCommandRefreshFlag.Name)) * time.Second)
	for {
		select {
		case event := <-termui.EventCh():
			if event.Type == termui.EventKey && event.Key == termui.KeyCtrlC {
				return
			}
			if event.Type == termui.EventResize {
				termui.Body.Width = termui.TermWidth()
				for _, chart := range charts {
					chart.Height = (termui.TermHeight() - footer.Height) / rows
				}
				termui.Body.Align()
				termui.Render(termui.Body)
			}
		case <-refresh:
			if refreshCharts(xeth, monitored, data, units, charts, ctx, footer) {
				termui.Body.Align()
			}
			termui.Render(termui.Body)
		}
	}
}
Exemple #29
0
func main() {
	pfile := flag.String("f", "", "psafe3 file")
	flag.Parse()

	fmt.Printf("Password: "******"Last Saved: %s\nLast Saved By %s @ %s",
		safe.Headers.LastSave.Format("2006-01-02 15:04:05"),
		safe.Headers.User, safe.Headers.Host))
	rightpar.Height = 2
	rightpar.HasBorder = false

	leftpar := termui.NewPar(fmt.Sprintf("File Name: %s\nLast Program: %s",
		filepath.Base(*pfile),
		safe.Headers.ProgramSave))
	leftpar.Height = 2
	leftpar.HasBorder = false

	recordlist := termui.NewList()
	recordlist.Height = termui.TermHeight() - 5
	recordlist.Items = getRecordList(safe)
	recordlist.Border.Label = fmt.Sprintf("Records (%d)", len(safe.Records))

	recorddetail := termui.NewPar("")
	recorddetail.Height = recordlist.Height
	recorddetail.Border.Label = "Record Information"

	inputbox := termui.NewPar("")
	inputbox.Height = 3
	inputbox.Border.Label = "Input Box ([Enter] to save, [Esc] to cancel)"
	inputrow := termui.NewRow(termui.NewCol(12, 0, inputbox))

	commandinfo := termui.NewPar(strings.Join([]string{
		"Select record by typing the index number. Edit field by typing field marker.",
	}, "\n"))
	commandinfo.Height = 3
	commandinfo.Border.Label = "Help"
	commandrow := termui.NewRow(termui.NewCol(12, 0, commandinfo))

	termui.Body.AddRows(
		termui.NewRow(
			termui.NewCol(6, 0, leftpar),
			termui.NewCol(6, 0, rightpar),
		),
		termui.NewRow(
			termui.NewCol(6, 0, recordlist),
			termui.NewCol(6, 0, recorddetail),
		),
		commandrow,
	)

	termui.Body.Align()
	termui.Render(termui.Body)

	evt := termui.EventCh()

	inputMode := false
	valBuffer := bytes.Buffer{}
	numBuffer := bytes.Buffer{}
	var selRecord *pwsafe.Record
	var selField *string
	var inputPrompt string
	var startIndex int
Main:
	for {
		select {
		case e := <-evt:
			if !inputMode && e.Type == termui.EventKey {
				switch e.Ch {
				case 'q':
					break Main
				case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
					numBuffer.WriteRune(e.Ch)
				case '#':
					selIndex, _ := strconv.ParseInt(numBuffer.String(), 10, 64)
					selRecord = &safe.Records[selIndex]
					selField = nil
					numBuffer.Reset()
				case 'j':
					startIndex++
					rlist := getRecordList(safe)
					recordlist.Items = rlist[startIndex:]
				case 'k':
					if startIndex > 1 {
						startIndex--
						rlist := getRecordList(safe)
						recordlist.Items = rlist[startIndex:]
					}
				case 'a':
					selIndex := len(safe.Records)
					safe.Records = append(safe.Records, pwsafe.Record{})
					selRecord = &safe.Records[selIndex]
					selRecord.UUID = uuid.NewV1()
					selRecord.CreationTime = time.Now()
					selField = nil
					rlist := getRecordList(safe)
					recordlist.Items = rlist[startIndex:]
					recordlist.Border.Label = fmt.Sprintf("Records (%d)", len(safe.Records))
				case 'g':
					selField = &selRecord.Group
					inputPrompt = "Group: "
					inputMode = true
					valBuffer.WriteString(selRecord.Group)
					inputbox.Text = inputPrompt + valBuffer.String()
				case 't':
					selField = &selRecord.Title
					inputPrompt = "Title: "
					inputMode = true
					valBuffer.WriteString(selRecord.Title)
					inputbox.Text = inputPrompt + valBuffer.String()
				case 'u':
					selField = &selRecord.Username
					inputPrompt = "Username: "******"Password: "******"Url: "
					inputMode = true
					valBuffer.WriteString(selRecord.Url)
					inputbox.Text = inputPrompt + valBuffer.String()
				case 'n':
					selField = &selRecord.Notes
					inputPrompt = "Notes: "
					inputMode = true
					valBuffer.WriteString(selRecord.Notes)
					inputbox.Text = inputPrompt + valBuffer.String()
				case 'e':
					selField = &selRecord.Email
					inputPrompt = "Email: "
					inputMode = true
					valBuffer.WriteString(selRecord.Email)
					inputbox.Text = inputPrompt + valBuffer.String()
				}
			} else if inputMode && e.Type == termui.EventKey {
				if e.Key == termui.KeyEnter {
					if selField != nil {
						*selField = valBuffer.String()
					}
					valBuffer.Reset()
					inputMode = false
					inputbox.Text = ""
					rlist := getRecordList(safe)
					recordlist.Items = rlist[startIndex:]
				} else if e.Key == termui.KeyEsc {
					valBuffer.Reset()
					inputMode = false
					inputbox.Text = ""
				} else if e.Key == termui.KeySpace {
					valBuffer.WriteRune(' ')
				} else if e.Key == termui.KeyBackspace || e.Ch == '' {
					s := valBuffer.String()
					valBuffer = bytes.Buffer{}
					if len(s) > 0 {
						s = s[0 : len(s)-1]
					}
					valBuffer.WriteString(s)
					inputbox.Text = inputPrompt + valBuffer.String()
				} else {
					valBuffer.WriteRune(e.Ch)
					inputbox.Text = inputPrompt + valBuffer.String()
				}
			}
			if e.Type == termui.EventResize {
				termui.Body.Width = termui.TermWidth()
				termui.Body.Align()
			}

			if selRecord != nil {
				recorddetail.Text = getRecordDetail(*selRecord)
			}

			if inputMode {
				termui.Body.Rows[2] = inputrow
			} else {
				termui.Body.Rows[2] = commandrow
			}
			termui.Body.Align()
			termui.Render(termui.Body)
		}
	}

	oerr := pwsafe.OutputFile(*pfile, string(pw), *safe)
	if oerr != nil {
		log.Fatalln(oerr)
	}

}
// monitor starts a terminal UI based monitoring tool for the requested metrics.
func monitor(ctx *cli.Context) error {
	var (
		client rpc.Client
		err    error
	)
	// Attach to an Expanse node over IPC or RPC
	endpoint := ctx.String(monitorCommandAttachFlag.Name)
	if client, err = utils.NewRemoteRPCClientFromString(endpoint); err != nil {
		utils.Fatalf("Unable to attach to gexp node: %v", err)
	}
	defer client.Close()

	// Retrieve all the available metrics and resolve the user pattens
	metrics, err := retrieveMetrics(client)
	if err != nil {
		utils.Fatalf("Failed to retrieve system metrics: %v", err)
	}
	monitored := resolveMetrics(metrics, ctx.Args())
	if len(monitored) == 0 {
		list := expandMetrics(metrics, "")
		sort.Strings(list)

		if len(list) > 0 {
			utils.Fatalf("No metrics specified.\n\nAvailable:\n - %s", strings.Join(list, "\n - "))
		} else {
			utils.Fatalf("No metrics collected by gexp (--%s).\n", utils.MetricsEnabledFlag.Name)
		}
	}
	sort.Strings(monitored)
	if cols := len(monitored) / ctx.Int(monitorCommandRowsFlag.Name); cols > 6 {
		utils.Fatalf("Requested metrics (%d) spans more that 6 columns:\n - %s", len(monitored), strings.Join(monitored, "\n - "))
	}
	// Create and configure the chart UI defaults
	if err := termui.Init(); err != nil {
		utils.Fatalf("Unable to initialize terminal UI: %v", err)
	}
	defer termui.Close()

	rows := len(monitored)
	if max := ctx.Int(monitorCommandRowsFlag.Name); rows > max {
		rows = max
	}
	cols := (len(monitored) + rows - 1) / rows
	for i := 0; i < rows; i++ {
		termui.Body.AddRows(termui.NewRow())
	}
	// Create each individual data chart
	footer := termui.NewPar("")
	footer.Block.Border = true
	footer.Height = 3

	charts := make([]*termui.LineChart, len(monitored))
	units := make([]int, len(monitored))
	data := make([][]float64, len(monitored))
	for i := 0; i < len(monitored); i++ {
		charts[i] = createChart((termui.TermHeight() - footer.Height) / rows)
		row := termui.Body.Rows[i%rows]
		row.Cols = append(row.Cols, termui.NewCol(12/cols, 0, charts[i]))
	}
	termui.Body.AddRows(termui.NewRow(termui.NewCol(12, 0, footer)))

	refreshCharts(client, monitored, data, units, charts, ctx, footer)
	termui.Body.Align()
	termui.Render(termui.Body)

	// Watch for various system events, and periodically refresh the charts
	termui.Handle("/sys/kbd/C-c", func(termui.Event) {
		termui.StopLoop()
	})
	termui.Handle("/sys/wnd/resize", func(termui.Event) {
		termui.Body.Width = termui.TermWidth()
		for _, chart := range charts {
			chart.Height = (termui.TermHeight() - footer.Height) / rows
		}
		termui.Body.Align()
		termui.Render(termui.Body)
	})
	go func() {
		tick := time.NewTicker(time.Duration(ctx.Int(monitorCommandRefreshFlag.Name)) * time.Second)
		for range tick.C {
			if refreshCharts(client, monitored, data, units, charts, ctx, footer) {
				termui.Body.Align()
			}
			termui.Render(termui.Body)
		}
	}()
	termui.Loop()
	return nil
}