Is it possible to use tk to create a text editor that can support syntax highlighting, autocomplete and even can be later extended to be an IDE for a specific language?
I found tkinter widget, but not sure if it can support that or not?
I think if a widget can do some processing on the text while the user is writing it, then it can used for this purpose.
Absolutely. The tkinter text widget is remarkably powerful. Everything you mentioned can be done, and more. You can also implement code folding, embedded images, hyperlinks, undo, etc.
Here are some answers to related questions you might find helpful:
you can use pygments for syntax highlighting. This answer has a tiny example: https://stackoverflow.com/a/11551277
line numbers and a custom event that fires whenever the widget changes is mentioned in this answer: https://stackoverflow.com/a/16375233
adding a search function is partially covered in this answer: https://stackoverflow.com/a/3781773
Not to be repetitive, since Bryan Oakley already answered this, but yes. And he's right. The text widget is extremely powerful. I've never seen another text widget that matches its breadth of features.
Tkinter is the most convenient GUI library I've ever found for making a text editor. Actually, I've been making one, myself, for a while. Are you interested in making one or are you looking for one already made with Tkinter?
For me, syntax highlighting and autocomplete aren't the most important features in a text editor. I care more about quick/convenient file/project access, launching/compiling/running programs, Unicode or special character input, widget color schemes, navigation key-bindings, tabs, and having all kinds of shortcuts for various wild tools that I like to make my life easier (and more fun). So, I'm actually just starting on syntax highlighting now (after already having done most of the other stuff). But, yes, syntax highlighting can be done in Tkinter.
Really, though, a lot of the features you might want in a text editor don't even require much to do with the GUI library. For instance, making it recognize what kind of file you're editing, so you can run your file with the correct program (or compile it with the correct compiler). That really has little to do with Tkinter.
Let me know if you want to chat in real-time about text editors.
The IDE that comes with Python, IDLE, seems to be written with Tkinter, too. Looking at the source code is sometimes helpful, but they tend to do things in a different way than I would personally recommend, although I'm sure some people like it more than the way I like things.
There are a few drawbacks to Tkinter, but they're better than the drawbacks I've seen with other GUI libraries, for my purposes. Some things require more work, but most also seem to offer more flexibility. Some things require less work, too. Impressively, Tkinter doesn't seem to have a lot of bugs, and most of the ones that exist can be programmed around. It's quite robust. It gets a bad rap, sometimes, for not having native widgets and not rendering fonts a certain way, but don't listen to people. The widgets are fine, whether or not they're native, and the fonts look great. If there ever was a problem with the fonts, I think they fixed it. Tell me if I'm wrong. Mine look perfect (exactly as they do in LibreOffice, if not better). Besides, the perks of Tkinter shouldn't be ignored. Tkinter is awesome.
Python's help() method will be your friend. Use it on classes and modules.
One of the best things about Tkinter is that it pretty much comes with Python. So, unlike something like WxPython (which isn't even on 3.x, although they're making something for it with another name), Tkinter will likely automatically be supported for all future releases of Python (until if/when they decide to replace it with something else—and I don't know that they will, unless they find something totally awesome). Plus, it's not a huge download.
Anyway, to get started, you'll want to learn about marks (especially the built-in ones) and tags. You'll likely use those a lot for a lot of stuff. These are important for accessing specific areas of text in your widget and doing things to them.
INSERT is a string, 'insert'. But, it's also a mark. Marks are variable indexes to mark a position. The 'insert' mark represents the index in your text widget where your text insert is. The beginning of your document is the index "1.0" not "0.0". 1 is row 1. 0 is character 0. I don't believe there's a mark for the beginning. You just use the index. The mark for the end is END (which is a string, 'end'). 'sel.first' and 'sel.last' represent the indexes at the beginning and end of selected text. SEL (or 'sel') is a tag. Tags are kind of like HTML tags in that they mark the beginning and end of things (and all the text in between). You can make your own tags to add text styles (like bold and italics, or just highlights, which could be useful for syntax highlighting). You can check a range of text to see if it has a certain tag. For instance,
SEL in self.myTextWidget.tag_names(INSERT)
Will return True if the character directly after (that is, at) the text insert is selected.
For marks, you can use some handy notation to get some handy index locations. For instance "insert wordstart" will give you the index for the beginning of whatever word the 'insert' mark is on. "insert+2c" will give you the position two characters after the insert. Anyway, there's lots of stuff like that.
If you're making a cross-platform application, you'll want to know that a few of the events are different on different platforms. So, check and make sure they all work.
You'll also want to realize that although some of the standard keyboard shortcuts in the text widget don't work (like Control-a doesn't select all) there actually are shortcuts. They're just different shortcuts. However, you can override them and make your own pretty easily:
…
#We're doing both a and A to make sure it works properly when caps-lock is on.
#Control-Shift-a is different from Control-A despite how it may seem.
self.myTextWidget.bind("<Control-a>", self.select_all)
self.myTextWidget.bind("<Control-A>", self.select_all)
def select_all(self, event):
self.myTextWidget.tag_add("sel", "1.0", "end-1c") #END actually goes beyond the end of the text, adding a new line (so, I subtract a character).
return "break" #If you want to override the default binding, you need to return "break"
Tkinter is fairly maliable, it can be used to accomplish a number of tasks on its own. I've actually made my own mini text editor using tkinter in python 2.7. It doesn't have the advanced functionality yet though. But I think this would be a good basis for your idea. Make sure you have python2.7 installed.
from Tkinter import *
import tkFileDialog
class Files(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
self.parent = parent
self.initUI()
def initUI(self):
self.parent.title("File dialog")
self.pack(fill=BOTH, expand=1)
menubar = Menu(self.parent)
self.parent.config(menu=menubar)
fileMenu = Menu(menubar)
fileMenu.add_command(label="Save", command = self.save_command)
fileMenu.add_command(label="Open", command = self.onOpen)
menubar.add_cascade(label="File", menu=fileMenu)
self.txt = Text(self)
self.txt.pack(fill=BOTH, expand=1)
def onOpen(self):
ftypes = [('Python files', '*.py'), ('All files', '*')]
dlg = tkFileDialog.Open(self, filetypes = ftypes)
fl = dlg.show()
if fl != '':
text = self.readFile(fl)
self.txt.insert(END, text)
def readFile(self, filename):
f = open(filename, "r")
text = f.read()
return text
def save_command(self):
file = tkFileDialog.asksaveasfile(mode='w')
if file != None:
data = self.txt.get('1.0', END+'-1c')
file.write(data)
file.close()
root = Tk()
top = Frame(root)
top.pack(fill=BOTH, expand=1)
def build():
l = Label(top, text="test phrase")
l.pack(side="left")
ent = Entry(top)
ent.pack(side="left")
bottom = Frame(root)
bottom.pack()
ex = Files(root)
ex.pack(side="bottom")
root.geometry("300x250+300+300")
root.mainloop()
Related
How to highlight variables in sublime text 3? like in netbeans
Your question is not very clear, but here are some options. First, if you're just trying to get variables highlighted differently, you'll need a color scheme with more options than the default Monokai. There are many available on Package Control, but one in particular that I know will work (since I'm its author) is Neon:
You can use the excellent tmTheme Editor to see how this or hundreds of other themes will look (sort of) in different languages. (I say "sort of" because the highlighting engine used on the website is different than the one in Sublime, so there will be some differences. Overall it's pretty good, though.)
On the other hand, if you're trying to highlight all the instances of the $page variable, you'll have to do two things. First, double-click on $page to select it. Then, select Find -> Quick Find All (or use its keyboard shortcut) to select all the instances of $page in the document:
The gutter icons and colored underlines are from the BracketHighlighter plugin
Unfortunately, this is the only way to get this to work when using PHP and other languages like JavaScript that denote variables with a $ or other symbol. If we were to use Python, for example, you could just double-click on page and it would look like so:
As you can see, all the other instances of page have boxes around them. This behavior is hard-coded into Sublime, so while it can be turned on and off, it can't be modified or told to recognize other characters in any way.
Good luck!
So, a few months back I made a small GUI for handling NPCs in a roleplaying campaign I was running. I haven't touched in since then, except that now I need it! Tomorrow, in fact...
I have a few odd error... Loading the GUI seems to work fine, but when I start to press buttons the troubles start. It seemed, at first, that it the script was very slow, which it shouldn't be, calling a two line dice function on a button press. I accidentally figured out that when I hover the mouse over the "close/minimize window" buttons (not in the GUI, but in the OS), the button would update with the result of the button press.
The same thing happens with a listbox I have: choosing an item may or may not select the item straight away (but hovering over the close/minimize updates it), and the results of the selection may or may not show. The results is in fact weirder: selecting a listbox item is supposed to get info from the selected item and print it in another frame. Even if the selection itself is fine without hovering, the printed text is somehow "clipped", showing only an area seeming to cover an arbitrarily sized square of text... Remedied by hovering, of course. The rest of the GUI have the exact same problems.
I have no clue what is going on here. The script was written on another computer, but that was also a Mac running the same OSX version (Mavericks), and it was a MUCH slower computer. This script shouldn't need any sort of advanced specs, though! I'm guessing it's something wrong with migrating to the new computer and the various version of different software? I'll paste the script down below, in case that'll help somehow.
Any help would be greatly appreciated, especially if it comes before the next epic campaign of Superheroes starts tomorrow afternoon! =P
[UPDATE]:
It was some time ago, but I still would like to have this problem solved. I've reduced my script to just a simple button, and the problem persists: clicking the button, even though there is no function or anything associated with it, only results in the frozen "button-clicked"-colour (i.e. light blue on OSX Yosemite), and I have to hover my mouse pointer over the close/minimize/etc. buttons in the top left corner to make it go back to "idle-button"-colour (i.e. grey).
#!/usr/bin/python
import tkinter as tk
root = tk.Tk()
test = tk.Button(root, text='test')
test.pack()
root.mainloop()
So, the problem obviously isn't with any of my "downstream" scripting, but something with the module or my way of calling it. Calling the script for the Terminal doesn't give me any error messages, and the problem is still there. Any ideas? It would be really, really good to get to the bottom of this problem!
I had the same problem when using Tk 8.5.13 on Mac OS X Sierra (10.12.3) with Python and IDLE v3.6.0.
Upgrading to TCL/Tk 8.5.18.0 as recommended on the Python Software Foundation page https://www.python.org/download/mac/tcltk/#activetcl-8-5-18-0 seemed to do the trick. This was the recommended version for my edition of the OS.
The interface I was building starting responding as I would expect, i.e. straight away when one of the controls was used. The only reservation I have so far is that normal buttons don't seem to have any sort of animation now, although the buttons do actually work.
-S.
I use https://github.com/nsf/gocode in conjunction with https://github.com/Shougo/neocomplete.vim for my Go autocompletion.
It works really well, except for one little thing. When I type something like
fmt.pri
I get autocomplete option like so:
fmt.Println(a ...interface{}) (n int, err error)
Since I'm new to Go, this is super helpful, because now I know what arguments the method takes, what are the types, and also what does it return.
Unfortunately, as soon as I write past bracket, the information is gone.
fmt.Println(
So on more complex methods that I'm using for first time, I'm stuck, and have to jump to source definition, or run godoc.
It would be much easier to have that information available somewhere, preferably on the bottom of Vim where the command/status line is.
Does anyone know how such a thing could be achieved?
Preview window breaks my Vim so it's not an option.
I use autocomplpop (well, my fork of it) and it has a feature where it does a small split window with the completion text in it that sticks around. It does this when you set...
let g:acp_completeoptPreview = 1
I'm sure neocomplcache has a similar feature. Glancing through its documentation it discusses a preview window in several places. Search for preview in its docs and see what you can find.
This is ultimately controlled by 'completeopt' containing 'preview' (:h completeopt). The auto-completing packages often set these values as part of their functionality, which is why with autocomplpop you need to use its option to control it instead of just doing 'completeopt+=preview'.
I am just getting into the WMD editor varieties out there :) Of all of them I like MarkEdit because of the ability to modify the menu items quite easily, but it doesn't do a couple of things that I really like in a couple of forks, for example, http://github.com/openlibrary/wmd.
Ideally my perfect WMD editor would:
create list items automatically on pressing return when in a list block (not implemented in MarkEdit)
allow the removal of menu items (implemented in MarkEdit)
the cheat of making a newline without the need for two spaces (implemented in MarkEdit)
As point 1. and 2. are both quite important to me, but I imagine 1. is harder to implement, I may have to use the forks such as the openlibrary-wmd rather than my preferred choice of MarkEdit.
How can I modify the menu buttons in a fork like openlibrary-wmd? The configuration function no longer seems to work as described for the original.
I recently used the markitup editor and found the skin implementation pretty useful. Each skin has its own images and styles which you can easily override if you need to. The editor is also jQuery-driven, which is nice if you're used to that syntax. Check it out
Does watir's browser.text.include? count text inside invisible divs? If so, how to search only for visible text?
I put all the instructions into the html from the beginning and use jQuery to hide and unhide the relevant parts.
How can I use watir's waiter to wait for only text that is visible?
My problem is, that the waiter always returns true, even before I have made visible a certain text.
Don't use Watir's text method. It is very quick and dirty, and has lots of misgivings, many not even related to this issue about visible text. Solid Watir test developers will avoid it. I almost never use it myself, and only when I am doing something extremely quick and dirty. Also, it is implemented differently with different browsers.
Instead you should access the text you care about in terms of the actual element that it is in. You should reference the div or whatever.
What's wrong with:
text_from_all_my_visible_divs = br.div(:id, 'divs I care about').divs.select do |div|
text_i_care_about(div) && div.visible?
end
def text_i_care_about(div)
div.text =~ /regexp/
end
.visible? is in the unit tests, it's official, don't be scared of it :)
Alan
include? sees all text, not just visible text. See WTR-433 ticket for details.
There is Element#visible? method that is not officially supported (as far as I know).
What are you trying to do? If you have a lot of text on the page, and want to show only some of it, you could put the text in a few divs and then see if the div is visible.