paginator.js 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. 'use strict';
  2. var _ = {
  3. sum: require('lodash/sum'),
  4. flatten: require('lodash/flatten'),
  5. };
  6. var chalk = require('chalk');
  7. /**
  8. * The paginator returns a subset of the choices if the list is too long.
  9. */
  10. class Paginator {
  11. constructor(screen, options = {}) {
  12. const { isInfinite = true } = options;
  13. this.lastIndex = 0;
  14. this.screen = screen;
  15. this.isInfinite = isInfinite;
  16. }
  17. paginate(output, active, pageSize) {
  18. pageSize = pageSize || 7;
  19. var lines = output.split('\n');
  20. if (this.screen) {
  21. lines = this.screen.breakLines(lines);
  22. active = _.sum(lines.map((lineParts) => lineParts.length).splice(0, active));
  23. lines = _.flatten(lines);
  24. }
  25. // Make sure there's enough lines to paginate
  26. if (lines.length <= pageSize) {
  27. return output;
  28. }
  29. const visibleLines = this.isInfinite
  30. ? this.getInfiniteLines(lines, active, pageSize)
  31. : this.getFiniteLines(lines, active, pageSize);
  32. this.lastIndex = active;
  33. return (
  34. visibleLines.join('\n') +
  35. '\n' +
  36. chalk.dim('(Move up and down to reveal more choices)')
  37. );
  38. }
  39. getInfiniteLines(lines, active, pageSize) {
  40. if (this.pointer === undefined) {
  41. this.pointer = 0;
  42. }
  43. var middleOfList = Math.floor(pageSize / 2);
  44. // Move the pointer only when the user go down and limit it to the middle of the list
  45. if (
  46. this.pointer < middleOfList &&
  47. this.lastIndex < active &&
  48. active - this.lastIndex < pageSize
  49. ) {
  50. this.pointer = Math.min(middleOfList, this.pointer + active - this.lastIndex);
  51. }
  52. // Duplicate the lines so it give an infinite list look
  53. var infinite = _.flatten([lines, lines, lines]);
  54. var topIndex = Math.max(0, active + lines.length - this.pointer);
  55. return infinite.splice(topIndex, pageSize);
  56. }
  57. getFiniteLines(lines, active, pageSize) {
  58. var topIndex = active - pageSize / 2;
  59. if (topIndex < 0) {
  60. topIndex = 0;
  61. } else if (topIndex + pageSize > lines.length) {
  62. topIndex = lines.length - pageSize;
  63. }
  64. return lines.splice(topIndex, pageSize);
  65. }
  66. }
  67. module.exports = Paginator;