Add closing bracket on press opening bracket - python

Alright, so in VSCode, when you use an opening bracket, it automatically uses a closing bracket. Instead, I want this to be angle brackets. How would I do this? For example:
Presses: <
Output: <>
Thanks in advance!
Edit: I'm going to clarify this. I'm doing this in a Tkinter text widget. So pressing < will insert a >. Soory for the lack of clarity.

A really simple solution is to bind a function to <KeyRelease>, since that will fire after the default bindings have actually inserted the character into the widget. Or, you could bind to <KeyPress> and manage inserting both the start original character and its closing character.
Let's start by defining a dictionary which defines which characters have matching characters. In this case we'll just use {} and <> for simplicity:
matched_pairs = {"{": "}", "<": ">"}
Next, lets define a function which examines the event to see if it is for a character which in in our dictionary. If we find a matching character we do two things: we insert the matching character, then move the insertion point back one so that the insertion character is between the pairs of characters.
def maybe_insert_matching_pair(event):
matching = matched_pairs.get(event.char, None)
if matching:
event.widget.insert("insert", matching)
event.widget.mark_set("insert", "insert-1c")
Finally, let's bind this function to every keypress, though you could also bind it to only the keys that you know have matching pairs.
the_text_widget.bind('<KeyRelease>', maybe_insert_matching_pair)

Related

Tag everything in a row after a certain character [tkinter Text widget]

As a coding challenge, I've been building a rich-text editor. So far, I've made working save/save as/load systems and working Headers. But, when you save as .txt all the heading data is lost. So I've been thinking about doing a system that relies on '#' to mark headers (basically syntax highlighting)(#-H1,##-H2,###-H3...). I've looked around, and haven't found anything of the sort. So far, I use this as my system of headings:
editor.tag_configure('heading7', font=heading7_font)
removeTags()
editor.tag_add('heading7', SEL_FIRST, SEL_LAST)
*heading7_font=("Consolas Bold", 16), removeTags(): lists through tags and removes all.
Basically, you just select on an OptionMenu if you wish to change the fontsize (or use a certain bind). This question is problably too vague, but, I would very much like so direction or an answer.
Here's the code of my entire project (YES, I know I'm not using classes, and it's a jittery mess, but, I'm going to work on that later): https://pastebin.com/wthVT6q4 (Here's the stylesheet variables: https://pastebin.com/WrX4EDKM)
You can use the text widget search method to search for a string or a pattern. Then it's just a matter of applying the tag to the results.
This is how it is documented in the Text class:
search(self, pattern, index, stopindex=None, forwards=None, backwards=None, exact=None, regexp=None, nocase=None, count=None, elide=None)
Search PATTERN beginning from INDEX until STOPINDEX.
Return the index of the first character of a match or an
empty string.
As you can see, you can use the search method to search on a regular expression. Since you won't always know the length of the matched text, you can specify an IntVar to be given the count of the matching characters.
For example, to search for a line that begins with ## you can do something like this:
count_var = tk.IntVar()
index = editor.search(r'## .*', "1.0", "end", count=count_var, regexp=True)
With that, you can use index as the start of the range, and "{} +{} chars".format(index, count_var.get()) for the end of the range. Or, use "{} lineend".format(index)" to add the highlight to the entire line.
If you only want to highlight the characters after ##, you can adjust index in a similar way: "{}+{}chars".format(index, 3)
Note: the regular expression syntax must follow the rules of Tcl regular expressions. Conceptually the same, they differ from python's rules in some of the special character classes.

Delete opening and closing quotes (or brackets,braces,etc) at once

