Exclude words when converting to "Title Case" - AutoHotkey Script

Joe WinogradDeveloper
CERTIFIED EXPERT
50+ years in computers
EE FELLOW 2017 — first ever recipient of Fellow award
MVE 2015,2016,2018
CERTIFIED GOLD EXPERT
DISTINGUISHED EXPERT
Published:
Updated:
Edited by: Andrew Leniart
In a recent question here at Experts Exchange, a member wants to enhance an AutoHotkey script that performs "Title Case" conversion. The enhancement is to allow specification of words that are excluded from the capitalization (conjunctions and prepositions). This article presents such a solution.

In an interesting question here at Experts Exchange, a member asked how an AutoHotkey script that performs "Title Case" capitalization can be enhanced to exclude words from the capitalization, such as the, to, and, from, for, etc. — i.e., specified conjunctions and prepositions. The AutoHotkey code in this article provides such a solution. It works as follows:


• Defines a keyboard shortcut (aka "hotkey") that performs the steps below.


• Operates on the selected (highlighted) text by first copying it to the clipboard via Ctrl+C.

• Capitalizes all words using the AutoHotkey built-in StringUpper command with the T (Title Case) option.

• Reads a simple, plain text file that contains the words to be excluded from capitalization. Each line in the file has one exclusion word on it. A sample exclude file is attached to this article.

• Un-capitalizes the words in the Title that are in the exclusion list, unless it is the first word in the Title, in which case it stays capitalized. For example, this:

the quick brown fox jumps over the lazy dog and a cat simply for fun

becomes this (using the attached exclude file):

The Quick Brown Fox Jumps Over the Lazy Dog and a Cat Simply for Fun

• Puts the converted Title on the clipboard and types it via the SendInput command.

The hotkey in the posted code is Alt+Ctrl+T (with the T standing for Title case), but you may change it to whatever you want. The general format is Modifiers+Key, where the Key may be (nearly) any key on the keyboard (including letters, numbers, function keys, and numeric keypad keys) and the Modifiers may be Alt, Ctrl, Shift, and Win (the Windows logo key), specified as follows:

! (exclamation mark) ==> Alt
^ (caret, circumflex, hat) ==> Ctrl
+ (plus sign) ==> Shift
# (hash mark, pound sign, octothorpe) ==> Win


You may use any number of those modifiers, and they may be in any order, that is, "!^" (Alt+Ctrl) behaves the same as "^!" (Ctrl+Alt). Also, you may use no modifiers. For example, you could have a function key or a numeric keypad key by itself be the hotkey.


The Key names are defined here:
List of Keys


As part of designing this script, I did some web research on capitalization. I thought it would be straightforward — being a bit of a grammarian myself, I should have known better. :)

First, I went after an easy-to-use list of prepositions and found these:

https://www.englishclub.com/grammar/prepositions-list.htm
https://www.english-grammar-revolution.com/list-of-prepositions.html

More than I was expecting! The list of conjunctions was much better:

https://www.english-grammar-revolution.com/list-of-conjunctions.html

Second, I wanted to be certain of the rules for Title Case capitalization and found this:

https://www.grammarcheck.net/capitalization-in-titles-101

Some of the advice there is perplexing, such as do not capitalize with, but do capitalize without. Apparently, the reason for this is the rule that says, "Always capitalize words of five or more letters..." Can't say I buy that one and, indeed, my attached sample exclude file contains several words with five or more letters. The choice, of course, is yours — create whatever exclude file you want.

The EE member specifically asked for an AutoHotkey solution. If other readers of this article are not familiar with AutoHotkey, my EE article will get you going on it:

AutoHotkey - Getting Started

Here is the script in a code block (it is also attached as a file at the end of the article for easy downloading):

; Joe Winograd 3-May-2020 Version 2 - puts new Title on clipboard
#Warn,UseUnsetLocal ; warning on uninitialized variables
#NoEnv ; avoid checking empty variables to see if they are environment variables
#SingleInstance Force ; replace old instance immediately
SetBatchLines,-1 ; run at maximum speed
ClipWaitTime:=3 ; number of seconds to wait for text to appear on clipboard before declaring it a timeout

!^t:: ; pick whatever hotkey you want - this is Alt+Ctrl+T (stands for Title case)
; I put exclude file in same folder as script - change line below to put it wherever you want
ExcludeFile:=A_ScriptDir . "\TitleCaseExclude.txt" ; file of words to exclude (conjunctions and prepositions)
FileRead,Exclude,%ExcludeFile%
If (ErrorLevel!=0)
{
  MsgBox,4112,Error,Error Level %ErrorLevel% trying to read exclude file:`n`n%ExcludeFile%
  Return
}
Clipboard:="" ; clear clipboard (with Ctrl+c below, this should not be needed, but just in case)
SendInput,^c ; copy selected text to clipboard
ClipWait,%ClipWaitTime% ; wait for text to appear on clipboard
If (ErrorLevel=1) ; copy timed out
{
  MsgBox,4144,Error,Text did not appear on clipboard after Ctrl+C
  Return
}
ClipboardFirstChar:=SubStr(Clipboard,1,1) ; get first character
StringUpper,ClipboardFirstChar,ClipboardFirstChar ; capitalize first letter to use later
StringUpper,ClipboardTitle,Clipboard,T ; convert to Title case
Loop,Parse,Exclude,`n,`r ; loop through all exclusions
  ClipboardTitle:=RegExReplace(ClipboardTitle,"i)\b" . A_LoopField . "\b",A_LoopField) ; change exclusions back to lower case
