{"thread":{"id":"11864","subject":"[PATCH] git-gui: Automatically spell check commit messages as the user types","startedAt":"2008-02-04T08:41:54Z","lastAt":"2008-02-05T05:06:02Z","messageCount":5,"participants":["Shawn O. Pearce","Wincent Colaiuta","Jakub Narebski","Adam Flott"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"67336","messageId":"20080204084153.GA9997@spearce.org","threadId":"11864","inReplyTo":null,"subject":"[PATCH] git-gui: Automatically spell check commit messages as the user types","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2008-02-04T08:41:54Z","receivedAt":"2008-02-04T08:41:54Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"[This is also in my `pu` branch on repo.or.cz/git-gui.]\n\nAs you can see the commit message was rather long.  I used this\nfeature the entire time while writing it, and I have to say, it\nsaved me from my horrible spelling and typing skills.  It also\ndidn't feel like there was any significant lag, although every\nonce in a while it will mark a word that you are in the middle\nof typing as misspelled, and catch up and correct that once you\nfinish the word.  I guess that's what you get for slowing down\nand taking a few extra milliseconds to move the fingers.  :)\n\nI need to test this on other platforms and with other languages,\nbut its working quite nicely on my Mac OS X system.  I did have to\ninstall Aspell through DarwinPorts, sadly Mac OS 10.4 does not come\nwith it pre-installed.\n\nPersonally I prefer this style of spellchecking over the \"lets show\na modal dialog and ask the user to check one word at a time through\nthe document\".  Mainly because this style gives you full context,\nwhile the modal dialog forms almost never do.\n\nI'm not sure how to configure Aspell for other languages, it just\nmagically came up with English on my system.  Since git-gui has i18n\nsupport almost everywhere else I want to get that settled before\nthis topic merges into my master branch.  I've CC'd Christian and\nJohannes as they have been a big help in the past with the git-gui\ni18n effort and I would value any input they might have.\n\n\n--8>--\n[PATCH] git-gui: Automatically spell check commit messages as the user types\n\nMany user friendly tools like word processors, email editors and web\nbrowsers allow users to spell check the message they are writing\nas they type it, making it easy to identify a common misspelling\nof a word and correct it on the fly.\n\nWe now open a bi-directional pipe to Aspell and feed the message\ntext the user is editing off to the program about once every 300\nmilliseconds.  This is frequent enough that the user sees the results\nalmost immediately, but is not so frequent as to cause significant\nadditional load on the system.  If the user has modified the message\ntext during the last 300 milliseconds we delay until the next period,\nensuring that we avoid flooding the Aspell process with a lot of\ntext while the user is actively typing their message.\n\nMisspelled words are highlighted in red and are given an underline,\ncausing the word to stand out from the others in the buffer.  This is\na very common user interface idiom for displaying misspelled words,\nbut differs from one platform to the next in slight variations.\nFor example the Mac OS X system prefers using a dashed red underline,\nleaving the word in the original text color.  Unfortunately the\ncontrol that Tk gives us over text display is not powerful enough\nto handle such formatting so we have to work with the least common\ndenominator.\n\nThe top suggestions for a misspelling are saved in an array and\noffered to the user when they right-click (or on the Mac ctrl-click)\na misspelled word.  Selecting an entry from this menu will replace\nthe misspelling with the correction shown.  Replacement is integrated\nwith the undo/redo stack so undoing a replacement will restore the\nmisspelled original text.\n\nIf Aspell could not be started during git-gui launch we silently eat\nthe error and run without spell checking support.  This way users\nwho do not have Aspell in their $PATH can continue to use git-gui,\nalthough they will not get the advanced spelling functionality.\n\nIf Aspell started successfully the version line and language are\nshown in git-gui's about box, below the Tcl/Tk versions.  This way\nthe user can verify the Aspell function has been activated.\n\nIf Aspell crashes while we are running we inform the user with an\nerror dialog and then disable Aspell entirely for the rest of this\ngit-gui session.  This prevents us from fork-bombing the system\nwith Aspell instances that always crash when presented with the\ncurrent message text, should there be a bug in either Aspell or in\ngit-gui's output to it.\n\nWe take the simple approach and shove the entire message at Aspell\neach time we decide to run the spellchecker.  The end of the message\nis determined by also sending a command to get the current language,\nas this line's result is uniquely different from the other output we\nare receiving from Aspell.  While Aspell is chewing on a message we\nstop sending output to it, even if the user has modified the message\nbuffer and waited at least our 300 millisecond window.  This single\nmessage at a time validation prevents flooding the pipe to Aspell.\n\nWe escape all input lines with ^, as recommended by the Aspell manual\npage, as this allows Aspell to properly ignore any input line that is\notherwise looking like a command (e.g. ! to enable terse output).  By\nusing this escape however we need to correct all word offsets by -1 as\nAspell is apparently considering the ^ escape to be part of the line's\ncharacter count, but our Tk text widget obviously does not.\n\nSigned-off-by: Shawn O. Pearce <spearce@spearce.org>\n---\n git-gui.sh         |   53 ++++++++++++++++-\n lib/about.tcl      |    5 ++\n lib/spellcheck.tcl |  169 ++++++++++++++++++++++++++++++++++++++++++++++++++++\n 3 files changed, 226 insertions(+), 1 deletions(-)\n create mode 100644 lib/spellcheck.tcl\n\ndiff --git a/git-gui.sh b/git-gui.sh\nindex f42e461..0f8627e 100755\n--- a/git-gui.sh\n+++ b/git-gui.sh\n@@ -1683,6 +1683,7 @@ set is_quitting 0\n proc do_quit {} {\n \tglobal ui_comm is_quitting repo_config commit_type\n \tglobal GITGUI_BCK_exists GITGUI_BCK_i\n+\tglobal SPELL_fd SPELL_i\n \n \tif {$is_quitting} return\n \tset is_quitting 1\n@@ -1710,6 +1711,16 @@ proc do_quit {} {\n \t\t\t}\n \t\t}\n \n+\t\t# -- Cancel our spellchecker if its running.\n+\t\t#\n+\t\tif {[info exists SPELL_fd]} {\n+\t\t\tcatch {fileevent $SPELL_fd readable {}}\n+\t\t\tcatch {close $SPELL_fd}\n+\t\t}\n+\t\tif {[info exists SPELL_i]} {\n+\t\t\tafter cancel $SPELL_i\n+\t\t}\n+\n \t\t# -- Remove our editor backup, its not needed.\n \t\t#\n \t\tafter cancel $GITGUI_BCK_i\n@@ -2416,6 +2427,9 @@ text $ui_comm -background white -borderwidth 1 \\\n \t-width 75 -height 9 -wrap none \\\n \t-font font_diff \\\n \t-yscrollcommand {.vpane.lower.commarea.buffer.sby set}\n+$ui_comm tag conf misspelled \\\n+\t-foreground red \\\n+\t-underline 1\n scrollbar .vpane.lower.commarea.buffer.sby \\\n \t-command [list $ui_comm yview]\n pack .vpane.lower.commarea.buffer.header -side top -fill x\n@@ -2454,7 +2468,7 @@ $ctxm add separator\n $ctxm add command \\\n \t-label [mc \"Sign Off\"] \\\n \t-command do_signoff\n-bind_button3 $ui_comm \"tk_popup $ctxm %X %Y\"\n+set ui_comm_ctxm $ctxm\n \n # -- Diff Header\n #\n@@ -2857,6 +2871,43 @@ if {[winfo exists $ui_comm]} {\n \t}\n \n \tbackup_commit_buffer\n+\n+\t# -- If the user has aspell available we can drive it\n+\t#    in pipe mode to spellcheck the commit message.\n+\t#\n+\tset spell_cmd [list |]\n+\tlappend spell_cmd aspell\n+\tlappend spell_cmd --mode=none\n+\tlappend spell_cmd --encoding=UTF-8\n+\tlappend spell_cmd pipe\n+\tif {[catch {set SPELL_fd [open $spell_cmd r+]} spell_err]} {\n+\t\tunset spell_err\n+\t\tset popcmd [list tk_popup $ui_comm_ctxm %X %Y]\n+\t} else {\n+\t\tfconfigure $SPELL_fd \\\n+\t\t\t-encoding utf-8 \\\n+\t\t\t-eofchar {} \\\n+\t\t\t-translation lf\n+\n+\t\tgets $SPELL_fd SPELL_version\n+\t\tif {{@(#) } eq [string range $SPELL_version 0 4]} {\n+\t\t\tset SPELL_version [string range $SPELL_version 5 end]\n+\t\t}\n+\n+\t\tputs $SPELL_fd !     ; # enable terse mode\n+\t\tputs $SPELL_fd {$$l} ; # fetch the language\n+\t\tflush $SPELL_fd\n+\t\tgets $SPELL_fd SPELL_lang\n+\t\tfconfigure $SPELL_fd -blocking 0\n+\t\tfileevent $SPELL_fd readable spellcheck_read\n+\t\tspellcheck_commit_buffer\n+\t\tset popcmd [list \\\n+\t\t\tspellcheck_popup_suggest \\\n+\t\t\t$ui_comm_ctxm \\\n+\t\t\t%X %Y @%x,%y]\n+\t}\n+\tbind_button3 $ui_comm $popcmd\n+\tunset spell_cmd popcmd\n }\n \n lock_index begin-read\ndiff --git a/lib/about.tcl b/lib/about.tcl\nindex 719fc54..bd62f2a 100644\n--- a/lib/about.tcl\n+++ b/lib/about.tcl\n@@ -4,6 +4,7 @@\n proc do_about {} {\n \tglobal appvers copyright oguilib\n \tglobal tcl_patchLevel tk_patchLevel\n+\tglobal SPELL_version SPELL_lang\n \n \tset w .about_dialog\n \ttoplevel $w\n@@ -40,6 +41,10 @@ proc do_about {} {\n \t\tappend v \"Tcl version $tcl_patchLevel\"\n \t\tappend v \", Tk version $tk_patchLevel\"\n \t}\n+\tif {[info exists SPELL_version]} {\n+\t\tappend v \"\\n\"\n+\t\tappend v \"$SPELL_version, $SPELL_lang\"\n+\t}\n \n \tset d {}\n \tappend d \"git wrapper: $::_git\\n\"\ndiff --git a/lib/spellcheck.tcl b/lib/spellcheck.tcl\nnew file mode 100644\nindex 0000000..c032725\n--- /dev/null\n+++ b/lib/spellcheck.tcl\n@@ -0,0 +1,169 @@\n+# git-gui spellchecking support through aspell\n+# Copyright (C) 2008 Shawn Pearce\n+\n+set SPELL_sent {}\n+set SPELL_last {}\n+set SPELL_line 0\n+set SPELL_clear 0\n+set SPELL_menuidx 0\n+array set SPELL_suggest [list]\n+\n+proc spellcheck_popup_suggest {menu X Y pos} {\n+\tglobal ui_comm SPELL_suggest SPELL_menuidx\n+\n+\twhile {$SPELL_menuidx > 0} {\n+\t\t$menu delete 0\n+\t\tincr SPELL_menuidx -1\n+\t}\n+\n+\tset b_loc [$ui_comm index \"$pos wordstart\"]\n+\tset e_loc [$ui_comm index \"$b_loc wordend\"]\n+\tset orig  [$ui_comm get $b_loc $e_loc]\n+\n+\tif {[lsearch -exact [$ui_comm tag names $b_loc] misspelled] >= 0} {\n+\t\tif {[info exists SPELL_suggest($orig)]} {\n+\t\t\tset cnt 0\n+\t\t\tforeach s $SPELL_suggest($orig) {\n+\t\t\t\tif {$cnt < 5} {\n+\t\t\t\t\t$menu insert $SPELL_menuidx command \\\n+\t\t\t\t\t\t-label $s \\\n+\t\t\t\t\t\t-command [list \\\n+\t\t\t\t\t\t\tspellcheck_replace \\\n+\t\t\t\t\t\t\t$b_loc \\\n+\t\t\t\t\t\t\t$e_loc \\\n+\t\t\t\t\t\t\t$s]\n+\t\t\t\t\tincr SPELL_menuidx\n+\t\t\t\t\tincr cnt\n+\t\t\t\t} else {\n+\t\t\t\t\tbreak\n+\t\t\t\t}\n+\t\t\t}\n+\t\t} else {\n+\t\t\t$menu insert $SPELL_menuidx command \\\n+\t\t\t\t-label [mc \"No Suggestions\"] \\\n+\t\t\t\t-state disabled\n+\t\t\tincr SPELL_menuidx\n+\t\t}\n+\t\t$menu insert $SPELL_menuidx separator\n+\t\tincr SPELL_menuidx\n+\t}\n+\n+\t$ui_comm mark set saved-insert insert\n+\ttk_popup $menu $X $Y\n+}\n+\n+proc spellcheck_replace {b_loc e_loc word} {\n+\tglobal ui_comm\n+\n+\t$ui_comm configure -autoseparators 0\n+\t$ui_comm edit separator\n+\n+\t$ui_comm delete $b_loc $e_loc\n+\t$ui_comm insert $b_loc $word\n+\n+\t$ui_comm edit separator\n+\t$ui_comm configure -autoseparators 1\n+\t$ui_comm mark set insert saved-insert\n+}\n+\n+proc spellcheck_commit_buffer {} {\n+\tglobal ui_comm \\\n+\t\tSPELL_i SPELL_sent SPELL_last \\\n+\t\tSPELL_fd SPELL_line SPELL_suggest\n+\n+\tset buf [$ui_comm get 1.0 end]\n+\tif {$buf ne $SPELL_sent && $buf eq $SPELL_last} {\n+\t\tforeach line [split $buf \"\\n\"] {\n+\t\t\tif {$line eq {}} continue\n+\t\t\tputs $SPELL_fd ^$line\n+\t\t}\n+\t\tputs $SPELL_fd {$$l}\n+\t\tflush $SPELL_fd\n+\n+\t\tset SPELL_sent $buf\n+\t\tset SPELL_line 1\n+\t\tset SPELL_clear 1\n+\t\tarray unset SPELL_suggest\n+\t} else {\n+\t\tset SPELL_last $buf\n+\t\tset SPELL_i [after 300 spellcheck_commit_buffer]\n+\t}\n+}\n+\n+proc spellcheck_read {} {\n+\tglobal ui_comm SPELL_fd SPELL_lang SPELL_i\n+\tglobal SPELL_line SPELL_clear SPELL_suggest\n+\n+\twhile {[gets $SPELL_fd line] >= 0} {\n+\t\tif {$line eq $SPELL_lang} {\n+\t\t\tset SPELL_i [after 300 spellcheck_commit_buffer]\n+\t\t\tcontinue\n+\t\t}\n+\n+\t\tif {$SPELL_clear} {\n+\t\t\t$ui_comm tag remove misspelled \\\n+\t\t\t\t\"$SPELL_line.0\" \\\n+\t\t\t\t\"$SPELL_line.end\"\n+\t\t\tset SPELL_clear 0\n+\t\t}\n+\n+\t\tif {$line eq {}} {\n+\t\t\tincr SPELL_line\n+\n+\t\t\tset max_line [lindex [split [$ui_comm index end] .] 0]\n+\t\t\twhile {$SPELL_line <= $max_line\n+\t\t\t\t&& [$ui_comm get \\\n+\t\t\t\t\"$SPELL_line.0\" \\\n+\t\t\t\t\"$SPELL_line.end -1c\"] eq {}} {\n+\t\t\t\t$ui_comm tag remove misspelled \\\n+\t\t\t\t\t\"$SPELL_line.0\" \\\n+\t\t\t\t\t\"$SPELL_line.end\"\n+\t\t\t\tincr SPELL_line\n+\t\t\t}\n+\n+\t\t\tset SPELL_clear 1\n+\t\t\tcontinue\n+\t\t}\n+\n+\t\tswitch -- [string range $line 0 1] {\n+\t\t{& } {\n+\t\t\tset line [split [string range $line 2 end] :]\n+\t\t\tset info [split [lindex $line 0] { }]\n+\t\t\tset orig [lindex $info 0]\n+\t\t\tset offs [lindex $info 2]\n+\t\t\tset sugg [list]\n+\t\t\tforeach s [split [lindex $line 1] ,] {\n+\t\t\t\tlappend sugg [string range $s 1 end]\n+\t\t\t}\n+\t\t\tset SPELL_suggest($orig) $sugg\n+\t\t}\n+\t\t{# } {\n+\t\t\tset info [split [string range $line 2 end] { }]\n+\t\t\tset orig [lindex $info 0]\n+\t\t\tset offs [lindex $info 1]\n+\t\t}\n+\t\tdefault {\n+\t\t\tputs stderr \"<spell> $line\"\n+\t\t\tcontinue\n+\t\t}\n+\t\t}\n+\n+\t\tincr offs -1\n+\t\tset b_loc \"$SPELL_line.$offs\"\n+\t\tset e_loc [$ui_comm index \"$SPELL_line.$offs wordend\"]\n+\t\tset curr [$ui_comm get $b_loc $e_loc]\n+\t\tif {$curr eq $orig} {\n+\t\t\t$ui_comm tag add misspelled $b_loc $e_loc\n+\t\t}\n+\t}\n+\n+\tfconfigure $SPELL_fd -block 1\n+\tif {[eof $SPELL_fd] && [catch {close $SPELL_fd} err]} {\n+\t\tcatch {after cancel $SPELL_i}\n+\t\tunset SPELL_i SPELL_fd\n+\t\t$ui_comm tag remove misspelled 1.0 end\n+\t\terror_popup [strcat \"Spell Checker Failed\" \"\\n\\n\" $err]\n+\t\treturn\n+\t}\n+\tfconfigure $SPELL_fd -block 0\n+}\n-- \n1.5.4.1134.ge34cf\n"},{"id":"67337","messageId":"5ED970B8-0196-4616-8968-6788B803EA7F@wincent.com","threadId":"11864","inReplyTo":"20080204084153.GA9997@spearce.org","subject":"Re: [PATCH] git-gui: Automatically spell check commit messages as the user types","fromName":"Wincent Colaiuta","fromEmail":"win@wincent.com","sentAt":"2008-02-04T08:53:46Z","receivedAt":"2008-02-04T08:53:46Z","isPatch":true,"sender":{"key":"greg@hurrell.net","avatar":"https://avatars.githubusercontent.com/u/7074?v=4"},"body":"El 4/2/2008, a las 9:41, Shawn O. Pearce escribió:\n\n> As you can see the commit message was rather long.  I used this\n> feature the entire time while writing it, and I have to say, it\n> saved me from my horrible spelling and typing skills.  It also\n> didn't feel like there was any significant lag, although every\n> once in a while it will mark a word that you are in the middle\n> of typing as misspelled, and catch up and correct that once you\n> finish the word.  I guess that's what you get for slowing down\n> and taking a few extra milliseconds to move the fingers.  :)\n\n\nRather than sending off the text to be spellchecked at intervals,  \ncouldn't you refrain from sending it when the cursor hasn't yet moved  \npast a word boundary? This is what most \"check spelling as you type  \nimplementations do\".\n\neg. If you type \"spellnig\" and leave the cursor immediately after the  \n\"g\", the word won't be highlighted until you hit space or otherwise  \ncause the cursor to move beyond the word boundary.\n\nCheers,\nWincent\n"},{"id":"67338","messageId":"20080204090318.GL24004@spearce.org","threadId":"11864","inReplyTo":"5ED970B8-0196-4616-8968-6788B803EA7F@wincent.com","subject":"Re: [PATCH] git-gui: Automatically spell check commit messages as the user types","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2008-02-04T09:03:18Z","receivedAt":"2008-02-04T09:03:18Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Wincent Colaiuta <win@wincent.com> wrote:\n> El 4/2/2008, a las 9:41, Shawn O. Pearce escribió:\n> \n> Rather than sending off the text to be spellchecked at intervals,  \n> couldn't you refrain from sending it when the cursor hasn't yet moved  \n> past a word boundary? This is what most \"check spelling as you type  \n> implementations do\".\n> \n> eg. If you type \"spellnig\" and leave the cursor immediately after the  \n> \"g\", the word won't be highlighted until you hit space or otherwise  \n> cause the cursor to move beyond the word boundary.\n\nIndeed, that's brillant.  Something like this on top would work:\n\ndiff --git a/lib/spellcheck.tcl b/lib/spellcheck.tcl\nindex c032725..088812d 100644\n--- a/lib/spellcheck.tcl\n+++ b/lib/spellcheck.tcl\n@@ -71,6 +71,14 @@ proc spellcheck_commit_buffer {} {\n \t\tSPELL_i SPELL_sent SPELL_last \\\n \t\tSPELL_fd SPELL_line SPELL_suggest\n \n+\tif {![regexp {^\\W$} [$ui_comm get {insert -1c} insert]]} {\n+\t\t$ui_comm tag remove misspelled \\\n+\t\t\t{insert -1c wordstart} \\\n+\t\t\t{insert -1c wordend}\n+\t\tset SPELL_i [after 300 spellcheck_commit_buffer]\n+\t\treturn\n+\t}\n+\n \tset buf [$ui_comm get 1.0 end]\n \tif {$buf ne $SPELL_sent && $buf eq $SPELL_last} {\n \t\tforeach line [split $buf \"\\n\"] {\n\n-- \nShawn.\n"},{"id":"67341","messageId":"m3d4rd58ri.fsf@localhost.localdomain","threadId":"11864","inReplyTo":"20080204084153.GA9997@spearce.org","subject":"Re: [PATCH] git-gui: Automatically spell check commit messages as the user types","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2008-02-04T10:14:08Z","receivedAt":"2008-02-04T10:14:08Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"\"Shawn O. Pearce\" <spearce@spearce.org> writes:\n\n> [This is also in my `pu` branch on repo.or.cz/git-gui.]\n> \n> As you can see the commit message was rather long.  I used this\n> feature the entire time while writing it, and I have to say, it\n> saved me from my horrible spelling and typing skills.  It also\n> didn't feel like there was any significant lag, although every\n> once in a while it will mark a word that you are in the middle\n> of typing as misspelled, and catch up and correct that once you\n> finish the word.  I guess that's what you get for slowing down\n> and taking a few extra milliseconds to move the fingers.  :)\n\n> Personally I prefer this style of spellchecking over the \"lets show\n> a modal dialog and ask the user to check one word at a time through\n> the document\".  Mainly because this style gives you full context,\n> while the modal dialog forms almost never do.\n\nIMHO both modes have their use. The \"flyspell\" mode can show you\nerrors as you type, so you wouldn't repeat mistakes (running spelling\nonly on finished words is a good idea), the \"modal dialog\" has its use\nfor final chackup, as it is much easier in this mode to use \"ignore\"\nor \"ignore all\" for the word which is not in dictionary and you know\nit is correct, select one of proposed corrections or write your and\nuse \"replace\" or \"replace all\", and add word to local dictionary, and\nchange language (if done right of course, i.e. with highlighting and\ngoing to the word currently being corrected, and not hiding/covering\nthe text being corrected so you can see the context).\n\nBTW. you can check how Emacs does that in its flyspell-mode, and how\nit does checking lazily; I guess the code should be readable even\nknowing next to nothing about Emacs Lisp\n \n> I'm not sure how to configure Aspell for other languages, it just\n> magically came up with English on my system.  Since git-gui has i18n\n> support almost everywhere else I want to get that settled before\n> this topic merges into my master branch.  I've CC'd Christian and\n> Johannes as they have been a big help in the past with the git-gui\n> i18n effort and I would value any input they might have.\n\naspell {-d|--master}=<dictionary>\n\n-- \nJakub Narebski\nPoland\nShadeHawk on #git\n"},{"id":"67481","messageId":"alpine.DEB.1.00.0802042305190.27012@an.sumeria","threadId":"11864","inReplyTo":"20080204084153.GA9997@spearce.org","subject":"Re: [PATCH] git-gui: Automatically spell check commit messages as the user types","fromName":"Adam Flott","fromEmail":"adam@npjh.com","sentAt":"2008-02-05T05:06:02Z","receivedAt":"2008-02-05T05:06:02Z","isPatch":true,"sender":{"key":"adam@npjh.com","avatar":"https://gravatar.com/avatar/b1499b03b4ec6de9607c0cc5c57de362b328a9cf646277f8f77b12f80c0e6228?d=mp&s=160"},"body":"\n\nOn Mon, 4 Feb 2008, Shawn O. Pearce wrote:\n\n> [PATCH] git-gui: Automatically spell check commit messages as the user types\n>\n\nVery impressive. I used it a bunch today and didn't find any problems.\nThanks again!\n\n\nAdam\n"}]}