Selaa lähdekoodia

Tab and Shift+Tab adjust indentation

Arthur Yefimov 4 vuotta sitten
vanhempi
commit
9fdb50c424
2 muutettua tiedostoa jossa 94 lisäystä ja 17 poistoa
  1. 16 4
      src/Editor.Mod
  2. 78 13
      src/EditorText.Mod

+ 16 - 4
src/Editor.Mod

@@ -666,7 +666,6 @@ END MoveToLineEdge;
 PROCEDURE HandleBackspace(c: Editor);
 BEGIN
   c.text.HandleBackspace;
-  c.text.selected := FALSE;
   PrintText(c)
 END HandleBackspace;
 
@@ -676,6 +675,21 @@ BEGIN
   PrintText(c)
 END HandleDelete;
 
+PROCEDURE HandleTab(e: Editor; shift: BOOLEAN);
+BEGIN
+  IF shift THEN e.text.RemoveIndent
+  ELSIF e.text.WholeLineSelected() THEN
+    IF shift THEN e.text.RemoveIndent
+    ELSE e.text.AddIndent
+    END
+  ELSE
+    IF e.text.selected THEN e.text.DeleteSelection END;
+    e.text.InsertChar(' ');
+    IF ODD(e.text.x MOD 2) THEN e.text.InsertChar(' ') END
+  END;
+  PrintText(e)
+END HandleTab;
+
 PROCEDURE HandleEnter(c: Editor);
 BEGIN
   c.text.HandleEnter(TRUE);
@@ -808,9 +822,7 @@ BEGIN
   | G.kBackspace: HandleBackspace(c(Editor))
   | G.kDel:       HandleDelete(c(Editor))
   | G.kEnter, G.kEnterPad: HandleEnter(c(Editor))
-  | G.kTab: c(Editor).text.InsertChar(' ');
-    IF ODD(c(Editor).text.x MOD 2) THEN c(Editor).text.InsertChar(' ') END;
-    PrintText(c(Editor))
+  | G.kTab:       HandleTab(c(Editor), key.mod * G.mShift # {})
   ELSE
   END
 END EditorKeyDown;

+ 78 - 13
src/EditorText.Mod

@@ -118,19 +118,6 @@ BEGIN
   t.RemoveLine(L.next)
 END Combine2Lines;
 
-PROCEDURE (t: Text) HandleBackspace*;
-BEGIN
-  IF t.x > 0 THEN
-    DEC(t.x); t.cur.Delete(t.x, 1);
-    t.changed := TRUE
-  ELSIF t.cur.prev # NIL THEN (* Курсор в начале строки и перед ней есть ещё строка *)
-    t.cur := t.cur.prev;
-    DEC(t.y); t.x := t.cur.len;
-    t.Combine2Lines(t.cur);
-    t.changed := TRUE
-  END
-END HandleBackspace;
-
 PROCEDURE (t: Text) GetFirstSelLine*(): Line;
 VAR y: INTEGER; L: Line;
 BEGIN
@@ -149,6 +136,70 @@ BEGIN t.selected := TRUE;
   t.selR := 5
 END SelectAll;
 
+(**Returns true if at least one whole line is selected,
+   but leading spaces may still be unselected*)
+PROCEDURE (t: Text) WholeLineSelected*(): BOOLEAN;
+VAR L: Line;
+  i: INTEGER;
+  res: BOOLEAN;
+BEGIN res := FALSE;
+  IF t.selected THEN
+    IF t.selT # t.selB THEN res := TRUE
+    ELSE
+      L := t.GetFirstSelLine();
+      IF t.selR = L.len THEN
+        i := 0;
+        WHILE (i # t.selL) & (L.s[i] = ' ') DO INC(i) END;
+        IF i = t.selL THEN res := TRUE END
+      END
+    END
+  END;
+RETURN res END WholeLineSelected;
+
+PROCEDURE (t: Text) RemoveIndent*;
+VAR L: Line;
+  i, y, endY: INTEGER;
+BEGIN
+  L := t.GetFirstSelLine(); y := t.selT;
+  endY := t.selB;
+  IF t.selR = 0 THEN DEC(endY) END;
+  WHILE y <= endY DO
+    FOR i := 1 TO 2 DO
+      IF L.s[0] = ' ' THEN
+        L.Delete(0, 1);
+        IF (y = t.selT) & (t.selL # 0) THEN
+          DEC(t.selL);
+          IF t.y = t.selT THEN DEC(t.x) END
+        ELSIF (y = t.selB) & (t.selR # 0) THEN
+          DEC(t.selR);
+          IF (t.y # t.selT) & (t.y = t.selB) THEN DEC(t.x) END
+        END
+      END
+    END;
+    L := L.next; INC(y)
+  END
+END RemoveIndent;
+
+PROCEDURE (t: Text) AddIndent*;
+VAR L: Line;
+  i, y, endY: INTEGER;
+BEGIN
+  L := t.GetFirstSelLine();
+  y := t.selT;
+  endY := t.selB;
+  IF t.selR = 0 THEN DEC(endY) END;
+  WHILE y <= endY DO
+    FOR i := 1 TO 2 DO IF L.len # 0 THEN L.InsertChar(' ', 0) END END;
+    L := L.next; INC(y)
+  END;
+  INC(t.selL, 2);
+  IF t.selT = t.y THEN INC(t.x, 2) END;
+  IF t.selR # 0 THEN
+    INC(t.selR, 2);
+    IF (t.selT # t.y) & (t.selB = t.y) THEN INC(t.x, 2) END
+  END
+END AddIndent;
+
 PROCEDURE (t: Text) DeleteSelection*;
 VAR x0, x, y: INTEGER; L0, L: Line;
 BEGIN
@@ -174,6 +225,20 @@ BEGIN
   END
 END DeleteSelection;
 
+PROCEDURE (t: Text) HandleBackspace*;
+BEGIN
+  IF t.selected THEN t.DeleteSelection
+  ELSIF t.x > 0 THEN
+    DEC(t.x); t.cur.Delete(t.x, 1);
+    t.changed := TRUE
+  ELSIF t.cur.prev # NIL THEN (* Курсор в начале строки и перед ней есть ещё строка *)
+    t.cur := t.cur.prev;
+    DEC(t.y); t.x := t.cur.len;
+    t.Combine2Lines(t.cur);
+    t.changed := TRUE
+  END
+END HandleBackspace;
+
 PROCEDURE (t: Text) HandleDelete*;
 BEGIN
   IF t.selected THEN