KnowBrainer Speech Recognition
Decrease font size
Increase font size
Topic Title: How to automatically insert a space if necessary before executing a Sendkeys?
Topic Summary:
Created On: 02/04/2021 02:59 PM
Status: Post and Reply
Linear : Threading : Single : Branch
 How to automatically insert a space if necessary before executing a Sendkeys?   - wristofdoom - 02/04/2021 02:59 PM  
 How to automatically insert a space if necessary before executing a Sendkeys?   - Edgar - 02/04/2021 03:53 PM  
 How to automatically insert a space if necessary before executing a Sendkeys?   - Lunis Orcutt - 02/04/2021 08:46 PM  
 How to automatically insert a space if necessary before executing a Sendkeys?   - wristofdoom - 02/05/2021 10:33 AM  
 How to automatically insert a space if necessary before executing a Sendkeys?   - Alan Cantor - 02/04/2021 11:32 PM  
 How to automatically insert a space if necessary before executing a Sendkeys?   - wristofdoom - 02/05/2021 10:21 AM  
 How to automatically insert a space if necessary before executing a Sendkeys?   - Alan Cantor - 02/05/2021 12:21 PM  
 How to automatically insert a space if necessary before executing a Sendkeys?   - wristofdoom - 02/05/2021 02:28 PM  
 How to automatically insert a space if necessary before executing a Sendkeys?   - monkey8 - 02/05/2021 02:32 PM  
 How to automatically insert a space if necessary before executing a Sendkeys?   - Alan Cantor - 02/05/2021 05:35 PM  
 How to automatically insert a space if necessary before executing a Sendkeys?   - wristofdoom - 02/05/2021 05:43 PM  
 How to automatically insert a space if necessary before executing a Sendkeys?   - speechpro - 02/06/2021 12:28 AM  
 How to automatically insert a space if necessary before executing a Sendkeys?   - PG LTU - 02/06/2021 01:23 AM  
 How to automatically insert a space if necessary before executing a Sendkeys?   - wristofdoom - 02/06/2021 10:46 AM  
 How to automatically insert a space if necessary before executing a Sendkeys?   - Edgar - 02/06/2021 12:29 PM  
 How to automatically insert a space if necessary before executing a Sendkeys?   - wristofdoom - 02/06/2021 01:08 PM  
 How to automatically insert a space if necessary before executing a Sendkeys?   - kkkwj - 02/06/2021 03:33 AM  
 How to automatically insert a space if necessary before executing a Sendkeys?   - wristofdoom - 02/06/2021 10:48 AM  
 How to automatically insert a space if necessary before executing a Sendkeys?   - PG LTU - 02/06/2021 04:47 PM  
Keyword
 02/04/2021 02:59 PM
User is offline View Users Profile Print this message

Author Icon
wristofdoom
Senior Member

Posts: 137
Joined: 09/03/2020

I have a lot of commands that format text in a special way before sending it.

 

Very basic example: I have a command called "caps lock <dictation>" which will capitalize the text that I dictate.

 

>> SendKeys UCase ListVar1


However, when I use this command, it will often Print the text directly after the previously dictated text without a space, so that I need to either manually insert a space before I can execute the command, or I need to go back and fix it later.

 

For an example of the problem, imagine if I had this text:

 

"My text|"

 

The "|" character represents my cursor.

 

Notice that there is NOT a space after the word "text". In this case, if I were to dictate the command "caps lock my new text here", then the resultant text would be:

 

"My textMY NEW TEXT HERE|"

 

Not what we want!

What I would like to do is add some code before the "SendKeys" line that will detect if there is a space prior to the cursor, and then add a space if there is not.

 

For example, imagine if I had that same text:

 

"My text|"

 

With my dream command, if I were to dictate the command "caps lock my new text here", then the command would look and see that there is no space before the cursor, so it would insert a space, and the resultant text would be:

 

"My text MY NEW TEXT HERE"

 

