mIRC Spell Checker

Remote scripts are designed to listen for and respond to remote events, in other words, events caused by people other than yourself. Typical events to respond to might be a PING or a FINGER request, a DCC CHAT or SEND request, a FILE SENT or FILE RECEIVED event, someone JOINing or QUITting a channel and so on. In this example we'll look at a slightly different event, the ON INPUT event, which happens every time you enter something in an edit box and press enter. In other words, every time you say something to someone on IRC.

This is what happens: You type something in, you press Enter, the ON INPUT event is triggered, any processing attached to that event is carried out, and the text is then sent to the server, and finally out to everyone else's screens. We're going to use the ON INPUT event to alter our text before it gets sent to the server; specifically; we're going to look for certain spelling mistakes and correct them.

How to enter the script

Open the Remote Events screen by clicking on the Events icon (it's the one next to the popups icon). Enter this text in the edit box.

on 1:INPUT:*: {
  if ($left($1,1) != /) {
    set %typed $spellchk($1-)
    msg $active %typed
    halt
  }
}

Make sure you enter this exactly as I've typed it here (you can cut and paste it from your browser if you prefer). Now click on the Aliases tab and enter this text at the bottom of your alias list:

spellchk {
  set %whatever $1-
  %whatever = $replace(%whatever,teh,the)
  %whatever = $replace($replace(%whatever,didnt,didn't),wasnt,wasn't)
  %whatever = $replace($replace($replace(%whatever,isnt,isn't),hte,the),htis,this)
  return %whatever
}

Ok, save your changes and if you're sitting comfortably, I'll explain what everything does. Let's take the first line of the first part

on 1:INPUT:#: {
on 1: - This indicates that the event tracking is switched on, if you want to turn off the spellchecker without removing it from the system, change this to read OFF. The first digit indicates that this is procedure will apply to all level 1 users of the system, in other words, everybody. Don't worry too much about this for now, It's explained in more detail in the access levels section.

INPUT - this is the event we're going to get mIRC to look at. Other events are JOIN, PART, QUIT and so on. You'll have to take a look at the mIRC FAQ or the list of remote events to see what other events are out there and what they look for. All you need to know is that the INPUT event processes whatever you type in to the edit box.

# - The hash character indicates a channel, so this script will pick up everything you type in to a channel. It will not catch what you type into a DCC chat or a Query chat.

Finally on this line, the { indicates that there is more than one command in the script. There are two ways of writing a script down, you can say

command1 | command2 | command3
(as with multi-command aliases) or you can say:
{ command1
  command2
  command3
} 
mIRC doesn't differentiate between the two, but the second one is a bit easier to read.

Now for line 2:
  if ($left($1,1) != /) {
  

This may look very complicated, but we'll take it step by step, starting in the middle:
$1 is the first parameter (i.e. the first word of whatever you typed in)
$left($1,x) is an identifier which tells us the left-hand x-most characters of whatever $1 is. So $left($1,1) gives us the first character of the first word of whatever we typed in.
!= means not equals to

So, the whole line means "if the first character of whatever we typed in is not a slash, then do the following". The reason we're doing this is because we don't want to process lines starting with a slash, because they are mIRC commands, or your own aliases, so we'd best leave them alone

Line 3:

    set %typed $spellchk($1-)

Now we're using a variable, which we're going to call %typed. All variable names start with the percent character, so you can differentiate between them and identifiers.

$spellchk starts with a dollar sign, so it's another identifier. You won't find this one in the help file, though, because we've written it ourselves, and put it in the Aliases file. I'll explain it step-by-step later. What identifiers do is take something you give it (the parameter), process it, and give you something else back. In the case of $left, above, the parameter is the first word of your sentence, and the return value is the first letter of that word. In this case, with $spellchk, the parameter is $1-, which means "the first word and everything after it", in other words, the whole sentence. This is known as a string, in fact any collection of characters is referred to as a string. All you need to know about $spellchk for the time being is that it takes the sentence you've typed in, does something with it, and gives us something back, which we're going to store in a variable we've called %typed.

Line 4:

    msg $active %typed

This line sends the modified text to the active channel. Using msg $active does the same thing as using the /say command (the slash at the beginning is optional when you're putting commands in remote scripts), but /say will not work with most remote events, so msg $active is preferred instead. $active is a standard mIRC identifier that returns the name of the active window.

Line 5:

    halt
    

This stops any other standard mIRC processing which may have been associated with the ON INPUT event. We want to do this because we've done our own processing instead and don't want mIRC to get in the way of things. If we leave this line out then mIRC sends our original text to the channel as well, which means you look like you're saying everything twice.

Finally, we have two closed curly brackets to match the two open ones we put in earlier. Notice the way the code is written down - it is indented so that certain lines match up with other lines. This is to make it slightly easier to see what is going on; we can see, for example, that the first close bracket is for the if statement, and the second one is for the ON INPUT statement.

Ok, now for the new identifier, $spellchk. Remember that identifiers take a parameter, do something with it and give you something back. In our case, $spellchk is going to take the string containing our sentence, scan it for incorrectly spelled words, and replace them with the correct spelling. Now this isn't quite as clever as it first sounds, because we're going to have to tell it what to look for. In a way this is good, because you can customise the routine to look for your own common spelling mistakes and typing errors. It works like this:

Line 1:

spellchk {

In this line we give the name of the identifier (it can be any name we like, as long as we call it by the same name in the ON INPUT routine, and the name we choose isn't already the name of an existing mIRC identifier) and the open curly bracket tells mIRC that there are several commands to follow.

Line 2:

  set %whatever $1-
  

This defines a variable, called %whatever, which is initially set to the entire sentence you typed in ($1- meaning the same as it did in the ON INPUT event).

Line 3:

  %whatever = $replace(%whatever,teh,the)
  

This line uses the $replace identifier (which is a pre-defined one, so it's in the mIRC help file) to replace the phrase "teh" with the phrase "the".

The $replace identifier has the following syntax: $replace(text you're looking through, text you're looking for, text to replace it with). If the text you're looking for isn't in the sentence, then the $replace does nothing. When it's finished with the sentence, it puts it back into the variable %whatever.

(aside - be careful with what you're getting the $replace command to look for. If the search phrase is too small then it might match letters in the middle of other words, and people won't have a clue what you're talking about! For example, replacing 'ti' with 'it' is fine in theory, but words like 'time' will come out as 'itme', so think ahead.) (Update 6 June 1999 - I've just found a way round this - click here for details.)

Line 5:
  %whatever = $replace($replace(%whatever,didnt,didn't),wasnt,wasn't)
  

This works in exactly the same way as the previous command, except that it can do two corrections in one go. This is simply a shortcut which saves you doing a lot more typing. Firstly the middle $replace is evaluated, and if the word didnt exists in the sentence then it is replaced with didn't. Then the outside $replace is evaluated, and if the word wasnt is in your sentence then it is replaced with wasn't. You can add as many $replace statements on the same line as you wish, as you can see, line 6 has three embedded $replace statements. You could write these separately if you wish, it makes no difference to mIRC. If you're thinking ahead, you may realise by now that this $spellchk identifier can have dozens, if not hundreds, of separate $replace statements. This is not a major problem, as you only have to set them up once.

New in mIRC 5.4 - the $replace identifier can now handle multiple replaces in one line, so you can now say:

%whatever = $replace(%whatever,didnt,didn't,wasnt,wasn't,isnt,isn't)
  

Line 8
  return %whatever
  

Finally the contents of the %whatever variable is passed back (returned) to whatever routine called $spellchk, in our case, the ON INPUT event. Back in the ON INPUT event, this returned value is then put into the %typed variable as described earlier. To finish off the identifier, we close the curly bracket to tell mIRC that we've come to the end of our set of commands.

In order to get the full benefit of this spell-checker, you will have to analyse what spelling and typing errors you make on a regular basis, and add them to the $spellchk routine.

Now that we have $spellchk defined as a new identifier, we can use it in other cases as well. This is the same as for any new identifier. Once they are defined, they can be used over and over again, in different routines.

Update 6 June 1999 - I mentioned earlier that the $replace identifier will just replace what text it sees regardless of whether it is a whole word or not. I've recently discovered a workaround for this, which is as follows:

  set %wrd1 = $chr(32) $+ ot $+ $chr(32)
  set %wrd2 = $chr(32) $+ to $+ $chr(32)
  %whatever = $replace(%whatever,%wrd1,%wrd2)
  

As you can see, we want to replace the word 'ot' with the word 'to', but only if it is a whole word surrounded by spaces ($chr(32) represents a space character). The $+ means "add the two strings together", so "Hi " $+ "there" will give you "hi there". In our example, $chr(32) $+ ot $+ $chr(32) gives us the string space-o-t-space. We have to use variables, as putting the whole thing in one line ($replace(%whatever,$chr(32) $+ ot $+ $chr(32),$chr(32) $+ to $+ $chr(32)) doesn't work for some unknown reason.

Using the code above will replace I went ot the zoo and had lots of fun with I went to the zoo and had lots of fun, correcting the spelling mistake but leaving the word lots alone.

Looking at this example it doesn't take us long to realise that we have to hard-code every word we want spell-checked in two variables, which is very time-consuming and wasteful. A better solution, perhaps, would be to list all the spelling errors and their corrections in a text file and get mIRC to read them in one at a time. This is what the next version of the script does.

Don't worry if you can't follow this new script just yet. I added it to the tutorial after the rest of it was written and a lot of the commands it uses are explained in greater detail on the next page, so if you're a bit confused about how this script works read about the Colourful Text script first and come back here later.

spellchk {
  ; first check that the file exists. If it doesn't, do nothing
  var %spellfile = $mircdir\spells.txt
  if $exists(%spellfile) {
    var %spellphrase $1-
    ; replace all the spaces with an arbitrary character unlikely to appear in normal conversation
    %spellphrase = $replace(%spellphrase,$chr(32),$chr(1))
    var %ct = 1
    var %nlns = $lines(%spellfile)
    ; repeat the indented code while the number in %ct is less than or equal to
    ; the number in %nlns
    while (%ct <= %nlns) {
      ; read line number %ct from the file
      var %wrd1 = $read -l $+ %ct %spellfile
      inc %ct
      ; read the next line
      var %wrd2 = $read -l $+ %ct %spellfile
      ; correct the spelling mistake if it is there
      %spellphrase = $replace(%spellphrase,%wrd1,%wrd2)
      ; go to the next line
      inc %ct
    }
    ; replace all the arbitrary characters with spaces
    %spellphrase = $replace(%spellphrase,$chr(1),$chr(32))
  return %spellphrase  }
  else return $1-
}

Now here's an explanation of the new ideas introduced in this script.

  ; first check that the file exists. If it doesn't, do nothing

This is a comment. Comments must be on a line on their own and start with a semi-colon. Everything on comment lines is ignored by mIRC. Comments are vital to any script, as they help you understand what is going on when you come back to it six months (or even a week!) later.

  var %spellfile = $mircdir\spells.txt

We're going to be using a file called spells.txt, which is going to be in the same directory as mIRC itself. We use the $mircdir identifier to get mIRC to tell us which directory it has been installed into. As we're going to be using the filename quite a bit in the script we allocate it to a variable, which should hopefully make the script a bit easier to read. Notice the use of the var command. This was introduced in mIRC 5.6, and defines the variable as being local to the alias, which means that it only exists while the alias is being executed. As soon as the alias finishes, the variable is deleted, which automatically frees up memory and also saves us the trouble of doing it. You will also notice that there are no unset commands in this alias.

  if $exists(%spellfile) {

$exists will tell us whether the file exists or not - if it doesn't exist then the alias simply ignores what is between the curly braces and returns whatever it was that we typed in in the first place.

    var %nlns = $lines(%spellfile)

This sets the variable %nlns to be the number of lines contained in the file represented by the variable %spellfile.

    while (%ct <= %nlns) {
The while command is new in mIRC 5.7, and it tells mIRC to run the commands between the {} brackets while the condition in the () brackets is true. In this example we're using the %ct variable to act as a counter as to which line in the file we're currently processing. While the counter is less than or equal to the number of lines in the file, run the commands in the loop. Otherwise, run the commands after the loop.

      var %wrd1 = $read -l $+ %ct %spellfile

Let's take this line bit by bit. The new command is the $read command. This command reads a line from a text file, and the -l switch tells it to read a specific line. So $read -l3 spells.txt will read the third line from the spells.txt file. The $+ will put the -l and the value of the %ct variable together as one string, so -l $+ %ct will give us -l3 if %ct is 3, -l7 if %ct is 7, and so on. Finally the whole thing (which is the contents of the relevant line of the spells.txt file, remember), is allocated to the %wrd1 variable for later use.

Using the $read command introduced a few of its own problems, which cropped up from the added functionality of checking for whole words rather than just sequences of characters. When $read reads in a line from a text file, it executes all the identifiers in the line, so when we read $chr(32) $+ ot $+ $chr(32) into %wrd1, %wrd1 is set to ot, losing the spaces. This is the same problem encountered in the colourful words script explained on the next page, so we use the same solution, using $chr(1) instead of $chr(32). Also, I had intended to put both words on the same line and use $gettok to separate them, i.e.

var %splline = $read -l $+ %ct $mircdir\spells.txt
var %wrd1 = $gettok(%splline,1,46) ; chr(46) is a full stop
var %wrd2 = $gettok(%splline,2,46)

This worked fine for the simple expressions like didnt.didn't but as soon as we got to a more complicated expression involving $chr and $+ the $gettok refused to work as anticipated. (see the next page for a more detailed explanation of $gettok). So the solution was to put each misspelled word and it's correction on separate lines in the text file.

      inc %ct

This line increases the number stored in %ct by one. inc is short for increment and there is a similar command, dec, short for decrement, which will reduce the value in the variable by one.

That's all for the new commands introduced in this script. The main advantages of this script over previous versions is that you can check for whole words a lot easier. When you encounter a new spelling mistake you only have to edit the text file and not the alias itself. The main disadvantage of this script is that it can be quite a bit slower than the original example.

The associated text file contains lines such as these:

didnt
didn't
whrer
where
hwo
who
$chr(1) $+ ot $+ $chr(1)
$chr(1) $+ to $+ $chr(1)
$chr(1) $+ nad $+ $chr(1)
$chr(1) $+ and $+ $chr(1)
$chr(1) $+ u $+ $chr(1)
$chr(1) $+ you $+ $chr(1)
$chr(1) $+ i $+ $chr(1)
$chr(1) $+ I $+ $chr(1)
$chr(1) $+ r $+ $chr(1)
$chr(1) $+ are $+ $chr(1)
$chr(1) $+ ht
$chr(1) $+ th
;t $+ $chr(1)
't $+ $chr(1)

Note that the last four lines are different to the others. The penultimate pair replace ht with th, but only if there is a space before the ht. This corrects mistakes such as I htought so. Note that it will not correct the spelling mistake if the word is the first one entered, as it will not be preceded by a space. The last pair replaces ;t with 't in cases where you type isn;t instead of isn't, but will not replace mistakes at the end of a line as they are not followed by a space.

New Techniques introduced in this section - see mIRC help file for more information
on INPUT event
$left identifier
$replace identifier
$read identifier
$chr identifier
$lines identifier
$mircdir identifier
$+ identifier
var command
halt command
if command
inc command
while command
return command