Shortcut to move to a specific part of a text file - keyboard-shortcuts

I'd like to create a keyboard shortcut (such as CTRL+T) that automatically moves the cursor to the line after the occurence of a fixed text, such as &todo.
Example:
foo
bar
&todo
fix bug #783
blah
blah2
Pressing CTRL+T would automatically move the cursor to the line beginning with fix ....
Currently I'm doing it like this:
CTRL F
enter &todo, ENTER
ESCAPE (closes the Search bottom panel)
HOME
DOWN ARROW (moves to next line)
but this requires too many actions.
How to do that in a single key shortcut?

The best solution is it use a plugin to do that.
The plugin below does what you require. It will find the next occurrence of pattern (i.e. the &todo marker) below the current cursor position, move the cursor to the line below it, and centre that position in the window. If the pattern is not found below the current cursor position it will search again from the top of the buffer providing a wrap around feature.
Copy and paste the following Python code into a buffer and save it in your Sublime Text config User folder as GoToPattern.py.
import sublime
import sublime_plugin
class GotoPatternCommand(sublime_plugin.TextCommand):
def run(self, edit, pattern):
sels = self.view.sel()
# Optional flags; see API.
flags = sublime.LITERAL | sublime.IGNORECASE
start_pos = sels[0].end() if len(sels) > 0 else 0
find_pos = self.view.find(pattern, start_pos, flags)
if not find_pos and start_pos > 0:
# Begin search again at the top of the buffer; wrap around
# feature, i.e. do not stop the search at the buffer's end.
find_pos = self.view.find(pattern, 0, flags)
if not find_pos:
sublime.status_message("'{}' not found".format(pattern))
return
sels.clear()
sels.add(find_pos.begin())
self.view.show_at_center(find_pos.begin())
row, col = self.view.rowcol(find_pos.begin())
self.view.run_command("goto_line", {"line": row + 2})
# Uncomment for: cursor to the end of the line.
# self.view.run_command("move_to", {"to": "eol"})
Add key bindings:
// The pattern arg, i.e. "&todo", can be changed to anything you want
// and other key bindings can also be added to use different patterns.
{"keys": ["???"], "command": "goto_pattern", "args": {"pattern": "&todo"}}
Add a Command Palette entry to Default.sublime-commands if you want:
{"caption": "GoToPattern: &todo", "command": "goto_pattern", "args": {"pattern": "&todo"}},
These links may be useful to you ST v. 2 API and ST v. 3 API.
P.S. Did you know that Sublime Text has bookmarks? [Just in case you didn't.]

The accepted answer is really better and I'm finally using it.
For reference, here an old solution I used: first create a gototodo.py file in "C:\Users\User\AppData\Roaming\Sublime Text 2\Packages\User\" containing:
import sublime, sublime_plugin
class GototodoCommand(sublime_plugin.TextCommand):
def run(self, edit):
contents = self.view.substr(sublime.Region(0, self.view.size())) # https://stackoverflow.com/questions/20182008/sublime-text-3-api-get-all-text-from-a-file
a = contents.find('&todo')
cursors = self.view.sel()
cursors.clear()
location = sublime.Region(a, a)
cursors.add(location)
self.view.show_at_center(location)
(row, col) = self.view.rowcol(self.view.sel()[0].begin()) # go to the next line
self.view.run_command("goto_line", {"line": row+2})
Then add this in "C:\Users\User\AppData\Roaming\Sublime Text 2\Packages\User\Default (Windows).sublime-keymap":
{ "keys": ["ctrl+t"], "command": "gototodo" }
Done!

Related

select text between two line breaks in sublime text

I was wondering if there is any shortcut key for sublime text(3) or plugin for selecting all the text between two line breaks.
For example:
$search_box = Input::get('search_box');
$city_code = Input::get('city_code');
$check_in = Input::get('check_in');
$check_out = Input::get('check_out');
$noofrooms = Input::get('noofrooms');
$adultguest = Input::get('adultguest');
$childguest = Input::get('childguest');
$childage = Input::get('childage');
Session::put('adultguest', $adultguest);
Session::put('childguest', $childguest);
Session::put('childage', $childage);
In above code, I want to select all the text from$noofrooms = Input::get('noofrooms'); to Input::get('childage'); with shortcut key at once. Is there any?
Add the following line to Preferences > Key Bindings - User
{ "keys": ["alt+p"], "command": "expand_selection_to_paragraph" }
(You can change the "alt+p" to whatever key combo you want)

Unable to save the file in specified location using Autoit

Followed the below steps to save a file in desired location:
Step1: Save As window getting opened(with the default downloads location, with file name as DOC)
Step2: entering the file name as "D:\temp\sample.pdf" (which is getting entered in the edit bar)
Step3: clicking the save button (button clicked, file downloaded in the default location rather than the "D:\temp" location)
I have created an .exe with the below .au3 script
WinWait("[CLASS:#32770]","",10)
Sleep(2000)
ControlSetText("Save As", "", "Edit1", $CmdLine[1])
Sleep(5000)
ControlClick("Save As", "", "Button1");
Sleep(5000)
On clicking save, it is getting saved in the default location rather than the specified location.
The below code, executing the script.
IO.popen('autoit_script.exe D:\temp') #Ruby Code
Is there a way to sort it out?
It depends on the software you are trying to automate but usually this happens because the software is not recognizing there is a change in the file save path box. The problem is in how ControlSetText works. Try using ControlSend with some error checking to make sure the file path you are try to set is getting put in right. Sometimes you have to play with a few different variations to see what works with the software you are automating. Here are two examples you can try:
Example one:
WinWait("[CLASS:#32770]", "", 10)
If Not #error Then ;make sure the window was found
$hWin = WinGetHandle("[CLASS:#32770]") ;get window handle
ControlSetText($hWin, "", "Edit1", $CmdLine[1]) ;set text
ControlFocus($hWin, "", "Edit1") ;just to make sure we have focus
ControlSend($hWin, "", "Edit1", "{ENTER}")) ;should work like click button 1 but you will have to check
;better then a sleep
$hTimer = TimerInit() ; Begin the timer and store the handle in a variable.
Do
Until WinExists($hWin) = 0 Or TimerDiff($hTimer) >= 10000
EndIf
Example two:
WinWait("[CLASS:#32770]", "", 10)
If Not #error Then ;make sure the window was found
$hWin = WinGetHandle("[CLASS:#32770]") ;get window handle
While 1
ControlSetText($hWin, "", "Edit1", "") ;just makes sure there is no text in the control text
ControlFocus($hWin, "", "Edit1") ;just to make sure we have focus
ControlSend($hWin, "", "Edit1", $CmdLine[1])) ;set text using ControlSend
If ControlGetText($hWin, "", "Edit1") = $CmdLine[1] Then ExitLoop ;makes sure that the control got ALL of the text before exiting loop
WEnd
ControlClick($hWin, "", "Button1");
;better then a sleep
$hTimer = TimerInit() ; Begin the timer and store the handle in a variable.
Do
Until WinExists($hWin) = 0 Or TimerDiff($hTimer) >= 10000
EndIf

