File.hx 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. import haxe.display.Position;
  2. class File {
  3. public var content(default, null):String;
  4. public var path(default, null):String;
  5. var lines:Array<Int>;
  6. public function new(path:String, content:String) {
  7. this.path = path;
  8. this.content = content;
  9. initLines();
  10. }
  11. function initLines() {
  12. lines = [];
  13. // составляем массив позиций начала строк
  14. var s = 0, p = 0;
  15. while (p < content.length) {
  16. inline function nextChar()
  17. return StringTools.fastCodeAt(content, p++);
  18. inline function line() {
  19. lines.push(s);
  20. s = p;
  21. };
  22. switch (nextChar()) {
  23. case "\n".code:
  24. line();
  25. case "\r".code:
  26. p++;
  27. line();
  28. }
  29. }
  30. }
  31. function findPosition(pos:Int):Position {
  32. function loop(min, max) {
  33. var mid = (min + max) >> 1;
  34. var start = lines[mid];
  35. return if (mid == min)
  36. {line: mid, character: pos - start + 1};
  37. else if (start > pos)
  38. loop(min, mid);
  39. else
  40. loop(mid, max);
  41. }
  42. return loop(0, lines.length);
  43. }
  44. public function findRange(min:Int, max:Int):Range {
  45. return {
  46. start: findPosition(min),
  47. end: findPosition(max)
  48. }
  49. }
  50. public function formatRange(min:Int, max:Int):String {
  51. var range = findRange(min, max);
  52. var start = range.start;
  53. var end = range.end;
  54. var pos = if (start.line == end.line) {
  55. if (start.character == end.character)
  56. 'character ${start.character}';
  57. else
  58. 'characters ${start.character}-${end.character}';
  59. } else {
  60. 'lines ${start.line + 1}-${end.line + 1}';
  61. }
  62. return '$path:${start.line + 1}: $pos';
  63. }
  64. public static inline function read(path:String) {
  65. return new File(path, sys.io.File.getContent(path));
  66. }
  67. }