func (p *plugin) loadPlugin() { fi := p.Get().([]os.FileInfo) for _, f := range fi { fn := f.Name() s, err := py.NewUnicode(path.Base(p.Name()) + "." + fn[:len(fn)-3]) if err != nil { log.Error(err) return } if r, err := p.m.Base().CallMethodObjArgs("reload_plugin", s); err != nil { log.Error(err) } else if r != nil { r.Decref() } } }
// Will load view settings respect to current syntax // e.g if current syntax is Python settings order will be: // Packages/Python/Python.sublime-settings // Packages/User/Python.sublime-settings // <Buffer Specific Settings> func (v *View) loadSettings() { syntax := v.Settings().Get("syntax", "").(string) if syntax == "" { v.Settings().SetParent(v.window) return } defSettings, usrSettings := &HasSettings{}, &HasSettings{} defSettings.Settings().SetParent(v.window) usrSettings.Settings().SetParent(defSettings) v.Settings().SetParent(usrSettings) ed := GetEditor() if r, err := rubex.Compile(`([A-Za-z]+?)\.(?:[^.]+)$`); err != nil { log.Error(err) return } else if s := r.FindStringSubmatch(syntax); s != nil { p := path.Join(LIME_PACKAGES_PATH, s[1], s[1]+".sublime-settings") ed.load(packages.NewPacket(p, defSettings.Settings())) p = path.Join(LIME_USER_PACKAGES_PATH, s[1]+".sublime-settings") ed.load(packages.NewPacket(p, usrSettings.Settings())) } }
func (c *CommandGlue) callBool(name string, args backend.Args) bool { gs := py.GilState_Ensure() defer gs.Release() var ( pyargs, r py.Object err error ) if pyargs, err = c.CreatePyArgs(args); err != nil { log.Error(err) return false } defer pyargs.Decref() if r, err = c.CallMethodObjArgs(name, pyargs); err != nil { log.Error(err) return true } defer r.Decref() if r, ok := r.(*py.Bool); ok { return r.Bool() } return true }
func (c *CommandGlue) Description() string { gs := py.GilState_Ensure() defer gs.Release() var ( pyargs, r py.Object err error ) if pyargs, err = c.CreatePyArgs(c.args); err != nil { log.Error(err) return "" } defer pyargs.Decref() if r, err = c.CallMethodObjArgs("description", pyargs); err != nil { log.Error(err) return "" } defer r.Decref() if r, ok := r.(*py.Unicode); ok { return r.String() } return "" }
func (v *View) Find(pat string, pos int, flags int) Region { r := Region{pos, v.buffer.Size()} s := v.buffer.Substr(r) if flags&LITERAL != 0 { pat = "\\Q" + pat } if flags&IGNORECASE != 0 { pat = "(?im)" + pat } else { pat = "(?m)" + pat } // Using regexp instead of rubex because rubex doesn't // support flag for treating pattern as a literal text if re, err := regexp.Compile(pat); err != nil { log.Error(err) } else if loc := re.FindStringIndex(s); loc != nil { return Region{pos + loc[0], pos + loc[1]} } return Region{-1, -1} }
func (h *DummyFrontend) ErrorMessage(msg string) { log.Error(msg) }
func TestSublime(t *testing.T) { ed := backend.GetEditor() ed.SetClipboardFuncs(func(n string) (err error) { dummyClipboard = n return nil }, func() (string, error) { return dummyClipboard, nil }) ed.Init() ed.Console().Buffer().AddObserver(&consoleObserver{T: t}) w := ed.NewWindow() l := py.NewLock() py.AddToPath("testdata") py.AddToPath("testdata/plugins") if m, err := py.Import("sublime_plugin"); err != nil { t.Fatal(err) } else { plugins := packages.ScanPlugins("testdata/", ".py") for _, p := range plugins { newPlugin(p, m) } } subl, err := py.Import("sublime") if err != nil { t.Fatal(err) } if w, err := _windowClass.Alloc(1); err != nil { t.Fatal(err) } else { (w.(*Window)).data = &backend.Window{} subl.AddObject("test_window", w) } // Testing plugin reload data := []byte(`import sublime, sublime_plugin class TestToxt(sublime_plugin.TextCommand): def run(self, edit): print("my view's id is: %d" % self.view.id()) self.view.insert(edit, 0, "Tada") `) if err := ioutil.WriteFile("testdata/plugins/reload.py", data, 0644); err != nil { t.Fatalf("Couldn't write testdata/plugins/reload.py: %s", err) } defer os.Remove("testdata/plugins/reload.py") time.Sleep(time.Millisecond * 50) if dir, err := os.Open("testdata"); err != nil { t.Error(err) } else if files, err := dir.Readdirnames(0); err != nil { t.Error(err) } else { for _, fn := range files { // FIXME: Skip reload_test.py to work around #531 on OSX. if fn == "reload_test.py" && ed.Platform() == "darwin" { continue } if filepath.Ext(fn) == ".py" { log.Debug("Running %s", fn) if _, err := py.Import(fn[:len(fn)-3]); err != nil { log.Error(err) t.Error(err) } else { log.Debug("Ran %s", fn) } } } } var f func(indent string, v py.Object, buf *bytes.Buffer) f = func(indent string, v py.Object, buf *bytes.Buffer) { b := v.Base() if dir, err := b.Dir(); err != nil { t.Error(err) } else { if l, ok := dir.(*py.List); ok { sl := l.Slice() if indent == "" { for _, v2 := range sl { if item, err := b.GetAttr(v2); err != nil { t.Error(err) } else { ty := item.Type() line := fmt.Sprintf("%s%s\n", indent, v2) buf.WriteString(line) if ty == py.TypeType { f(indent+"\t", item, buf) } item.Decref() } } } else { for _, v2 := range sl { buf.WriteString(fmt.Sprintf("%s%s\n", indent, v2)) } } } else { ty := dir.Type() t.Error("Unexpected type:", ty) } dir.Decref() } } buf := bytes.NewBuffer(nil) f("", subl, buf) l.Unlock() const expfile = "testdata/api.txt" if d, err := ioutil.ReadFile(expfile); err != nil { if err := ioutil.WriteFile(expfile, buf.Bytes(), 0644); err != nil { t.Error(err) } } else if diff := util.Diff(string(d), buf.String()); diff != "" { t.Error(diff) } ed.LogCommands(true) tests := []string{ "state", "registers", "settings", "constants", "registers", "cmd_data", "marks", } for _, test := range tests { ed.CommandHandler().RunWindowCommand(w, "vintage_ex_run_data_file_based_tests", backend.Args{"suite_name": test}) } for _, w := range ed.Windows() { for _, v := range w.Views() { if strings.HasSuffix(v.Buffer().FileName(), "sample.txt") { continue } if strings.Index(v.Buffer().Substr(text.Region{A: 0, B: v.Buffer().Size()}), "FAILED") != -1 { t.Error(v.Buffer()) } } } var v *backend.View for _, v2 := range w.Views() { if v == nil || v2.Buffer().Size() > v.Buffer().Size() { v = v2 } } }
// Classifies point, returning a bitwise OR of zero or more of defined flags func (v *View) Classify(point int) (res int) { var a, b string = "", "" ws := v.Settings().Get("word_separators", DEFAULT_SEPARATORS).(string) if point > 0 { a = v.buffer.Substr(Region{point - 1, point}) } if point < v.buffer.Size() { b = v.buffer.Substr(Region{point, point + 1}) } // Out of range if v.buffer.Size() == 0 || point < 0 || point > v.buffer.Size() { res = 3520 return } // If before and after the point are separators return 0 if re, err := rubex.Compile(ws); err != nil { log.Error(err) } else if a == b && re.MatchString(a) { res = 0 return } // SubWord start & end if re, err := rubex.Compile("[A-Z]"); err != nil { log.Error(err) } else { if re.MatchString(b) && !re.MatchString(a) { res |= CLASS_SUB_WORD_START res |= CLASS_SUB_WORD_END } } if a == "_" && b != "_" { res |= CLASS_SUB_WORD_START } if b == "_" && a != "_" { res |= CLASS_SUB_WORD_END } // Punc start & end if re, err := rubex.Compile(ws); err != nil { log.Error(err) } else { // Why ws != ""? See https://github.com/gbbr/textmate/vendor/limetext/rubex/issues/2 if ((re.MatchString(b) && ws != "") || b == "") && !(re.MatchString(a) && ws != "") { res |= CLASS_PUNCTUATION_START } if ((re.MatchString(a) && ws != "") || a == "") && !(re.MatchString(b) && ws != "") { res |= CLASS_PUNCTUATION_END } // Word start & end if re1, err := rubex.Compile("\\w"); err != nil { log.Error(err) } else if re2, err := rubex.Compile("\\s"); err != nil { log.Error(err) } else { if re1.MatchString(b) && ((re.MatchString(a) && ws != "") || re2.MatchString(a) || a == "") { res |= CLASS_WORD_START } if re1.MatchString(a) && ((re.MatchString(b) && ws != "") || re2.MatchString(b) || b == "") { res |= CLASS_WORD_END } } } // Line start & end if a == "\n" || a == "" { res |= CLASS_LINE_START } if b == "\n" || b == "" { res |= CLASS_LINE_END if ws == "" { res |= CLASS_WORD_END } } // Empty line if (a == "\n" && b == "\n") || (a == "" && b == "") { res |= CLASS_EMPTY_LINE } // Middle word if re, err := rubex.Compile("\\w"); err != nil { log.Error(err) } else { if re.MatchString(a) && re.MatchString(b) { res |= CLASS_MIDDLE_WORD } } // Word start & end with punc if re, err := rubex.Compile("\\s"); err != nil { log.Error(err) } else { if (res&CLASS_PUNCTUATION_START != 0) && (re.MatchString(a) || a == "") { res |= CLASS_WORD_START_WITH_PUNCTUATION } if (res&CLASS_PUNCTUATION_END != 0) && (re.MatchString(b) || b == "") { res |= CLASS_WORD_END_WITH_PUNCTUATION } } // Openning & closing parentheses if re, err := rubex.Compile("[(\\[{]"); err != nil { log.Error(err) } else { if re.MatchString(a) || re.MatchString(b) { res |= CLASS_OPENING_PARENTHESIS } } if re, err := rubex.Compile("[)\\]}]"); err != nil { log.Error(err) } else { if re.MatchString(a) || re.MatchString(b) { res |= CLASS_CLOSING_PARENTHESIS } } // TODO: isn't this a bug? what's the relation between // ',' and parentheses if a == "," { res |= CLASS_OPENING_PARENTHESIS } if b == "," { res |= CLASS_CLOSING_PARENTHESIS } return }