-
Notifications
You must be signed in to change notification settings - Fork 17
Expand file tree
/
Copy pathcode_editor_tab.dart
More file actions
114 lines (101 loc) · 2.94 KB
/
code_editor_tab.dart
File metadata and controls
114 lines (101 loc) · 2.94 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
// Import the language & theme
import 'package:fluent_ui/fluent_ui.dart';
import 'package:highlight/highlight.dart';
import 'package:code_text_field/code_text_field.dart';
import 'package:flex_tabs/flex_tabs.dart';
import 'package:highlight/languages/all.dart';
import 'package:terminal_studio/src/core/fs.dart';
class CodeEditorTab extends TabItem {
final File file;
CodeEditorTab(this.file) {
title.value = Text(file.basename);
content.value = CodeEditorView(this);
loadContent();
}
final codeController = ValueNotifier<CodeController?>(null);
Future<void> loadContent() async {
final content = await file.readAsString();
codeController.value = CodeController(
text: content,
language: _detectLanguage(content),
);
}
}
class CodeEditorView extends StatelessWidget {
const CodeEditorView(this.tab, {super.key});
final CodeEditorTab tab;
static const fontFamily = 'SourceCode';
static const fontFamilyFallback = [
'Menlo', // macos
'Consolas', // windows
'monospace',
];
@override
Widget build(BuildContext context) {
return NavigationView(
content: Column(
children: [
_buildToolbar(),
const Divider(),
Expanded(child: _buildEditor()),
],
),
);
}
Widget _buildToolbar() {
return Padding(
padding: const EdgeInsets.all(8),
child: CommandBar(
mainAxisAlignment: MainAxisAlignment.end,
primaryItems: [
// CommandBarButton(
// icon: const Icon(FluentIcons.back),
// label: const Text('Back'),
// onPressed: () {},
// ),
CommandBarButton(
icon: const Icon(FluentIcons.save),
label: const Text('Save'),
onPressed: () async {
final controller = tab.codeController.value;
if (controller == null) return;
await tab.file.writeAsString(controller.value.text);
},
),
],
),
);
}
Widget _buildEditor() {
return ValueListenableBuilder(
valueListenable: tab.codeController,
builder: (context, codeController, child) {
if (codeController == null) {
return const Center(
child: ProgressRing(),
);
}
return SingleChildScrollView(
child: CodeField(
controller: codeController,
lineNumberStyle: const LineNumberStyle(
textStyle: TextStyle(
fontFamily: fontFamily,
fontFamilyFallback: fontFamilyFallback,
),
),
textStyle: const TextStyle(
fontFamily: fontFamily,
fontSize: 12,
fontFamilyFallback: fontFamilyFallback,
),
),
);
},
);
}
}
Mode _detectLanguage(String source) {
final result = highlight.parse(source, autoDetection: true);
return allLanguages[result.language]!;
}