github.com/jmigpin/editor@v1.6.0/core/openerow.go (about) 1 package core 2 3 import ( 4 "errors" 5 6 "github.com/jmigpin/editor/ui" 7 "github.com/jmigpin/editor/util/iout/iorw" 8 "github.com/jmigpin/editor/util/parseutil" 9 ) 10 11 type OpenFileERowConfig struct { 12 FilePos *parseutil.FilePos 13 RowPos *ui.RowPos 14 15 CancelIfExistent bool 16 NewIfNotExistent bool 17 NewIfOffsetNotVisible bool 18 19 //FlashRowsIfNotFlashed bool 20 FlashVisibleOffsets bool // flashes rows if not visible 21 } 22 23 // TODO: make it UI safe? rename to openfileerowasync? 24 func OpenFileERow(ed *Editor, conf *OpenFileERowConfig) { 25 if _, err := openFileERow2(ed, conf); err != nil { 26 ed.Error(err) 27 } 28 } 29 30 func openFileERow2(ed *Editor, conf *OpenFileERowConfig) (isNew bool, _ error) { 31 // filename 32 var filename string 33 if conf.FilePos != nil { 34 filename = conf.FilePos.Filename 35 } else { 36 return false, errors.New("missing filename") 37 } 38 39 info := ed.ReadERowInfo(filename) 40 41 // do nothing if existent 42 if conf.CancelIfExistent && len(info.ERows) > 0 { 43 return false, nil 44 } 45 46 createNew := false 47 48 // helper func: cache for LineColumnIndex 49 lciVal := 0 50 lciDone := false 51 cacheLineColumnIndex := func(rd iorw.ReaderAt) int { 52 if lciDone { 53 return lciVal 54 } 55 lciDone = true 56 if conf.FilePos.Line == 0 { // missing line/col, should be ">=1" 57 lciVal = -1 58 } else { 59 u, err := parseutil.LineColumnIndex(rd, conf.FilePos.Line, conf.FilePos.Column) 60 if err != nil { 61 lciVal = -1 62 } else { 63 lciVal = u 64 } 65 } 66 return lciVal 67 } 68 69 // helper func: get offset 70 getOffset := func() int { 71 if conf.FilePos != nil { 72 if conf.FilePos.HasOffset() { 73 return conf.FilePos.Offset 74 } 75 if erow0, ok := info.FirstERow(); ok { 76 ta := erow0.Row.TextArea 77 return cacheLineColumnIndex(ta.RW()) 78 } 79 } 80 return -1 81 } 82 83 // should create new if not existent 84 if conf.NewIfNotExistent { 85 if len(info.ERows) == 0 { 86 createNew = true 87 } 88 } 89 90 // should create new if offset not visible 91 if conf.NewIfOffsetNotVisible { 92 if !createNew { 93 if len(info.ERows) == 0 { 94 createNew = true 95 } else { 96 offset := getOffset() 97 if offset >= 0 { 98 visible := false 99 for _, e := range info.ERows { 100 if e.Row.TextArea.IndexVisible(offset) { 101 visible = true 102 break 103 } 104 } 105 createNew = !visible 106 } 107 } 108 } 109 } 110 111 // create new erow 112 var newERow *ERow 113 if createNew { 114 isNew = true 115 if conf.RowPos == nil { 116 return isNew, errors.New("missing row position") 117 } 118 erow, err := NewLoadedERow(info, conf.RowPos) 119 if err != nil { 120 return isNew, err 121 } 122 newERow = erow 123 } 124 125 // make offset visible 126 flashed := make(map[*ERow]bool) 127 offset := getOffset() 128 if offset >= 0 { 129 if len(info.ERows) == 0 { 130 return isNew, errors.New("missing erow to make offset visible") 131 } 132 133 // use newly created erow 134 erow := newERow 135 136 // use existing row with visible offset 137 if erow == nil { 138 for _, e := range info.ERows { 139 if e.Row.TextArea.IndexVisible(offset) { 140 erow = e 141 break 142 } 143 } 144 } 145 146 // use first row in UI order 147 if erow == nil { 148 erow = info.ERowsInUIOrder()[0] 149 } 150 151 // setup chosen erow 152 //erow.Row.EnsureTextAreaMinimumHeight() 153 erow.Row.EnsureOneToolbarLineYVisible() 154 erow.Row.TextArea.Cursor().SetIndexSelectionOff(offset) 155 erow.Row.TextArea.MakeIndexVisible(offset) 156 157 // flash visible offsets 158 if conf.FlashVisibleOffsets { 159 o, l := 0, 0 160 if conf.FilePos != nil { 161 if conf.FilePos.HasOffset() { 162 o, l = conf.FilePos.Offset, conf.FilePos.Len 163 } else { 164 o = offset 165 } 166 } 167 168 for _, e := range info.ERows { 169 if e.Row.TextArea.IndexVisible(offset) { 170 e.MakeRangeVisibleAndFlash(o, l) 171 flashed[e] = true 172 } 173 } 174 } 175 176 // no flashes were done (no index visible, small rows), flash target 177 if len(flashed) == 0 { 178 erow.Flash() 179 flashed[erow] = true 180 } 181 } 182 183 // flash rows if not flashed already 184 //if conf.FlashRowsIfNotFlashed || 185 if conf.FlashVisibleOffsets && offset < 0 { 186 for _, e := range info.ERows { 187 if !flashed[e] { 188 e.Flash() 189 } 190 } 191 } 192 193 return isNew, nil 194 }