Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

Convert text - uppercase, lowercase, capitalized or inverted


  • Please log in to reply
31 replies to this topic
JDN
  • Members
  • 313 posts
  • Last active: Apr 20 2013 08:23 AM
  • Joined: 24 Mar 2004
One of the things I like best about NoteTab is that it has a bunch of features for converting the case of text. If you highlight a string of text, you can instantly convert it to any one of lower case, upper case, capitalized case, sentence case or inverted case. Once you have highlighted the case, the following codes will convert it as follows:

CTL+L - convert to lowercase
CTL+U - convert to uppercase
CTL+K - invert the case (e.g. "The Big Dog" becomes "tHE bIG dOG")
SHIFT+CTL+K - convert to capitalized (e.g. "the big dog" becomes "The Big Dog")
SHIFT+CTL+U - convert to sentence case

Unfortunately, anytime I am creating text but not using NoteTab, (for example, at the present time, when I am preparing this post to write to this message board - I'm using some editor that is built into this particular message board) or I'm using a word processor or another editor, I find myself often needing to use these features. But they aren't available anywhere other than the editor NoteTab and I have to either convert the text manually or copy it into NoteTab, convert it there and then copy it back.

So, I wrote a similar set of features using AutoHotkey and they can be used in any editor or word processor. The way they work is that you copy the text into the clipboard, then press one of the hotkeys to convert it, then you can position the cursor anywhere you like and then send the text to that position. There is no real reason why I wrote the code this way. I suppose I could have equally well written it to perform in the same way as the code in NoteTab. The advantage to this method is that you don't have to convert the text in place. Once you copy it into the clipboard, you can move the cursor anywhere and produce the text at that point.

I find it so amazing that the original author of NoteTab probably spent many hours to write and debug this code, whereas it only took me an hour to write it using AutoHotkey. Here are the hotkeys. It's interesting that they all are pretty straightforward except for "invert text" which is a little complex:

^u::                                                                 ; Convert text to upper
 StringUpper Clipboard, Clipboard
 Send %Clipboard%
RETURN

^l::                                                                 ; Convert text to lower
 StringLower Clipboard, Clipboard
 Send %Clipboard%
RETURN

+^k::                                                                ; Convert text to capitalized
 StringUpper Clipboard, Clipboard, T
 Send %Clipboard%
RETURN

^k::                                                                 ; Convert text to inverted
 Lab_Invert_Char_Out:= ""
 Loop % Strlen(Clipboard) {
    Lab_Invert_Char:= Substr(Clipboard, A_Index, 1)
    if Lab_Invert_Char is upper
       Lab_Invert_Char_Out:= Lab_Invert_Char_Out Chr(Asc(Lab_Invert_Char) + 32)
    else if Lab_Invert_Char is lower
       Lab_Invert_Char_Out:= Lab_Invert_Char_Out Chr(Asc(Lab_Invert_Char) - 32)
    else
       Lab_Invert_Char_Out:= Lab_Invert_Char_Out Lab_Invert_Char
 }
 Send %Lab_Invert_Char_Out%
RETURN


ManaUser
  • Members
  • 1121 posts
  • Last active: Mar 03 2011 09:08 PM
  • Joined: 24 May 2007
I was working on something similar a while ago. Here's code for "Sentence case":
!^k::                                           ; Sentence case
StringLower, Clipboard, Clipboard
Clipboard := RegExReplace(Clipboard, "((?:^|[.!?]\s+)[a-z])", "$u1")
Send %Clipboard%
RETURN
Feel free to merge it into your script. I'm sure it's not perfect (it doesn't know that "I" should always be uppercase, for instance) perhaps still useful. Basically it will capitalize the first letter and any letter that follows of ., ! or ?.

JDN
  • Members
  • 313 posts
  • Last active: Apr 20 2013 08:23 AM
  • Joined: 24 Mar 2004
This post became obsolete.

JDN
  • Members
  • 313 posts
  • Last active: Apr 20 2013 08:23 AM
  • Joined: 24 Mar 2004
Thanks very much, ManaUser. I'll have to study up on Regular Expressions cuz it's been a long time. But it looks like a good way to identify a sentence.

In the meantime, I will post an improved version that saves the clipboard before it starts and then restores the clipboard at the end so as to protect the integrity of the clipboard.

I will integrate your code as soon as I review Regular Expressions. If it is not perfect, hopefully someone who is more expert with Reg Exps than you or I will give us a helping hand.

Here is an improved version that protects the Clipboard by saving it before the functions start and then restoring it at the end. I've changed the lettering of the codes so that I could leave the original NoteTab functions in place and use them to compare to the new ones. I've also changed them to operate in the same way as NoteTab. You just highlight the text you want and the functions change the text and keep the text highlighted without ever changing the clipboard.

I use functions as much as possible in order to use local variables to protect the code against conflicts with global variables. Here are the new codes (note I use the uppercase L in this post instead of the lowercase because the lowercase is too hard to distinguish between the number 1 and the letter l). Of course, you can change these to any keys you like.

+#L - convert to lower case
+#U - convert to upper case
+#K - convert to capitalized case
+#I - convert to inverted case

+#l::                                                                ; convert to lower case
 Convert_Lower()
RETURN
Convert_Lower()
{
 Clip_Save:= ClipboardAll                                                 ; save original contents of clipboard
 Clipboard:= ""                                                           ; empty clipboard
 Send ^c{delete}                                                          ; copy highlighted text to clipboard
 StringLower Clipboard, Clipboard                                         ; convert clipboard to desired case
 Send %Clipboard%                                                         ; send desired text
 Len:= Strlen(Clipboard)
 Send +{left %Len%}                                                       ; highlight text
 Clipboard:= Clip_Save                                                    ; restore clipboard
}

+#u::                                                                ; convert to upper case
 Convert_Upper()
RETURN
Convert_Upper()
{
 Clip_Save:= ClipboardAll                                                 ; save original contents of clipboard
 Clipboard:= ""                                                           ; empty clipboard
 Send ^c{delete}                                                          ; copy highlighted text to clipboard
 StringLower Clipboard, Clipboard                                         ; convert clipboard to desired case
 Send %Clipboard%                                                         ; send desired text
 Len:= Strlen(Clipboard)
 Send +{left %Len%}                                                       ; highlight text
 Clipboard:= Clip_Save                                                    ; restore clipboard
}

+#k::                                                                ; convert to capitalized case
 Convert_Cap()
RETURN
Convert_Cap()
{
 Clip_Save:= ClipboardAll                                                 ; save original contents of clipboard
 Clipboard:= ""                                                           ; empty clipboard
 Send ^c{delete}                                                          ; copy highlighted text to clipboard
 StringLower Clipboard, Clipboard                                         ; convert clipboard to desired case
 Send %Clipboard%                                                         ; send desired text
 Len:= Strlen(Clipboard)
 Send +{left %Len%}                                                       ; highlight text
 Clipboard:= Clip_Save                                                    ; restore clipboard
}

+#i::                                                                ; convert to inverted case
 Convert_Inv()
RETURN
Convert_Inv()
{
 Clip_Save:= ClipboardAll                                            ; save original contents of clipboard
 Clipboard:= ""                                                      ; empty clipboard
 Send ^c{delete}                                                     ; copy highlighted text to clipboard

 Inv_Char_Out:= ""                                                   ; clear variable that will hold output string
 Loop % Strlen(Clipboard) {                                          ; loop for each character in the clipboard
    Inv_Char:= Substr(Clipboard, A_Index, 1)                         ; isolate the character
    if Inv_Char is upper                                             ; if upper case
       Inv_Char_Out:= Inv_Char_Out Chr(Asc(Inv_Char) + 32)           ; convert to lower case
    else if Inv_Char is lower                                        ; if lower case
       Inv_Char_Out:= Inv_Char_Out Chr(Asc(Inv_Char) - 32)           ; convert to upper case
    else
       Inv_Char_Out:= Inv_Char_Out Inv_Char                          ; copy character to output var unchanged
 }
 Send %Inv_Char_Out%                                                 ; send desired text
 Len:= Strlen(Inv_Char_Out)
 Send +{left %Len%}                                                  ; highlight desired text
 Clipboard:= Clip_Save                                               ; restore original clipboard
}


JDN
  • Members
  • 313 posts
  • Last active: Apr 20 2013 08:23 AM
  • Joined: 24 Mar 2004
ManaUser,

!^k::                                           ; Sentence case 
StringLower, Clipboard, Clipboard 
Clipboard := RegExReplace(Clipboard, "((?:^|[.!?]\s+)[a-z])", "$u1") 
Send %Clipboard% 
RETURN

I have reviewed PCRE's and think I understand your call to RegExReplace except for one thing. The documentation was not very robust about the use of "?:" to avoid the side-effect of capturing a subpattern. So, I'm afraid I don't understand your use of "?:^". Can you explain that to me? I'm guessing it means to anchor the search at the beginning of the string so as to search for the first alpha in the string or one followed by one or more end line chars [.!?] followed by one or more whitespace chars? But I'm still not clear about why "?:" is needed. What would be wrong with specifying:

((^|([.!?]+\s+))[a-z])

Even better, this seems to handle the " i " problem:

(((^|([.!?]+\s+))[a-z])| i )

Does that seem OK to you?

Also, I would suggest a change as follows and wonder if you agree?

"((?:^|[.!?]+\s+)[a-z])"

ManaUser
  • Members
  • 1121 posts
  • Last active: Mar 03 2011 09:08 PM
  • Joined: 24 May 2007
Actually, the non-capturing thing was gratuitous. I hoped that would make it clearer but it probably made it more confusing instead. :) It could be written without that for the same effect.
TempText := RegExReplace(TempText, "((^|[.!?]\s+)[a-z])", "$u1")
So in English, that's: ((the begining OR [one of ., ! or ?] and one or more whitespace characters) followed by a letter)

On the suggestion of putting + after [.!?], I don't see why that's necessary.

JDN
  • Members
  • 313 posts
  • Last active: Apr 20 2013 08:23 AM
  • Joined: 24 Mar 2004
The suggestion handles cases where there are multiple periods or one or more periods, ex points or question marks followed by some whitespace followed by an alpha letter. It is very rare, but I'm guessing it's best to handle it should it come up.

I also made a change to get the " i " but posted it after you posted yours. I hope you like it.

JDN
  • Members
  • 313 posts
  • Last active: Apr 20 2013 08:23 AM
  • Joined: 24 Mar 2004
Thanks very much to ManaUser, I have now included a hotkey to change the case of a text string to "Sentence case". Essentially that takes a string and makes it look like English sentences by capitalizing all letters found after an End Of Sentence character (period, ex point or question mark) followed by some whitespace. If the first character of the string is a letter, it also capitalizes that. It also capitalizes all occurrences of " i ".

In order to use this hotkey, just highlight the text you want to convert. You don't have to copy it into the clipboard. Then activate the hotkey. I have used the hotkey SHIFT+WIN+S but you may use any key you like, of course. I also like to put as much of the code as possible inside functions to prevent accidental conflicts with global variables.

Here it is:

+#s::
case
 Convert_Sentence()
RETURN
Convert_Sentence()
{
 Clip_Save:= ClipboardAll
 Clipboard:= ""
 Send ^c{delete}                                                     ; copy highlighted text to clipboard
 StringLower, Clipboard, Clipboard
 Clipboard := RegExReplace(Clipboard, "(((^|([.!?]+\s+))[a-z])| i | i')", "$u1")
 Send %Clipboard%                                                    ; send desired text
 Len:= Strlen(Clipboard)
 Send +{left %Len%}
 Clipboard:= Clip_Save
}


ManaUser
  • Members
  • 1121 posts
  • Last active: Mar 03 2011 09:08 PM
  • Joined: 24 May 2007
That's a good idea about "I", but we could make it better. How about:
RegExReplace(Clipboard, "(((^|([.!?]+\s+))[a-z])|\Wi\W)", "$u1")
\W means "not a letter or number", so this will catch contractions using "I" as well as unusual cases where some other symbol is next to it. For example:
if you think that's a good idea (i do), i'll implement it right away.
Now one the [.!?]+ thing, I still don't see the need. [.!?] alone should match the last sentence terminator anyway if there are more than one. Try it yourself:
OH MY GOD!!! THAT'S TERRIBLE!


JDN
  • Members
  • 313 posts
  • Last active: Apr 20 2013 08:23 AM
  • Joined: 24 Mar 2004
You are perfectly correct about the multiple [.!?] thing. I stand corrected. I will implement your improved version as soon as I can test it out. I'm sure it's probably good to go, but I'm also sure you understand about wanting to test all code before I post it for others. One concern I have is dealing with abbreviations like c.i.t. where the whole thing should remain lower case. But the new version capitalizes the "I". Also it will capitalize things like "Put it into array element i[5] if it is greater than 10." Maybe it would be easier just to search for "I'd I've I'll I'm"? I think those four words are the only English language contractions for I?

Also, you should be aware of the following problems. I can't see any way to solve these. But I thought you might get a laugh from seeing them. Doctor and drive are both shown as Dr. The same goes for Saint and Street. They're both St. I think we should always capitalize the word following Dr. and St., but when it comes to Drive, sometimes it should be capitalized but other times not. It's impossible to tell. The same goes for Street. For example:

He lives on John St. between numbers 10 and 12.
He lives on John St. He moved there a year ago.
It happened on St. Stevens day.

He lives on Pleasant Dr. between numbers 10 and 12.
He lives on Pleasant Dr. He moved there a year ago.
He gave it to Dr. Jones.


Want a good laugh? NoteTab changes the following line:
He lives on John St. between numbers 10 and 12.
to the following:
He lives on john st. between numbers 10 and 12.

NoteTab also messes up the following in the same way:
It happened on St. Stevens day.
He gave it to Dr. Jones

I guess NoteTab figures it knows better than the writer when words should not be capitalized. I think that's very funny. It actually removes capitalization that the author created. I want to thank you very much. You've been a great help and I really appreciate it. If you ever think of any interesting project you might like to co-operate on, please send me a PM and we can discuss it?

ManaUser
  • Members
  • 1121 posts
  • Last active: Mar 03 2011 09:08 PM
  • Joined: 24 May 2007
Well, obviously it's never going to know how to handle proper nouns (names). But hadn't really thought about abbreviations that use dots. (Who's bright idea was it to use the same symbol for ending a sentence and marking abbreviations anyway?) I suppose it could be made to handle some of those cases, but I think we've reached the point of diminishing returns.

JDN
  • Members
  • 313 posts
  • Last active: Apr 20 2013 08:23 AM
  • Joined: 24 Mar 2004
I definitely agree. And since converting to sentence case is so rarely used, it's just not worth chasing it any further.

By the way, I changed the RE to pick up "I'm" "I'd" "I'll" and "I've" as follows:

Clipboard := RegExReplace(Clipboard, "(((^|([.!?]\s+))[a-z])| i | i')", "$u1")

It's a long way from perfect, but it's got to be a million times better than NoteTab (since it never removes any capitalization) and that is a real satisfaction since NoteTab is usually recognized as the best freeware editor around.

sashabe
  • Members
  • 24 posts
  • Last active: Aug 05 2013 11:34 AM
  • Joined: 09 Oct 2006
How about unicode support for this script? Is it possible?

TotalBalance
  • Members
  • 207 posts
  • Last active: Feb 25 2013 07:17 AM
  • Joined: 22 Jan 2007
JDN, I'm a little confused. Is the code on the 1st page updated to reflect all the changes discussed? I like what you've done, just want to make sure I'm copying what's needed.

amitk
  • Members
  • 7 posts
  • Last active: Nov 13 2012 11:32 AM
  • Joined: 13 Mar 2008
Guys,

I was working on doing myself earlier and was almost there but this sounds better. However, can we finally have a perfect version based on all inputs?

Also, it will be great if someone can verify the script by selecting multiple lines with a few words in uppercase and few in mixed case. Thanks.

Regards.