@@ -30,6 +30,7 @@ import 'package:clide/src/pql/client.dart';
|
||||
class BackendBootMessage {
|
||||
const BackendBootMessage({required this.frontendPort, this.hintRoot});
|
||||
final SendPort frontendPort;
|
||||
|
||||
/// Optional path hint for initial toolchain resolution (e.g. CLIDE_PROJECT).
|
||||
/// Used to find project-local binaries like dugite before a project opens.
|
||||
final String? hintRoot;
|
||||
@@ -61,8 +62,7 @@ void backendEntry(BackendBootMessage boot) {
|
||||
final path = message['path'] as String;
|
||||
final id = message['id'] as String;
|
||||
try {
|
||||
final r = await Process.run(toolchain.git, ['rev-parse', '--show-toplevel'],
|
||||
workingDirectory: path, environment: toolchain.gitEnv);
|
||||
final r = await Process.run(toolchain.git, ['rev-parse', '--show-toplevel'], workingDirectory: path, environment: toolchain.gitEnv);
|
||||
if (r.exitCode == 0) {
|
||||
final root = (r.stdout as String).trim();
|
||||
frontendPort.send({'type': 'project.validated', 'id': id, 'root': root});
|
||||
|
||||
@@ -22,8 +22,7 @@ class ClideClipboard {
|
||||
bucket.insert(0, value);
|
||||
if (bucket.length > historyLimit) bucket.removeLast();
|
||||
if (toPlain != null) {
|
||||
await flutter_services.Clipboard.setData(
|
||||
flutter_services.ClipboardData(text: toPlain(value)));
|
||||
await flutter_services.Clipboard.setData(flutter_services.ClipboardData(text: toPlain(value)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,8 +44,7 @@ class ClideClipboard {
|
||||
}
|
||||
|
||||
Future<void> writePlain(String text) async {
|
||||
await flutter_services.Clipboard.setData(
|
||||
flutter_services.ClipboardData(text: text));
|
||||
await flutter_services.Clipboard.setData(flutter_services.ClipboardData(text: text));
|
||||
final bucket = _history.putIfAbsent(String, () => <Object>[]);
|
||||
bucket.insert(0, text);
|
||||
if (bucket.length > historyLimit) bucket.removeLast();
|
||||
|
||||
@@ -36,10 +36,7 @@ class Keybinding {
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
other is Keybinding &&
|
||||
other.key == key &&
|
||||
listEquals(other.modifiers, modifiers);
|
||||
bool operator ==(Object other) => other is Keybinding && other.key == key && listEquals(other.modifiers, modifiers);
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(key, Object.hashAll(modifiers));
|
||||
|
||||
@@ -5,13 +5,11 @@ import 'package:clide/kernel/src/events/types.dart';
|
||||
class DaemonBus {
|
||||
DaemonBus();
|
||||
|
||||
final StreamController<ClideEventEnvelope> _controller =
|
||||
StreamController<ClideEventEnvelope>.broadcast();
|
||||
final StreamController<ClideEventEnvelope> _controller = StreamController<ClideEventEnvelope>.broadcast();
|
||||
|
||||
Stream<ClideEventEnvelope> get stream => _controller.stream;
|
||||
|
||||
Stream<T> on<T extends ClideEvent>() =>
|
||||
_controller.stream.where((e) => e.event is T).map((e) => e.event as T);
|
||||
Stream<T> on<T extends ClideEvent>() => _controller.stream.where((e) => e.event is T).map((e) => e.event as T);
|
||||
|
||||
void emit(ClideEvent event) {
|
||||
if (_controller.isClosed) return;
|
||||
|
||||
@@ -124,8 +124,7 @@ class ExtensionManager extends ChangeNotifier {
|
||||
}
|
||||
for (final dep in ext.dependsOn) {
|
||||
if (!_activated.contains(dep)) {
|
||||
log.warn(
|
||||
'extensions', 'skipping ${ext.id}: dependency not activated: $dep');
|
||||
log.warn('extensions', 'skipping ${ext.id}: dependency not activated: $dep');
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -140,8 +139,7 @@ class ExtensionManager extends ChangeNotifier {
|
||||
notifyListeners();
|
||||
log.info('extensions', 'activated $id');
|
||||
} catch (e, st) {
|
||||
log.error('extensions', 'activate failed for $id',
|
||||
error: e, stackTrace: st);
|
||||
log.error('extensions', 'activate failed for $id', error: e, stackTrace: st);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,8 +157,7 @@ class ExtensionManager extends ChangeNotifier {
|
||||
notifyListeners();
|
||||
log.info('extensions', 'deactivated $id');
|
||||
} catch (e, st) {
|
||||
log.error('extensions', 'deactivate failed for $id',
|
||||
error: e, stackTrace: st);
|
||||
log.error('extensions', 'deactivate failed for $id', error: e, stackTrace: st);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -154,8 +154,8 @@ class KernelServices {
|
||||
onProjectOpen: onProjectOpen,
|
||||
onValidateProject: onValidateProject,
|
||||
);
|
||||
final ipc = isolateClient
|
||||
?? (daemonClientFactory != null
|
||||
final ipc = isolateClient ??
|
||||
(daemonClientFactory != null
|
||||
? daemonClientFactory(log, events)
|
||||
: DaemonClient(
|
||||
socketPath: socketPath ?? defaultSocketPath(),
|
||||
@@ -257,13 +257,11 @@ class ClideKernel extends InheritedWidget {
|
||||
static KernelServices of(BuildContext context) {
|
||||
final w = context.dependOnInheritedWidgetOfExactType<ClideKernel>();
|
||||
if (w == null) {
|
||||
throw FlutterError(
|
||||
'ClideKernel.of() called with a context that is not a descendant of a ClideKernel.');
|
||||
throw FlutterError('ClideKernel.of() called with a context that is not a descendant of a ClideKernel.');
|
||||
}
|
||||
return w.services;
|
||||
}
|
||||
|
||||
@override
|
||||
bool updateShouldNotify(ClideKernel oldWidget) =>
|
||||
services != oldWidget.services;
|
||||
bool updateShouldNotify(ClideKernel oldWidget) => services != oldWidget.services;
|
||||
}
|
||||
|
||||
@@ -88,6 +88,5 @@ class InMemoryCatalogLoader implements CatalogLoader {
|
||||
return const {};
|
||||
}
|
||||
|
||||
static bool _eq(Locale a, Locale b) =>
|
||||
a.languageCode == b.languageCode && a.countryCode == b.countryCode;
|
||||
static bool _eq(Locale a, Locale b) => a.languageCode == b.languageCode && a.countryCode == b.countryCode;
|
||||
}
|
||||
|
||||
@@ -55,8 +55,7 @@ class I18n extends ChangeNotifier {
|
||||
Locale locale,
|
||||
Map<String, Object?> catalog,
|
||||
) {
|
||||
_cache.putIfAbsent(
|
||||
namespace, () => <Locale, Map<String, Object?>>{})[locale] = catalog;
|
||||
_cache.putIfAbsent(namespace, () => <Locale, Map<String, Object?>>{})[locale] = catalog;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
|
||||
@@ -79,11 +79,7 @@ class DaemonClient extends ChangeNotifier {
|
||||
_backoff = const Duration(milliseconds: 200);
|
||||
_setConnected(true);
|
||||
_log.info('ipc', 'connected to $socketPath');
|
||||
socket
|
||||
.cast<List<int>>()
|
||||
.transform(utf8.decoder)
|
||||
.transform(const LineSplitter())
|
||||
.listen(
|
||||
socket.cast<List<int>>().transform(utf8.decoder).transform(const LineSplitter()).listen(
|
||||
_handleLine,
|
||||
onDone: _handleDisconnect,
|
||||
onError: (Object e) {
|
||||
@@ -93,8 +89,7 @@ class DaemonClient extends ChangeNotifier {
|
||||
cancelOnError: true,
|
||||
);
|
||||
} catch (e) {
|
||||
_log.debug(
|
||||
'ipc', 'connect failed ($e); retry in ${_backoff.inMilliseconds}ms');
|
||||
_log.debug('ipc', 'connect failed ($e); retry in ${_backoff.inMilliseconds}ms');
|
||||
_scheduleReconnect();
|
||||
}
|
||||
}
|
||||
|
||||
+10
-20
@@ -23,8 +23,7 @@ class LogRecord {
|
||||
@override
|
||||
String toString() {
|
||||
final lv = level.name.toUpperCase().padRight(5);
|
||||
final buf =
|
||||
StringBuffer('${timestamp.toIso8601String()} $lv [$source] $message');
|
||||
final buf = StringBuffer('${timestamp.toIso8601String()} $lv [$source] $message');
|
||||
if (error != null) buf.write(' | error=$error');
|
||||
return buf.toString();
|
||||
}
|
||||
@@ -33,33 +32,24 @@ class LogRecord {
|
||||
typedef LogSink = void Function(LogRecord);
|
||||
|
||||
class Logger {
|
||||
Logger({this.minLevel = LogLevel.info, List<LogSink>? sinks})
|
||||
: _sinks = List<LogSink>.from(sinks ?? <LogSink>[stderrSink]);
|
||||
Logger({this.minLevel = LogLevel.info, List<LogSink>? sinks}) : _sinks = List<LogSink>.from(sinks ?? <LogSink>[stderrSink]);
|
||||
|
||||
LogLevel minLevel;
|
||||
final List<LogSink> _sinks;
|
||||
final StreamController<LogRecord> _stream =
|
||||
StreamController<LogRecord>.broadcast();
|
||||
final StreamController<LogRecord> _stream = StreamController<LogRecord>.broadcast();
|
||||
|
||||
Stream<LogRecord> get records => _stream.stream;
|
||||
|
||||
void addSink(LogSink sink) => _sinks.add(sink);
|
||||
|
||||
void trace(String source, String message) =>
|
||||
_emit(LogLevel.trace, source, message);
|
||||
void debug(String source, String message) =>
|
||||
_emit(LogLevel.debug, source, message);
|
||||
void info(String source, String message) =>
|
||||
_emit(LogLevel.info, source, message);
|
||||
void warn(String source, String message, {Object? error}) =>
|
||||
_emit(LogLevel.warn, source, message, error: error);
|
||||
void error(String source, String message,
|
||||
{Object? error, StackTrace? stackTrace}) =>
|
||||
_emit(LogLevel.error, source, message,
|
||||
error: error, stackTrace: stackTrace);
|
||||
void trace(String source, String message) => _emit(LogLevel.trace, source, message);
|
||||
void debug(String source, String message) => _emit(LogLevel.debug, source, message);
|
||||
void info(String source, String message) => _emit(LogLevel.info, source, message);
|
||||
void warn(String source, String message, {Object? error}) => _emit(LogLevel.warn, source, message, error: error);
|
||||
void error(String source, String message, {Object? error, StackTrace? stackTrace}) =>
|
||||
_emit(LogLevel.error, source, message, error: error, stackTrace: stackTrace);
|
||||
|
||||
void _emit(LogLevel level, String source, String message,
|
||||
{Object? error, StackTrace? stackTrace}) {
|
||||
void _emit(LogLevel level, String source, String message, {Object? error, StackTrace? stackTrace}) {
|
||||
if (level.index < minLevel.index) return;
|
||||
final rec = LogRecord(
|
||||
level: level,
|
||||
|
||||
@@ -29,16 +29,10 @@ class Notifications extends ChangeNotifier {
|
||||
|
||||
List<ClideNotification> get active => List.unmodifiable(_active);
|
||||
|
||||
void info(String message, {String? title, Duration? duration}) =>
|
||||
_push(NotificationLevel.info, message, title: title, duration: duration);
|
||||
void warn(String message, {String? title, Duration? duration}) =>
|
||||
_push(NotificationLevel.warning, message,
|
||||
title: title, duration: duration);
|
||||
void error(String message, {String? title, Duration? duration}) =>
|
||||
_push(NotificationLevel.error, message, title: title, duration: duration);
|
||||
void success(String message, {String? title, Duration? duration}) =>
|
||||
_push(NotificationLevel.success, message,
|
||||
title: title, duration: duration);
|
||||
void info(String message, {String? title, Duration? duration}) => _push(NotificationLevel.info, message, title: title, duration: duration);
|
||||
void warn(String message, {String? title, Duration? duration}) => _push(NotificationLevel.warning, message, title: title, duration: duration);
|
||||
void error(String message, {String? title, Duration? duration}) => _push(NotificationLevel.error, message, title: title, duration: duration);
|
||||
void success(String message, {String? title, Duration? duration}) => _push(NotificationLevel.success, message, title: title, duration: duration);
|
||||
|
||||
void dismiss(String id) {
|
||||
_timers.remove(id)?.cancel();
|
||||
|
||||
@@ -37,9 +37,7 @@ class _DragResizeHandleState extends State<DragResizeHandle> {
|
||||
final lineColor = _hovered ? tokens.panelActiveBorder : tokens.dividerColor;
|
||||
|
||||
return MouseRegion(
|
||||
cursor: widget.axis == Axis.horizontal
|
||||
? SystemMouseCursors.resizeColumn
|
||||
: SystemMouseCursors.resizeRow,
|
||||
cursor: widget.axis == Axis.horizontal ? SystemMouseCursors.resizeColumn : SystemMouseCursors.resizeRow,
|
||||
onEnter: (_) => setState(() => _hovered = true),
|
||||
onExit: (_) => setState(() => _hovered = false),
|
||||
child: Listener(
|
||||
@@ -72,9 +70,7 @@ class _DragResizeHandleState extends State<DragResizeHandle> {
|
||||
final start = _dragStartSize;
|
||||
final startPt = _dragStartPointer;
|
||||
if (start == null || startPt == null) return;
|
||||
final rawDelta = widget.axis == Axis.horizontal
|
||||
? e.position.dx - startPt.dx
|
||||
: e.position.dy - startPt.dy;
|
||||
final rawDelta = widget.axis == Axis.horizontal ? e.position.dx - startPt.dx : e.position.dy - startPt.dy;
|
||||
final delta = widget.slot == Slots.contextPanel ? -rawDelta : rawDelta;
|
||||
widget.arrangement.setSize(widget.slot, start + delta);
|
||||
}
|
||||
|
||||
@@ -53,9 +53,7 @@ class SettingsStore extends ChangeNotifier {
|
||||
return _projectValues[key];
|
||||
case SettingsScope.ext:
|
||||
// project overrides app for the same ext.* key
|
||||
return _projectValues.containsKey(key)
|
||||
? _projectValues[key]
|
||||
: _appValues[key];
|
||||
return _projectValues.containsKey(key) ? _projectValues[key] : _appValues[key];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,8 +64,7 @@ class SettingsStore extends ChangeNotifier {
|
||||
await _writeFile(_appFile, _appValues);
|
||||
case SettingsScope.project:
|
||||
if (projectDir == null) {
|
||||
throw StateError(
|
||||
'Cannot set project-scoped key with no project open: $key');
|
||||
throw StateError('Cannot set project-scoped key with no project open: $key');
|
||||
}
|
||||
_projectValues[key] = value;
|
||||
await _writeFile(_projectFile, _projectValues);
|
||||
@@ -109,8 +106,7 @@ class SettingsStore extends ChangeNotifier {
|
||||
if (key.startsWith('app.')) return SettingsScope.app;
|
||||
if (key.startsWith('project.')) return SettingsScope.project;
|
||||
if (key.startsWith('ext.')) return SettingsScope.ext;
|
||||
throw ArgumentError(
|
||||
'Settings key must start with app.|project.|ext.: "$key"');
|
||||
throw ArgumentError('Settings key must start with app.|project.|ext.: "$key"');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,10 +8,15 @@ import 'package:ffi/ffi.dart';
|
||||
// -- Opaque handles ----------------------------------------------------------
|
||||
|
||||
final class TSParser extends Opaque {}
|
||||
|
||||
final class TSTree extends Opaque {}
|
||||
|
||||
final class TSQuery extends Opaque {}
|
||||
|
||||
final class TSQueryCursor extends Opaque {}
|
||||
|
||||
final class TSWasmStore extends Opaque {}
|
||||
|
||||
final class TSWasmEngine extends Opaque {}
|
||||
|
||||
// -- Structs -----------------------------------------------------------------
|
||||
@@ -51,10 +56,8 @@ final class TSWasmError extends Struct {
|
||||
typedef _TsParserNew = Pointer<TSParser> Function();
|
||||
typedef _TsParserDelete = Void Function(Pointer<TSParser>);
|
||||
typedef _TsParserSetLanguage = Bool Function(Pointer<TSParser>, Pointer<Void>);
|
||||
typedef _TsParserSetWasmStore = Void Function(
|
||||
Pointer<TSParser>, Pointer<TSWasmStore>);
|
||||
typedef _TsParserParseString = Pointer<TSTree> Function(
|
||||
Pointer<TSParser>, Pointer<TSTree>, Pointer<Utf8>, Uint32);
|
||||
typedef _TsParserSetWasmStore = Void Function(Pointer<TSParser>, Pointer<TSWasmStore>);
|
||||
typedef _TsParserParseString = Pointer<TSTree> Function(Pointer<TSParser>, Pointer<TSTree>, Pointer<Utf8>, Uint32);
|
||||
|
||||
// Tree
|
||||
typedef _TsTreeDelete = Void Function(Pointer<TSTree>);
|
||||
@@ -65,28 +68,21 @@ typedef _TsNodeStartByte = Uint32 Function(TSNode);
|
||||
typedef _TsNodeEndByte = Uint32 Function(TSNode);
|
||||
|
||||
// Query
|
||||
typedef _TsQueryNew = Pointer<TSQuery> Function(
|
||||
Pointer<Void>, Pointer<Utf8>, Uint32, Pointer<Uint32>, Pointer<Int32>);
|
||||
typedef _TsQueryNew = Pointer<TSQuery> Function(Pointer<Void>, Pointer<Utf8>, Uint32, Pointer<Uint32>, Pointer<Int32>);
|
||||
typedef _TsQueryDelete = Void Function(Pointer<TSQuery>);
|
||||
typedef _TsQueryCaptureCount = Uint32 Function(Pointer<TSQuery>);
|
||||
typedef _TsQueryCaptureNameForId = Pointer<Utf8> Function(
|
||||
Pointer<TSQuery>, Uint32, Pointer<Uint32>);
|
||||
typedef _TsQueryCaptureNameForId = Pointer<Utf8> Function(Pointer<TSQuery>, Uint32, Pointer<Uint32>);
|
||||
|
||||
// Query cursor
|
||||
typedef _TsQueryCursorNew = Pointer<TSQueryCursor> Function();
|
||||
typedef _TsQueryCursorDelete = Void Function(Pointer<TSQueryCursor>);
|
||||
typedef _TsQueryCursorExec = Void Function(
|
||||
Pointer<TSQueryCursor>, Pointer<TSQuery>, TSNode);
|
||||
typedef _TsQueryCursorNextMatch = Bool Function(
|
||||
Pointer<TSQueryCursor>, Pointer<TSQueryMatch>);
|
||||
typedef _TsQueryCursorExec = Void Function(Pointer<TSQueryCursor>, Pointer<TSQuery>, TSNode);
|
||||
typedef _TsQueryCursorNextMatch = Bool Function(Pointer<TSQueryCursor>, Pointer<TSQueryMatch>);
|
||||
|
||||
// WASM store
|
||||
typedef _TsWasmStoreNew = Pointer<TSWasmStore> Function(
|
||||
Pointer<TSWasmEngine>, Pointer<TSWasmError>);
|
||||
typedef _TsWasmStoreNew = Pointer<TSWasmStore> Function(Pointer<TSWasmEngine>, Pointer<TSWasmError>);
|
||||
typedef _TsWasmStoreDelete = Void Function(Pointer<TSWasmStore>);
|
||||
typedef _TsWasmStoreLoadLanguage = Pointer<Void> Function(
|
||||
Pointer<TSWasmStore>, Pointer<Utf8>, Pointer<Uint8>, Uint32,
|
||||
Pointer<TSWasmError>);
|
||||
typedef _TsWasmStoreLoadLanguage = Pointer<Void> Function(Pointer<TSWasmStore>, Pointer<Utf8>, Pointer<Uint8>, Uint32, Pointer<TSWasmError>);
|
||||
|
||||
// WASM engine (from wasmtime C API, re-exported by tree-sitter)
|
||||
typedef _WasmEngineNew = Pointer<TSWasmEngine> Function();
|
||||
@@ -97,10 +93,8 @@ typedef _WasmEngineDelete = Void Function(Pointer<TSWasmEngine>);
|
||||
typedef DTsParserNew = Pointer<TSParser> Function();
|
||||
typedef DTsParserDelete = void Function(Pointer<TSParser>);
|
||||
typedef DTsParserSetLanguage = bool Function(Pointer<TSParser>, Pointer<Void>);
|
||||
typedef DTsParserSetWasmStore = void Function(
|
||||
Pointer<TSParser>, Pointer<TSWasmStore>);
|
||||
typedef DTsParserParseString = Pointer<TSTree> Function(
|
||||
Pointer<TSParser>, Pointer<TSTree>, Pointer<Utf8>, int);
|
||||
typedef DTsParserSetWasmStore = void Function(Pointer<TSParser>, Pointer<TSWasmStore>);
|
||||
typedef DTsParserParseString = Pointer<TSTree> Function(Pointer<TSParser>, Pointer<TSTree>, Pointer<Utf8>, int);
|
||||
|
||||
typedef DTsTreeDelete = void Function(Pointer<TSTree>);
|
||||
typedef DTsTreeRootNode = TSNode Function(Pointer<TSTree>);
|
||||
@@ -108,26 +102,19 @@ typedef DTsTreeRootNode = TSNode Function(Pointer<TSTree>);
|
||||
typedef DTsNodeStartByte = int Function(TSNode);
|
||||
typedef DTsNodeEndByte = int Function(TSNode);
|
||||
|
||||
typedef DTsQueryNew = Pointer<TSQuery> Function(
|
||||
Pointer<Void>, Pointer<Utf8>, int, Pointer<Uint32>, Pointer<Int32>);
|
||||
typedef DTsQueryNew = Pointer<TSQuery> Function(Pointer<Void>, Pointer<Utf8>, int, Pointer<Uint32>, Pointer<Int32>);
|
||||
typedef DTsQueryDelete = void Function(Pointer<TSQuery>);
|
||||
typedef DTsQueryCaptureCount = int Function(Pointer<TSQuery>);
|
||||
typedef DTsQueryCaptureNameForId = Pointer<Utf8> Function(
|
||||
Pointer<TSQuery>, int, Pointer<Uint32>);
|
||||
typedef DTsQueryCaptureNameForId = Pointer<Utf8> Function(Pointer<TSQuery>, int, Pointer<Uint32>);
|
||||
|
||||
typedef DTsQueryCursorNew = Pointer<TSQueryCursor> Function();
|
||||
typedef DTsQueryCursorDelete = void Function(Pointer<TSQueryCursor>);
|
||||
typedef DTsQueryCursorExec = void Function(
|
||||
Pointer<TSQueryCursor>, Pointer<TSQuery>, TSNode);
|
||||
typedef DTsQueryCursorNextMatch = bool Function(
|
||||
Pointer<TSQueryCursor>, Pointer<TSQueryMatch>);
|
||||
typedef DTsQueryCursorExec = void Function(Pointer<TSQueryCursor>, Pointer<TSQuery>, TSNode);
|
||||
typedef DTsQueryCursorNextMatch = bool Function(Pointer<TSQueryCursor>, Pointer<TSQueryMatch>);
|
||||
|
||||
typedef DTsWasmStoreNew = Pointer<TSWasmStore> Function(
|
||||
Pointer<TSWasmEngine>, Pointer<TSWasmError>);
|
||||
typedef DTsWasmStoreNew = Pointer<TSWasmStore> Function(Pointer<TSWasmEngine>, Pointer<TSWasmError>);
|
||||
typedef DTsWasmStoreDelete = void Function(Pointer<TSWasmStore>);
|
||||
typedef DTsWasmStoreLoadLanguage = Pointer<Void> Function(
|
||||
Pointer<TSWasmStore>, Pointer<Utf8>, Pointer<Uint8>, int,
|
||||
Pointer<TSWasmError>);
|
||||
typedef DTsWasmStoreLoadLanguage = Pointer<Void> Function(Pointer<TSWasmStore>, Pointer<Utf8>, Pointer<Uint8>, int, Pointer<TSWasmError>);
|
||||
|
||||
typedef DWasmEngineNew = Pointer<TSWasmEngine> Function();
|
||||
typedef DWasmEngineDelete = void Function(Pointer<TSWasmEngine>);
|
||||
@@ -136,60 +123,28 @@ typedef DWasmEngineDelete = void Function(Pointer<TSWasmEngine>);
|
||||
|
||||
class TreeSitterLib {
|
||||
TreeSitterLib._(DynamicLibrary lib)
|
||||
: parserNew = lib.lookupFunction<_TsParserNew, DTsParserNew>(
|
||||
'ts_parser_new'),
|
||||
parserDelete = lib.lookupFunction<_TsParserDelete, DTsParserDelete>(
|
||||
'ts_parser_delete'),
|
||||
parserSetLanguage =
|
||||
lib.lookupFunction<_TsParserSetLanguage, DTsParserSetLanguage>(
|
||||
'ts_parser_set_language'),
|
||||
parserSetWasmStore =
|
||||
lib.lookupFunction<_TsParserSetWasmStore, DTsParserSetWasmStore>(
|
||||
'ts_parser_set_wasm_store'),
|
||||
parserParseString =
|
||||
lib.lookupFunction<_TsParserParseString, DTsParserParseString>(
|
||||
'ts_parser_parse_string'),
|
||||
treeDelete = lib.lookupFunction<_TsTreeDelete, DTsTreeDelete>(
|
||||
'ts_tree_delete'),
|
||||
treeRootNode = lib.lookupFunction<_TsTreeRootNode, DTsTreeRootNode>(
|
||||
'ts_tree_root_node'),
|
||||
nodeStartByte = lib.lookupFunction<_TsNodeStartByte, DTsNodeStartByte>(
|
||||
'ts_node_start_byte'),
|
||||
nodeEndByte = lib.lookupFunction<_TsNodeEndByte, DTsNodeEndByte>(
|
||||
'ts_node_end_byte'),
|
||||
queryNew =
|
||||
lib.lookupFunction<_TsQueryNew, DTsQueryNew>('ts_query_new'),
|
||||
queryDelete = lib.lookupFunction<_TsQueryDelete, DTsQueryDelete>(
|
||||
'ts_query_delete'),
|
||||
queryCaptureCount =
|
||||
lib.lookupFunction<_TsQueryCaptureCount, DTsQueryCaptureCount>(
|
||||
'ts_query_capture_count'),
|
||||
queryCaptureNameForId = lib.lookupFunction<_TsQueryCaptureNameForId,
|
||||
DTsQueryCaptureNameForId>('ts_query_capture_name_for_id'),
|
||||
queryCursorNew =
|
||||
lib.lookupFunction<_TsQueryCursorNew, DTsQueryCursorNew>(
|
||||
'ts_query_cursor_new'),
|
||||
queryCursorDelete =
|
||||
lib.lookupFunction<_TsQueryCursorDelete, DTsQueryCursorDelete>(
|
||||
'ts_query_cursor_delete'),
|
||||
queryCursorExec =
|
||||
lib.lookupFunction<_TsQueryCursorExec, DTsQueryCursorExec>(
|
||||
'ts_query_cursor_exec'),
|
||||
queryCursorNextMatch =
|
||||
lib.lookupFunction<_TsQueryCursorNextMatch, DTsQueryCursorNextMatch>(
|
||||
'ts_query_cursor_next_match'),
|
||||
wasmStoreNew = lib.lookupFunction<_TsWasmStoreNew, DTsWasmStoreNew>(
|
||||
'ts_wasm_store_new'),
|
||||
wasmStoreDelete =
|
||||
lib.lookupFunction<_TsWasmStoreDelete, DTsWasmStoreDelete>(
|
||||
'ts_wasm_store_delete'),
|
||||
wasmStoreLoadLanguage = lib.lookupFunction<_TsWasmStoreLoadLanguage,
|
||||
DTsWasmStoreLoadLanguage>('ts_wasm_store_load_language'),
|
||||
wasmEngineNew = lib.lookupFunction<_WasmEngineNew, DWasmEngineNew>(
|
||||
'wasm_engine_new'),
|
||||
wasmEngineDelete =
|
||||
lib.lookupFunction<_WasmEngineDelete, DWasmEngineDelete>(
|
||||
'wasm_engine_delete');
|
||||
: parserNew = lib.lookupFunction<_TsParserNew, DTsParserNew>('ts_parser_new'),
|
||||
parserDelete = lib.lookupFunction<_TsParserDelete, DTsParserDelete>('ts_parser_delete'),
|
||||
parserSetLanguage = lib.lookupFunction<_TsParserSetLanguage, DTsParserSetLanguage>('ts_parser_set_language'),
|
||||
parserSetWasmStore = lib.lookupFunction<_TsParserSetWasmStore, DTsParserSetWasmStore>('ts_parser_set_wasm_store'),
|
||||
parserParseString = lib.lookupFunction<_TsParserParseString, DTsParserParseString>('ts_parser_parse_string'),
|
||||
treeDelete = lib.lookupFunction<_TsTreeDelete, DTsTreeDelete>('ts_tree_delete'),
|
||||
treeRootNode = lib.lookupFunction<_TsTreeRootNode, DTsTreeRootNode>('ts_tree_root_node'),
|
||||
nodeStartByte = lib.lookupFunction<_TsNodeStartByte, DTsNodeStartByte>('ts_node_start_byte'),
|
||||
nodeEndByte = lib.lookupFunction<_TsNodeEndByte, DTsNodeEndByte>('ts_node_end_byte'),
|
||||
queryNew = lib.lookupFunction<_TsQueryNew, DTsQueryNew>('ts_query_new'),
|
||||
queryDelete = lib.lookupFunction<_TsQueryDelete, DTsQueryDelete>('ts_query_delete'),
|
||||
queryCaptureCount = lib.lookupFunction<_TsQueryCaptureCount, DTsQueryCaptureCount>('ts_query_capture_count'),
|
||||
queryCaptureNameForId = lib.lookupFunction<_TsQueryCaptureNameForId, DTsQueryCaptureNameForId>('ts_query_capture_name_for_id'),
|
||||
queryCursorNew = lib.lookupFunction<_TsQueryCursorNew, DTsQueryCursorNew>('ts_query_cursor_new'),
|
||||
queryCursorDelete = lib.lookupFunction<_TsQueryCursorDelete, DTsQueryCursorDelete>('ts_query_cursor_delete'),
|
||||
queryCursorExec = lib.lookupFunction<_TsQueryCursorExec, DTsQueryCursorExec>('ts_query_cursor_exec'),
|
||||
queryCursorNextMatch = lib.lookupFunction<_TsQueryCursorNextMatch, DTsQueryCursorNextMatch>('ts_query_cursor_next_match'),
|
||||
wasmStoreNew = lib.lookupFunction<_TsWasmStoreNew, DTsWasmStoreNew>('ts_wasm_store_new'),
|
||||
wasmStoreDelete = lib.lookupFunction<_TsWasmStoreDelete, DTsWasmStoreDelete>('ts_wasm_store_delete'),
|
||||
wasmStoreLoadLanguage = lib.lookupFunction<_TsWasmStoreLoadLanguage, DTsWasmStoreLoadLanguage>('ts_wasm_store_load_language'),
|
||||
wasmEngineNew = lib.lookupFunction<_WasmEngineNew, DWasmEngineNew>('wasm_engine_new'),
|
||||
wasmEngineDelete = lib.lookupFunction<_WasmEngineDelete, DWasmEngineDelete>('wasm_engine_delete');
|
||||
|
||||
final DTsParserNew parserNew;
|
||||
final DTsParserDelete parserDelete;
|
||||
|
||||
@@ -96,8 +96,7 @@ class TreeSitterService {
|
||||
|
||||
try {
|
||||
// Load grammar WASM bytes.
|
||||
final wasmData =
|
||||
await rootBundle.load('assets/grammars/$language.wasm');
|
||||
final wasmData = await rootBundle.load('assets/grammars/$language.wasm');
|
||||
final wasmBytes = wasmData.buffer.asUint8List();
|
||||
|
||||
// Load into WASM store.
|
||||
@@ -107,7 +106,11 @@ class TreeSitterService {
|
||||
final error = calloc<TSWasmError>();
|
||||
|
||||
final lang = lib.wasmStoreLoadLanguage(
|
||||
_store!, nameNative.cast(), wasmNative, wasmBytes.length, error,
|
||||
_store!,
|
||||
nameNative.cast(),
|
||||
wasmNative,
|
||||
wasmBytes.length,
|
||||
error,
|
||||
);
|
||||
|
||||
calloc.free(wasmNative);
|
||||
@@ -125,8 +128,7 @@ class TreeSitterService {
|
||||
// Load highlight query.
|
||||
String? querySource;
|
||||
try {
|
||||
querySource =
|
||||
await rootBundle.loadString('assets/queries/$language.scm');
|
||||
querySource = await rootBundle.loadString('assets/queries/$language.scm');
|
||||
} catch (_) {}
|
||||
|
||||
Pointer<TSQuery> query = nullptr;
|
||||
@@ -139,7 +141,11 @@ class TreeSitterService {
|
||||
final errorType = calloc<Int32>();
|
||||
|
||||
query = lib.queryNew(
|
||||
lang, queryNative.cast(), queryLen, errorOffset, errorType,
|
||||
lang,
|
||||
queryNative.cast(),
|
||||
queryLen,
|
||||
errorOffset,
|
||||
errorType,
|
||||
);
|
||||
|
||||
calloc.free(queryNative);
|
||||
@@ -205,7 +211,10 @@ class TreeSitterService {
|
||||
final sourceNative = source.toNativeUtf8();
|
||||
final sourceLen = utf8.encode(source).length;
|
||||
final tree = lib.parserParseString(
|
||||
parser, nullptr, sourceNative.cast(), sourceLen,
|
||||
parser,
|
||||
nullptr,
|
||||
sourceNative.cast(),
|
||||
sourceLen,
|
||||
);
|
||||
|
||||
if (tree == nullptr) {
|
||||
@@ -266,21 +275,14 @@ class TreeSitterService {
|
||||
|
||||
static Color colorForRole(String role, SurfaceTokens tokens) {
|
||||
return switch (role) {
|
||||
'keyword' || 'repeat' || 'conditional' || 'include' ||
|
||||
'exception' || 'operator' =>
|
||||
tokens.syntaxKeyword,
|
||||
'keyword' || 'repeat' || 'conditional' || 'include' || 'exception' || 'operator' => tokens.syntaxKeyword,
|
||||
'type' || 'type.builtin' || 'constructor' => tokens.syntaxType,
|
||||
'string' || 'string.special' => tokens.syntaxString,
|
||||
'number' || 'float' || 'boolean' => tokens.syntaxNumber,
|
||||
'comment' => tokens.syntaxComment,
|
||||
'function' || 'function.builtin' || 'function.method' ||
|
||||
'method' =>
|
||||
tokens.syntaxMethod,
|
||||
'punctuation.bracket' || 'punctuation.delimiter' ||
|
||||
'punctuation.special' =>
|
||||
tokens.syntaxPunct,
|
||||
'variable' || 'variable.builtin' || 'variable.parameter' =>
|
||||
tokens.globalForeground,
|
||||
'function' || 'function.builtin' || 'function.method' || 'method' => tokens.syntaxMethod,
|
||||
'punctuation.bracket' || 'punctuation.delimiter' || 'punctuation.special' => tokens.syntaxPunct,
|
||||
'variable' || 'variable.builtin' || 'variable.parameter' => tokens.globalForeground,
|
||||
'property' || 'field' => tokens.syntaxMethod,
|
||||
'constant' || 'constant.builtin' => tokens.syntaxNumber,
|
||||
'tag' || 'attribute' => tokens.syntaxKeyword,
|
||||
|
||||
@@ -145,7 +145,6 @@ Color _composite(Color src, Color dst) {
|
||||
}
|
||||
|
||||
double _relativeLuminance(Color c) {
|
||||
double chan(double v) =>
|
||||
v <= 0.03928 ? v / 12.92 : math.pow((v + 0.055) / 1.055, 2.4).toDouble();
|
||||
double chan(double v) => v <= 0.03928 ? v / 12.92 : math.pow((v + 0.055) / 1.055, 2.4).toDouble();
|
||||
return 0.2126 * chan(c.r) + 0.7152 * chan(c.g) + 0.0722 * chan(c.b);
|
||||
}
|
||||
|
||||
@@ -25,9 +25,7 @@ class ThemeController extends ChangeNotifier {
|
||||
String? initialName,
|
||||
}) : _resolver = resolver,
|
||||
_defs = Map.fromEntries(bundled.map((d) => MapEntry(d.name, d))) {
|
||||
final first = initialName != null && _defs.containsKey(initialName)
|
||||
? initialName
|
||||
: bundled.first.name;
|
||||
final first = initialName != null && _defs.containsKey(initialName) ? initialName : bundled.first.name;
|
||||
_currentName = first;
|
||||
_current = _build(first);
|
||||
}
|
||||
@@ -89,8 +87,7 @@ class ClideTheme extends InheritedNotifier<ThemeController> {
|
||||
static ClideThemeData of(BuildContext context) {
|
||||
final w = context.dependOnInheritedWidgetOfExactType<ClideTheme>();
|
||||
if (w == null) {
|
||||
throw FlutterError(
|
||||
'ClideTheme.of() called with a context that is not a descendant of a ClideTheme.');
|
||||
throw FlutterError('ClideTheme.of() called with a context that is not a descendant of a ClideTheme.');
|
||||
}
|
||||
return w.notifier!.current;
|
||||
}
|
||||
@@ -98,8 +95,7 @@ class ClideTheme extends InheritedNotifier<ThemeController> {
|
||||
static ThemeController controllerOf(BuildContext context) {
|
||||
final w = context.dependOnInheritedWidgetOfExactType<ClideTheme>();
|
||||
if (w == null) {
|
||||
throw FlutterError(
|
||||
'ClideTheme.controllerOf() called with a context that is not a descendant of a ClideTheme.');
|
||||
throw FlutterError('ClideTheme.controllerOf() called with a context that is not a descendant of a ClideTheme.');
|
||||
}
|
||||
return w.notifier!;
|
||||
}
|
||||
|
||||
@@ -80,15 +80,13 @@ class ThemeLoader {
|
||||
displayName: displayName,
|
||||
dark: dark,
|
||||
palette: palette,
|
||||
semanticOverride:
|
||||
semantic is Map ? _parseSemantic(semantic, palette) : null,
|
||||
semanticOverride: semantic is Map ? _parseSemantic(semantic, palette) : null,
|
||||
surfaceOverride: mergedSurface.isNotEmpty ? mergedSurface : null,
|
||||
extensionOverride: extension is Map ? _parseRefMap(extension) : null,
|
||||
);
|
||||
}
|
||||
|
||||
Future<ThemeDefinition> fromAsset(
|
||||
AssetBundle bundle, String assetPath) async {
|
||||
Future<ThemeDefinition> fromAsset(AssetBundle bundle, String assetPath) async {
|
||||
final txt = await bundle.loadString(assetPath);
|
||||
final fallback = assetPath.split('/').last.replaceAll('.yaml', '');
|
||||
return fromYamlString(txt, fallbackName: fallback);
|
||||
@@ -115,8 +113,7 @@ SemanticRoles _parseSemantic(Map src, Palette palette) {
|
||||
final roles = <String, Color>{};
|
||||
src.forEach((k, v) {
|
||||
if (v is! String) return;
|
||||
final resolved =
|
||||
v.startsWith('#') ? Palette.parseHex(v) : palette.lookup(v);
|
||||
final resolved = v.startsWith('#') ? Palette.parseHex(v) : palette.lookup(v);
|
||||
if (resolved != null) roles['$k'] = resolved;
|
||||
});
|
||||
return SemanticRoles(roles);
|
||||
|
||||
@@ -65,10 +65,8 @@ class ThemeResolver {
|
||||
sidebarSectionHeader: surface[TokenKeys.sidebarSectionHeader]!,
|
||||
statusBarBackground: surface[TokenKeys.statusBarBackground]!,
|
||||
statusBarForeground: surface[TokenKeys.statusBarForeground]!,
|
||||
statusBarItemActiveBackground:
|
||||
surface[TokenKeys.statusBarItemActiveBackground]!,
|
||||
statusBarItemHoverBackground:
|
||||
surface[TokenKeys.statusBarItemHoverBackground]!,
|
||||
statusBarItemActiveBackground: surface[TokenKeys.statusBarItemActiveBackground]!,
|
||||
statusBarItemHoverBackground: surface[TokenKeys.statusBarItemHoverBackground]!,
|
||||
tabBarBackground: surface[TokenKeys.tabBarBackground]!,
|
||||
tabActive: surface[TokenKeys.tabActive]!,
|
||||
tabInactive: surface[TokenKeys.tabInactive]!,
|
||||
@@ -84,10 +82,8 @@ class ThemeResolver {
|
||||
listItemBackground: surface[TokenKeys.listItemBackground]!,
|
||||
listItemForeground: surface[TokenKeys.listItemForeground]!,
|
||||
listItemHoverBackground: surface[TokenKeys.listItemHoverBackground]!,
|
||||
listItemSelectedBackground:
|
||||
surface[TokenKeys.listItemSelectedBackground]!,
|
||||
listItemSelectedForeground:
|
||||
surface[TokenKeys.listItemSelectedForeground]!,
|
||||
listItemSelectedBackground: surface[TokenKeys.listItemSelectedBackground]!,
|
||||
listItemSelectedForeground: surface[TokenKeys.listItemSelectedForeground]!,
|
||||
scrollbarSlider: surface[TokenKeys.scrollbarSlider]!,
|
||||
scrollbarSliderHover: surface[TokenKeys.scrollbarSliderHover]!,
|
||||
scrollbarTrack: surface[TokenKeys.scrollbarTrack]!,
|
||||
@@ -135,9 +131,7 @@ class ThemeResolver {
|
||||
// theme never has a null surface color. Themes that omit these
|
||||
// will land readable if uninspired.
|
||||
roles.putIfAbsent(role, () {
|
||||
return palette.lookup('foreground') ??
|
||||
palette.lookup('background') ??
|
||||
const Color(0xFFFFFFFF);
|
||||
return palette.lookup('foreground') ?? palette.lookup('background') ?? const Color(0xFFFFFFFF);
|
||||
});
|
||||
}
|
||||
return SemanticRoles(roles);
|
||||
|
||||
@@ -67,6 +67,7 @@ class Toolchain extends ChangeNotifier {
|
||||
if (!c.isCompleted) c.complete();
|
||||
}
|
||||
}
|
||||
|
||||
addListener(listener);
|
||||
return c.future;
|
||||
}
|
||||
@@ -104,17 +105,16 @@ class Toolchain extends ChangeNotifier {
|
||||
|
||||
final pql = _findOnPath('pql');
|
||||
final tmux = _findOnPath('tmux');
|
||||
final shell = _findOnPath(
|
||||
Platform.environment['SHELL']?.split('/').last ?? 'bash');
|
||||
final shell = _findOnPath(Platform.environment['SHELL']?.split('/').last ?? 'bash');
|
||||
|
||||
final ptyc = _firstExisting([
|
||||
'$workspaceRoot/ptyc/bin/ptyc',
|
||||
'$workspaceRoot/native/linux-x64/ptyc',
|
||||
'$workspaceRoot/native/macos-arm64/ptyc',
|
||||
'$workspaceRoot/native/macos-x64/ptyc',
|
||||
if (Platform.environment['HOME'] case final home?)
|
||||
'$home/.local/bin/ptyc',
|
||||
]) ?? _findOnPath('ptyc');
|
||||
'$workspaceRoot/ptyc/bin/ptyc',
|
||||
'$workspaceRoot/native/linux-x64/ptyc',
|
||||
'$workspaceRoot/native/macos-arm64/ptyc',
|
||||
'$workspaceRoot/native/macos-x64/ptyc',
|
||||
if (Platform.environment['HOME'] case final home?) '$home/.local/bin/ptyc',
|
||||
]) ??
|
||||
_findOnPath('ptyc');
|
||||
|
||||
return ResolvedPaths(
|
||||
git: git,
|
||||
@@ -184,15 +184,14 @@ ResolvedPaths resolveToolchainPaths(String workspaceRoot) {
|
||||
pql: _findOnPathStandalone('pql'),
|
||||
tmux: _findOnPathStandalone('tmux'),
|
||||
ptyc: _firstExistingStandalone([
|
||||
'$workspaceRoot/ptyc/bin/ptyc',
|
||||
'$workspaceRoot/native/linux-x64/ptyc',
|
||||
'$workspaceRoot/native/macos-arm64/ptyc',
|
||||
'$workspaceRoot/native/macos-x64/ptyc',
|
||||
if (Platform.environment['HOME'] case final home?)
|
||||
'$home/.local/bin/ptyc',
|
||||
]) ?? _findOnPathStandalone('ptyc'),
|
||||
shell: _findOnPathStandalone(
|
||||
Platform.environment['SHELL']?.split('/').last ?? 'bash'),
|
||||
'$workspaceRoot/ptyc/bin/ptyc',
|
||||
'$workspaceRoot/native/linux-x64/ptyc',
|
||||
'$workspaceRoot/native/macos-arm64/ptyc',
|
||||
'$workspaceRoot/native/macos-x64/ptyc',
|
||||
if (Platform.environment['HOME'] case final home?) '$home/.local/bin/ptyc',
|
||||
]) ??
|
||||
_findOnPathStandalone('ptyc'),
|
||||
shell: _findOnPathStandalone(Platform.environment['SHELL']?.split('/').last ?? 'bash'),
|
||||
gitEnv: gitEnv,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -20,8 +20,7 @@ class TrayRegistry extends ChangeNotifier {
|
||||
}
|
||||
|
||||
Iterable<TrayItemContribution> get items {
|
||||
final sorted = _items.values.toList()
|
||||
..sort((a, b) => a.priority.compareTo(b.priority));
|
||||
final sorted = _items.values.toList()..sort((a, b) => a.priority.compareTo(b.priority));
|
||||
return sorted;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user