code for getting nearest to cursor word - python

I develop plugin for sublme text 3. I need code for getting nearest to cursor word.
For example if I got cursor as on image...
... this plugin should return word run
....or at least number 10 which corresponds position of char u in line 4:
And then I will be able to get word run from number 10 and text of line 4.
But now I only can get linetext on which I got cursor:
import sublime, sublime_plugin
class line_nearest_to_cursor_wordCommand(sublime_plugin.WindowCommand):
def run(self):
print('line_nearest_to_cursor_word called')
view = self.window.active_view()
region1 = view.sel()[0]
line = view.line(region1)
linetext = view.substr(line)
print(linetext)
When I print region1 it gives two numbers, but they are wierd:
print (region1) # prints (113, 113), but 113 is not position of char "u" in line " def run(self):"
So problem reduced to writing method getXcoordPositionOnLine...
xCoord = getXcoordPositionOnLine(region1)
print xCoord
... which will give me x position of cursor on line.
Or maybe there is a better solution.

I answered a similar question for you yesterday. Looking at the docs, if you simply replace line in yesterday's answer with word, I believe you will get what you are looking for.
view = self.window.active_view()
word = view.word(view.sel()[0])
wordtext = view.substr(word)
As #skuroda suggests, this is easily answered by looking at the documentation. It isn't that difficult to understand.

Though I suppose the formatting leaves something to be desired, please try to take a look at the API documentation. A large number of your questions can likely be answered by exploring the docs. These are available here for ST3. With that being said, take a look at view#word(point) and view#word(region) in the documentation.