Clipboard:=ClipboardFirstChar . SubStr(ClipboardTitle,2) ; capitalize first word even if an exclusion
ClipWait,%ClipWaitTime% ; wait for text to appear on clipboard
If (ErrorLevel=1) ; copy timed out
{
  MsgBox,4144,Error,Text did not appear on clipboard after changing Title
  Return
}
SendInput {Text}%Clipboard% ; {Text} mode interprets ^+!#{} literally instead of translating, but `r, `n, `t, `b are still translated
Return

My hope is that the descriptive variable names along with the comments in the script provide enough documentation for readers to modify it, but if you have any questions, post them here and I'll try to assist.


Note that there's a variable called ClipWaitTime that is the number of seconds to wait for text to appear on the clipboard before declaring it a timeout. I set this to 3, which should be adequate in most cases, but you may need to experiment with this value.

The script should work in all versions of Windows from XP through W10, both 32-bit and 64-bit. I tested it on W7/64-bit, W8.1/64-bit, W10/32-bit, and W10/64-bit. The products that I tested it with are KEDIT, Notepad, Notepad++, WordPad, and Word 365. All worked perfectly, and it should work in any product that handles text, but please let me know if you have any problems.

Important Caveat: The script uses AutoHotkey's {Text} mode when sending the updated Title. The purpose of this is to interpret the ^+!#{} characters literally instead of translating them (such as ^ to Ctrl, ! to Alt, etc.). However, it is important to note that these characters are still translated:

`n   newline (linefeed/LF)
`r   carriage return (CR)
`b   backspace
`t   tab (horizontal)


Article Update on 3-May-2020: The script initially posted puts the new Title on the clipboard, which some users may want. But based on an EE member's feedback, I created another version of the script that retains what was on the clipboard before the hotkey fired. It does this by saving the entire contents of the clipboard before doing the Ctrl+C and then restoring the original contents before exiting. Here's the new version in a code block (it is also attached as a file at the end of the article for easy downloading — the names of the files make it clear which is which):

; Joe Winograd 3-May-2020 Version 3 - restores original clipboard
#Warn,UseUnsetLocal ; warning on uninitialized variables
#NoEnv ; avoid checking empty variables to see if they are environment variables
#SingleInstance Force ; replace old instance immediately
SetBatchLines,-1 ; run at maximum speed
ClipWaitTime:=3 ; number of seconds to wait for text to appear on clipboard before declaring it a timeout

!^t:: ; pick whatever hotkey you want - this is Alt+Ctrl+T (stands for Title case)
; I put exclude file in same folder as script - change line below to put it wherever you want
ExcludeFile:=A_ScriptDir . "\TitleCaseExclude.txt" ; file of words to exclude (conjunctions and prepositions)
FileRead,Exclude,%ExcludeFile%
If (ErrorLevel!=0)
{
  MsgBox,4112,Error,Error Level %ErrorLevel% trying to read exclude file:`n`n%ExcludeFile%
  Return
}
ClipboardSave:=ClipboardAll ; save clipboard to restore later
Clipboard:="" ; clear clipboard (with Ctrl+c below, this should not be needed, but just in case)
SendInput,^c ; copy selected text to clipboard
ClipWait,%ClipWaitTime% ; wait for text to appear on clipboard
If (ErrorLevel=1) ; copy timed out
{
  MsgBox,4144,Error,Text did not appear on clipboard after Ctrl+C
  Clipboard:=ClipboardSave ; restore original clipboard
  ClipboardSave:="" ; free memory in case clipboard was big
  Return
}
SelectedText:=Clipboard ; get selected text
Clipboard:=ClipboardSave ; restore original clipboard
ClipboardSave:="" ; free memory in case clipboard was big
FirstChar:=SubStr(SelectedText,1,1) ; get first character
StringUpper,FirstChar,FirstChar ; capitalize first letter to use later
StringUpper,NewTitle,SelectedText,T ; convert to Title case
Loop,Parse,Exclude,`n,`r ; loop through all exclusions
  NewTitle:=RegExReplace(NewTitle,"i)\b" . A_LoopField . "\b",A_LoopField) ; change exclusions back to lower case
NewTitle:=FirstChar . SubStr(NewTitle,2) ; capitalize first word even if an exclusion
SendInput {Text}%NewTitle% ; {Text} mode interprets ^+!#{} literally instead of translating, but `r, `n, `t, `b are still translated
Return


If you find this article to be helpful, please click the thumbs-up icon below. This lets me know what is valuable for EE members and provides direction for future articles. Thanks very much! Regards, Joe


TitleCase-New-Title-On-Clipboard.ahk
TitleCase-Original-Clipboard-Restored.ahk

TitleCaseExclude.txt

3
4,257 Views
Joe WinogradDeveloper
CERTIFIED EXPERT
50+ years in computers
EE FELLOW 2017 — first ever recipient of Fellow award
MVE 2015,2016,2018
CERTIFIED GOLD EXPERT
DISTINGUISHED EXPERT

Comments (0)

Have a question about something in this article? You can receive help directly from the article author. Sign up for a free trial to get started.