extractExecutable function
Extract the primary executable from a command string.
Handles env prefixes, sudo, nice, time, etc.
Implementation
String? extractExecutable(String input) {
final trimmed = input.trim();
if (trimmed.isEmpty) return null;
final commands = extractCommands(trimmed);
if (commands.isEmpty) return null;
final cmd = commands.first;
var exe = cmd.executable;
// Skip through env-prefix commands.
const prefixCommands = {
'env',
'sudo',
'nice',
'nohup',
'time',
'timeout',
'strace',
'ltrace',
'ionice',
'chrt',
'taskset',
'numactl',
'command',
'builtin',
};
if (prefixCommands.contains(exe)) {
// Skip flags (starting with -), VAR=value env assignments, and known
// flag arguments that take a numeric / string parameter (e.g. `nice -n 10`,
// `timeout 5s`, `taskset -c 0`). Heuristic: also skip purely numeric
// tokens, which are nearly always values for the previous flag, never
// an executable name.
var skipNext = false;
for (final arg in cmd.arguments) {
if (skipNext) {
skipNext = false;
continue;
}
if (arg.startsWith('-')) {
// Single-letter flags like `-n`, `-c` typically take a value.
if (RegExp(r'^-[A-Za-z]$').hasMatch(arg)) {
skipNext = true;
}
continue;
}
// Skip env-var assignments like PATH=/usr/bin or FOO=bar.
if (RegExp(r'^[A-Za-z_][A-Za-z0-9_]*=').hasMatch(arg)) {
continue;
}
// Skip purely numeric / duration tokens (e.g. `5`, `10`, `5s`).
if (RegExp(r'^\d+[smhd]?$').hasMatch(arg)) {
continue;
}
return arg.split('/').last;
}
}
// Skip env-var assignments that appear as the executable (shouldn't happen
// after proper parsing, but be defensive).
if (exe.contains('=') && !exe.startsWith('-')) {
for (final arg in cmd.arguments) {
if (!arg.contains('=') || arg.startsWith('-')) {
return arg.split('/').last;
}
}
return null;
}
return exe.split('/').last;
}