choices.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. 'use strict';
  2. const assert = require('assert');
  3. const _ = {
  4. filter: require('lodash/filter'),
  5. map: require('lodash/map'),
  6. };
  7. const Separator = require('./separator');
  8. const Choice = require('./choice');
  9. /**
  10. * Choices collection
  11. * Collection of multiple `choice` object
  12. */
  13. module.exports = class Choices {
  14. /** @param {Array} choices All `choice` to keep in the collection */
  15. constructor(choices, answers) {
  16. this.choices = choices.map((val) => {
  17. if (val.type === 'separator') {
  18. if (!(val instanceof Separator)) {
  19. val = new Separator(val.line);
  20. }
  21. return val;
  22. }
  23. return new Choice(val, answers);
  24. });
  25. this.realChoices = this.choices
  26. .filter(Separator.exclude)
  27. .filter((item) => !item.disabled);
  28. Object.defineProperty(this, 'length', {
  29. get() {
  30. return this.choices.length;
  31. },
  32. set(val) {
  33. this.choices.length = val;
  34. },
  35. });
  36. Object.defineProperty(this, 'realLength', {
  37. get() {
  38. return this.realChoices.length;
  39. },
  40. set() {
  41. throw new Error('Cannot set `realLength` of a Choices collection');
  42. },
  43. });
  44. }
  45. /**
  46. * Get a valid choice from the collection
  47. * @param {Number} selector The selected choice index
  48. * @return {Choice|Undefined} Return the matched choice or undefined
  49. */
  50. getChoice(selector) {
  51. assert(typeof selector === 'number');
  52. return this.realChoices[selector];
  53. }
  54. /**
  55. * Get a raw element from the collection
  56. * @param {Number} selector The selected index value
  57. * @return {Choice|Undefined} Return the matched choice or undefined
  58. */
  59. get(selector) {
  60. assert(typeof selector === 'number');
  61. return this.choices[selector];
  62. }
  63. /**
  64. * Match the valid choices against a where clause
  65. * @param {Object} whereClause Lodash `where` clause
  66. * @return {Array} Matching choices or empty array
  67. */
  68. where(whereClause) {
  69. return _.filter(this.realChoices, whereClause);
  70. }
  71. /**
  72. * Pluck a particular key from the choices
  73. * @param {String} propertyName Property name to select
  74. * @return {Array} Selected properties
  75. */
  76. pluck(propertyName) {
  77. return _.map(this.realChoices, propertyName);
  78. }
  79. // Expose usual Array methods
  80. indexOf(...args) {
  81. return this.choices.indexOf(...args);
  82. }
  83. forEach(...args) {
  84. return this.choices.forEach(...args);
  85. }
  86. filter(...args) {
  87. return this.choices.filter(...args);
  88. }
  89. reduce(...args) {
  90. return this.choices.reduce(...args);
  91. }
  92. find(func) {
  93. return this.choices.find(func);
  94. }
  95. push(...args) {
  96. const objs = args.map((val) => new Choice(val));
  97. this.choices.push(...objs);
  98. this.realChoices = this.choices
  99. .filter(Separator.exclude)
  100. .filter((item) => !item.disabled);
  101. return this.choices;
  102. }
  103. };