cli.ts 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. import { app } from 'electron'
  2. interface YargsOption {
  3. type?: 'string' | 'number' | 'boolean' | 'array'
  4. alias?: string
  5. describe?: string
  6. default?: any
  7. choices?: string[]
  8. }
  9. interface CommandConfig {
  10. command: string | string[]
  11. description: string
  12. options?: Record<string, YargsOption>
  13. positionals?: Record<string, YargsOption>
  14. }
  15. interface ParserConfig {
  16. usage: string
  17. commands: CommandConfig[]
  18. options: Record<string, YargsOption>
  19. version: string
  20. }
  21. export function createParserConfig (cwd: string): ParserConfig {
  22. return {
  23. usage: 'tabby [command] [arguments]',
  24. commands: [
  25. {
  26. command: 'open [directory]',
  27. description: 'open a shell in a directory',
  28. options: {
  29. directory: { type: 'string', 'default': cwd },
  30. },
  31. },
  32. {
  33. command: ['run [command...]', '/k'],
  34. description: 'run a command in the terminal',
  35. options: {
  36. command: { type: 'array' },
  37. },
  38. },
  39. {
  40. command: 'profile [profileName]',
  41. description: 'open a tab with specified profile',
  42. options: {
  43. profileName: { type: 'string' },
  44. },
  45. },
  46. {
  47. command: 'paste [text]',
  48. description: 'paste stdin into the active tab',
  49. options: {
  50. escape: {
  51. alias: 'e',
  52. type: 'boolean',
  53. describe: 'Perform shell escaping',
  54. },
  55. },
  56. positionals: {
  57. text: { type: 'string' },
  58. },
  59. },
  60. {
  61. command: 'recent [index]',
  62. description: 'open a tab with a recent profile',
  63. options: {
  64. profileNumber: { type: 'number' },
  65. },
  66. },
  67. {
  68. command: 'quickConnect <providerId> <query>',
  69. description: 'open a tab for specified quick connect provider',
  70. positionals: {
  71. providerId: {
  72. describe: 'The name of a quick connect profile provider',
  73. type: 'string',
  74. },
  75. query: {
  76. describe: 'The quick connect query string',
  77. type: 'string',
  78. },
  79. },
  80. },
  81. ],
  82. options: {
  83. debug: {
  84. alias: 'd',
  85. describe: 'Show DevTools on start',
  86. type: 'boolean',
  87. },
  88. hidden: {
  89. describe: 'Start minimized',
  90. type: 'boolean',
  91. },
  92. },
  93. version: app.getVersion(),
  94. }
  95. }
  96. function applyOptionsToYargs (yargsInstance: any, options: Record<string, YargsOption>, method: 'option' | 'positional') {
  97. return Object.entries(options).reduce(
  98. (yargs, [key, value]) => yargs[method](key, value),
  99. yargsInstance,
  100. )
  101. }
  102. function createParserFromConfig (config: ParserConfig) {
  103. const yargs = require('yargs/yargs')
  104. let parser = yargs().usage(config.usage)
  105. config.commands.forEach(cmd => {
  106. const builder = (yargsInstance: any) => {
  107. let instance = yargsInstance
  108. if (cmd.options) {
  109. instance = applyOptionsToYargs(instance, cmd.options, 'option')
  110. }
  111. if (cmd.positionals) {
  112. instance = applyOptionsToYargs(instance, cmd.positionals, 'positional')
  113. }
  114. return instance
  115. }
  116. parser = parser.command(cmd.command, cmd.description, builder)
  117. })
  118. parser = applyOptionsToYargs(parser, config.options, 'option')
  119. return parser.version(config.version).help('help')
  120. }
  121. export function parseArgs (argv: string[], cwd: string): any {
  122. const args = argv[0].includes('node') ? argv.slice(2) : argv.slice(1)
  123. const config = createParserConfig(cwd)
  124. const parser = createParserFromConfig(config)
  125. return parser.parse(args)
  126. }