├── .gitignore ├── .gitmodules ├── .travis.yml ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── glide.yaml ├── main ├── index.html ├── main.go └── main_test.go └── tasks └── local └── ci └── build.sh /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | 3 | *.sublime-project 4 | *.sublime-workspace 5 | 6 | vendor/ 7 | main/main 8 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "packages"] 2 | path = packages 3 | url = https://github.com/limetext/lime-packages.git 4 | [submodule "tasks/general"] 5 | path = tasks/general 6 | url = https://github.com/limetext/lime-tasks.git 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | os: 2 | - osx 3 | - linux 4 | 5 | sudo: false 6 | 7 | language: go 8 | 9 | go: 1.5.1 10 | 11 | addons: 12 | apt: 13 | sources: 14 | - deadsnakes 15 | packages: 16 | - libonig-dev 17 | - python3.5 18 | - python3.5-dev 19 | 20 | install: 21 | - ./tasks/general/ci/install.sh 22 | 23 | script: 24 | - ./tasks/general/ci/run_tests.sh main 25 | - ./tasks/local/ci/build.sh 26 | - ./tasks/general/ci/check_fmt.sh 27 | 28 | notifications: 29 | webhooks: 30 | urls: 31 | - https://webhooks.gitter.im/e/3e692a5224c8490f19bd 32 | on_success: change 33 | on_failure: always 34 | on_start: false 35 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ### 1. The issues list is for development purposes only. 2 | 3 | All issues reported here should result in **code being changed, added and/or removed**. 4 | 5 | For support requests, please use [limetext/support](https://github.com/limetext/support) instead. 6 | 7 | 8 | ### 2. Issues should be opened up in the correct repository. 9 | 10 | All issues reported here should result in code being changed, added and/or removed **in *this* repository**. If the issue relates to a different package, please file it there. There are a number of supporting packages maintained by us, which can be found [here](https://github.com/limetext). 11 | 12 | 13 | ### 3. Feature requests belong here, unless they can be implemented via a plugin. 14 | 15 | If the feature can be implemented via a plugin it fails by proxy to satisfy [#2](CONTRIBUTING.md#2-issues-should-be-openened-up-in-the-correct-repository). 16 | 17 | 18 | ### 4. Bug reports belong here. 19 | 20 | Bug reports should include a description of current behaviour and the expected behaviour in cases where this isn't obvious. 21 | 22 | User errors where the error does not result in a code change count as support and fail to satisfy [#1](CONTRIBUTING.md#1-the-issues-list-is-for-development-purposes-only). 23 | 24 | ### 5. If you'd like to help but don't know how. 25 | 26 | There's plenty of work that needs to be done, requiring a wide variety of skills and skill levels. The [Contributing wiki page](https://github.com/limetext/lime/wiki/Contributing) is a good place to start for some ideas. 27 | 28 | There isn't a roadmap with well staked out milestones along the way where we can just give you a specific task to work on if you are up for anything within your skill level, and the few [volunteers](https://github.com/limetext/lime/graphs/contributors) who are activily involved at the moment are already having a hard time managing everything. 29 | 30 | This is after all not a commercially backed project and any time spent here by our volunteers is their own spare time that they kindly donate to the project instead of spending time with friends, family and other interests. 31 | 32 | We do need your help. Even if its just 5 minutes every month, that's 1 hour a year. If we could get just 0.1% of the people who have starred this project to donate 5 minutes every month it'd be a total of ~100 man hours per year and a significant impact on the project. 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 The lime Authors 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 17 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.org/limetext/lime-html.svg?branch=master)](https://travis-ci.org/limetext/lime-html) 2 | [![Coverage Status](https://img.shields.io/coveralls/limetext/lime-html.svg?branch=master)](https://coveralls.io/r/limetext/lime-html?branch=master) 3 | [![Go Report Card](http://goreportcard.com/badge/limetext/lime-html)](http://goreportcard.com/report/limetext/lime-html) 4 | 5 | [![GoDoc](https://godoc.org/github.com/limetext/lime-html?status.svg)](https://godoc.org/github.com/limetext/lime-html) 6 | 7 | [![Bountysource Bounties](https://www.bountysource.com/badge/team?team_id=8742&style=bounties_received)](https://www.bountysource.com/teams/limetext/issues?utm_source=limetext&utm_medium=shield&utm_campaign=bounties_received) 8 | [![Bountysource Raised](https://www.bountysource.com/badge/team?team_id=8742&style=raised)](https://www.bountysource.com/teams/limetext?utm_source=limetext&utm_medium=shield&utm_campaign=raised) 9 | 10 | [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/limetext/lime) 11 | 12 | 13 | # lime-html 14 | 15 | This is the HTML frontend for [Lime](http://limetext.org/). For more information about the project, please see [limetext/lime](https://github.com/limetext/lime). 16 | -------------------------------------------------------------------------------- /glide.yaml: -------------------------------------------------------------------------------- 1 | package: github.com/limetext/lime-html 2 | import: 3 | - package: github.com/limetext/lime-backend 4 | ref: 2c5030159bc2d5743904274e45c3cd0563dcc184 5 | - flatten: true 6 | package: github.com/limetext/gopy 7 | ref: 953f768831d5f6389aacdc9c016ff2fb8c2ca579 8 | - package: github.com/limetext/log4go 9 | ref: 2aba105a605a9ebe476f35d7610704e4e723d4ab 10 | - package: github.com/limetext/rubex 11 | ref: 3fc130e580797e3d9c6fdab36e6a961141f9fd5f 12 | - flatten: true 13 | package: github.com/limetext/text 14 | ref: d6b8f8c60fe38232a5b59388bbba0f3802c182e9 15 | - package: golang.org/x/net/websockets 16 | ref: 03affa02f16950ea3188823456766ed60bfed9bb 17 | -------------------------------------------------------------------------------- /main/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Lime 6 | 7 | 8 | 9 | 10 | 79 | 80 | 81 | 82 |
83 | 94 | 95 | 356 | 357 | -------------------------------------------------------------------------------- /main/main.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The lime Authors. 2 | // Use of this source code is governed by a 2-clause 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import ( 8 | "bufio" 9 | "bytes" 10 | "flag" 11 | "fmt" 12 | "github.com/limetext/gopy/lib" 13 | "github.com/limetext/lime-backend/lib" 14 | _ "github.com/limetext/lime-backend/lib/commands" 15 | "github.com/limetext/lime-backend/lib/keys" 16 | "github.com/limetext/lime-backend/lib/log" 17 | "github.com/limetext/lime-backend/lib/render" 18 | _ "github.com/limetext/lime-backend/lib/sublime" 19 | "github.com/limetext/lime-backend/lib/textmate" 20 | "github.com/limetext/lime-backend/lib/util" 21 | . "github.com/limetext/text" 22 | "golang.org/x/net/websocket" 23 | "io" 24 | "io/ioutil" 25 | "net/http" 26 | "net/url" 27 | "os" 28 | "path" 29 | "runtime/debug" 30 | "strconv" 31 | "strings" 32 | "sync" 33 | "time" 34 | "unicode" 35 | "unicode/utf8" 36 | ) 37 | 38 | var ( 39 | scheme *textmate.Theme 40 | blink bool 41 | port = flag.Int("port", 8080, "Configures which port to host lime on") 42 | ) 43 | 44 | const ( 45 | console_height = 20 46 | render_chan_len = 2 47 | ) 48 | 49 | type layout struct { 50 | x, y int 51 | width, height int 52 | visible Region 53 | lastUpdate int 54 | } 55 | type tbfe struct { 56 | layout map[*backend.View]layout 57 | status_message string 58 | dorender chan bool 59 | lock sync.Mutex 60 | dirty bool 61 | } 62 | 63 | func (t *tbfe) Erased(changed_buffer Buffer, region_removed Region, data_removed []rune) { 64 | t.scroll(changed_buffer) 65 | } 66 | 67 | func (t *tbfe) Inserted(changed_buffer Buffer, region_inserted Region, data_inserted []rune) { 68 | t.scroll(changed_buffer) 69 | } 70 | 71 | func htmlcol(c render.Colour) string { 72 | return fmt.Sprintf("%02X%02X%02X", c.R, c.G, c.B) 73 | } 74 | 75 | func (t *tbfe) renderView(wr io.Writer, v *backend.View, lay layout) { 76 | p := util.Prof.Enter("render") 77 | defer p.Exit() 78 | 79 | vr := lay.visible 80 | runes := v.Buffer().Substr(vr) 81 | recipie := v.Transform(scheme, vr).Transcribe() 82 | highlight_line := false 83 | if b, ok := v.Settings().Get("highlight_line", highlight_line).(bool); ok { 84 | highlight_line = b 85 | } 86 | lastEnd := 0 87 | for _, reg := range recipie { 88 | if lastEnd != reg.Region.Begin() { 89 | io.WriteString(wr, runes[lastEnd:reg.Region.Begin()]) 90 | } 91 | fmt.Fprintf(wr, "%s", htmlcol(reg.Flavour.Foreground), htmlcol(reg.Flavour.Background), runes[reg.Region.Begin():reg.Region.End()]) 92 | lastEnd = reg.Region.End() 93 | } 94 | if lastEnd != vr.End() { 95 | io.WriteString(wr, v.Buffer().Substr(Region{lastEnd, vr.End()})) 96 | } 97 | } 98 | 99 | func (t *tbfe) clip(v *backend.View, s, e int) Region { 100 | p := util.Prof.Enter("clip") 101 | defer p.Exit() 102 | h := t.layout[v].height 103 | if e-s > h { 104 | e = s + h 105 | } else if e-s < h { 106 | s = e - h 107 | } 108 | if e2, _ := v.Buffer().RowCol(v.Buffer().TextPoint(e, 0)); e2 < e { 109 | e = e2 110 | } 111 | if s < 0 { 112 | s = 0 113 | } 114 | e = s + h 115 | r := Region{v.Buffer().TextPoint(s, 0), v.Buffer().TextPoint(e, 0)} 116 | return v.Buffer().LineR(r) 117 | } 118 | 119 | func (t *tbfe) Show(v *backend.View, r Region) { 120 | t.lock.Lock() 121 | l := t.layout[v] 122 | t.lock.Unlock() 123 | if l.visible.Covers(r) { 124 | return 125 | } 126 | p := util.Prof.Enter("show") 127 | defer p.Exit() 128 | 129 | lv := l.visible 130 | 131 | s1, _ := v.Buffer().RowCol(lv.Begin()) 132 | e1, _ := v.Buffer().RowCol(lv.End()) 133 | s2, _ := v.Buffer().RowCol(r.Begin()) 134 | e2, _ := v.Buffer().RowCol(r.End()) 135 | 136 | r1 := Region{s1, e1} 137 | r2 := Region{s2, e2} 138 | 139 | r3 := r1.Cover(r2) 140 | diff := 0 141 | if d1, d2 := Abs(r1.Begin()-r3.Begin()), Abs(r1.End()-r3.End()); d1 > d2 { 142 | diff = r3.Begin() - r1.Begin() 143 | } else { 144 | diff = r3.End() - r1.End() 145 | } 146 | r3.A = r1.Begin() + diff 147 | r3.B = r1.End() + diff 148 | 149 | r3 = t.clip(v, r3.A, r3.B) 150 | l.visible = r3 151 | t.lock.Lock() 152 | t.layout[v] = l 153 | t.lock.Unlock() 154 | } 155 | 156 | func (t *tbfe) VisibleRegion(v *backend.View) Region { 157 | t.lock.Lock() 158 | r, ok := t.layout[v] 159 | t.lock.Unlock() 160 | if !ok || r.lastUpdate != v.Buffer().ChangeCount() { 161 | t.Show(v, r.visible) 162 | t.lock.Lock() 163 | r = t.layout[v] 164 | t.lock.Unlock() 165 | } 166 | return r.visible 167 | } 168 | 169 | func (t *tbfe) StatusMessage(msg string) { 170 | t.lock.Lock() 171 | defer t.lock.Unlock() 172 | t.status_message = msg 173 | 174 | t.BroadcastData(map[string]interface{}{"type": "statusMessage", "msg": msg}) 175 | } 176 | 177 | func (t *tbfe) ErrorMessage(msg string) { 178 | log.Error(msg) 179 | 180 | t.BroadcastData(map[string]interface{}{"type": "errorMessage", "msg": msg}) 181 | } 182 | 183 | func (t *tbfe) MessageDialog(msg string) { 184 | log.Info(msg) 185 | 186 | t.BroadcastData(map[string]interface{}{"type": "messageDialog", "msg": msg}) 187 | } 188 | 189 | // TODO: wait for client response, return true/false 190 | func (t *tbfe) OkCancelDialog(msg, ok string) bool { 191 | log.Info(msg, ok) 192 | 193 | t.BroadcastData(map[string]interface{}{"type": "okCancelDialog", "msg": msg, "ok": ok}) 194 | 195 | return false 196 | } 197 | 198 | func (t *tbfe) scroll(b Buffer) { 199 | t.Show(backend.GetEditor().Console(), Region{b.Size(), b.Size()}) 200 | } 201 | 202 | var pc = 0 203 | 204 | func (t *tbfe) render(w io.Writer) { 205 | defer func() { 206 | if r := recover(); r != nil { 207 | log.Error("Panic in renderthread: %v\n%s", r, string(debug.Stack())) 208 | if pc > 1 { 209 | panic(r) 210 | } 211 | pc++ 212 | } 213 | }() 214 | vs := make([]*backend.View, 0, len(t.layout)) 215 | l := make([]layout, 0, len(t.layout)) 216 | for k, v := range t.layout { 217 | vs = append(vs, k) 218 | l = append(l, v) 219 | } 220 | for i, v := range vs { 221 | t.renderView(w, v, l[i]) 222 | } 223 | // runes := []rune(t.status_message) 224 | } 225 | 226 | // key HandleFunc for the http /key endpoint. This only happens if the client 227 | // doesn't support websockets. 228 | func (t *tbfe) key(w http.ResponseWriter, req *http.Request) { 229 | log.Debug("key: %s", req) 230 | kc := req.FormValue("keyCode") 231 | var kp keys.KeyPress 232 | v, _ := strconv.ParseInt(kc, 10, 32) 233 | 234 | if req.FormValue("altKey") == "true" { 235 | kp.Alt = true 236 | } 237 | if req.FormValue("ctrlKey") == "true" { 238 | kp.Ctrl = true 239 | } 240 | if req.FormValue("metaKey") == "true" { 241 | kp.Super = true 242 | } 243 | if req.FormValue("shiftKey") == "true" { 244 | kp.Shift = true 245 | } 246 | 247 | if !kp.Shift { 248 | v = int64(unicode.ToLower(rune(v))) 249 | } 250 | kp.Key = keys.Key(v) 251 | kp.Text = string(v) 252 | backend.GetEditor().HandleInput(kp) 253 | } 254 | 255 | func (t *tbfe) view(w http.ResponseWriter, req *http.Request) { 256 | log.Debug("view: %s", req) 257 | if t.dirty { 258 | t.dirty = false 259 | t.render(w) 260 | } else { 261 | w.WriteHeader(404) 262 | } 263 | } 264 | 265 | func (t *tbfe) theme(w http.ResponseWriter, req *http.Request) { 266 | log.Debug("theme: %s", req) 267 | 268 | reqpath, _ := url.QueryUnescape(req.RequestURI) 269 | 270 | // Make sure the URL starts with "/themes/" 271 | // Don't allow ".." in URLs 272 | if !strings.HasPrefix(reqpath, "/themes/") || strings.Index(reqpath, "..") != -1 { 273 | w.WriteHeader(404) 274 | return 275 | } 276 | 277 | filepath := path.Join(backend.LIME_PACKAGES_PATH, reqpath) 278 | 279 | exists := false 280 | if s, err := os.Stat(filepath); err == nil { 281 | if !s.IsDir() { 282 | exists = true 283 | } 284 | } 285 | 286 | if exists { 287 | fi, err := os.Open(filepath) 288 | if err != nil { 289 | w.WriteHeader(500) 290 | log.Error(err) 291 | return 292 | } 293 | 294 | defer fi.Close() 295 | 296 | io.Copy(w, fi) 297 | } else { 298 | w.WriteHeader(404) 299 | } 300 | } 301 | 302 | func (t *tbfe) ServeHTTP(w http.ResponseWriter, req *http.Request) { 303 | s := time.Now() 304 | w.Header().Set("Content-Type", "text/html") 305 | log.Debug("Serving client: %s", req) 306 | 307 | c := scheme.Spice(&render.ViewRegions{}) 308 | 309 | html, err := ioutil.ReadFile("index.html") 310 | if err != nil { 311 | w.WriteHeader(404) 312 | panic(err) 313 | } 314 | 315 | r := strings.NewReplacer("{{foregroundColor}}", htmlcol(c.Foreground), "{{backgroundColor}}", htmlcol(c.Background)) 316 | r.WriteString(w, string(html)) 317 | 318 | log.Debug("Done serving client: %s", time.Since(s)) 319 | } 320 | 321 | var clients []*websocket.Conn 322 | 323 | func (t *tbfe) WebsocketServer(ws *websocket.Conn) { 324 | clients = append(clients, ws) 325 | 326 | // Send status message 327 | if t.status_message != "" { 328 | websocket.JSON.Send(ws, map[string]string{"type": "statusMessage", "msg": t.status_message}) 329 | } 330 | 331 | // Send cursor position 332 | websocket.JSON.Send(ws, t.GetSelectionMessage(backend.GetEditor().ActiveWindow().ActiveView())) 333 | 334 | // Send editor content 335 | var buf bytes.Buffer 336 | t.render(bufio.NewWriter(&buf)) 337 | websocket.Message.Send(ws, buf.Bytes()) 338 | buf.Reset() 339 | 340 | var data map[string]interface{} 341 | var kp keys.KeyPress 342 | for { 343 | err := websocket.JSON.Receive(ws, &data) 344 | if err != nil { 345 | log.Error(err) 346 | return 347 | } 348 | //log.LogDebug("Received: %s", data) 349 | 350 | msgType := data["type"].(string) 351 | 352 | if msgType == "key" { 353 | kp.Alt = data["altKey"].(bool) 354 | kp.Ctrl = data["ctrlKey"].(bool) 355 | kp.Super = data["metaKey"].(bool) 356 | kp.Shift = data["shiftKey"].(bool) 357 | 358 | if keyName, ok := data["key"].(string); ok { 359 | if utf8.RuneCountInString(keyName) == 1 { // One char 360 | r, _ := utf8.DecodeRuneInString(keyName) 361 | kp.Key = keys.Key(int64(r)) 362 | } else { 363 | // TODO: automatic lookup instead of this manual lookup 364 | // See https://github.com/limetext/lime/pull/421/files#r19269236 365 | keymap := map[string]keys.Key{ 366 | "ArrowLeft": keys.Left, 367 | "ArrowUp": keys.Up, 368 | "ArrowRight": keys.Right, 369 | "ArrowDown": keys.Down, 370 | "Left": keys.Left, 371 | "Up": keys.Up, 372 | "Right": keys.Right, 373 | "Down": keys.Down, 374 | "Enter": keys.Enter, 375 | "Escape": keys.Escape, 376 | "Backspace": keys.Backspace, 377 | "Delete": keys.Delete, 378 | "Del": keys.Delete, // Deprecated: some old browsers still use "Del" instead of "Delete" 379 | "KeypadEnter": keys.KeypadEnter, 380 | "F1": keys.F1, 381 | "F2": keys.F2, 382 | "F3": keys.F3, 383 | "F4": keys.F4, 384 | "F5": keys.F5, 385 | "F6": keys.F6, 386 | "F7": keys.F7, 387 | "F8": keys.F8, 388 | "F9": keys.F9, 389 | "F10": keys.F10, 390 | "F11": keys.F11, 391 | "F12": keys.F12, 392 | "Insert": keys.Insert, 393 | "PageUp": keys.PageUp, 394 | "PageDown": keys.PageDown, 395 | "Home": keys.Home, 396 | "End": keys.End, 397 | "Break": keys.Break, 398 | } 399 | 400 | if key, ok := keymap[keyName]; ok { 401 | kp.Key = key 402 | } else { 403 | log.Debug("Unknown key: %s", keyName) 404 | continue 405 | } 406 | } 407 | } else { 408 | v := int64(data["keyCode"].(float64)) 409 | if !kp.Shift { 410 | v = int64(unicode.ToLower(rune(v))) 411 | } 412 | kp.Key = keys.Key(v) 413 | kp.Text = string(v) 414 | } 415 | 416 | backend.GetEditor().HandleInput(kp) 417 | } else if msgType == "command" { 418 | command := data["name"].(string) 419 | //args := data["args"].([]string) //TODO: add arguments support 420 | 421 | ed := backend.GetEditor() 422 | go ed.RunCommand(command, make(backend.Args)) 423 | } else { 424 | log.Info("Unhandled message type: %s", msgType) 425 | } 426 | } 427 | } 428 | 429 | func (t *tbfe) BroadcastData(data map[string]interface{}) { 430 | for _, ws := range clients { 431 | websocket.JSON.Send(ws, data) 432 | } 433 | } 434 | 435 | func (t *tbfe) SetDirty() { 436 | t.dirty = true 437 | 438 | var buf bytes.Buffer 439 | t.render(bufio.NewWriter(&buf)) 440 | for _, ws := range clients { 441 | websocket.Message.Send(ws, buf.Bytes()) 442 | } 443 | } 444 | 445 | func (t *tbfe) GetSelectionMessage(v *backend.View) map[string]interface{} { 446 | return map[string]interface{}{ 447 | "type": "selection", 448 | "sel": v.Sel().Regions(), 449 | } 450 | } 451 | 452 | func (t *tbfe) loop() { 453 | backend.OnNew.Add(func(v *backend.View) { 454 | v.Settings().AddOnChange("lime.frontend.html.render", func(name string) { 455 | if name != "lime.syntax.updated" { 456 | return 457 | } 458 | t.SetDirty() 459 | }) 460 | }) 461 | // TODO: maybe not useful? 462 | /*backend.OnModified.Add(func(v *backend.View) { 463 | t.SetDirty() 464 | })*/ 465 | backend.OnSelectionModified.Add(func(v *backend.View) { 466 | t.BroadcastData(t.GetSelectionMessage(v)) 467 | }) 468 | 469 | ed := backend.GetEditor() 470 | ed.SetFrontend(t) 471 | ed.LogInput(false) 472 | ed.LogCommands(false) 473 | c := ed.Console() 474 | if sc, err := textmate.LoadTheme(path.Join(backend.LIME_PACKAGES_PATH, "themes", "TextMate-Themes", "Monokai.tmTheme")); err != nil { 475 | log.Error(err) 476 | } else { 477 | scheme = sc 478 | } 479 | 480 | defer func() { 481 | fmt.Println(util.Prof) 482 | }() 483 | 484 | w := ed.NewWindow() 485 | v := w.OpenFile("main.go", 0) 486 | //v.Settings().Set("trace", true) 487 | v.Settings().Set("syntax", path.Join(backend.LIME_PACKAGES_PATH, "go.tmbundle", "Syntaxes", "Go.tmLanguage")) 488 | c.Buffer().AddObserver(t) 489 | 490 | sel := v.Sel() 491 | sel.Clear() 492 | // end := v.Buffer().Size() - 2 493 | sel.Add(Region{0, 0}) 494 | // sel.Add(Region{end - 22, end - 22}) 495 | // sel.Add(Region{end - 16, end - 20}) 496 | // sel.Add(Region{end - 13, end - 10}) 497 | 498 | { 499 | w, h := 800, 600 500 | t.lock.Lock() 501 | t.layout[v] = layout{0, 0, w, h - console_height - 1, Region{}, 0} 502 | t.layout[c] = layout{0, h - console_height + 1, w, console_height - 5, Region{}, 0} 503 | t.lock.Unlock() 504 | t.Show(v, Region{1, 1}) 505 | } 506 | t.Show(v, Region{100, 100}) 507 | t.Show(v, Region{1, 1}) 508 | 509 | go ed.Init() 510 | log.Debug("Serving on port %d", *port) 511 | http.HandleFunc("/", t.ServeHTTP) 512 | http.HandleFunc("/view", t.view) 513 | http.HandleFunc("/key", t.key) 514 | http.HandleFunc("/themes/", t.theme) 515 | http.Handle("/ws", websocket.Handler(t.WebsocketServer)) 516 | if err := http.ListenAndServe(fmt.Sprintf("localhost:%d", *port), nil); err != nil { 517 | log.Error("Error serving: %s", err) 518 | } 519 | log.Debug("Done") 520 | } 521 | 522 | func main() { 523 | flag.Parse() 524 | log.AddFilter("file", log.FINEST, log.NewConsoleLogWriter()) 525 | defer func() { 526 | py.NewLock() 527 | py.Finalize() 528 | }() 529 | 530 | var t tbfe 531 | t.dorender = make(chan bool, render_chan_len) 532 | t.layout = make(map[*backend.View]layout) 533 | t.loop() 534 | } 535 | -------------------------------------------------------------------------------- /main/main_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The lime Authors. 2 | // Use of this source code is governed by a 2-clause 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | package main 6 | -------------------------------------------------------------------------------- /tasks/local/ci/build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source "$(dirname -- "$0")/../../general/ci/setup.sh" 4 | 5 | ret=0 6 | 7 | fold_start "build" "build" 8 | build "main" 9 | let ret=$ret+$build_result 10 | fold_end "build" 11 | 12 | exit $ret 13 | --------------------------------------------------------------------------------