# jedit_cmds.tcl - most user-visible commands for jedit
#   (preference commands are in jedit_prefs.tcl)
#
###############################################################################
#  Copyright 1992-2002 by Jay Sekora.  This file may be freely distributed,   #
#  modified or unmodified, for any purpose, provided that this copyright      #
#  notice is retained verbatim in all copies and no attempt is made to        #
#  obscure the authorship of this file.  If you distribute any modified       #
#  versions, I ask, but do not require, that you clearly mark any changes     #
#  you make as such and that you provide your users with instructions for     #
#  getting the original sources.                                              #
###############################################################################

catch {
  package require jldb
  namespace import ::jldb::shortcuts::*
}

::jldb::set_defaults {
  {JErt:about_jedit {
    j:rt:hl "jedit"
    j:rt:cr
    j:rt:rm "by Jay Sekora, "
    j:rt:tt "js@aq.org"
    j:rt:par
    j:rt:rm "A customisable text editor for X Windows."
    j:rt:cr
    j:rt:rm "Version $JSTOOLS_VERSION."
    j:rt:par
    j:rt:rm "Copyright \251 1992-2002 by Jay Sekora.  "
    j:rt:rm "Terms for copying are specified in the documentation and "
    j:rt:rm "in comments in the code."
    j:rt:par
    j:rt:rm "If you find bugs or have suggestions for improvement, "
    j:rt:rm "please let me know.  "
    j:rt:rm "Feel free to use bits of this code in your own "
    j:rt:tt "wish"
    j:rt:rm " scripts."
  }}
  
  {JEabout:jedit {jedit}}
  {JEabout:author {Author}}
  {JEabout:tk+tcl {Tk and Tcl}}
  {JEprompt:mode {Editing Mode:}}
  {JEconfirm:close_window {Are you sure you want to close this window?}}
  {JEconfirm:quit {Are you sure you want to quit?}}
  {JEprompt:load {Load:}}
  {JEprompt:saveas {Save as:}}
  {JEconfirm:...exists_replace {File "$filename" exists; replace it?}}
  {JEconfirm:print_to... 
    {Print using `lpr' to printer `$J_PREFS(printer)'?}}
  {JEconfirm:print_ps_to... 
    {Print as PostScript using `lpr' to printer `$J_PREFS(printer)'?}}
  {JEprompt:insert {Insert:}}
  {JEtitle:note {Note}}
  {JEprompt:unix_filter {Unix filter:}}
  {JEprompt:unix_cmd {Unix command:}}
  {JEprompt:go_to_line {Go to line number:}}
  {JEmsg:at_line...column...
    {The insertion point is at line $line, column $column.}}
  {JEtitle:characters {Characters}}
  {JEmsg:click_on_char {Click on a character to insert it.}}
  {JEbutton:done {Done}}
}

######################################################################
#
# NOTE: these mostly take the arguments "t args", where t is the text
# widget they apply to.  That way they can be used in a j:tkb:mkmap
# table (where %W %K %A will be appended to the command before 
# execution) as well as with just %W in bindings.  In a few cases
# where t would be ignored, they just take "args".
#
######################################################################

######################################################################
# make the about box
######################################################################

::aq::command_register jedit:cmd:about {About the Editor...}
proc jedit:cmd:about { t args } {
  global JSTOOLS_VERSION
  set about_editor [subst -nobackslashes -nocommands [= JErt:about_jedit]]
  j:about .about $about_editor
  j:about:button .about [- JEabout:jedit] $about_editor
  j:about:button .about [- JEabout:author] [j:about_jay]
  j:about:button .about [- JEabout:tk+tcl] [j:about_tktcl]
  
  tkwait window .about
}

######################################################################
# open a new editor window
######################################################################

::aq::command_register jedit:cmd:new_window {New Window}
proc jedit:cmd:new_window { args } {
  jedit:jedit
}

######################################################################
# prompt user for mode
######################################################################

::aq::command_register jedit:cmd:ask_mode {Mode...}
proc jedit:cmd:ask_mode { t args } {
  global MODE
  
  set window [jedit:text_to_top $t]
  set prompt_result [::aq::prompt -text JEprompt:mode]
  if {$prompt_result != {}} then {
    jedit:set_mode $t $prompt_result
    jedit:apply_mode $window
  }
}

######################################################################
# close a window
######################################################################

::aq::command_register jedit:cmd:close {Close Window}
proc jedit:cmd:close { t args } {
  global JEDIT_WINDOW_COUNT
  global JEDIT_EMBEDDED
  global JEDIT_COMMAND
  
  set toplevel [jedit:text_to_top $t]
  
  if {(!$JEDIT_EMBEDDED) && $JEDIT_WINDOW_COUNT == 1} {
    jedit:cmd:quit $t
  } else {
    set mode [jedit:get_mode $t]
    if {[info procs mode:$mode:pre_close_hook] != {}} {
      mode:$mode:pre_close_hook $t
    }
    
    if {[info procs mode:$mode:close] == {}} {
      if [::aq::confirm -text [= JEconfirm:close_window]] {
        # thanks to ndanner@indiana.edu for the following:
        # We need to unset the filename so that if we open a new window,
        # jedit doesn't think that it already has a filename associated to
        # it and hence overwrite that file when we try to save.
        jedit:unset_filename $toplevel
        incr JEDIT_WINDOW_COUNT -1	;# one fewer window
        destroy [jedit:text_to_top $t]
      }
    } else {
      mode:$mode:close $t
    }
  }
  
  # implement -command option to jedit:jedit
  #
  if {"x$JEDIT_COMMAND" != "x"} {
    eval $JEDIT_COMMAND
  }
}

######################################################################
# quit the editor
######################################################################

::aq::command_register jedit:cmd:quit {Quit}
proc jedit:cmd:quit { t args } {
  global JEDIT_EMBEDDED
  if $JEDIT_EMBEDDED {
    return
  }
  
  set mode [jedit:get_mode $t]
  
  if {[info procs mode:$mode:pre_quit_hook] != {}} {
    mode:$mode:pre_quit_hook $t
  }
  
  if {[info procs mode:$mode:quit] == {}} {
    if [::aq::confirm -text [= JEconfirm:quit]] {
      exit 0
    }
  } else {
    mode:$mode:quit $t
  }
}

######################################################################
# read in a file
######################################################################

::aq::command_register jedit:cmd:load {Load...}
proc jedit:cmd:load { t args } {
  jedit:save_checkpoint $t	;# save undo information

  set filename [::aq::fs -prompt [= JEprompt:load]]
  if {"x$filename" != "x"} then {
    jedit:set_filename $t $filename
    
    # if new filename should have a different mode, set it:
    set old_mode [jedit:get_mode $t]
    set new_mode [jedit:guess_mode $filename]
    if {[string compare $old_mode $new_mode] != 0} {
      jedit:set_mode $t $new_mode
      jedit:apply_mode $t
    }
    
    jedit:read $filename $t
  }
}
  
######################################################################
# write out a file, using window's filename if defined
######################################################################

::aq::command_register jedit:cmd:save {Save}
proc jedit:cmd:save { t args } {
  set filename [jedit:get_filename $t]
  if {"x$filename" != "x"} then {
    jedit:write $filename $t
  } else {
    set filename [::aq::fs -prompt [= "Save as:"]]
    if {"x$filename" != "x"} then {
      jedit:set_filename $t $filename
      jedit:set_label [jedit:text_to_top $t]
      jedit:write $filename $t
    }
  }
}

######################################################################
# write out a file, prompting for a filename
######################################################################

::aq::command_register jedit:cmd:saveas {Save As...}
proc jedit:cmd:saveas { t args } {
  set filename [::aq::fs -prompt -prompt [= "Save as:"]]
  if {"x$filename" != "x" && \
     ( ! [file exists $filename] || \
      [::aq::confirm \
      -text [subst [= JEconfirm:...exists_replace]]] )} then {
    jedit:set_filename $t $filename
    jedit:set_label [jedit:text_to_top $t]
    jedit:write $filename $t
  }
}

######################################################################
# print the file using lpr
######################################################################

::aq::command_register jedit:cmd:print {Print...}
proc jedit:cmd:print { t args } {
  ::aq::print -data [$t get 1.0 end]
}


######################################################################
# print rich-text as postscript using lpr
######################################################################

::aq::command_register jedit:cmd:print_postscript {Print PostScript}
proc jedit:cmd:print_postscript { t args } {
  ::aq::print_ps -data [::aq::tc::ps_convert_text $t]
}

######################################################################
# read in a file and insert it at the insert mark
######################################################################

::aq::command_register jedit:cmd:insfile {Insert File...}
proc jedit:cmd:insfile { t args } {
  jedit:save_checkpoint $t			;# save undo information
  set prompt_result [::aq::fs -prompt [= JEprompt:insert]]
  if {$prompt_result != {}} then {
    j:text:insert $t [::aq::read_file $prompt_result]
    j:text:insert $t "\n"
  }
}

######################################################################
# delete the selection and copy it to CUTBUFFER
######################################################################

::aq::command_register jedit:cmd:cut {Cut}
proc jedit:cmd:cut { t args } {
  jedit:save_checkpoint $t			;# save undo information
  
  j:cmd:text_cut $t
}

######################################################################
# copy the selection into CUTBUFFER
######################################################################

::aq::command_register jedit:cmd:copy {Copy}
proc jedit:cmd:copy { t args } {
  j:cmd:text_copy $t
}

######################################################################
# insert CUTBUFFER
######################################################################

::aq::command_register jedit:cmd:paste {Paste}
proc jedit:cmd:paste { t args } {
  global CUTBUFFER
  
  set mode [jedit:get_mode $t]
  
  jedit:save_checkpoint $t			;# save undo information

  if {[info procs mode:$mode:pre_paste_hook] != {}} {
    mode:$mode:pre_paste_hook $t
  }

  j:cmd:text_paste $t

  if {[info procs mode:$mode:post_paste_hook] != {}} {
    mode:$mode:post_paste_hook $t
  }
}

######################################################################
# copy the selection into a text panel (as a note)
######################################################################

::aq::command_register jedit:cmd:note {Note}
proc jedit:cmd:note { t args } {
  ::aq::more \
    -title [= JEtitle:note] \
    -text [$t get sel.first sel.last]
}

######################################################################
# mark the entire text as selected
######################################################################

::aq::command_register jedit:cmd:select_all {Select All}
proc jedit:cmd:select_all { t args } {
  $t tag add sel 1.0 end
}

######################################################################
# prompt for a Unix command to run on the selection
######################################################################

::aq::command_register jedit:cmd:run_pipe {Pipe Through...}
proc jedit:cmd:run_pipe { t args } {
  global UNIX_PIPE; append UNIX_PIPE {}

  set prompt_result [::aq::prompt \
    -text JEprompt:unix_filter \
    -default $UNIX_PIPE \
    -history j_pipe]
  if {$prompt_result != {}} then {
    set UNIX_PIPE $prompt_result
    jedit:pipe $t $UNIX_PIPE		;# handles checkpointing
  }
}

######################################################################
# prompt for a Unix command to insert
######################################################################

::aq::command_register jedit:cmd:run_command {Insert Output of...}
proc jedit:cmd:run_command { t args } {
  global UNIX_COMMAND; append UNIX_COMMAND {}

  set prompt_result [::aq::prompt \
    -text JEprompt:unix_cmd \
    -default $UNIX_COMMAND \
    -history j_unix]
  if {$prompt_result != {}} then {
    set UNIX_COMMAND $prompt_result
    catch { eval exec $UNIX_COMMAND } result
    if {$result != {}} {
      append result "\n"
      jedit:save_checkpoint $t			;# save undo information
      j:text:insert $t $result
    }
  }
}

######################################################################
# expand dynamic abbreviation before insert
######################################################################

::aq::command_register jedit:cmd:dabbrev {Expand Dynamic Abbreviation}
proc jedit:cmd:dabbrev { t args } {
  # THIS COULD BE SIMPLIFIED: do i need both match... and abbrev... vars?
  # PROBLEM: this depends on the Text widget's notion of words.
  # it would be nice to be able to expand, say, $tk_l to $tk_library.

  global ABBREV ABBREV_POS MATCH MATCH_POS

  $t mark set abbrevend insert
  $t mark set abbrevstart insert
  while {[$t compare abbrevstart != 1.0] &&
         [string match {[a-zA-Z0-9']} [$t get {abbrevstart - 1 char}]]} {
    $t mark set abbrevstart {abbrevstart -1char}
  }

  set ABBREV_POS [$t index abbrevstart]	;# for dabbrev_again

  set ABBREV [$t get abbrevstart insert]

  set context [$t get 0.0 abbrevstart]

  while {1} {
    set matchpos [string last $ABBREV $context]
  
    if {$matchpos == -1} {return 0}	;# not found

    $t mark set matchstart [$t index "0.0 +$matchpos chars"]
    if {[$t compare matchstart == {matchstart wordstart}]} {
      $t mark set matchend [$t index {matchstart wordend}]
      break				;# sort of an `until'
    }
    set context [$t get 0.0 matchstart]
  }

  set MATCH [$t get matchstart matchend]

  set MATCH_POS [$t index matchstart]

  j:text:replace $t abbrevstart abbrevend $MATCH
  return 1
}

# ######################################################################
# # dabbrev_again - search earlier in the text for abbrevs
# #   CURRENTLY NOT USED
# ######################################################################
# 
# proc dabbrev_again { t args } {
#   # THIS COULD BE SIMPLIFIED: do i need both match... and abbrev... vars?
#   # PROBLEM: this depends on the Text widget's notion of words.
#   # it would be nice to be able to expand, say, $tk_l to $tk_library.
# 
#   global ABBREV ABBREV_POS MATCH MATCH_POS
# 
#   set context [$t get 0.0 $MATCH_POS]
# 
#   while {1} {
#     set matchpos [string last $ABBREV $context]
#   
#     if {$matchpos == -1} {
#       return [sabbrev]			;# try the static table
#     }
#     $t mark set matchstart [$t index "0.0 +$matchpos chars"]
#     if {[$t compare matchstart == {matchstart wordstart}]} {
#       $t mark set matchend [$t index {matchstart wordend}]
#       break				;# sort of an `until'
#     }
#     set context [$t get 0.0 matchstart]
#   }
# 
#   set MATCH [$t get matchstart matchend]
# 
#   set MATCH_POS [$t index matchstart]
# 
#   j:text:replace $t $ABBREV_POS abbrevend "$MATCH "
# }

######################################################################
# look up and expand static abbrev before insert
######################################################################

::aq::command_register jedit:cmd:sabbrev {Expand Static Abbreviation}
proc jedit:cmd:sabbrev { t args } {
  $t mark set abbrevend insert
  # following don't really need to be global (shared with dabbrev):
  global ABBREV ABBREV_POS ABBREVS

  $t mark set abbrevend insert
  $t mark set abbrevstart insert
  while {[$t compare abbrevstart != 1.0] &&
         [string match {[a-zA-Z0-9_']} [$t get {abbrevstart - 1 char}]]} {
    $t mark set abbrevstart {abbrevstart -1char}
  }

  # avoid expanding things like \def, .PP, file.c, etc.:
  set prefix [$t get {abbrevstart -2chars} {abbrevstart}]
  if {[string length $prefix] > 0} {
    if {[string match {?[@$%&+=\:~.]} $prefix]} {
      return 0
    }
    # don't expand "l" in "ls -l", but do expand "this---l"
    if {[string match "\[ \t\n\]-" $prefix]} {	;# don't expand "ls -l"
      return 0
    }
    # don't expand "s" in "house(s)", but do expand "so (s) of"
    if {[string match "\[a-zA-Z](" $prefix]} {	;# don't expand "house(s)"
      return 0
    }
  }

  set ABBREV_POS [$t index abbrevstart]	;# for dabbrev_again

  # first try regular version:
  set ABBREV [$t get abbrevstart insert]
  if {[info exists ABBREVS($ABBREV)]} {
    j:text:replace $t $ABBREV_POS abbrevend $ABBREVS($ABBREV)
    return 1
  }
  # else try capitalised version
  if {[string match {[A-Z][a-z]*} $ABBREV]} {
    set lcabbrev [jedit:uncapitalise $ABBREV]
    if {[info exists ABBREVS($lcabbrev)]} {
      j:text:replace $t $ABBREV_POS abbrevend \
        [jedit:capitalise $ABBREVS($lcabbrev)]
      return 1
    }
  }
  return 0
}

######################################################################
# edit your abbrevs file
######################################################################

::aq::command_register jedit:cmd:edit_abbrevs {Edit Static Abbreviations}
proc jedit:cmd:edit_abbrevs { args } {
  global HOME
  if {! [file isdirectory "$HOME/.tk"]} then {
    file mkdir [file join $HOME .tk]
    # above should have error-checking
  }
  # following doesn't currently use arg
  exec jabbrevs [file join $HOME .tk abbrevs.tcl] &
}

######################################################################
# read abbrevs file
######################################################################

::aq::command_register jedit:cmd:read_abbrevs {Reread Static Abbreviations}
proc jedit:cmd:read_abbrevs { args } {
  j:source_config abbrevs.tcl
}

######################################################################
# toggle static abbrevs
######################################################################

proc jedit:cmd:toggle_sabbrev { t args } {
  global JEDIT_MODEPREFS
  
  set mode [jedit:get_mode $t]
  
  set JEDIT_MODEPREFS($mode,sabbrev) \
    [expr {! $JEDIT_MODEPREFS($mode,sabbrev)}]
}

######################################################################
# toggle dynamic abbrevs
######################################################################

proc jedit:cmd:toggle_dabbrev { t args } {
  global JEDIT_MODEPREFS
  
  set mode [jedit:get_mode $t]
  
  set JEDIT_MODEPREFS($mode,dabbrev) \
    [expr {! $JEDIT_MODEPREFS($mode,dabbrev)}]
}

######################################################################
# go to a particular line
######## NEED TO CHECK THAT AN INDEX WAS TYPED!
######################################################################

::aq::command_register jedit:cmd:go_to_line {Go to Line...}
proc jedit:cmd:go_to_line { t args } {
  set prompt_result [::aq::prompt -text JEprompt:go_to_line]
  if {$prompt_result != {}} then {
    jedit:go_to_line $t $prompt_result
  }
}

######################################################################
# display which line the cursor is on
######################################################################

::aq::command_register jedit:cmd:current_line {Show Current Position}
proc jedit:cmd:current_line { t args } {
  set insertindex [split [$t index insert] {.}]
  set line [lindex $insertindex 0]
  set column [lindex $insertindex 1]
  ::aq::alert -title [- Notice] \
    -text [subst -nobackslashes -nocommands [= JEmsg:at_line...column...]]
}

######################################################################
# insert X selection
######################################################################

::aq::command_register jedit:cmd:xpaste {Insert X Selection}
proc jedit:cmd:xpaste { t args } {
  set mode [jedit:get_mode $t]
  
  jedit:save_checkpoint $t			;# save undo information
  
  if {[info procs mode:$mode:pre_xpaste_hook] != {}} {
    mode:$mode:pre_xpaste_hook $t
  }

  j:text:insert $t [::aq::selection_if_any]

  if {[info procs mode:$mode:post_xpaste_hook] != {}} {
    mode:$mode:post_xpaste_hook $t
  }
}

######################################################################
# front end for ::aq::find to match jedit:cmd argument convention
######################################################################

::aq::command_register jedit:cmd:find {Find...}
proc jedit:cmd:find { t args } {
  jedit:save_checkpoint $t
  ::aq::find $t
}

######################################################################
# find same string again (same kind of search)
######################################################################

::aq::command_register jedit:cmd:find_again {Find Again}
proc jedit:cmd:find_again { t args } {
  jedit:save_checkpoint $t
  ::aq::find_again $t
}

######################################################################
# replace found string with replaced string
# UTTERLY BOGUS - uses loads of information internal to ::aq::find
######################################################################

::aq::command_register jedit:cmd:replace {Replace}
proc jedit:cmd:replace { t args } {
  global j_find
  
  if {! ([info exists j_find(replacewith)] && [j:text:has_selection $t])}  {
    jedit:cmd:find
  } else {
    jedit:save_checkpoint $t
    
    j:text:replace $t sel.first sel.last $j_find(replacewith)
  }
}

######################################################################
# hacks for more-specific kinds of finds (for vi/emacs bindings)
# BOGUS!  jedit should not need to know about the internals of ::aq::find!
######################################################################
#############################################
#############################################
#############################################
proc jedit:cmd:find_forward { t args } {
  global j_find
  set j_find(backwards) 0
  ::aq::find $t
}
#############################################
#############################################
#############################################
proc jedit:cmd:find_backward { t args } {
  global j_find
  set j_find(backwards) 1
  ::aq::find $t
}

######################################################################
# save all windows and quit
######################################################################

# we need to make sure there's a filename before calling save, because
# a cancel in the saveas file selector box will cancel the save, but
# not the close!

::aq::command_register jedit:cmd:done {Done}
proc jedit:cmd:done { t args } {
  set mode [jedit:get_mode $t]
  
  if {[info procs mode:$mode:done] == {}} {
    set filename [jedit:get_filename $t]
    if {"x$filename" == "x"} then {
      set filename [::aq::fs -prompt [= JEprompt:saveas]]
      if {"x$filename" == "x"} {			;# user clicked cancel
        return
      } else {
        jedit:set_filename $t $filename
      }
    }

    jedit:cmd:save $t
    jedit:cmd:close $t
  } else {
    mode:$mode:done $t
  }
}

######################################################################
# panel to let user insert any iso-8859 character
######################################################################

::aq::command_register jedit:cmd:char_panel {Select Character}
proc jedit:cmd:char_panel { t args } {
  set tl [::aq::new_toplevel .high_bit]
  wm title $tl [= JEtitle:characters]
  
  message $tl.m -aspect 400 \
    -text [= JEmsg:click_on_char]
  text $tl.t -width 16 -height 12 -wrap none \
    -cursor top_left_arrow \
    -font -*-courier-bold-r-normal-*-*-140-* \
    -borderwidth 2 -relief groove
  
  # using ::aq::buttonbar for visual consistency:  
  ::aq::buttonbar $tl.b -buttons {
    {ok JEbutton:done {}}
  }
  $tl.b.ok configure \
    -command "destroy $tl"
  
  for {set i 32} {$i < 112} {incr i 16} {
    for {set j 0} {$j < 16} {incr j} {
      $tl.t insert end [format %c [expr {$i + $j}]]
    }
    $tl.t insert end "\n"
  }
  for {set j 112} {$j < 127} {incr j} {
    $tl.t insert end [format %c $j]
  }
  $tl.t insert end " \n "
  for {set i 160} {$i < 256} {incr i 16} {
    for {set j 0} {$j < 16} {incr j} {
      $tl.t insert end [format %c [expr {$i + $j}]]
    }
    $tl.t insert end "\n"
  }
  $tl.t configure -state disabled
  
  pack $tl.m -fill x
  pack $tl.t -padx 10
  pack $tl.b -anchor e
  
  bind $tl.t <ButtonRelease-1> "
    j:text:insert $t \[%W get @%x,%y\]
  "
  foreach event {
    <ButtonRelease-3> <B3-Motion> <Button-3> <ButtonRelease-2>
    <ButtonRelease-1><B2-Motion> <Button-2> <Shift-B1-Motion>
    <Shift-Button-1> <B1-Motion> <Triple-Button-1> <Double-Button-1>
    <Button-1>
  } {
    bind $tl.t $event {break}
  }
}

######################################################################
# insert a hyphen
######################################################################

::aq::command_register jedit:cmd:hyphen {Insert Hyphen}
proc jedit:cmd:hyphen { t args } {
  j:text:insert $t "\xad"
}

######################################################################
# insert a copyright symbol
######################################################################

::aq::command_register jedit:cmd:copyright {Insert Copyright Symbol}
proc jedit:cmd:copyright { t args } {
  j:text:insert $t "\xa9"
}

######################################################################
# rich-text save (front-end to ::aq::tc::saveas)
######################################################################

::aq::command_register jedit:cmd:rich_saveas {Rich Save As...}
proc jedit:cmd:rich_saveas { w args } {
  ::aq::tc::saveas $w
}

######################################################################
######################################################################
# various filtering commands
######################################################################
######################################################################

::aq::command_register jedit:cmd:fmt {Format Lines with `fmt'}
proc jedit:cmd:fmt { w args } {
  jedit:pipe $w {fmt}
}

::aq::command_register jedit:cmd:indent {Indent}
proc jedit:cmd:indent { w args } {
  jedit:guarantee_selection $w
  jedit:text_regsub $w "(^|\n)" {\1  }
}

::aq::command_register jedit:cmd:quote_email {Quote Email}
proc jedit:cmd:quote_email { w args } {
  jedit:guarantee_selection $w
  jedit:text_regsub $w "(^|\n)" {\1> }
}

::aq::command_register jedit:cmd:unindent {Unindent/Unquote}
proc jedit:cmd:unindent { w args } {
  jedit:guarantee_selection $w
  jedit:text_regsub $w "(^|\n)\t" {\1        }
  jedit:text_regsub $w "(^|\n)\[> \] " {\1}
}

::aq::command_register jedit:cmd:uppercase {Uppercase}
proc jedit:cmd:uppercase { w args } {
  jedit:pipe $w {tr {[a-z]} {[A-Z]}}
}

::aq::command_register jedit:cmd:lowercase {Lowercase}
proc jedit:cmd:lowercase { w args } {
  jedit:pipe $w {tr {[A-Z]} {[a-z]}}
}

::aq::command_register jedit:cmd:toggle_case {Toggle Case}
proc jedit:cmd:toggle_case { w args } {
  jedit:pipe $w {tr {[A-Z][a-z]} {[a-z][A-Z]}}
}

::aq::command_register jedit:cmd:sort {Sort by Character Codes}
proc jedit:cmd:sort { w args } {
  jedit:pipe $w {sort}
}

::aq::command_register jedit:cmd:sort-n {Sort Numerically}
proc jedit:cmd:sort-n { w args } {
  jedit:pipe $w {sort -n}
}

::aq::command_register jedit:cmd:sort-if {Sort Alphabetically}
proc jedit:cmd:sort-if { w args } {
  jedit:pipe $w {sort -if}
}

######################################################################
# commands defined elsewhere:

::aq::command_register jedit:cmd:edit_prefs {Editor Preferences...}
::aq::command_register jedit:cmd:mode_prefs {Mode Preferences...}
::aq::command_register jedit:cmd:save_checkpoint {Checkpoint}
::aq::command_register jedit:cmd:undo {Undo}
::aq::command_register jedit:cmd:redo {Redo}
::aq::command_register jedit:font:plain {Plain Font}
::aq::command_register jedit:font:roman {Roman}
::aq::command_register jedit:font:italic {Italic}
::aq::command_register jedit:font:bold {Bold}
::aq::command_register jedit:font:bolditalic {Bold Italic}
::aq::command_register jedit:font:typewriter {Typewriter}
::aq::command_register jedit:font:heading0 {Level 0 Heading (Title)}
::aq::command_register jedit:font:heading1 {Level 1 Heading}
::aq::command_register jedit:font:heading2 {Level 2 Heading}
::aq::command_register jedit:font:heading3 {Level 3 Heading}
::aq::command_register jedit:font:heading4 {Level 4 Heading}
::aq::command_register jedit:font:heading5 {Level 5 Heading}
::aq::command_register jedit:font:l_em {Emphasised Text}
::aq::command_register jedit:font:l_cite {Citation}
::aq::command_register jedit:font:l_var {Variable Reference}
::aq::command_register jedit:font:l_dfn {Definition Text}
::aq::command_register jedit:font:l_strong {Strong Text}
::aq::command_register jedit:font:l_kbd {Keyboard}
::aq::command_register jedit:font:l_code {Code Listing}
::aq::command_register jedit:font:l_samp {Sample Text}
::aq::command_register jedit:format:background:clear {Plain Background}
::aq::command_register jedit:format:foreground:clear {Plain Foreground}
::aq::command_register jedit:format:list_item {List Item}
::aq::command_register jedit:format:nest_list {Deeper List Level}
::aq::command_register jedit:format:unnest_list {Shallower List Level}

######################################################################
# dummy to force autoloading of this file (for registration of cmds):

proc jedit:register_commands {} {}

