|
| 1 | +// Copyright 2020 The Go-Python Authors. All rights reserved. |
| 2 | +// Use of this source code is governed by a BSD-style |
| 3 | +// license that can be found in the LICENSE file. |
| 4 | + |
| 5 | +package main |
| 6 | + |
| 7 | +import ( |
| 8 | + "bytes" |
| 9 | + "strings" |
| 10 | +) |
| 11 | + |
| 12 | +// moveLines moves the st,ed region to 'to' line |
| 13 | +func moveLines(lines *[][]byte, to, st, ed int) { |
| 14 | + mvln := (*lines)[st:ed] |
| 15 | + btwn := (*lines)[to:st] |
| 16 | + aft := (*lines)[ed:len(*lines)] |
| 17 | + nln := make([][]byte, to, len(*lines)) |
| 18 | + copy(nln, (*lines)[:to]) |
| 19 | + nln = append(nln, mvln...) |
| 20 | + nln = append(nln, btwn...) |
| 21 | + nln = append(nln, aft...) |
| 22 | + *lines = nln |
| 23 | +} |
| 24 | + |
| 25 | +// pyMove moves python segments around, e.g., methods |
| 26 | +// into their proper classes |
| 27 | +func pyMove(src []byte) []byte { |
| 28 | + type sted struct { |
| 29 | + st, ed int |
| 30 | + } |
| 31 | + |
| 32 | + classes := map[string]sted{} |
| 33 | + |
| 34 | + nl := []byte("\n") |
| 35 | + class := []byte("class ") |
| 36 | + pymark := []byte("<<<<") |
| 37 | + pyend := []byte(">>>>") |
| 38 | + endclass := "EndClass: " |
| 39 | + method := "Method: " |
| 40 | + endmethod := "EndMethod" |
| 41 | + |
| 42 | + lines := bytes.Split(src, nl) |
| 43 | + |
| 44 | + lastMethSt := -1 |
| 45 | + var lastMeth string |
| 46 | + curComSt := -1 |
| 47 | + lastComSt := -1 |
| 48 | + lastComEd := -1 |
| 49 | + |
| 50 | + li := 0 |
| 51 | + for { |
| 52 | + if li >= len(lines) { |
| 53 | + break |
| 54 | + } |
| 55 | + ln := lines[li] |
| 56 | + if len(ln) > 0 && ln[0] == '#' { |
| 57 | + if curComSt >= 0 { |
| 58 | + lastComEd = li |
| 59 | + } else { |
| 60 | + curComSt = li |
| 61 | + lastComSt = li |
| 62 | + lastComEd = li |
| 63 | + } |
| 64 | + } else { |
| 65 | + curComSt = -1 |
| 66 | + } |
| 67 | + |
| 68 | + switch { |
| 69 | + case bytes.Equal(ln, []byte(" :")) || bytes.Equal(ln, []byte(":")): |
| 70 | + lines = append(lines[:li], lines[li+1:]...) // delete marker |
| 71 | + li-- |
| 72 | + case bytes.HasPrefix(ln, class): |
| 73 | + cl := string(ln[len(class):]) |
| 74 | + if idx := strings.Index(cl, "("); idx > 0 { |
| 75 | + cl = cl[:idx] |
| 76 | + } else if idx := strings.Index(cl, ":"); idx > 0 { // should have |
| 77 | + cl = cl[:idx] |
| 78 | + } |
| 79 | + cl = strings.TrimSpace(cl) |
| 80 | + classes[cl] = sted{st: li} |
| 81 | + // fmt.Printf("cl: %s at %d\n", cl, li) |
| 82 | + case bytes.HasPrefix(ln, pymark) && bytes.HasSuffix(ln, pyend): |
| 83 | + tag := string(ln[4 : len(ln)-4]) |
| 84 | + // fmt.Printf("tag: %s at: %d\n", tag, li) |
| 85 | + switch { |
| 86 | + case strings.HasPrefix(tag, endclass): |
| 87 | + cl := tag[len(endclass):] |
| 88 | + st := classes[cl] |
| 89 | + classes[cl] = sted{st: st.st, ed: li} |
| 90 | + lines = append(lines[:li], lines[li+1:]...) // delete marker |
| 91 | + // fmt.Printf("cl: %s at %v\n", cl, classes[cl]) |
| 92 | + li-- |
| 93 | + case strings.HasPrefix(tag, method): |
| 94 | + cl := tag[len(method):] |
| 95 | + lines = append(lines[:li], lines[li+1:]...) // delete marker |
| 96 | + li-- |
| 97 | + lastMeth = cl |
| 98 | + if lastComEd == li { |
| 99 | + lines = append(lines[:lastComSt], lines[lastComEd+1:]...) // delete comments |
| 100 | + lastMethSt = lastComSt |
| 101 | + li = lastComSt - 1 |
| 102 | + } else { |
| 103 | + lastMethSt = li + 1 |
| 104 | + } |
| 105 | + case tag == endmethod: |
| 106 | + se, ok := classes[lastMeth] |
| 107 | + if ok { |
| 108 | + lines = append(lines[:li], lines[li+1:]...) // delete marker |
| 109 | + moveLines(&lines, se.ed, lastMethSt, li) |
| 110 | + classes[lastMeth] = sted{st: se.st, ed: se.ed + (li - lastMethSt)} |
| 111 | + li -= 2 |
| 112 | + } |
| 113 | + } |
| 114 | + } |
| 115 | + li++ |
| 116 | + } |
| 117 | + |
| 118 | + return bytes.Join(lines, nl) |
| 119 | +} |
0 commit comments