Skip to content

Commit

Permalink
chore: improve error logging
Browse files Browse the repository at this point in the history
  • Loading branch information
chenasraf committed Jul 21, 2024
1 parent c192e6c commit 74e1674
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 38 deletions.
16 changes: 10 additions & 6 deletions bin/script_runner.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import 'package:script_runner/utils.dart';
/// Main entrypoint for CMD script runner.
Future<void> main(List<String> args) async {
if (args.isEmpty) {
printColor('No script command provided. Use -h to see available commands.', [TerminalColor.red]);
printColor(
'No script command provided. Use -h or -ls to see available commands.',
[TerminalColor.red]);
return;
}
final scriptCmd = args.first;
Expand All @@ -15,13 +17,15 @@ Future<void> main(List<String> args) async {
final code = await runScript(scriptCmd, scriptArgs);
io.exit(code);
} catch (e, stack) {
if (e is ScriptStateError) {
if (e is ScriptError) {
printColor(e.toString(), [TerminalColor.red]);
} else {
printColor('$e\n$stack', [TerminalColor.red]);
}
if (e is io.ProcessException) {
} else if (e is io.ProcessException) {
printColor(
'Error in script "$scriptCmd": ${e.message}', [TerminalColor.red]);
io.exit(e.errorCode);
} else {
printColor('Error executing script: $e\n$stack', [TerminalColor.red]);
io.exit(1);
}
}
}
19 changes: 12 additions & 7 deletions lib/base.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Future<int> runScript(String entryName, List<String> args) async {
final config = await ScriptRunnerConfig.get();

if (config.scripts.isEmpty) {
throw ScriptStateError('No scripts found');
throw ScriptNotFoundError('No scripts found');
}

if (['-h', '--help'].contains(entryName)) {
Expand All @@ -24,27 +24,32 @@ Future<int> runScript(String entryName, List<String> args) async {
final entry = config.scriptsMap[entryName];

if (entry == null) {
final suggestions =
config.scriptsMap.keys.where((key) => key.toLowerCase().startsWith(entryName.toLowerCase())).toList();
final suggestions = config.scriptsMap.keys
.where((key) => key.toLowerCase().startsWith(entryName.toLowerCase()))
.toList();

if (suggestions.isNotEmpty) {
if (suggestions.length == 1) {
throw ScriptStateError(
throw ScriptNotFoundError(
'No script named "$entryName" found. Did you mean "${suggestions.single}"?',
);
} else {
throw ScriptStateError(
throw ScriptNotFoundError(
'No script named "$entryName" found.\n'
'Did you mean one of: "${suggestions.join('", "')}"?',
);
}
} else {
throw ScriptStateError(
throw ScriptNotFoundError(
'No script named "$entryName" found.\n'
'Available scripts: ${config.scriptsMap.keys.join('", "')}',
);
}
}

return entry.run(args);
try {
return entry.run(args);
} catch (e, stack) {
throw ScriptError('Error running script "$entryName": $e\n$stack');
}
}
30 changes: 21 additions & 9 deletions lib/config.dart
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@ class ScriptRunnerConfig {
final sourceMap = await _tryFindConfig(fs, startDir);

if (sourceMap.isEmpty) {
throw ScriptStateError('Must provide scripts in either pubspec.yaml or script_runner.yaml');
throw ScriptStateError(
'Must provide scripts in either pubspec.yaml or script_runner.yaml');
}

final source = sourceMap.values.first;
Expand All @@ -100,7 +101,9 @@ class ScriptRunnerConfig {
List<dynamic>? scriptsRaw, {
FileSystem? fileSystem,
}) {
final scripts = (scriptsRaw ?? []).map((script) => RunnableScript.fromMap(script, fileSystem: fileSystem)).toList();
final scripts = (scriptsRaw ?? [])
.map((script) => RunnableScript.fromMap(script, fileSystem: fileSystem))
.toList();
return scripts.map((s) => s..preloadScripts = scripts).toList();
}

Expand Down Expand Up @@ -138,7 +141,8 @@ class ScriptRunnerConfig {
(configSource?.isNotEmpty == true
? [
colorize(' on ', titleStyle),
colorize(configSource!, [...titleStyle, TerminalColor.underline]),
colorize(
configSource!, [...titleStyle, TerminalColor.underline]),
colorize(':', titleStyle)
].join('')
: ':'),
Expand All @@ -165,10 +169,15 @@ class ScriptRunnerConfig {

final filtered = search.isEmpty
? scripts
: scripts.where((scr) => [scr.name, scr.description].any((s) => s != null && s.contains(search))).toList();
: scripts
.where((scr) => [scr.name, scr.description]
.any((s) => s != null && s.contains(search)))
.toList();

final mapped =
filtered.map((scr) => TableRow(scr.name, scr.description ?? '\$ ${[scr.cmd, ...scr.args].join(' ')}')).toList();
final mapped = filtered
.map((scr) => TableRow(scr.name,
scr.description ?? '\$ ${[scr.cmd, ...scr.args].join(' ')}'))
.toList();

final padLen = _getPadLen(mapped.map((r) => r.name).toList(), maxLen);

Expand All @@ -180,7 +189,8 @@ class ScriptRunnerConfig {
/// If [search] is provided, it filters the scripts to only those that contain the search string.
void printBuiltins([String search = '']) {
final builtins = [
TableRow('-ls, --list [search]', 'List available scripts. Add search term to filter.'),
TableRow('-ls, --list [search]',
'List available scripts. Add search term to filter.'),
TableRow('-h, --help', 'Print this help message'),
];

Expand All @@ -197,15 +207,17 @@ class ScriptRunnerConfig {
stripColors: true,
wrapLine: (line) => colorize(line, [TerminalColor.gray]),
);
printColor(' ${scr.name.padRight(padLen, ' ')} ${lines.first}', [TerminalColor.yellow]);
printColor(' ${scr.name.padRight(padLen, ' ')} ${lines.first}',
[TerminalColor.yellow]);
for (final line in lines.sublist(1)) {
print(' ${''.padRight(padLen, ' ')} $line');
}
print('');
}
}

static Future<Map<String, Map>> _tryFindConfig(FileSystem fs, String startDir) async {
static Future<Map<String, Map>> _tryFindConfig(
FileSystem fs, String startDir) async {
final explorer = Unaconfig('script_runner', fs: fs);
final config = await explorer.search();
if (config != null) {
Expand Down
13 changes: 9 additions & 4 deletions lib/runnable_script.dart
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ class RunnableScript {
env: map['env'] as Map<String, String>? ?? {},
);
} catch (e) {
throw ScriptStateError('Failed to parse script, arguments: $map, $fileSystem. Error: $e');
throw ScriptStateError(
'Failed to parse script, arguments: $map, $fileSystem. Error: $e');
}
}

Expand Down Expand Up @@ -162,7 +163,8 @@ class RunnableScript {
return exitCode;
}

String _getScriptPath() => _fileSystem.path.join(_fileSystem.systemTempDirectory.path, 'script_runner_$name.sh');
String _getScriptPath() => _fileSystem.path
.join(_fileSystem.systemTempDirectory.path, 'script_runner_$name.sh');

String _getScriptContents(
ScriptRunnerConfig config, {
Expand All @@ -182,8 +184,11 @@ class RunnableScript {
].join('\n');
case OS.linux:
case OS.macos:
return [...preloadScripts.map((e) => "[[ ! \$(which ${e.name}) ]] && alias ${e.name}='scr ${e.name}'"), script]
.join('\n');
return [
...preloadScripts.map((e) =>
"[[ ! \$(which ${e.name}) ]] && alias ${e.name}='scr ${e.name}'"),
script
].join('\n');
}
}
}
15 changes: 13 additions & 2 deletions lib/utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,20 @@ class TerminalColor {
static const TerminalColor underline = TerminalColor._(4);
}

class ScriptStateError extends StateError {
ScriptStateError(super.message);
/// An error that occurs that is related to a script.
class ScriptError extends StateError {
ScriptError(super.message);

@override
String toString() => message;
}

/// An error that occurs during script execution.
class ScriptStateError extends ScriptError {
ScriptStateError(super.message);
}

/// An error that occurs when a script is not found.
class ScriptNotFoundError extends ScriptError {
ScriptNotFoundError(super.message);
}
17 changes: 8 additions & 9 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,12 @@ dev_dependencies:
btool: any

script_runner:
# line_length: 100
scripts:
# ================================================================================
# Real
# ================================================================================
- auto-fix: dart fix --apply
- publish: dart format .; dart pub publish; format
- publish: dart format .; dart pub publish
- publish:dry: dart pub publish --dry-run
- doc: dart doc
- name: version
Expand All @@ -33,15 +34,13 @@ script_runner:
- name: 'version:set'
cmd: dart run btool set packageVersion
display_cmd: false
- format: dart format --line-length 120 .
- name: clean
cmd: rm -rf .dart_tool/pub/bin/script_runner/script_runner.dart-*.snapshot
- name: activate-local
cmd: scr clean && dart pub global deactivate script_runner; dart pub global activate --source path ./
- name: activate-global
cmd: scr clean && dart pub global deactivate script_runner; dart pub global activate script_runner
- clean: rm -rf .dart_tool/pub/bin/script_runner/script_runner.dart-*.snapshot
- activate-local: scr clean && dart pub global deactivate script_runner; dart pub global activate --source path ./
- activate-global: scr clean && dart pub global deactivate script_runner; dart pub global activate script_runner

# ================================================================================
# Examples
# ================================================================================
- name: echo1
cmd: echo "Hello World" $SHELL
description: Interdum a scelerisque arcu felis taciti ligula pellentesque curabitur, suspendisse adipiscing quisque sed luctus elementum in imperdiet id, praesent enim sem justo sapien diam nec. Quisque erat risus sagittis penatibus per, vehicula sociosqu cubilia convallis, sollicitudin scelerisque cras aptent. Natoque ornare dictumst netus litora mollis suspendisse cubilia proin morbi primis consequat eu massa, cursus non urna ridiculus dolor duis tempus ut nam velit lacus viverra. A interdum senectus eu mus leo aptent facilisi augue tristique ante purus condimentum pulvinar porta viverra morbi, et tellus gravida porttitor non euismod suscipit neque egestas praesent arcu luctus pharetra fusce. Luctus mauris a venenatis tempus cras ante efficitur massa ultricies mollis lacus, volutpat nisi lacinia himenaeos facilisi in aliquet sodales purus integer vitae quisque, libero torquent enim mattis placerat tortor mi dignissim viverra sem.
Expand Down
3 changes: 2 additions & 1 deletion test/config_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,8 @@ Future<void> _writeCustomConf(FileSystem fs, [String? contents]) async {
final homeDir = fs.directory(Platform.environment['HOME']!);
homeDir.create(recursive: true);
fs.currentDirectory = homeDir;
final pubFile = fs.file(path.join(fs.currentDirectory.path, 'script_runner.yaml'));
final pubFile =
fs.file(path.join(fs.currentDirectory.path, 'script_runner.yaml'));
pubFile.create(recursive: true);
print('writing custom conf to ${pubFile.path}');
await pubFile.writeAsString(
Expand Down

0 comments on commit 74e1674

Please sign in to comment.