func init() { if err := termbox.Init(); err != nil { panic(err) } termbox.SetCursor(0, 0) termbox.HideCursor() }
func (s *Session) Draw() { s.View.SetRef(s.CursorL, 0, 0, s.Ypivot) surf := s.View.Render() // draw cursor x, y := view.RenderPos(surf, s.CursorL, s.CursorC) termbox.SetCursor(x, y) // draw content view.Draw(surf, 0, 0) }
// Draws the editbox at (x,y) position. func (eb *editbox) draw() { drawRect(eb.x, eb.y, eb.w, eb.h) t := eb.text lx := 0 for { if len(t) == 0 { break } r, size := utf8.DecodeRune(t) // topdown words if lx == 0 && unicode.IsLetter(r) { termbox.SetCell(eb.x, eb.y, '↓', fgcolor|termbox.AttrBold, bgcolor) } // leftright words if lx == 0 && unicode.IsNumber(r) { termbox.SetCell(eb.x, eb.y, '→', fgcolor|termbox.AttrBold, bgcolor) } // pass if lx == 0 && r == '-' { termbox.SetCell(eb.x, eb.y, '⚐', fgcolor|termbox.AttrBold, bgcolor) } termbox.SetCell(eb.x+lx+2, eb.y, r, fgcolor, bgcolor) lx += 1 t = t[size:] } termbox.SetCursor(eb.x+lx+2, eb.y) // error/warning indicator if eb.warn { drawRectWithAttr(eb.x, eb.y, eb.w, eb.h, fgcolor, bgcolor) termbox.SetCell(eb.x, eb.y, '❗', fgcolor, bgcolor) eb.warn = false } else if eb.err { drawRectWithAttr(eb.x, eb.y, eb.w, eb.h, fgcolor, bgcolor) termbox.SetCell(eb.x, eb.y, '⊗', fgcolor, bgcolor) eb.err = false } }
// SetCursorPos sets text caret position. Used by controls like EditField func SetCursorPos(x int, y int) { term.SetCursor(x, y) }
func setCursor(p Point) { termbox.SetCursor(p.X, p.Y) }
func main() { var newFlag bool flag.BoolVar(&newFlag, "new", false, "let tor to edit a new file.") flag.Parse() args := flag.Args() if len(args) == 0 { fmt.Println("please, set text file") os.Exit(1) } farg := args[len(args)-1] f, initL, initO, err := parseFileArg(farg) if err != nil { fmt.Println("file arg is invalid: ", err) os.Exit(1) } exist := true if _, err := os.Stat(f); os.IsNotExist(err) { exist = false } if !exist && !newFlag { fmt.Println("file not exist. please retry with -new flag.") os.Exit(1) } else if exist && newFlag { fmt.Println("file already exist.") os.Exit(1) } var text *Text if exist { text, err = open(f) if err != nil { fmt.Println(err) os.Exit(1) } } else { lines := make([]Line, 0) lines = append(lines, Line{""}) text = &Text{lines: lines, tabToSpace: false, tabWidth: 4, edited: false} } err = term.Init() if err != nil { panic(err) } defer term.Close() term.SetInputMode(term.InputAlt) // term.SetOutputMode(term.Output256) term.Clear(term.ColorDefault, term.ColorDefault) term.Flush() termw, termh := term.Size() mainarea := NewArea(Point{0, 0}, Point{termh - 1, termw}) win := NewWindow(mainarea.Size()) cursor := &Cursor{} selection := &Selection{} history := newHistory() mode := &ModeSelector{} mode.normal = &NormalMode{ text: text, cursor: cursor, selection: selection, history: history, f: f, mode: mode, copied: loadConfig("copy"), } mode.find = &FindMode{ mode: mode, str: loadConfig("find"), } mode.replace = &ReplaceMode{ mode: mode, str: loadConfig("replace"), } mode.gotoline = &GotoLineMode{ cursor: cursor, mode: mode, } mode.exit = &ExitMode{ f: f, cursor: cursor, mode: mode, } mode.current = mode.normal // will start tor as normal mode. selection.m = mode.normal // Set cursor. cursor.m = mode.normal if initL != -1 { l := initL // to internal line number if l != 0 { l-- } cursor.GotoLine(l) if initO != -1 { cursor.SetO(initO) } } else { l, b := loadLastPosition(f) cursor.GotoLine(l) cursor.SetCloseToB(b) } events := make(chan term.Event, 20) go func() { for { events <- term.PollEvent() } }() for { win.Follow(cursor, 3) clearScreen(mainarea) drawScreen(mainarea, win, mode.normal.text, selection, cursor) if mode.current.Error() != "" { printErrorStatus(mode.current.Error()) } else { printStatus(mode.current.Status()) } if mode.current == mode.normal { winP := cursor.Position().Sub(win.min) term.SetCursor(mainarea.min.o+winP.o, mainarea.min.l+winP.l) } else { term.SetCursor(vlen(mode.current.Status(), mode.normal.text.tabWidth), termh) } term.Flush() // wait for keyboard input select { case ev := <-events: switch ev.Type { case term.EventKey: mode.current.Handle(ev) case term.EventResize: term.Clear(term.ColorDefault, term.ColorDefault) termw, termh = term.Size() resizeScreen(mainarea, win, termw, termh) } } } }
func (panel *Unbuffered) SetCursor(x, y int) { if panel.contains(x, y) { termbox.SetCursor(panel.r.Min.X+x, panel.r.Min.Y+y) } }
func main() { cwd, _ := os.Getwd() dir, _ := os.Open(cwd) media, err := dir.Readdir(-1) if err != nil { panic(err) } u, _ := user.Current() cache = u.HomeDir + "/.movietin/" // TODO make this cleaner and replace periods etc // regex to cleanup filenames from extensions and misc data titleRegex, _ = regexp.Compile("[\\w\\d\\s]+") if err := termbox.Init(); err != nil { panic(err) } defer termbox.Close() termbox.SetCursor(-1, -1) filenames := make([]string, len(media)) for i, file := range media { prettyName := titleRegex.FindString(file.Name()) cachedImdb, cacherr := cacheLookup(prettyName) if cacherr != nil { filenames[i] = prettyName } else { filenames[i] = cachedImdb.Title + "\t" + cachedImdb.Year } } screen := termboxutil.Screen{} mainWindow := screen.NewWindow( termbox.ColorWhite, termbox.ColorDefault, termbox.ColorGreen, termbox.ColorBlack) mainWindow.Scrollable(true) searchWindow := screen.NewWindow( termbox.ColorWhite, termbox.ColorDefault, termbox.ColorGreen, termbox.ColorBlack) searchWindow.Scrollable(true) err = mainWindow.Draw(filenames) screen.Focus(&mainWindow) if err != nil { panic(err) } termbox.Flush() var searchResult []Movie mainWindow.CatchEvent = func(event termbox.Event) { if event.Ch == 'j' || event.Key == termbox.KeyArrowDown { mainWindow.NextRow() } else if event.Ch == 'k' || event.Key == termbox.KeyArrowUp { mainWindow.PrevRow() } else if event.Key == termbox.KeyEnter { // do a search for titleRegex match of the filename curRow, _ := mainWindow.CurrentRow() searchData := omdbLookup(fmt.Sprintf( omdbUrl, "s", url.QueryEscape(titleRegex.FindString(curRow.Text)))) var sr SearchResult err = json.Unmarshal(searchData, &sr) if err != nil { panic(err) } searchResult = sr.Search titles := make([]string, len(searchResult)) for i, movie := range searchResult { titles[i] = movie.Title } searchWindow.Draw(titles) screen.Focus(&searchWindow) termbox.Flush() return } mainWindow.Redraw() termbox.Flush() } searchWindow.CatchEvent = func(event termbox.Event) { if event.Ch == 'j' || event.Key == termbox.KeyArrowDown { searchWindow.NextRow() } else if event.Ch == 'k' || event.Key == termbox.KeyArrowUp { searchWindow.PrevRow() } else if event.Key == termbox.KeyEnter { currentRow, index := searchWindow.CurrentRow() // do movie lookup by id lookupData := omdbLookup(fmt.Sprintf( omdbUrl, "i", searchResult[index].ImdbID)) var movie Movie err = json.Unmarshal(lookupData, &movie) if err != nil { panic(err) } err = cacheSave(titleRegex.FindString(currentRow.Text), movie) if err != nil { panic(err) } screen.Focus(&mainWindow) mainWindow.Redraw() termbox.Flush() return } else if event.Ch == 'q' || event.Key == termbox.KeyEsc { screen.Focus(&mainWindow) mainWindow.Redraw() termbox.Flush() return } searchWindow.Redraw() termbox.Flush() } screen.Loop() }
func main() { err := termbox.Init() if err != nil { panic(err) } defer termbox.Close() termbox.SetInputMode(termbox.InputEsc | termbox.InputMouse) x := 0 y := 0 termbox.SetCursor(x, y) termbox.Flush() loop: for { switch ev := termbox.PollEvent(); ev.Type { case termbox.EventKey: if ev.Key == termbox.KeyCtrlS { // Syncでコンソールが消えるっぽい x = 0 y = 0 termbox.Sync() termbox.SetCursor(x, y) termbox.Flush() break } // Ctrl+Xモード時のCtrl+Qでループを抜ける制御 if ev.Key == termbox.KeyCtrlQ { break loop } if ev.Key == termbox.KeyEnter { x = 0 y++ termbox.SetCursor(x, y) termbox.Flush() break } // タイプした文字を出力 msg := string(ev.Ch) for _, c := range msg { termbox.SetCell(x, y, c, termbox.ColorWhite, termbox.ColorBlack) x++ } // 画面端まで行ったら行を更新 xx, _ := termbox.Size() if x == xx { x = 0 y++ } debugPrint(fmt.Sprintf("x = %d xx = %d", x, xx)) termbox.SetCursor(x, y) termbox.Flush() case termbox.EventResize: // ターミナルのサイズ変更で呼ばれる termbox.Flush() case termbox.EventMouse: // ターミナルにタッチすると呼ばれる termbox.Flush() case termbox.EventError: panic(ev.Err) } } }