The opening and closing quotes (or brackets, braces etc) are highlighted in PyCharm(and other editors). So this means it can identify the pair.
Now, is there a way to delete both the quotes at once (or brackets, braces etc) when either of the opening or closing quotes are deleted, Since it identifies the pair?
For eg. I want this in one keyboard action (by both cases either deleting the opening or closing square bracket):
From this: [[a for a in l1 if a!=0]]
To this: [a for a in l1 if a!=0]
I googled and searched on SO but couldn't find it.
I know of 2 quick ways, but none of them is quick enough.
1: Using the AceJump addon, you just jump to one parens, hit delete, then jump to the other one, and hit delete... Naturally this has the disadvantage that parentheses in a situation like this: ([{(([]))}) would be harder to jump to.
2: There is a command called "Move caret to matching brace". Then, using either AceJump to jump directly to your first brace (or just navigating to it in any way), you activate the function "Move caret to matching brace 2 times". After moving the caret 2 times, you can delete the first matching parens, and then use the action to navigate back ("Back"), and then delete your second brace.
3: Solution 2 does not work for quotes. For them, instead of executing the action "Move to matching brace" you can use the incremental selection, and jump to the most convenient of the 2 quote signs... This however doesn't allow you to navigate back to the previous(or next) quote and delete that one. Therefore for quotes, I have no solution, but this "incremental selection" can work in a few situations (when one of the quotes is at the beginning or the end of a line)

Why use an ampersand character (&) in PyQt Strings for GUI elements?

I've read several tutorials for PyQt and they use an ampersand character (&) in Strings which are used to label buttons. For example:
self.submitButton = QPushButton("&Submit")
I searched for some explanation, but one problem is, that common search engines think they're so smart and ignore the & character, which is annoying. When I add quotes around it, it only makes me find less results and none, which explains anything about strange '&' characters.
Is it something very basic and that's why no one is explaining it?
Or is it PyQt specific?
And why would I add an unnecessary character like that?
Doesn't it only clutter the String unnecessarily?
What kind of effect does it have on the handling of that String?
I also tried in the python console:
a = "&abc"
b = "abc"
a == b
which returns false.
Then I tried giving it as an argument to the print function:
print(a)
print(b)
which simple prints:
&abc
abc
So I still don't know what to make of this.
From msdn.microsoft.com: (not related to python itself, but the concept is the same)
Gets or sets a value indicating whether the control interprets an
ampersand character (&) in the control's Text property to be an access
key prefix character.
If the UseMnemonic property is set to true and a mnemonic character (a
character preceded by the ampersand) is defined in the Text property
of the Label, pressing ALT+ the mnemonic character sets the focus to
the control that follows the Label in the tab order. You can use this
property to provide proper keyboard navigation to the controls on your
form.
And from pyqt.sourceforge.net:
A QLabel is often used as a label for an interactive widget. For this
use QLabel provides a useful mechanism for adding an mnemonic (see
QKeySequence) that will set the keyboard focus to the other widget.
E.g.:
QLineEdit* phoneEdit = new QLineEdit(this);
QLabel* phoneLabel = new QLabel("&Phone:", this);
phoneLabel->setBuddy(phoneEdit);

Tkinter simulating the up/down arrow keys

I need to make my own event handler that includes the standard up/down arrow keys' functionalities in a text widget. However, there are some quirks I have to program around somehow.
You might think you could just add/subtract a line and it would go up/down as expected. Well, that's sort of true. But, if you have the word-wrap on or something, you'll go up further than you expected on wrapped lines. Plus, the arrow key might not go up eveningly as it usually does whether or not the word wrap is on (seeing as it will stay on the same character no matter where that character is).
So, how do I simulate the regular functionality in Tkinter?
Here's why I need to reprogram the up arrow key (down also)—this isn't essential to my question, but because people like to ask and come up with alternative approaches, here you go:
I'm making a text editor, and the natural way it does things in a Tkinter Text widget has a bug that I plan to eliminate. The bug is that if you select text with shift-home or something and then try to select further text with shift-up (or shift-down, or control-shift-left or control-shift-right) then it might select or deselect some inappropriate stuff, depending on how you do it. It should be easy enough to fix control-shift-left and control-shift-right, but I have the positioning problems with shift-up and shift-down. I've already reprogrammed home, end, left, right, shift-left and shift-right for similar reasons (and Tkinter is awesome because you actually can reprogram stuff like this).
I'm using Python 3.4.
I'm thinking maybe getting the x,y coordinates of the insert might be helpful. I didn't see anything for that, though (just the mouse coordinates).
I'm not entirely sure what the problem is that you are having. Are you aware you can ask the text widget to calculate an index of the previous line or next line, and to either take wrapped lines into account or ignore the wrapping?
From the tk text widget docs on index modifiers:
+ count ?submodifier? lines
Adjust the index forward by count lines, retaining the same character position within the line. If there are
fewer than count lines after the line containing the current index,
then set the index to refer to the same character position on the last
line of the text. Then, if the line is not long enough to contain a
character at the indicated character position, adjust the character
position to refer to the last character of the line (the newline).
Spaces on either side of count are optional. If the display
submodifier is given, then each visual display line is counted
separately. Otherwise, if any (or no modifier) is given, then each
logical line (no matter how many times it is visually wrapped) counts
just once. If the relevant lines are not wrapped, then these two
methods of counting are equivalent.
You can also use a minus sign to go backwards.
For example:
next_line = the_widget.index("insert +1 display lines")

Remove last character from wxPython wxTextCtrl?

I am trying to remove the very last character from a TextCtrl object in wxPython. I'm using wxPython 2.8.12 and Python 2.7.2.
My code is as follows:
def btnBkClicked(self, e):
self.txtItem.Remove(self, (self.txtItem.GetLastPosition()[-1]), (self.txtItem.GetLastPosition()))
However, that doesn't work :( What do I need to change/do?
If you need to remove the very last character from the string, try
self.txtItem.SetValue(self.txtItem.GetValue()[:-1])
This code gets current text from TextCtrl and sets and sets its value to this text up to the last symbol.
Regarding your input, TextCtrl.Remove needs two parameters: from and to, which are integer numbers giving the first and the last positions to be removed. As GetLastPosition returns the number of characters in the control, your code should be modified as
self.txtItem.Remove(self.txtItem.GetLastPosition()-1, self.txtItem.GetLastPosition())

Categories