Quick spell check
Please note: This article assumes you are using Linux and KDE 3.x. If you're not sure whether you are or not, you are probably not :-)
First, a confession: this is inspired mostly from the Spellcheck Anywhere In KDE how-to in the KDE Wiki. I wrote this how-to because:
- I couldn't get his method to work (although I have now)
- This solution is quite a bit quicker (but simply produces a list of misspelled words, while the one above does a proper spell check)
The solution below appeals to me because:
- It uses classic command line UNIX utilities and methods
- It combines these with a modern technology - KDE's dcop
- The whole lot is achieved through a 'single line' script
- It's quick, even on this old 500 MHz machine
- My spelling is usually OK, but my typing is pretty bad, so a list of misspelled words is what I need.
The script
So for the impatient among you, the script is below (or you can download it):
#!/bin/sh # misspelled_words.sh dcop knotify Notify notify spellcheckcomplete misspelled_words.sh "Misspelled words:$(echo -e '\n ')$(dcop klipper klipper getClipboardContents | aspell list | sort | uniq -c | sed 's/^ *//g; s/ /\*/' | tr "\n" ' ' | fold -s)" '' '' 2 0
The script requires aspell which is probably present on most systems that have KDE. It also uses 5 classic UNIX utilities (or their GNU clones): sort, uniq, sed, tr and fold, making this one of my favorite one liners. How to use it is given at the bottom, but first:
Explanation
How did I arrive at that monstrosity? Those experienced in the command line will know how to break it down, outside in, but to others it might seem impossibly complicated. I'll start at the beginning.
For this bit you'll need to open a terminal - xterm or konsole for example. (One very important tip that makes things much quicker from here in is the 'history' capability of bash - pressing the up arrow key shows you the previous command you entered, which you can then modify).
The first task is to find a command line program that will do the spell checking for us. A great command for this sort of task is 'apropos':
$ apropos spell
american (5) - flag format for English ispell dictionaries
aspell (1) - An interactive spell checker
aspell-import (1) - import old personal dictionaries into GNU Aspell
british (5) - flag format for English ispell dictionaries
buildhash (1) - Interactive spelling checking
english (5) [american] - flag format for English ispell dictionaries
findaffix (1) - Interactive spelling checking
icombine (1) - Interactive spelling checking
ijoin (1) - Interactive spelling checking
ispell (1) - Interactive spelling checking
...
I know I have aspell installed and configured from KDE's spelling checker, so I'll use that. A quick look at it's help:
$ aspell --help
Aspell 0.50.5 alpha. Copyright 2000 by Kevin Atkinson.
Usage: aspell [options] <command>
<command> is one of:
-?|help display this help message
-c|check <file> to check a file
-a|pipe "ispell -a" compatibility mode
-l|list produce a list of misspelled words from standard input
[dump] config dumps the current configuration to stdout
config <key> prints the current value of an option
soundslike returns the soundslike equivalent for each word entered
filter passes standard input through filters
-v|version prints a version line
dump|create|merge master|personal|repl [word list]
dumps, creates or merges a master, personal, or replacement word list.
[options] is any of the following:
...
I don't want interactive mode, as that would require opening a terminal. Instead the 'aspell list' option looks good - it just produces a list of misspelled words. I need to pass the text to check into it's 'standard input'. You can enter text into the standard input by typing directly - but that won't be any good for this use, as I've already typed it and just want it checking. So I need to do it using 'pipes' - the | character. The output of one command can simply be 'piped' into the input of another command (see 'man bash' and the section 'Pipelines' for more information). As a test, I'll use echo, which simply outputs its argument to the standard output:
$ echo "A line with a misspeled word" A line with a misspeled word $ echo "A line with a misspeled word" | aspell list misspeled
It worked! Now I need to use the clipboard contents as the input to aspell. Thankfully, if you have klipper running, this is very easy to do using dcop. I have a long bit of text from a previous article in the clipboard for test purposes.
$ dcop klipper klipper getClipboardContents This is an article/tutorial .... $ dcop klipper klipper getClipboardContents | aspell list KNotify KNotify DCOP KNotify
That's nice, but I'd rather have 'KNotify' written once, perhaps with something to show how many times it occurred. Thankfully the command 'uniq' comes to the rescue - it will merge any identical consecutive lines. To get identical lines to be consecutive, I must first sort the list using 'sort', and if I pass it the '-c' option to uniq it will give me a count as well.
$ dcop klipper klipper getClipboardContents | aspell list | sort | uniq -c
1 DCOP
3 KNotify
I really want to get rid of those leading spaces, and change '3 KNotify' into '3*Knotify'. A simple sed script containing two substitutions, tacked onto the end of the chain, should do the trick (for information on how this works, see the sed manual):
$ dcop klipper klipper getClipboardContents | aspell list | sort | uniq -c | sed 's/^ *//g; s/ /\*/'
1*DCOP
3*KNotify
For display purposes, I want the list formatted so that it will make the most of both horizontal and vertical space. To do this, I'll turn the new lines into spaces (which gives us one long line), and then wrap that line to a width of 80 columns, but only breaking on spaces. A combination of 'tr' and 'fold' will do that:
$ dcop klipper klipper getClipboardContents | aspell list | sort | uniq -c | sed 's/^ *//g; s/ /\*/' | tr "\n" ' ' | fold -s
1*DCOP 3*KNotify
Finally, I've got to get this to be displayed outside of an xterm. I'll use the method described in my KNotify tutorial to display a KDE message box. This step will introduce command substitution using $(...) syntax. The command inside the $(...) is run first, and its output placed back into the line as if it had been typed there. I'll also add "Misspelled words" to the front of the message that is seen, and a new line:
$ dcop knotify Notify notify spellcheckcomplete misspelled_words.sh "Misspelled words:$(echo -e '\n ')$(dcop klipper klipper getClipboardContents | aspell list | sort | uniq -c | sed 's/^ *//g; s/ /\*/' | tr "\n" ' ' | fold -s)" '' '' 2 0
Using it
To use it, save the script above as misspelled_words.sh in a convenient directory (preferably your personal bin directory), and make sure it is 'executable'.
Now use KHotKeys to set up a global shortcut:
Open the KDE Control Center
Open the KHotKeys module - it's in Regional & Accessibility
- For convenience, create a new group for various global shortcuts:
- Click on New Group
- On the right hand side, set the Action group name to global (or misc, or whatever you like).
- Now to create a new action:
- Click New Action, and on the right hand side set it's name to Misspelled words
- I tend to use Generic actions, as they are easier to modify later (for example to add a new trigger, or change the implementation). So leave the action type as Generic.
- In the Triggers tab, select New/Shortcut trigger. Now you need to choose a shortcut - I tend to use the Windows key for 'global' shortcuts, that way it's unlikely to interfere with any shortcuts that are defined in individual applications (by default, KDE and Unix/Linux apps don't tend to use the Windows key). So 'Win+S' is my shortcut here.
- In the Actions tab, select New/Command/URL. Enter the path to the script - in my case this is /home/luke/bin/misspelled_words.sh - and press OK
Now press Apply
And that's it! To test it out, copy some text to the clipboard - how about this line:
A line of text with a mandatory misspeling
Then try using the keyboard shortcut you defined above. If all is well, you'll get a message box like the one above saying 'Misspelled words: 1*misspeling'.
Other ideas
- Use a very similar method to the one above to text statistics e.g. number of characters, number of words. The command wc will help
- Use klipper's 'setClipboardContents' command in conjunction with 'getClipboardContents', and you can create 'filters' - actions that replace the clipboard contents with a filtered version. Useful things might include HTML-ising some text (escaping HTML entities), or expanding common acronyms.
Links
Article written by Luke Plant, 2004-10-13.
Changelog:
- fixed to work with later versions of aspell that use '-l' for
language, 2006-01-15
- minor changes plus 'Other ideas' and 'Links' sections on 2004-10-14, 15:30.
Comments
No comments posted