How do I set the text attributes on an empty line in a PyGtk TextView?

The first section of code is the original code posted. The second code is modification of Bob's answer who led me in the right direction.
I need the user, when they reach a specific line (where this is a new line, which of course is empty) in the gtk.TextBuffer to be typing in a bold font.
If possible, what change is necessary in the code below that would make the font bold from where the user begins to type?
import gtk, pango
class BoldTestWindow(gtk.Window):
def __init__(self):
gtk.Window.__init__(self)
self.connect( "destroy", lambda *w: gtk.main_quit() )
self.set_default_size(280, 80)
# Create a text view and get it's buffer.
self.tv = gtk.TextView()
buffer = self.tv.get_buffer()
# Create the Tags and add them to the Tag Table.
tags = [["weight", pango.WEIGHT_BOLD], ]
for tag in tags:
newTag = gtk.TextTag(name=tag[0])
newTag.set_property(tag[0], tag[1])
textTable = buffer.get_tag_table()
textTable.add(newTag)
# Grab an Iter to insert text.
startIter = buffer.get_start_iter()
# Insert some text in which to apply the bold attribute.
buffer.insert(startIter, "A Bold Statement.")
# startIter must be asked for again, because text was inserted.
startIter = buffer.get_start_iter()
endIter = buffer.get_end_iter()
# Apply the tags to entire range of TextBuffer
tags = ["weight",]
for tag in tags:
buffer.apply_tag_by_name(tag, startIter, endIter)
# Let's see what happens.
self.add(self.tv)
self.tv.grab_focus()
self.set_position(gtk.WIN_POS_CENTER)
self.show_all()
if __name__ == "__main__":
bww = BoldTestWindow()
gtk.main()
Bob's answer was the expose event, accept the expose event floods with thousands of calls to change the attributes, where only one call is neccessary per character added.
In order to stop a flooding of events, I experimented with key events.
I tried using key-press-event, but the character was not modified until the next event round, which left no style changes for the last character pressed.
I tried key-release-event and this worked, but there was a small delay in adding the attributes. The character would be no attribute for a split second, then the bold attribute would be added.
Finally, I tried a mix of key-press-event with expose-event, but that bottle necked some, then Juhaz from irc #pygtk recommended changed event which seems to work well. I believe the anser is close, I will use the following section to post it when done. I still have to work out line justification properties, they are still buggy.
import gtk, pango
# TaggedCursorTextView attempts to only add one feature to gtk.TextView: make the cursor dynamically settable
# to a list of tags. This forces the current text being typed to the set of tags set.
class TaggedCursorTextView(gtk.TextView):
def __init__(self):
gtk.TextView.__init__(self)
# Create buffer variable that point to it's internal TextBuffer.
self.buffer = self.get_buffer()
# Listen for the changed event. (User types, deletes or pastes text, etc.)
self.connect("key-press-event", self.on_key_press_event)
# What ever tags are place in here determines the text attributes (font type, bold, etc.)
# That is being typed by the user at any given moment.
# Default should be kept empty, no styles.
self.cursorTags = []
self.handlerID = None
def addTags(self, tagList):
# Create the Tags and add them to the Tag Table. Ignores duplicate tag names.
for tag in tagList:
newTag = gtk.TextTag(name=tag[0])
textTable = self.buffer.get_tag_table()
tagNameFound = textTable.lookup(tag[0])
if not tagNameFound:
newTag.set_property(tag[1], tag[2])
textTable.add(newTag)
def removeTags(self, tagNameList):
pass
def setCursorTags(self, tagList):
self.cursorTags = tagList
def on_key_press_event(self, widget, event):
self.handlerID = self.buffer.connect("changed", self.on_changed_event)
def on_changed_event(self, widget):
"""This method updates the last character type to the cursor style."""
self.buffer.disconnect(self.handlerID)
# Get the iter that falls before and after the last char typed.
endIter = self.buffer.get_end_iter()
offset = endIter.get_offset() - 1
startIter = self.buffer.get_iter_at_offset(offset)
# Apply the tags to the newly typed char
for tag in self.cursorTags:
self.buffer.apply_tag_by_name(tag, startIter, endIter)
class TaggedCurserTextViewTestWindow(gtk.Window):
def __init__(self):
gtk.Window.__init__(self)
self.connect( "destroy", lambda *w: gtk.main_quit() )
self.set_default_size(280, 80)
# Create a TaggedCursorTextView.
tctv = TaggedCursorTextView()
# Add some cursors tags that will be used at some point later in the app.
# Each tag element list is: [tag name, tag property, tag value]
tagList = [["Italic", "style", pango.STYLE_ITALIC], ["Bold", "weight", pango.WEIGHT_BOLD], ["Center", "justification", gtk.JUSTIFY_CENTER]]
tctv.addTags(tagList)
# Use the names of the tags in a list to set the cursor tags.
tctv.setCursorTags(["Italic", "Bold", "Center"]) # Comment out this line for no style.
# Let's see what happens.
self.add(tctv)
tctv.grab_focus()
self.set_position(gtk.WIN_POS_CENTER)
self.show_all()
if __name__ == "__main__":
TaggedCurserTextViewTestWindow()
gtk.main()
Here's a rather crude modification of your code. I've just created an expose-event handler for your textview and whenever expose-event is invoked (i.e. when your textview requests to redraw), it redraws everything with bold font.
I'm not sure, if this is what you wanted; please explain in more detail your purpose, if it's not (I'm in IRC).
import gtk, pango
class BoldTestWindow(gtk.Window):
def __init__(self):
gtk.Window.__init__(self)
self.connect( "destroy", lambda *w: gtk.main_quit() )
self.set_default_size(280, 80)
# Create a text view and get it's buffer.
self.tv = gtk.TextView()
buffer = self.tv.get_buffer()
# Create the Tags and add them to the Tag Table.
tags = [["weight", pango.WEIGHT_BOLD], ]
for tag in tags:
newTag = gtk.TextTag(name=tag[0])
newTag.set_property(tag[0], tag[1])
textTable = buffer.get_tag_table()
textTable.add(newTag)
# Grab an Iter to insert text.
startIter = buffer.get_start_iter()
# Insert some text in which to apply the bold attribute.
buffer.insert(startIter, "A Bold Statement.")
# startIter must be asked for again, because text was inserted.
startIter = buffer.get_start_iter()
endIter = buffer.get_end_iter()
# Apply the tags to entire range of TextBuffer
tags = ["weight",]
for tag in tags:
buffer.apply_tag_by_name(tag, startIter, endIter)
# Let's see what happens.
self.add(self.tv)
self.tv.grab_focus()
self.set_position(gtk.WIN_POS_CENTER)
self.show_all()
def on_expose_event(self, widget, event, data=None):
buffer = self.tv.get_buffer()
startIter = buffer.get_start_iter()
endIter = buffer.get_end_iter()
# Apply the tags to entire range of TextBuffer
tags = ["weight",]
for tag in tags:
buffer.apply_tag_by_name(tag, startIter, endIter)
if __name__ == "__main__":
bww = BoldTestWindow()
bww.tv.connect("expose-event", bww.on_expose_event)
gtk.main()

Sublime Text 2 shortcut line substitution

Excuse me for the non-informative title. Just can't shortly describe what I want within one question.
Okay, let's say we have two lines in our text file. The cursor is somewhere in the 1st line (the example shows cursor position):
SO helps| people
People like SO
What I want is to substitute the first line with an empty line or with another line and cursor should be at the start of this empty line.
I tried CTRL +L and type the "new line". But CTRL +L expands selection to the line + \n and that causes this result (the example shows cursor position):
new line|People like SO
If the cursor is at the begining of the line, CTRL +K+K works perfect. But how can do the same when the cursor is not at the begining (without pressing ENTER , arrows and using mouse)?
The equivalent of Ctrl + K + K at the beginning of a line when the cursor is somewhere in the line is : Ctrl + Shift + K
Here:
first line with text
second line| with other text
third line with another text
-> Ctrl + Shift + K :
first line with text
|third line with another text
EDIT
Since it is requested that the result should be:
first line
|
third line
You could either do what is written above and press ENTER or go to Packages/Delete Line.sublime-macro and replace the file with the following code:
[
{"command": "expand_selection", "args": {"to": "line"}},
{"command": "add_to_kill_ring", "args": {"forward": true}},
{"command": "left_delete"},
{"command": "insert", "args": {"characters": "\n"}},
{"command": "move", "args": {"by": "lines", "forward": false}}
]

How to extract Highlighted Parts from PDF files

Is there any way to extract highlighted text from a PDF file programmatically? Any language is welcome. I have found several libraries with Python, Java, and also PHP but none of them do the job.
To extract highlighted parts, you can use PyMuPDF. Here is an example which works with this pdf file:
Direct download
# Based on https://stackoverflow.com/a/62859169/562769
from typing import List, Tuple
import fitz # install with 'pip install pymupdf'
def _parse_highlight(annot: fitz.Annot, wordlist: List[Tuple[float, float, float, float, str, int, int, int]]) -> str:
points = annot.vertices
quad_count = int(len(points) / 4)
sentences = []
for i in range(quad_count):
# where the highlighted part is
r = fitz.Quad(points[i * 4 : i * 4 + 4]).rect
words = [w for w in wordlist if fitz.Rect(w[:4]).intersects(r)]
sentences.append(" ".join(w[4] for w in words))
sentence = " ".join(sentences)
return sentence
def handle_page(page):
wordlist = page.get_text("words") # list of words on page
wordlist.sort(key=lambda w: (w[3], w[0])) # ascending y, then x
highlights = []
annot = page.first_annot
while annot:
if annot.type[0] == 8:
highlights.append(_parse_highlight(annot, wordlist))
annot = annot.next
return highlights
def main(filepath: str) -> List:
doc = fitz.open(filepath)
highlights = []
for page in doc:
highlights += handle_page(page)
return highlights
if __name__ == "__main__":
print(main("PDF-export-example-with-notes.pdf"))
Ok, after looking I found a solution for exporting highlighted text from a pdf to a text file. Is not very hard:
First, you highlight your text with the tool you like to use (in my case, I highlight while I'm reading on an iPad using Goodreader app).
Transfer your pdf to a computer and open it using Skim (a pdf reader, free and easy to find on the web)
On FILE, choose CONVERT NOTES and convert all the notes of your document to SKIM NOTES.
That's all: simply go to EXPORT an choose EXPORT SKIM NOTES. It will export you a list of your highlighted text. Once opened this list can be exported again to a txt format file.
Not much work to do, and the result is fantastic.