dev
dart 107 lines 3.59 KB
Raw
1 import 'dart:io';
2 import 'dart:math';
3 import 'package:flutter/foundation.dart';
4
5 enum LogLevel { info, debug, warn, error }
6
7 /// Pass an optional [file] to also write the log to a file.
8 void printV(
9 dynamic content, {
10 String? file,
11 LogLevel level = LogLevel.info,
12 }) {
13 final programInfo = CustomTrace(StackTrace.current);
14 final logLine =
15 "[${level.name.toUpperCase()}] ${programInfo.fileName}#${programInfo.lineNumber}:${programInfo.columnNumber} ${programInfo.callerFunctionName}: $content";
16
17 print(logLine);
18
19 if (file != null) {
20 final logFile = File(file);
21 if (!logFile.existsSync()) {
22 logFile.createSync(recursive: true);
23 }
24 logFile.writeAsStringSync("$logLine\n", mode: FileMode.append, flush: true);
25 }
26 }
27
28 // https://stackoverflow.com/a/59386101
29
30 class CustomTrace {
31 final StackTrace _trace;
32
33 String? fileName;
34 String? functionName;
35 String? callerFunctionName;
36 int? lineNumber;
37 int? columnNumber;
38
39 CustomTrace(this._trace) {
40 try {
41 _parseTrace();
42 } catch (e) {
43 if (kDebugMode) print("Unable to parse trace (printV): $e");
44 }
45 }
46
47 String _getFunctionNameFromFrame(String frame) {
48 /* Just giving another nickname to the frame */
49 var currentTrace = frame;
50 /* To get rid off the #number thing, get the index of the first whitespace */
51 var indexOfWhiteSpace = currentTrace.indexOf(' ');
52
53 /* Create a substring from the first whitespace index till the end of the string */
54 var subStr = currentTrace.substring(max(0, indexOfWhiteSpace));
55
56 /* Grab the function name using reg expr */
57 var indexOfFunction = subStr.indexOf(RegExp(r'[A-Za-z0-9_]'));
58
59 /* Create a new substring from the function name index till the end of string */
60 subStr = subStr.substring(indexOfFunction);
61
62 indexOfWhiteSpace = subStr.indexOf(RegExp(r'[ .]'));
63
64 /* Create a new substring from start to the first index of a whitespace. This substring gives us the function name */
65 subStr = subStr.substring(0, max(0, indexOfWhiteSpace));
66
67 return subStr;
68 }
69
70 void _parseTrace() {
71 /* The trace comes with multiple lines of strings, (each line is also known as a frame), so split the trace's string by lines to get all the frames */
72 var frames = this._trace.toString().split("\n");
73
74 /* The first frame is the current function */
75 this.functionName = _getFunctionNameFromFrame(frames[0]);
76
77 /* The second frame is the caller function */
78 this.callerFunctionName = _getFunctionNameFromFrame(frames[1]);
79
80 /* The first frame has all the information we need */
81 var traceString = frames[1];
82
83 /* Search through the string and find the index of the file name by looking for the '.dart' regex */
84 var indexOfFileName = traceString.indexOf(
85 RegExp(r'[/A-Za-z_]+.dart'), 1); // 1 to offest and not print the printV function name
86
87 var fileInfo = traceString.substring(max(0, indexOfFileName));
88
89 var listOfInfos = fileInfo.split(":");
90
91 /* Splitting fileInfo by the character ":" separates the file name, the line number and the column counter nicely.
92 Example: main.dart:5:12
93 To get the file name, we split with ":" and get the first index
94 To get the line number, we would have to get the second index
95 To get the column number, we would have to get the third index
96 */
97 try {
98 this.fileName = listOfInfos[0];
99 this.lineNumber = int.tryParse(listOfInfos[1]);
100 var columnStr = listOfInfos[2];
101 columnStr = columnStr.replaceFirst(")", "");
102 this.columnNumber = int.tryParse(columnStr);
103 } catch (e) {
104 if (kDebugMode) print("Unable to parse trace (printV): $e");
105 }
106 }
107 }