If there are existing commands out there that do this, I would love to take a look at the code so I can steal it.

 

I think what I am looking for is code that will select the character to the left of the cursor, detect if it is a space or not, and if it is not a space, then insert a space.

 

Thanks.



-------------------------

Dragon Professional Individual v15.6. Windows 10. Knowbrainer 2017.

 02/04/2021 03:53 PM
User is offline View Users Profile Print this message

Author Icon
Edgar
Top-Tier Member

Posts: 1109
Joined: 04/03/2009

Originally posted by: wristofdoom […]

 

If there are existing commands out there that do this, I would love to take a look at the code so I can steal it.

 

I think what I am looking for is code that will select the character to the left of the cursor, detect if it is a space or not, and if it is not a space, then insert a space.

Both of your assumptions are correct.

I'm not going to bother to go searching for the code now as the author will probably chime in <grin>. But, if not, search (probably for "leading space") - it should be easy to find from the title!

In your code start out by doing a:
SendKeys "+{Left}", 1
which will select a single letter to the left of the insertion point. Copy that letter:
SendKeys "^c", 1
Dim previousLetter As String
previousLetter = Clipboard
SendKeys "{Right}", 1
we need to restore the insertion point. If the previous letter is NOT a space, add a space to the beginning of your return string.

 



-------------------------

-Edgar
DPI 15.3, 64-bit Windows 10 Pro, OpenOffice & Office 365, Norton Security, Shure X2U XLR to USB mic adapter with Audio Technica DB135 vocal mic, Asus X299-Deluxe Prime, Intel Core i9-7940X (14 core, 4.3 GHz overclocked to 4.9 GHz), G.SKILL TridentZ Series 64GB (4 x 16GB) DDR4 3333 (PC4 26600) F4-3333C16Q-64GTZ, NVIDIA GIGABYTE GeForce GTX 1060 GV-N1060G1 GAMING-6GD REV 2.0 6GB graphics card with 3 1920x1080 monitors

 02/04/2021 08:46 PM
User is offline View Users Profile Print this message

Author Icon
Lunis Orcutt
Top-Tier Member

Posts: 38667
Joined: 10/01/2006

We are not certain why you need to duplicate existing KnowBrainer commands which are Title <dictation>, UPPER <dictation> and lower <dictation>



-------------------------

Forum Mission Statement
Trial Downloads
Dragon/Sales@KnowBrainer.com 
(615) 884-4558 ext 1

 02/05/2021 10:33 AM
User is offline View Users Profile Print this message

Author Icon
wristofdoom
Senior Member

Posts: 137
Joined: 09/03/2020

Those Knowbrainer commands have the same issue that I've described.

 

Here's a video showing the "title <dictation>" command having the same problem I am trying to resolve here:

https://www.dropbox.com/s/i35j7kxafcbmjmp/2021-02-05%20Knowbrainer%20title%20command%20does%20not%20work%20with%20spacing%20issue.mp4?dl=0



I used my "caps lock <dictation>" command is an example because it's simpler than my actual use case.

 

 



-------------------------

Dragon Professional Individual v15.6. Windows 10. Knowbrainer 2017.

 02/04/2021 11:32 PM
User is offline View Users Profile Print this message


Alan Cantor
Top-Tier Member

Posts: 4031
Joined: 12/08/2007


I think what I am looking for is code that will select the character to the left of the cursor, detect if it is a space or not, and if it is not a space, then insert a space.


If you are dictating into Microsoft Word only, you can check the previous character without copying it to the clipboard.

Selection.MoveLeft Unit:=wdCharacter, Extend:=wdExtend ' Select one character to the left
If Selection = " " Then
MsgBox "Yes, there is a space before the insertion point"
Else
MsgBox "No space before"
End If
Selection.MoveRight Unit:=wdCharacter ' Restore the cursor position

It's not bulletproof. This script might fail if the insertion point is in a table, at the very start of a document, etc. But it should run at lightning speed and won't tie up the clipboard.

 

