// This function assumes it is given byte indices corresponding to a word, // and i, n are the beginning and end of that word, respectively. func isWord(txt string, i, n int) bool { if i == 0 { return !syntax.IsWordChar(rune(txt[n+1])) } else if n == len(txt)-1 { return !syntax.IsWordChar(rune(txt[i-1])) } return !syntax.IsWordChar(rune(txt[i-1])) && !syntax.IsWordChar(rune(txt[n+1])) }
// handleEvent processes keyboard events an processes valid input accordingly. func handleEvent(ev tb.Event) { switch term.mode { case cmdMode: if term.dm.Curr != nil { if ev.Ch == 'q' && term.cur.sec == 1 { term.dm.ClearBeats(term.cur.row) } else if ev.Ch == 't' { term.mode = tempoMode } else if ev.Ch == 'r' { term.dm.ChangeTempo(term.dm.Curr.Tempo - 2) } else if ev.Ch == 'y' { term.dm.ChangeTempo(term.dm.Curr.Tempo + 2) } else if ev.Ch == 'e' && term.cur.sec == 1 { term.dm.EnableSection(term.cur.row) } else if ev.Ch == 'w' && term.cur.sec == 1 { term.dm.ToggleBeat(term.cur.row, term.cur.col) } else if ev.Ch == 's' { term.dm.SaveCurrentSequence(term.dm.Curr.Name) } else if ev.Ch == 'u' { cr := term.cur.row if term.cur.sec == 1 && cr < len(term.dm.Curr.Sections)-1 { s := term.dm.Curr.Sections s[cr], s[cr+1] = s[cr+1], s[cr] term.cur.row++ } } else if ev.Ch == 'i' { cr := term.cur.row if term.cur.sec == 1 && cr > 0 { s := term.dm.Curr.Sections s[cr], s[cr-1] = s[cr-1], s[cr] term.cur.row-- } } else if ev.Ch == 'b' { term.mode = backupMode } else if ev.Key == tb.KeySpace { term.dm.TogglePlayPause() } } if ev.Ch == 'n' { term.mode = newModePickSample term.cur.sec = 0 term.cur.row = 0 } else if ev.Key == tb.KeyEnter { if term.cur.sec == 0 { term.dm.LoadSequence(term.cur.row) } } else { handleMovement(ev) } default: if ev.Ch != 0 { if term.mode == tempoMode { if unicode.IsDigit(ev.Ch) || ev.Ch == '.' { term.input.WriteRune(ev.Ch) } } else if term.mode == newModePickSample { handleMovement(ev) } else { if syntax.IsWordChar(ev.Ch) { term.input.WriteRune(ev.Ch) } } } else if ev.Key == tb.KeyEnter { if term.mode == tempoMode { f, err := strconv.ParseFloat(term.input.String(), 32) if err == nil { term.dm.ChangeTempo(float32(f)) } } else if term.mode == backupMode { term.dm.SaveCurrentSequence(term.input.String()) } else if term.mode == newModeEnterName { term.dm.NewSequence(term.input.String(), term.newSample) } term.input.Reset() if term.mode == newModePickSample { term.newSample = term.sampleNames[term.cur.row] term.mode = newModeEnterName } else { term.mode = cmdMode } } else if ev.Key == tb.KeyBackspace || ev.Key == tb.KeyBackspace2 { if term.input.Len() > 0 { term.input.Truncate(term.input.Len() - 1) } } else if ev.Key == tb.KeyEsc { term.input.Reset() term.mode = cmdMode } } drawDrumMachine() }