UNPKG

linear-cmd

Version:

A GitHub CLI-like tool for Linear - manage issues, accounts, and more

237 lines (223 loc) 7.58 kB
import { accessSync, constants, existsSync, mkdirSync, writeFileSync } from 'node:fs'; import { homedir } from 'node:os'; import { join } from 'node:path'; import chalk from 'chalk'; import { Command } from 'commander'; import { Logger } from '../lib/logger.js'; const ZSH_COMPLETION_SCRIPT = `#compdef linear _linear() { local state line context typeset -A opt_args _arguments -C \ '1: :_linear_commands' \ '*::arg:->args' case $state in args) case $line[1] in account) _linear_account ;; issue) _linear_issue ;; update) # No subcommands for update ;; esac ;; esac } _linear_commands() { local commands commands=( 'account:Manage Linear accounts' 'issue:Manage Linear issues' 'update:Update linear-cmd to latest version' 'completion:Generate shell completion scripts' ) _describe 'command' commands } _linear_account() { local account_commands account_commands=( 'add:Add a new Linear account' 'list:List all configured accounts' 'remove:Remove an account' 'test:Test connection of all accounts' ) _describe 'account command' account_commands } _linear_issue() { local issue_commands issue_commands=( 'show:Show details of an issue' 'create:Create a new issue' 'list:List issues' 'update:Update an issue' 'comment:Add a comment to an issue' ) _describe 'issue command' issue_commands } _linear "$@" `; const BASH_COMPLETION_SCRIPT = `#!/bin/bash _linear_completion() { local cur prev words cword _init_completion || return # Main commands local commands="account issue update completion" # Account subcommands local account_commands="add list remove test" # Issue subcommands local issue_commands="show create list update comment" if [[ \$cword -eq 1 ]]; then COMPREPLY=(\$(compgen -W "\$commands" -- "\$cur")) elif [[ \$cword -eq 2 ]]; then case "\${COMP_WORDS[1]}" in account) COMPREPLY=(\$(compgen -W "\$account_commands" -- "\$cur")) ;; issue) COMPREPLY=(\$(compgen -W "\$issue_commands" -- "\$cur")) ;; completion) COMPREPLY=(\$(compgen -W "install" -- "\$cur")) ;; esac fi } complete -F _linear_completion linear complete -F _linear_completion lin `; export function createCompletionCommand() { const completion = new Command('completion'); completion.description('Generate shell completion scripts'); completion .command('install') .description('Install shell completion for your current shell') .action(async () => { const shell = detectShell(); try { switch (shell) { case 'zsh': await installZshCompletion(); break; case 'bash': await installBashCompletion(); break; default: Logger.error(`❌ Unsupported shell: ${shell}`); Logger.info(''); Logger.info('🐚 Supported shells: zsh, bash'); Logger.info('💡 Please switch to a supported shell to use autocompletion'); process.exit(1); } } catch (error) { Logger.error(`Failed to install completion: ${error}`); process.exit(1); } }); return completion; } function detectShell() { const shell = process.env.SHELL || ''; if (shell.includes('zsh')) { return 'zsh'; } else if (shell.includes('bash')) { return 'bash'; } // Fallback to zsh if we can't detect return 'zsh'; } async function installZshCompletion() { const homeDir = homedir(); // Try different zsh completion directories (prioritize user directories) const possibleDirs = [ join(homeDir, '.oh-my-zsh', 'completions'), join(homeDir, '.zsh', 'completions'), join(homeDir, '.config', 'zsh', 'completions'), join(homeDir, '.local', 'share', 'zsh', 'site-functions'), '/usr/local/share/zsh/site-functions' ]; let targetDir = null; // Find the first existing and writable directory for (const dir of possibleDirs) { if (existsSync(dir)) { try { // Check if we can write to this directory accessSync(dir, constants.W_OK); targetDir = dir; break; } catch { } } } // If no existing directory found, create one in user's home if (!targetDir) { targetDir = join(homeDir, '.zsh', 'completions'); mkdirSync(targetDir, { recursive: true }); } const completionFile = join(targetDir, '_linear'); writeFileSync(completionFile, ZSH_COMPLETION_SCRIPT); Logger.success(`✅ Zsh completion installed to ${completionFile}`); Logger.info(''); Logger.info('To activate completion, add this to your ~/.zshrc:'); Logger.info(chalk.cyan(` fpath=(${targetDir} $fpath)`)); Logger.info(chalk.cyan(' autoload -U compinit && compinit')); Logger.info(''); Logger.info('Then restart your shell or run:'); Logger.info(chalk.cyan(' source ~/.zshrc')); // Check if fpath already includes the directory try { const zshrc = join(homeDir, '.zshrc'); if (existsSync(zshrc)) { const zshrcContent = require('fs').readFileSync(zshrc, 'utf8'); if (!zshrcContent.includes(targetDir)) { Logger.info(''); Logger.warning('⚠️ Remember to add the fpath line to your ~/.zshrc for autocompletion to work!'); } } } catch (_error) { // Ignore errors when checking .zshrc } } async function installBashCompletion() { const homeDir = homedir(); // Try different bash completion directories (prioritize user directories) const possibleDirs = [ join(homeDir, '.bash_completion.d'), join(homeDir, '.local', 'share', 'bash-completion', 'completions'), '/usr/local/etc/bash_completion.d', '/etc/bash_completion.d' ]; let targetDir = null; // Find the first existing and writable directory for (const dir of possibleDirs) { if (existsSync(dir)) { try { // Check if we can write to this directory accessSync(dir, constants.W_OK); targetDir = dir; break; } catch { } } } // If no existing directory found, create one in user's home if (!targetDir) { targetDir = join(homeDir, '.bash_completion.d'); mkdirSync(targetDir, { recursive: true }); } const completionFile = join(targetDir, 'linear'); writeFileSync(completionFile, BASH_COMPLETION_SCRIPT); Logger.success(`✅ Bash completion installed to ${completionFile}`); Logger.info(''); Logger.info('To activate completion, add this to your ~/.bashrc:'); Logger.info(chalk.cyan(` source ${completionFile}`)); Logger.info(''); Logger.info('Then restart your shell or run:'); Logger.info(chalk.cyan(' source ~/.bashrc')); }