To use this code sample, you'll need to set a "Reference" to the "Microsoft Word  xx.0 Object Library." The values of "xx" vary from version to version of Word.



 02/05/2021 10:21 AM
User is offline View Users Profile Print this message

Author Icon
wristofdoom
Senior Member

Posts: 137
Joined: 09/03/2020

Thank you. I use Microsoft Word a lot, so it would be helpful to have commands running in there even if it's not running everywhere else.

Once I find the version number from my version of Word (it's the most recent Office 365 version), would I put this reference?



-------------------------

Dragon Professional Individual v15.6. Windows 10. Knowbrainer 2017.

 02/05/2021 12:21 PM
User is offline View Users Profile Print this message


Alan Cantor
Top-Tier Member

Posts: 4031
Joined: 12/08/2007


Once I find the version number from my version of Word (it's the most recent Office 365 version), would I put this reference?



While focus is in the scripting pane, press Alt + Enter.

This will open the "References" dialog box. Scroll down until you find the Microsoft Word xx.0 Object Library - it's a long way down! - and check the checkbox.

You don't need to know the number. There is only one item in the list with this name, and I think it refers to the version of Word installed on your computer. Make sure you don't inadvertently choose the Microsoft Office xx.0 Object Library. It doesn't work here.
 02/05/2021 02:28 PM
User is offline View Users Profile Print this message

Author Icon
wristofdoom
Senior Member

Posts: 137
Joined: 09/03/2020

Thanks, this is great.

This raises a question that I have always had with these scripts: how do I make a "does not equal" type condition?

 

In every coding language of ever used, != Is used to evaluate whether something is NOT a certain value. That doesn't work in the Dragon scripting language.

 

Currently what I have working correctly is:

Sub Main
Selection.MoveLeft Unit:=wdCharacter, Extend:=wdExtend ' Select one character to the left
If Selection = " " Then
' blank line here
Else
    SendKeys "{Space}"
End If
Selection.MoveRight Unit:=wdCharacter ' Restore the cursor position
SendKeys UCase ListVar1
End Sub

But that obviously is weird and funky. I don't want to have an empty "then" case. What I want is something like this:

 

Sub Main
Selection.MoveLeft Unit:=wdCharacter, Extend:=wdExtend ' Select one character to the left
If Selection != " " Then SendKeys "{Space}"
Selection.MoveRight Unit:=wdCharacter ' Restore the cursor position
SendKeys UCase ListVar1
End Sub


but that doesn't work. Dragon code doesn't like the !=

 

I'm assuming there must be some sort of equivalent?



-------------------------

Dragon Professional Individual v15.6. Windows 10. Knowbrainer 2017.

 02/05/2021 02:32 PM
User is offline View Users Profile Print this message

Author Icon
monkey8
Top-Tier Member

Posts: 3724
Joined: 01/14/2008

At the start of your script you can test for a space and insert a space if one does not exist using the following code which is the same as Edgard's pseudocode, this will work with any editor:

 

Sub Main
  SendKeys "+{Left}"

Wait 0.1
SendKeys "^c"
Wait 0.1
If(Clipboard = " ") Then
    SendKeys "{Right}"
Else
    SendKeys "{Right} "
End If

'The rest of your script goes here


End Sub

 

 

EDIT: If (A <> B) for does not equal



-------------------------



 02/05/2021 05:35 PM
User is offline View Users Profile Print this message


Alan Cantor
Top-Tier Member

Posts: 4031
Joined: 12/08/2007

If you're going to make this only for Word, consider upping its usefulness by, for example, checking if the previous character is a non-breaking space, a Tab character, a line break, and so on.
 02/05/2021 05:43 PM
User is offline View Users Profile Print this message

Author Icon
wristofdoom
Senior Member

Posts: 137
Joined: 09/03/2020

Thanks everybody. I want a universal command first and foremost, but I also have a Microsoft Word specific alternative based on Alan's comment.

Here is my current version of the UNIVERSAL command for converting dictated text to all caps:

name: caps lock < dictation >

Sub Main
oldClipboard = Clipboard ' saves the old clipboard
Wait 0.1
SendKeys "+{Left}" ' selects the character directly to the left of the cursor
Wait 0.1
SendKeys "^c" ' copy the selected character
Wait 0.1
If(Clipboard = " ") Then ' evaluate if the character is a space
SendKeys "{Right}" ' if the character is a space, then just press the right arrow key to move back to where the cursor was
Else
SendKeys "{Right} " ' otherwise, if it's not a space, press the right arrow and also insert a space
End If
SendKeys UCase ListVar1 ' send the dictated text in uppercase
Wait 0.1
Clipboard oldclipboard ' restore the original clipboard
End Sub



-------------------------

Dragon Professional Individual v15.6. Windows 10. Knowbrainer 2017.



 02/06/2021 12:28 AM
User is offline View Users Profile Print this message


speechpro
Power Member

Posts: 74
Joined: 11/09/2006

If you are referencing the word object, you do *not* have to move the cursor or use ^c to copy - you can test the character to the left of the cursor directly and act accordingly

 

...

testText = ActiveDocument.Range(Start:=Selection.Start - 1, End:=Selection.Start)

If testText <> " " Then

    sendkeys " "

End If

sendkeys "your text here"

...
 02/06/2021 01:23 AM
User is offline View Users Profile Print this message

Author Icon
PG LTU
Top-Tier Member

Posts: 2134
Joined: 03/21/2007

I did something like that. It still works. In many ways it's just like the above solutions, just adding more options.

' pgCheckNewPara in pgGlobal.bas.txt
' Determines the prior character for proper sentence formatting
' (c) PG Service
Function pgCheckNewPara()
    Clipboard$()
    SendKeys "+{Left}^c", True ' copy previous character
    Select Case Clipboard$()
    Case "" ' if the prior character is nothing
        pgCheckNewPara = "" ' add no space
    Case Chr(13)&Chr(10) ' if the prior character is a Lf-CR
        SendKeys "{Right}", True
        pgCheckNewPara = "" ' add no space
    Case "." ' if the prior character is a period
        SendKeys "{Right}", True
        Clipboard$() ' check for No.
        SendKeys "+{Left 3}^c", True ' copy prior three characters
        SendKeys "{Right}", True
        If Clipboard$() = "No." Then
            pgCheckNewPara = " " ' add one space after No.
        Else
            pgCheckNewPara = "  " ' add two spaces after period
        End If
    Case "?", "!"
        SendKeys "{Right}", True
        pgCheckNewPara = "   " ' add two spaces after other ends of sentence
    Case Else
        SendKeys "{Right}", True
        pgCheckNewPara = " " ' add one space in the usual case
    End Select
    Clipboard$()
End Function


Hth



-------------------------




PG





Remember folks, my comments and this forum are for entertainment value only, please, no wagering or other reliance on the contents herein.  I permit no commercial use of my ideas (whether expressions or embodiments) without my written consent.



 02/06/2021 10:46 AM
User is offline View Users Profile Print this message

Author Icon
wristofdoom
Senior Member

Posts: 137
Joined: 09/03/2020

I've got a lot to learn from PG's function, quoted below:

 

' pgCheckNewPara in pgGlobal.bas.txt
' Determines the prior character for proper sentence formatting
' (c) PG Service
Function pgCheckNewPara()
    Clipboard$()

    SendKeys "+{Left}^c", True ' copy previous character
    Select Case Clipboard$()
    Case "" ' if the prior character is nothing
        pgCheckNewPara = "" ' add no space
    Case Chr(13)&Chr(10) ' if the prior character is a Lf-CR
        SendKeys "{Right}", True
        pgCheckNewPara = "" ' add no space
    Case "." ' if the prior character is a period
        SendKeys "{Right}", True
        Clipboard$() ' check for No.
        SendKeys "+{Left 3}^c", True ' copy prior three characters
        SendKeys "{Right}", True
        If Clipboard$() = "No." Then
            pgCheckNewPara = " " ' add one space after No.
        Else
            pgCheckNewPara = " " ' add two spaces after period
        End If
    Case "?", "!"
        SendKeys "{Right}", True
        pgCheckNewPara = " " ' add two spaces after other ends of sentence
    Case Else
        SendKeys "{Right}", True
        pgCheckNewPara = " " ' add one space in the usual case
    End Select
    Clipboard$()
End Function

 

  1. Why is the whole thing wrapped in a function/end function, instead of Sub/end sub (which is what I am used to seeing in Dragon commands)?
  2. When I have used the clipboard variable before, I have simply referred to as "clipboard", but here, in PG's script, it is being referred to as Clipboard$(), which has the appearance of a function. Has it been defined as a function in some separate script?
  3. What are the characters Chr13&Chr10, referred to in the script as "LF-CR? 
  4. After the SendKeys command, why do people often have "True" or "1" after? For example, why put "SendKeys "{Right}", True" when "SendKeys "{Right}"" works on its own?



-------------------------

Dragon Professional Individual v15.6. Windows 10. Knowbrainer 2017.

 02/06/2021 12:29 PM
User is offline View Users Profile Print this message

Author Icon
Edgar
Top-Tier Member

Posts: 1109
Joined: 04/03/2009

Originally posted by: wristofdoom

  1. Why is the whole thing wrapped in a function/end function, instead of Sub/end sub (which is what I am used to seeing in Dragon commands)?
  2. When I have used the clipboard variable before, I have simply referred to as "clipboard", but here, in PG's script, it is being referred to as Clipboard$(), which has the appearance of a function. Has it been defined as a function in some separate script?
  3. What are the characters Chr13&Chr10, referred to in the script as "LF-CR? 
  4. After the SendKeys command, why do people often have "True" or "1" after? For example, why put "SendKeys "{Right}", True" when "SendKeys "{Right}"" works on its own?

 

I hope the formatting remains intact…
Using the function/end function syntax allows you to put this bit of code in its own text file and refer to it by using a "uses" directive:
'#Uses "[…]\[…].txt"
as an example:
'#Uses "C:\Program Files (x86)\KnowBrainer\KnowBrainer Professional 2017\GlobalFunctions.txt"
where "GlobalFunctions.txt" is a file containing a bunch of function definitions. This way there is only one copy of the function and when you change it every script that relies on it automatically gets the change. It can also be used within a single script where you might have the following situation:

Sub Main

   ' do some stuff

   DoSomething

   ' do some more stuff

   DoSomething' do the exact same thing over again

End Sub


Function DoSomething()

   ' do something special and complicated

   ' involving many lines of code

End Function

"clipboard" & Clipboard$() - just two ways of referring to the same thing. The second way might be more historical but either works just as well.

"Chr(13)&Chr(10), referred to in the script as "LF-CR" - for more details look up the documentation:
https://www.nuance.com/products/help/dragon/dragon-for-pc/scriptref/Content/vbs/chr_function.htm
for the Chr() function. In this case they are referring to the characters for "carriage return" and "linefeed".

As for the "SendKeys "", 1" debate, here is the documentation:
https://www.nuance.com/products/help/dragon/dragon-for-pc/scriptref/Content/vbs/sendkeys_instruction.htm?Highlight=SendKeys
according to this adding the "true"/"1" optional parameter could have an effect if the string you are sending is very long and the following statements have an effect like moving the insertion point. It's probably an unnecessary habit in many cases, but… Have you ever seen a situation where your SendKeys command starts placing the characters slowly, one character at a time? Imagine what would happen if somehow the text cursor was moved during this operation!



-------------------------

-Edgar
DPI 15.3, 64-bit Windows 10 Pro, OpenOffice & Office 365, Norton Security, Shure X2U XLR to USB mic adapter with Audio Technica DB135 vocal mic, Asus X299-Deluxe Prime, Intel Core i9-7940X (14 core, 4.3 GHz overclocked to 4.9 GHz), G.SKILL TridentZ Series 64GB (4 x 16GB) DDR4 3333 (PC4 26600) F4-3333C16Q-64GTZ, NVIDIA GIGABYTE GeForce GTX 1060 GV-N1060G1 GAMING-6GD REV 2.0 6GB graphics card with 3 1920x1080 monitors

 02/06/2021 01:08 PM
User is offline View Users Profile Print this message

Author Icon
wristofdoom
Senior Member

Posts: 137
Joined: 09/03/2020

Amazing, okay. I didn't know this was possible, although I wanted to do something like this. I am constantly reusing code snippets in my scripts, and I wish I could just call a function so that I only need update the snippets in one place, rather than going to all my scripts that use the same snippet.



So in PG's script, did he define a function called Clipboard$() in a .txt file, and then invoke that within the script he posted above?



-------------------------

Dragon Professional Individual v15.6. Windows 10. Knowbrainer 2017.

 02/06/2021 03:33 AM
User is offline View Users Profile Print this message

Author Icon
kkkwj
Top-Tier Member

Posts: 698
Joined: 11/05/2015

Lots of times, I want to join utterances *without* a space, which is a situation where a "universal" command that forces in a space would not do the right thing. I just made separate commands to add a space (or not), add a leading capital (or not), add title case, and so on.

-------------------------

Win10/x64, AMD Ryzen 7 3700X, 64GB RAM, Dragon 15.3, SP 6 PRO, SpeechStart, Office 365, KB 2017, Dragon Capture, Samson Meteor USB Desk Mic, Klim and JUKSTG earbuds with microphones, 3 BenQ 2560x1440 monitors, Microsoft Sculpt Keyboard and fat mouse

 02/06/2021 10:48 AM
User is offline View Users Profile Print this message

Author Icon
wristofdoom
Senior Member

Posts: 137
Joined: 09/03/2020

I run into that situation myself, but I have the opposite problem more often than needing to join text together.

In some of my primary non-Dragon compatible applications, the default behavior is to join the text automatically, so I would rather create custom commands for a "tight" text insertion, and have most commands default to inserting a space where needed.



-------------------------

Dragon Professional Individual v15.6. Windows 10. Knowbrainer 2017.

 02/06/2021 04:47 PM
User is offline View Users Profile Print this message

Author Icon
PG LTU
Top-Tier Member

Posts: 2134
Joined: 03/21/2007

The function can be used anywhere once defined. Yes, you can access it in a '#Uses referenced link, or just put it in the same command (after the End Sub line). Then use it. It will put a space or two where and when needed or do nothing when it is not needed.

SendKeys pgCheckNewPara & "Result"

Will run the function when needed and return the result, either adding a space or perhaps two before "Result" or not, depending on what the function computes.

 

Also note, the forum changes two spaces to one, so the code for after a period and other terminal punctuation needs a second space if you use two spaces after sentences.  Also, the Clipboard thing is just from much older versions of Dragon when I first wrote this.



-------------------------




PG





Remember folks, my comments and this forum are for entertainment value only, please, no wagering or other reliance on the contents herein.  I permit no commercial use of my ideas (whether expressions or embodiments) without my written consent.



Statistics
31980 users are registered to the KnowBrainer Speech Recognition forum.
There are currently 0 users logged in.
The most users ever online was 12124 on 09/09/2020 at 04:59 AM.
There are currently 531 guests browsing this forum, which makes a total of 531 users using this forum.

FuseTalk Standard Edition v4.0 - © 1999-2021 FuseTalk™ Inc. All rights reserved.