You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

629 lines
11 KiB

  1. package readline
  2. import (
  3. "bufio"
  4. "bytes"
  5. "io"
  6. "strconv"
  7. "strings"
  8. "sync"
  9. )
  10. type runeBufferBck struct {
  11. buf []rune
  12. idx int
  13. }
  14. type RuneBuffer struct {
  15. buf []rune
  16. idx int
  17. prompt []rune
  18. w io.Writer
  19. hadClean bool
  20. interactive bool
  21. cfg *Config
  22. width int
  23. bck *runeBufferBck
  24. offset string
  25. lastKill []rune
  26. sync.Mutex
  27. }
  28. func (r* RuneBuffer) pushKill(text []rune) {
  29. r.lastKill = append([]rune{}, text...)
  30. }
  31. func (r *RuneBuffer) OnWidthChange(newWidth int) {
  32. r.Lock()
  33. r.width = newWidth
  34. r.Unlock()
  35. }
  36. func (r *RuneBuffer) Backup() {
  37. r.Lock()
  38. r.bck = &runeBufferBck{r.buf, r.idx}
  39. r.Unlock()
  40. }
  41. func (r *RuneBuffer) Restore() {
  42. r.Refresh(func() {
  43. if r.bck == nil {
  44. return
  45. }
  46. r.buf = r.bck.buf
  47. r.idx = r.bck.idx
  48. })
  49. }
  50. func NewRuneBuffer(w io.Writer, prompt string, cfg *Config, width int) *RuneBuffer {
  51. rb := &RuneBuffer{
  52. w: w,
  53. interactive: cfg.useInteractive(),
  54. cfg: cfg,
  55. width: width,
  56. }
  57. rb.SetPrompt(prompt)
  58. return rb
  59. }
  60. func (r *RuneBuffer) SetConfig(cfg *Config) {
  61. r.Lock()
  62. r.cfg = cfg
  63. r.interactive = cfg.useInteractive()
  64. r.Unlock()
  65. }
  66. func (r *RuneBuffer) SetMask(m rune) {
  67. r.Lock()
  68. r.cfg.MaskRune = m
  69. r.Unlock()
  70. }
  71. func (r *RuneBuffer) CurrentWidth(x int) int {
  72. r.Lock()
  73. defer r.Unlock()
  74. return runes.WidthAll(r.buf[:x])
  75. }
  76. func (r *RuneBuffer) PromptLen() int {
  77. r.Lock()
  78. width := r.promptLen()
  79. r.Unlock()
  80. return width
  81. }
  82. func (r *RuneBuffer) promptLen() int {
  83. return runes.WidthAll(runes.ColorFilter(r.prompt))
  84. }
  85. func (r *RuneBuffer) RuneSlice(i int) []rune {
  86. r.Lock()
  87. defer r.Unlock()
  88. if i > 0 {
  89. rs := make([]rune, i)
  90. copy(rs, r.buf[r.idx:r.idx+i])
  91. return rs
  92. }
  93. rs := make([]rune, -i)
  94. copy(rs, r.buf[r.idx+i:r.idx])
  95. return rs
  96. }
  97. func (r *RuneBuffer) Runes() []rune {
  98. r.Lock()
  99. newr := make([]rune, len(r.buf))
  100. copy(newr, r.buf)
  101. r.Unlock()
  102. return newr
  103. }
  104. func (r *RuneBuffer) Pos() int {
  105. r.Lock()
  106. defer r.Unlock()
  107. return r.idx
  108. }
  109. func (r *RuneBuffer) Len() int {
  110. r.Lock()
  111. defer r.Unlock()
  112. return len(r.buf)
  113. }
  114. func (r *RuneBuffer) MoveToLineStart() {
  115. r.Refresh(func() {
  116. if r.idx == 0 {
  117. return
  118. }
  119. r.idx = 0
  120. })
  121. }
  122. func (r *RuneBuffer) MoveBackward() {
  123. r.Refresh(func() {
  124. if r.idx == 0 {
  125. return
  126. }
  127. r.idx--
  128. })
  129. }
  130. func (r *RuneBuffer) WriteString(s string) {
  131. r.WriteRunes([]rune(s))
  132. }
  133. func (r *RuneBuffer) WriteRune(s rune) {
  134. r.WriteRunes([]rune{s})
  135. }
  136. func (r *RuneBuffer) WriteRunes(s []rune) {
  137. r.Refresh(func() {
  138. tail := append(s, r.buf[r.idx:]...)
  139. r.buf = append(r.buf[:r.idx], tail...)
  140. r.idx += len(s)
  141. })
  142. }
  143. func (r *RuneBuffer) MoveForward() {
  144. r.Refresh(func() {
  145. if r.idx == len(r.buf) {
  146. return
  147. }
  148. r.idx++
  149. })
  150. }
  151. func (r *RuneBuffer) IsCursorInEnd() bool {
  152. r.Lock()
  153. defer r.Unlock()
  154. return r.idx == len(r.buf)
  155. }
  156. func (r *RuneBuffer) Replace(ch rune) {
  157. r.Refresh(func() {
  158. r.buf[r.idx] = ch
  159. })
  160. }
  161. func (r *RuneBuffer) Erase() {
  162. r.Refresh(func() {
  163. r.idx = 0
  164. r.pushKill(r.buf[:])
  165. r.buf = r.buf[:0]
  166. })
  167. }
  168. func (r *RuneBuffer) Delete() (success bool) {
  169. r.Refresh(func() {
  170. if r.idx == len(r.buf) {
  171. return
  172. }
  173. r.pushKill(r.buf[r.idx : r.idx+1])
  174. r.buf = append(r.buf[:r.idx], r.buf[r.idx+1:]...)
  175. success = true
  176. })
  177. return
  178. }
  179. func (r *RuneBuffer) DeleteWord() {
  180. if r.idx == len(r.buf) {
  181. return
  182. }
  183. init := r.idx
  184. for init < len(r.buf) && IsWordBreak(r.buf[init]) {
  185. init++
  186. }
  187. for i := init + 1; i < len(r.buf); i++ {
  188. if !IsWordBreak(r.buf[i]) && IsWordBreak(r.buf[i-1]) {
  189. r.pushKill(r.buf[r.idx:i-1])
  190. r.Refresh(func() {
  191. r.buf = append(r.buf[:r.idx], r.buf[i-1:]...)
  192. })
  193. return
  194. }
  195. }
  196. r.Kill()
  197. }
  198. func (r *RuneBuffer) MoveToPrevWord() (success bool) {
  199. r.Refresh(func() {
  200. if r.idx == 0 {
  201. return
  202. }
  203. for i := r.idx - 1; i > 0; i-- {
  204. if !IsWordBreak(r.buf[i]) && IsWordBreak(r.buf[i-1]) {
  205. r.idx = i
  206. success = true
  207. return
  208. }
  209. }
  210. r.idx = 0
  211. success = true
  212. })
  213. return
  214. }
  215. func (r *RuneBuffer) KillFront() {
  216. r.Refresh(func() {
  217. if r.idx == 0 {
  218. return
  219. }
  220. length := len(r.buf) - r.idx
  221. r.pushKill(r.buf[:r.idx])
  222. copy(r.buf[:length], r.buf[r.idx:])
  223. r.idx = 0
  224. r.buf = r.buf[:length]
  225. })
  226. }
  227. func (r *RuneBuffer) Kill() {
  228. r.Refresh(func() {
  229. r.pushKill(r.buf[r.idx:])
  230. r.buf = r.buf[:r.idx]
  231. })
  232. }
  233. func (r *RuneBuffer) Transpose() {
  234. r.Refresh(func() {
  235. if len(r.buf) == 1 {
  236. r.idx++
  237. }
  238. if len(r.buf) < 2 {
  239. return
  240. }
  241. if r.idx == 0 {
  242. r.idx = 1
  243. } else if r.idx >= len(r.buf) {
  244. r.idx = len(r.buf) - 1
  245. }
  246. r.buf[r.idx], r.buf[r.idx-1] = r.buf[r.idx-1], r.buf[r.idx]
  247. r.idx++
  248. })
  249. }
  250. func (r *RuneBuffer) MoveToNextWord() {
  251. r.Refresh(func() {
  252. for i := r.idx + 1; i < len(r.buf); i++ {
  253. if !IsWordBreak(r.buf[i]) && IsWordBreak(r.buf[i-1]) {
  254. r.idx = i
  255. return
  256. }
  257. }
  258. r.idx = len(r.buf)
  259. })
  260. }
  261. func (r *RuneBuffer) MoveToEndWord() {
  262. r.Refresh(func() {
  263. // already at the end, so do nothing
  264. if r.idx == len(r.buf) {
  265. return
  266. }
  267. // if we are at the end of a word already, go to next
  268. if !IsWordBreak(r.buf[r.idx]) && IsWordBreak(r.buf[r.idx+1]) {
  269. r.idx++
  270. }
  271. // keep going until at the end of a word
  272. for i := r.idx + 1; i < len(r.buf); i++ {
  273. if IsWordBreak(r.buf[i]) && !IsWordBreak(r.buf[i-1]) {
  274. r.idx = i - 1
  275. return
  276. }
  277. }
  278. r.idx = len(r.buf)
  279. })
  280. }
  281. func (r *RuneBuffer) BackEscapeWord() {
  282. r.Refresh(func() {
  283. if r.idx == 0 {
  284. return
  285. }
  286. for i := r.idx - 1; i > 0; i-- {
  287. if !IsWordBreak(r.buf[i]) && IsWordBreak(r.buf[i-1]) {
  288. r.pushKill(r.buf[i:r.idx])
  289. r.buf = append(r.buf[:i], r.buf[r.idx:]...)
  290. r.idx = i
  291. return
  292. }
  293. }
  294. r.buf = r.buf[:0]
  295. r.idx = 0
  296. })
  297. }
  298. func (r *RuneBuffer) Yank() {
  299. if len(r.lastKill) == 0 {
  300. return
  301. }
  302. r.Refresh(func() {
  303. buf := make([]rune, 0, len(r.buf) + len(r.lastKill))
  304. buf = append(buf, r.buf[:r.idx]...)
  305. buf = append(buf, r.lastKill...)
  306. buf = append(buf, r.buf[r.idx:]...)
  307. r.buf = buf
  308. r.idx += len(r.lastKill)
  309. })
  310. }
  311. func (r *RuneBuffer) Backspace() {
  312. r.Refresh(func() {
  313. if r.idx == 0 {
  314. return
  315. }
  316. r.idx--
  317. r.buf = append(r.buf[:r.idx], r.buf[r.idx+1:]...)
  318. })
  319. }
  320. func (r *RuneBuffer) MoveToLineEnd() {
  321. r.Refresh(func() {
  322. if r.idx == len(r.buf) {
  323. return
  324. }
  325. r.idx = len(r.buf)
  326. })
  327. }
  328. func (r *RuneBuffer) LineCount(width int) int {
  329. if width == -1 {
  330. width = r.width
  331. }
  332. return LineCount(width,
  333. runes.WidthAll(r.buf)+r.PromptLen())
  334. }
  335. func (r *RuneBuffer) MoveTo(ch rune, prevChar, reverse bool) (success bool) {
  336. r.Refresh(func() {
  337. if reverse {
  338. for i := r.idx - 1; i >= 0; i-- {
  339. if r.buf[i] == ch {
  340. r.idx = i
  341. if prevChar {
  342. r.idx++
  343. }
  344. success = true
  345. return
  346. }
  347. }
  348. return
  349. }
  350. for i := r.idx + 1; i < len(r.buf); i++ {
  351. if r.buf[i] == ch {
  352. r.idx = i
  353. if prevChar {
  354. r.idx--
  355. }
  356. success = true
  357. return
  358. }
  359. }
  360. })
  361. return
  362. }
  363. func (r *RuneBuffer) isInLineEdge() bool {
  364. if isWindows {
  365. return false
  366. }
  367. sp := r.getSplitByLine(r.buf)
  368. return len(sp[len(sp)-1]) == 0
  369. }
  370. func (r *RuneBuffer) getSplitByLine(rs []rune) []string {
  371. return SplitByLine(r.promptLen(), r.width, rs)
  372. }
  373. func (r *RuneBuffer) IdxLine(width int) int {
  374. r.Lock()
  375. defer r.Unlock()
  376. return r.idxLine(width)
  377. }
  378. func (r *RuneBuffer) idxLine(width int) int {
  379. if width == 0 {
  380. return 0
  381. }
  382. sp := r.getSplitByLine(r.buf[:r.idx])
  383. return len(sp) - 1
  384. }
  385. func (r *RuneBuffer) CursorLineCount() int {
  386. return r.LineCount(r.width) - r.IdxLine(r.width)
  387. }
  388. func (r *RuneBuffer) Refresh(f func()) {
  389. r.Lock()
  390. defer r.Unlock()
  391. if !r.interactive {
  392. if f != nil {
  393. f()
  394. }
  395. return
  396. }
  397. r.clean()
  398. if f != nil {
  399. f()
  400. }
  401. r.print()
  402. }
  403. func (r *RuneBuffer) SetOffset(offset string) {
  404. r.Lock()
  405. r.offset = offset
  406. r.Unlock()
  407. }
  408. func (r *RuneBuffer) print() {
  409. r.w.Write(r.output())
  410. r.hadClean = false
  411. }
  412. func (r *RuneBuffer) output() []byte {
  413. buf := bytes.NewBuffer(nil)
  414. buf.WriteString(string(r.prompt))
  415. if r.cfg.EnableMask && len(r.buf) > 0 {
  416. buf.Write([]byte(strings.Repeat(string(r.cfg.MaskRune), len(r.buf)-1)))
  417. if r.buf[len(r.buf)-1] == '\n' {
  418. buf.Write([]byte{'\n'})
  419. } else {
  420. buf.Write([]byte(string(r.cfg.MaskRune)))
  421. }
  422. if len(r.buf) > r.idx {
  423. buf.Write(r.getBackspaceSequence())
  424. }
  425. } else {
  426. for _, e := range r.cfg.Painter.Paint(r.buf, r.idx) {
  427. if e == '\t' {
  428. buf.WriteString(strings.Repeat(" ", TabWidth))
  429. } else {
  430. buf.WriteRune(e)
  431. }
  432. }
  433. if r.isInLineEdge() {
  434. buf.Write([]byte(" \b"))
  435. }
  436. }
  437. // cursor position
  438. if len(r.buf) > r.idx {
  439. buf.Write(r.getBackspaceSequence())
  440. }
  441. return buf.Bytes()
  442. }
  443. func (r *RuneBuffer) getBackspaceSequence() []byte {
  444. var sep = map[int]bool{}
  445. var i int
  446. for {
  447. if i >= runes.WidthAll(r.buf) {
  448. break
  449. }
  450. if i == 0 {
  451. i -= r.promptLen()
  452. }
  453. i += r.width
  454. sep[i] = true
  455. }
  456. var buf []byte
  457. for i := len(r.buf); i > r.idx; i-- {
  458. // move input to the left of one
  459. buf = append(buf, '\b')
  460. if sep[i] {
  461. // up one line, go to the start of the line and move cursor right to the end (r.width)
  462. buf = append(buf, "\033[A\r"+"\033["+strconv.Itoa(r.width)+"C"...)
  463. }
  464. }
  465. return buf
  466. }
  467. func (r *RuneBuffer) Reset() []rune {
  468. ret := runes.Copy(r.buf)
  469. r.buf = r.buf[:0]
  470. r.idx = 0
  471. return ret
  472. }
  473. func (r *RuneBuffer) calWidth(m int) int {
  474. if m > 0 {
  475. return runes.WidthAll(r.buf[r.idx : r.idx+m])
  476. }
  477. return runes.WidthAll(r.buf[r.idx+m : r.idx])
  478. }
  479. func (r *RuneBuffer) SetStyle(start, end int, style string) {
  480. if end < start {
  481. panic("end < start")
  482. }
  483. // goto start
  484. move := start - r.idx
  485. if move > 0 {
  486. r.w.Write([]byte(string(r.buf[r.idx : r.idx+move])))
  487. } else {
  488. r.w.Write(bytes.Repeat([]byte("\b"), r.calWidth(move)))
  489. }
  490. r.w.Write([]byte("\033[" + style + "m"))
  491. r.w.Write([]byte(string(r.buf[start:end])))
  492. r.w.Write([]byte("\033[0m"))
  493. // TODO: move back
  494. }
  495. func (r *RuneBuffer) SetWithIdx(idx int, buf []rune) {
  496. r.Refresh(func() {
  497. r.buf = buf
  498. r.idx = idx
  499. })
  500. }
  501. func (r *RuneBuffer) Set(buf []rune) {
  502. r.SetWithIdx(len(buf), buf)
  503. }
  504. func (r *RuneBuffer) SetPrompt(prompt string) {
  505. r.Lock()
  506. r.prompt = []rune(prompt)
  507. r.Unlock()
  508. }
  509. func (r *RuneBuffer) cleanOutput(w io.Writer, idxLine int) {
  510. buf := bufio.NewWriter(w)
  511. if r.width == 0 {
  512. buf.WriteString(strings.Repeat("\r\b", len(r.buf)+r.promptLen()))
  513. buf.Write([]byte("\033[J"))
  514. } else {
  515. buf.Write([]byte("\033[J")) // just like ^k :)
  516. if idxLine == 0 {
  517. buf.WriteString("\033[2K")
  518. buf.WriteString("\r")
  519. } else {
  520. for i := 0; i < idxLine; i++ {
  521. io.WriteString(buf, "\033[2K\r\033[A")
  522. }
  523. io.WriteString(buf, "\033[2K\r")
  524. }
  525. }
  526. buf.Flush()
  527. return
  528. }
  529. func (r *RuneBuffer) Clean() {
  530. r.Lock()
  531. r.clean()
  532. r.Unlock()
  533. }
  534. func (r *RuneBuffer) clean() {
  535. r.cleanWithIdxLine(r.idxLine(r.width))
  536. }
  537. func (r *RuneBuffer) cleanWithIdxLine(idxLine int) {
  538. if r.hadClean || !r.interactive {
  539. return
  540. }
  541. r.hadClean = true
  542. r.cleanOutput(r.w, idxLine)
  543. }