Here's what I think region1 being (113, 113) means, how you might be able to use it with the API to get what you want, or at least provide you with enough information to be able to write something like a getXcoordPositionOnLine() function yourself.
The API documentation says a sublime.Region has two properties, a and b, which represent the first and second ends of the region. I believe these are just two integer offsets from the beginning of the text buffer, and the reason they're the same in this case is because the region is empty (i.e. no characters are actually selected by it since they're the same value, which mean it's effectively the position of a cursor).
To illustrate that below is a screenshot of the code snippet shown in your question in another editor in which I've selected all the text from the beginning to the point between the "r" and the "u" in the word "run". This editor has an indicator near the bottom right that shows shows the total of Bytes/Lines currently selected. Notice that this is displaying 113/4 -- meaning that the "r" is 113th character in the text buffer and it's on the 4th line because there are 3 newline characters preceding it.
sublime.Regions also have an xpos property which sounds like it represents the offset of the character from the last newline (and would be something like 10 in this case I guess). Further reading of the documentation leads me to suspect you might be able to get the closest word to the cursor represented by region1 is the value returned from view.substr(view.word(region1).

Related

Clear line to the right of the text displayed by progressbar.FormatCustomText (python)

I am using progressbar2 with FormatCustomText. The text is parameterized (eg "%s") and the width of the string to display varies.
Let's say on the first iteration, the substituted text is "AA." On the second iteration, the text is "B."
progressbar displays BA on the second iteration instead of B.
Is there a way to clear everything to the right of the cursor to the end of the line after B? Normally, this is done with control-K (chr(11)).
Unfortunately, adding chr(11) to the end of the string given to FormatCustomText causes a newline character to be output for each iteration.
Any other ideas?
Print "\033[K" at the end
progressbar.ProgressBar(widgets=[format_custom_text, "\033[K"])
Ideally the text to substitute should have a maximum length based on a percentage of the width of the terminal. I found a way to get the width but there is probably a better way! (How to get Linux console window width in Python)
This works in python3+:
import shutil
shutil.get_terminal_size((80, 20)) # Provide default values
There is a better answer on github

Generating organized excel spreadsheet from a word document

I have Microsoft document which we want to transfer to excel. Every sentence needs to be separated and then pasted into the next appropriate cell in excel. These sentences also need to be analyzed as a heading, requirement, or informational.
I will recreate what the typical word format looks like
2.3.4 Lightening Transient Response
The device shall meet spec 24532. Voltage must resemble figure.
Figure 1.
which translates to
<numbering> <Heading>
<Requirements/information>
In excel that is almost exactly how I would the document to look except the second requirement sentence should be in row just below the previous requirement sentence.
2.3.4 | Lightening Transient Response | Heading
| The device shall meet spec 24532. | Requirement
|Voltage must resemble figure | Requirement
|figure 1 | Informational
I have attempted this project with python using openxl and docx modules. I have code that can go into word and get sentences and then code that can analyze the sentence.I'm retrieving runs from paragraphs. I am having problems because not all sentences are coming back due to how the word document is formatted. I am typically only getting the headings back. The heading numbers are not stored in runs. The requirements underneath the headings are stored in tables. I have written some code to get into the tables an extract the text from cells so that is one way to get the requirements however that snippet of code is giving problems(giving me the same sentence three times in a row).
I'm looking for other possible ways to do this. I'm thinking a format switch. XML has been mentioned and then also the pdf and pythons pdf module may be possible.
Any thoughts or advice would be greatly appreciated.
-Chris
XML is going to be harder, not easier. You're closer than you seem to think. I recommend attacking each problem separately until you crack it.
The sentence three times problem in the table is because of merged cells. The way python-docx works on tables, there is an underlying table layout of x rows and y columns. If two side-by-side cells are merged, you get the same results for both those cells. You can detect this be comparing the two cells for equality. Roughly like "if this_cell == last_cell skip this cell".
There's no way around the heading problem. Heading numbers only exist inside a running instance of Word; they are generated at display (or print) time. To get those you need to use the same rules to generate your own numbers. So you'd need to keep track of the number of headings you've passed through etc. and form your own dot-separated numbering.
Why are you using Python for this? Just use VBA, since you are working with Excel and Word.
Something like this should get you pretty close to where you want to be. It may need some tweaking...
Sub Demo()
Dim wdApp As Word.Application
Set wdApp = Word.Application
Dim wdDoc As Word.Document
Set wdDoc = wdApp.ActiveDocument
wdDoc.Range.Copy
ActiveSheet.Paste Destination:=ActiveSheet.Range("A1")
With ActiveSheet
.Paste Destination:=Range("A" & .Cells.SpecialCells(xlCellTypeLastCell).Row + 1)
End With
Set myRange = Range("A1:A100")
For i = 1 To myRange.Rows.Count
If InStr(myRange.Cells(i, "A").Value, "Voltage") > 0 Then
myRange.Cells(i, "A").Offset(1, 0).Select
ActiveCell.EntireRow.Insert
ActiveCell.Offset(-1, 0).Select
If InStr(myRange.Cells(i, "A").Value, "Voltage") > 0 Then
position1 = InStr(1, ActiveCell.Value, "Voltage")
myRange.Cells(i + 1, "A").Value = Mid(ActiveCell.Value, position1, 99)
ActiveCell.Value = Left(ActiveCell.Value, position1 - 2)
i = i + 2
End If
End If
Next i
End Sub
So, copy the text from your Word doc, which should be open and active, and you're good to go. There are other ways to do this too.

how can i change the size of a table in word using python (pywin32)

ms word table with python
I am working with python on word tables, i am generating tables, but all of them are
auto fit window..
is it possible to change it to auto fit contents?
i had tried something like this:
table = location.Tables.Add(location,len(df)+1,len(df.columns)
table.AutoFit(AutoFitBehavior.AutoFitToContents)
but it keeps to raise errors
You want to change you table creation to use this:
//''#Add two ones after your columns
table = location.Tables.Add(location,len(df)+1,len(df.columns),1,1)
Information about why you need those variables can be read here:
http://msdn.microsoft.com/en-us/library/office/ff845710(v=office.15).aspx
But basically, the default behavior is to disable Cell Autofitting and Use Table Autofit to Window. The first "1" enables Cell Autofitting. From the link I posted above, the DefaultTableBehavior can either be wdWord8TableBehavior (Autofit disabled --default) or wdWord9TableBehavior (Autofit enabled). The number comes from opening up Word's VBA editor and typing in the Immediate Window:
?Word.wdWord9TableBehavior
Next, from the link, we see another option called AutoFitBehavior. This is defined as:
Sets the AutoFit rules for how Word sizes tables. Can be one of the WdAutoFitBehavior constants.
So now we have another term to look up. In the VBA editor's Immediate window again type:
?Word.wdAutoFitBehavior.
After the last dot, the possible options should appear. These will be:
wdAutoFitContent
wdAutoFitFixed
wdAutoFitWindow
AutoFitContent looks to be the option we want, so let's finish up that previous line with:
?Word.wdAutoFitBehavior.wdAutoFitContent
The result will be a "1".
Now you may ask, why do we have to go through all this trouble finding the numerical representations of the values. From my experience, with using pywin32 with Excel, is that you can't get the Built-in values, from the string, most of the time. But putting in the numerical representation works just the same.
Also, One more reason for why your code may be failing is that the table object may not have a function "Autofit".
I'm using Word 2007, and Table has the function, AutoFitBehavior.
So Change:
table.AutoFit(AutoFitBehaviour.AutoFitToContent)
To:
table.AutoFitBehavior(1)
//''Which we know the 1 means wd.wdAutoFitBehavior.wdAutoFitContent
Hope I got it right, and this helps you out.

How do I edit the color of a word without generating EVT_TEXT in wxPython?

This is one part of a two part question (other part is here)
So I'm working with wxPython and PyEnchant trying to get some fancy features going. Specifically, I want my text controls to change the color of mispelled words. I can do this if I bind the following code to a button. (where input is a wx.TextCtrl)
chkr = SpellChecker("en_US",self.input.GetValue())
words = self.input.GetValue().split()
wrongWords = [err.word for err in chkr]
self.input.ChangeValue("")
for word in words:
if not word in wrongWords:
self.input.SetDefaultStyle(wx.TextAttr(wx.BLACK))
self.input.AppendText(word+" ")
else:
self.input.SetDefaultStyle(wx.TextAttr(wx.RED))
self.input.AppendText(word+" ")
This works exactly how I want it, except that I do not want to have to bind it to a button.
This is where the second question comes in. I want it to happen automatically after the user has finished editing. You can see the other question for a full discussion of whhat that means, but in the scope of this question, all it means is that I must do the above operation without generating an EVT_TEXT event.
ChangeValue() is identical to SetValue(), but it does not generate EVT_TEXT, so is there an analogous function to AppendText() which does same? Or failing that, is there a way to suppress EVT_TEXT when it is generated by AppendText() or someway to determine if the event came from AppendText()? Thanks in advance.
EDIT: I've managed to get a work around going by using Unbind(), but I'm still open to a better method if anyone can find one

How to highlight more than two characters per line in difflibs html output

I am using difflib.HtmlDiff to compare two files. I want the differences to be highlighted in the outputted html.
This already works when there are a maximum of two different chars in one line:
a = "2.000"
b = "2.120"
But when there are more different characters on one line then in the output the whole line is marked red (on the left side) or green (on the right side of the table):
a = "2.000"
b = "2.123"
Is this behaviour configurable? So can I set the number of different characters at which the line is marked as deleted / added?
EDIT:
Example:
import difflib
diff=difflib.HtmlDiff()
print(diff.make_file(
'''
2.000
2.000
2.000
'''.splitlines(),
'''
2.001
2.010
2.011
'''.splitlines()))
Gives me this output:
Line 2 is the output I want. It highlights the differences in yellow.
Line 3 is odd for me because it does not detect the one character change but instead shows it as delete / add.
Line 4 same as for line 3 but the whole line is marked.
difflib's algorithm does not claim to yield minimal edit sequences.
Although that statement comes from the docs for SequenceMatcher, I suspect it applies to difflib in general, and HTMLDiff in particular.
While googling around for "python alternative difflib minimal edit"
I found google-diff-match-patch. If you try out their demo for Diff
with your example strings, it yields
Although the output is not exactly what you requested, it does show that it found the minimal edits.
The API docs state
diff_prettyHtml(diffs) => html
Takes a diff array and returns a pretty HTML sequence. This
function is mainly intended as an example from which to write ones own
display functions.
which suggests looking at the source code for diff_prettyHtml might be a good starting point from which to build the HTML table you are looking for.

Categories

Resources