Coverage for aipyapp/cli/command/cmd_custom.py: 0%

1 import os

2 from pathlib import Path

3

4 from rich import print

5 from rich.panel import Panel

6 from rich.syntax import Syntax

7

8 from ... import T

9 from .base import CommandMode, Completable

10 from .base_parser import ParserCommand

11 from .utils import print_table

12

13

14 class CustomCommand(ParserCommand):

15 name = 'custom'

16 description = T('Manage custom commands')

17 modes = [CommandMode.MAIN, CommandMode.TASK]

18

19 def add_subcommands(self, subparsers):

20 subparsers.add_parser('list', help=T('List all custom commands'))

21 subparsers.add_parser('reload', help=T('Reload custom commands from disk'))

22

23 show_parser = subparsers.add_parser('show', help=T('Show custom command details'))

24 show_parser.add_argument('name', type=str, help=T('Custom command name'))

25

26 create_parser = subparsers.add_parser('create', help=T('Create new custom command'))

27 create_parser.add_argument('name', type=str, help=T('Command name'))

28 create_parser.add_argument('--description', type=str, default='', help=T('Command description'))

29 create_parser.add_argument('--mode', choices=['main', 'task', 'both'], default='task', help=T('Command mode'))

30

31 def get_arg_values(self, arg, subcommand=None, partial_value=''):

32 if arg.name == 'name' and subcommand == 'show':

33 custom_commands = self.manager.custom_command_manager.get_all_commands()

34 return [Completable(cmd.name, cmd.description) for cmd in custom_commands]

35 return super().get_arg_values(arg, subcommand, partial_value)

36

37 def cmd_list(self, args, ctx):

38 """List all custom commands"""

39 custom_commands = self.manager.custom_command_manager.get_all_commands()

40

41 if not custom_commands:

42 print(f"[yellow]{T('No custom commands found')}[/yellow]")

43 dirs_str = ', '.join(str(d) for d in self.manager.custom_command_manager.command_dirs)

44 print(f"{T('Custom commands directories')}: {dirs_str}")

45 return

46

47 rows = []

48 for cmd in custom_commands:

49 modes_str = ', '.join([mode.value for mode in cmd.modes])

50

51 # Find which directory this command belongs to

52 file_path_str = str(cmd.file_path)

53 for command_dir in self.manager.custom_command_manager.command_dirs:

54 try:

55 relative_path = cmd.file_path.relative_to(command_dir)

56 file_path_str = str(relative_path)

57 break

58 except ValueError:

59 # This file is not in this directory, try next

60 continue

61

62 rows.append([cmd.name, cmd.description, modes_str, file_path_str])

63

64 print_table(

65 rows,

66 headers=[T('Name'), T('Description'), T('Modes'), T('File')],

67 title=T('Custom Commands')

68 )

69

70 def cmd_reload(self, args, ctx):

71 """Reload custom commands from disk"""

72 count = self.manager.reload_custom_commands()

73 print(f"[green]{T('Reloaded')} {count} {T('custom commands')}[/green]")

74

75 def cmd_show(self, args, ctx):

76 """Show custom command details"""

77 command = self.manager.custom_command_manager.get_command(args.name)

78 if not command:

79 print(f"[red]{T('Custom command not found')}: {args.name}[/red]")

80 return

81

82 # Show command info

83 print(Panel(

84 f"**{T('Name')}:** {command.name}\n"

85 f"**{T('Description')}:** {command.description}\n"

86 f"**{T('Modes')}:** {', '.join([mode.value for mode in command.modes])}\n"

87 f"**{T('File')}:** {command.file_path}",

88 title=T('Command Details'),

89 border_style="blue"

90 ))

91

92 # Show command content

93 try:

94 content = command.file_path.read_text(encoding='utf-8')

95 syntax = Syntax(content, "markdown", theme="monokai", line_numbers=True)

96 print(Panel(syntax, title=T('Command Content'), border_style="green"))

97 except Exception as e:

98 print(f"[red]{T('Error reading file')}: {e}[/red]")

99

100 def cmd_create(self, args, ctx):

101 """Create a new custom command"""

102 # Use the first available directory or create a default one

103 command_dirs = self.manager.custom_command_manager.command_dirs

104

105 if not command_dirs:

106 print(f"[red]{T('No custom command directories configured')}[/red]")

107 return

108

109 # Use the first directory for creation

110 command_dir = next(iter(command_dirs))

111

112 # Ensure the directory exists

113 command_dir.mkdir(parents=True, exist_ok=True)

114

115 command_file = command_dir / f"{args.name}.md"

116

117 if command_file.exists():

118 print(f"[red]{T('Command already exists')}: {args.name}[/red]")

119 return

120

121 # Determine modes

122 if args.mode == 'both':

123 modes = ['main', 'task']

124 else:

125 modes = [args.mode]

126

127 # Create command template

128 template_content = f'''---

129 name: "{args.name}"

130 description: "{args.description or f'Custom {args.name} command'}"

131 modes: {modes}

132 arguments:

133 - name: "input"

134 type: "str"

135 required: false

136 help: "Input parameter"

137---

138

139# {args.name.title()} Command

140

141 This is a custom command: {{{{input}}}}

142

143 You can modify this template to create your custom command logic.

144

145## Available template variables:

146- {{{{input}}}}: The input parameter

147- {{{{subcommand}}}}: The subcommand if any

148

149## Template syntax:

150- Use Jinja2 syntax for advanced templating

151- Simple {{{{variable}}}} replacement for basic usage

152'''

153

154 try:

155 command_file.write_text(template_content, encoding='utf-8')

156 print(f"[green]{T('Created custom command')}: {command_file}[/green]")

157 print(f"[yellow]{T('Run')}: /custom reload {T('to load the new command')}[/yellow]")

158 except Exception as e:

159 print(f"[red]{T('Error creating command')}: {e}[/red]")

160

161 def cmd(self, args, ctx):

162 """Default action: list commands"""

163 self.cmd_list(args, ctx)