linear-github-cli 1.3.7 → 1.3.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/input-handler.js +111 -22
  2. package/package.json +1 -1
@@ -5,7 +5,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.InputHandler = void 0;
7
7
  const child_process_1 = require("child_process");
8
+ const fs_1 = require("fs");
8
9
  const inquirer_1 = __importDefault(require("inquirer"));
10
+ const path_1 = require("path");
11
+ const readline_1 = __importDefault(require("readline"));
12
+ const os_1 = require("os");
9
13
  const isValidDateYmd = (input) => {
10
14
  if (!/^\d{4}-\d{2}-\d{2}$/.test(input))
11
15
  return false;
@@ -15,6 +19,87 @@ const isValidDateYmd = (input) => {
15
19
  date.getUTCMonth() === month - 1 &&
16
20
  date.getUTCDate() === day);
17
21
  };
22
+ const WAIT_FLAG_EDITORS = {
23
+ code: '--wait',
24
+ 'code-insiders': '--wait',
25
+ cursor: '--wait',
26
+ 'cursor-insiders': '--wait',
27
+ subl: '-w',
28
+ sublime_text: '-w',
29
+ atom: '--wait',
30
+ };
31
+ const hasWaitFlag = (command) => /\s--wait\b/.test(command) || /\s-w\b/.test(command);
32
+ const resolveEditorCommand = () => {
33
+ const envEditor = process.env.LG_EDITOR || process.env.VISUAL || process.env.EDITOR;
34
+ const base = (envEditor && envEditor.trim().length > 0 ? envEditor : 'vim').trim();
35
+ const binary = base.split(/\s+/)[0];
36
+ const waitFlag = WAIT_FLAG_EDITORS[binary];
37
+ if (waitFlag && !hasWaitFlag(base)) {
38
+ return `${base} ${waitFlag}`;
39
+ }
40
+ return base;
41
+ };
42
+ const openEditorForText = (editorCommand, initialText = '') => {
43
+ const tempDir = (0, fs_1.mkdtempSync)((0, path_1.join)((0, os_1.tmpdir)(), 'lg-editor-'));
44
+ const tempFilePath = (0, path_1.join)(tempDir, 'issue-body.md');
45
+ try {
46
+ (0, fs_1.writeFileSync)(tempFilePath, initialText, 'utf-8');
47
+ const quotedPath = `"${tempFilePath.replace(/"/g, '\\"')}"`;
48
+ const command = `${editorCommand} ${quotedPath}`;
49
+ const result = (0, child_process_1.spawnSync)(command, { stdio: 'inherit', shell: true });
50
+ if (result.error) {
51
+ throw result.error;
52
+ }
53
+ return (0, fs_1.readFileSync)(tempFilePath, 'utf-8');
54
+ }
55
+ finally {
56
+ (0, fs_1.rmSync)(tempDir, { recursive: true, force: true });
57
+ }
58
+ };
59
+ const promptDescriptionAction = async () => {
60
+ const stdin = process.stdin;
61
+ const stdout = process.stdout;
62
+ if (!stdin.isTTY || !stdout.isTTY) {
63
+ return 'skip';
64
+ }
65
+ stdout.write('Body [press e to launch editor, Enter to skip]: ');
66
+ const rl = readline_1.default.createInterface({ input: stdin, output: stdout });
67
+ readline_1.default.emitKeypressEvents(stdin, rl);
68
+ if (typeof stdin.setRawMode === 'function') {
69
+ stdin.setRawMode(true);
70
+ }
71
+ stdin.resume();
72
+ return new Promise(resolve => {
73
+ const cleanup = () => {
74
+ stdin.removeListener('keypress', onKeypress);
75
+ if (typeof stdin.setRawMode === 'function') {
76
+ stdin.setRawMode(false);
77
+ }
78
+ rl.close();
79
+ };
80
+ const onKeypress = (_, key) => {
81
+ const keyName = key?.name ?? '';
82
+ const keySeq = key?.sequence ?? '';
83
+ if (key?.ctrl && keyName === 'c') {
84
+ stdout.write('\n');
85
+ cleanup();
86
+ process.exit(130);
87
+ }
88
+ if (keyName === 'return' || keySeq === '\r') {
89
+ stdout.write('\n');
90
+ cleanup();
91
+ resolve('skip');
92
+ return;
93
+ }
94
+ if (keyName.toLowerCase() === 'e' || keySeq.toLowerCase() === 'e') {
95
+ stdout.write('\n');
96
+ cleanup();
97
+ resolve('edit');
98
+ }
99
+ };
100
+ stdin.on('keypress', onKeypress);
101
+ });
102
+ };
18
103
  class InputHandler {
19
104
  linearClient;
20
105
  githubClient;
@@ -155,22 +240,37 @@ class InputHandler {
155
240
  'research',
156
241
  ];
157
242
  }
158
- const answers = await inquirer_1.default.prompt([
243
+ const baseAnswers = await inquirer_1.default.prompt([
159
244
  {
160
245
  type: 'input',
161
246
  name: 'title',
162
247
  message: 'Issue title (required):',
163
248
  validate: (input) => input.length > 0 || 'Title is required',
164
249
  },
165
- {
166
- type: 'input',
167
- name: 'descriptionAction',
168
- message: 'Body [(e) to launch vim, enter to skip]:',
169
- validate: (input) => {
170
- const value = input.trim().toLowerCase();
171
- return value === '' || value === 'e' || 'Enter "e" to edit or press enter to skip';
172
- },
173
- },
250
+ ]);
251
+ let description = '';
252
+ const descriptionAction = await promptDescriptionAction();
253
+ if (descriptionAction === 'edit') {
254
+ const editorCommand = resolveEditorCommand();
255
+ try {
256
+ description = openEditorForText(editorCommand).trimEnd();
257
+ }
258
+ catch (error) {
259
+ console.error('\n⚠️ Failed to open editor for issue description.');
260
+ console.error(` Editor command: ${editorCommand}`);
261
+ console.error(' Tip: set $EDITOR or $VISUAL to a terminal editor (e.g. "vim")');
262
+ console.error(' or a GUI editor with wait flag (e.g. "code --wait").\n');
263
+ const { description: fallbackDescription } = await inquirer_1.default.prompt([
264
+ {
265
+ type: 'input',
266
+ name: 'description',
267
+ message: 'Issue description (single line or paste text):',
268
+ },
269
+ ]);
270
+ description = fallbackDescription || '';
271
+ }
272
+ }
273
+ const answers = await inquirer_1.default.prompt([
174
274
  {
175
275
  type: 'input',
176
276
  name: 'startDate',
@@ -198,19 +298,8 @@ class InputHandler {
198
298
  choices: labelChoices,
199
299
  },
200
300
  ]);
201
- let description = '';
202
- if (answers.descriptionAction.trim().toLowerCase() === 'e') {
203
- const { description: editedDescription } = await inquirer_1.default.prompt([
204
- {
205
- type: 'editor',
206
- name: 'description',
207
- message: 'Issue description:',
208
- },
209
- ]);
210
- description = editedDescription || '';
211
- }
212
301
  return {
213
- title: answers.title,
302
+ title: baseAnswers.title,
214
303
  description,
215
304
  dueDate: answers.dueDate || '',
216
305
  startDate: answers.startDate || '',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "linear-github-cli",
3
- "version": "1.3.7",
3
+ "version": "1.3.8",
4
4
  "description": "CLI tool for creating GitHub issues with Linear integration",
5
5
  "main": "dist/cli.js",
6
6
  "bin": {