# jedit_cmds.tcl - most user-visible commands for jedit
#   (preference commands are in jedit_prefs.tcl)
#
######################################################################
# Copyright 1992-1995 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.     #
######################################################################

j:ldb: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-1995 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}}
  {JEabout:donations {Donations}}
  {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: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
######################################################################

j:command:register jedit:cmd:about {About the Editor...}
proc jedit:cmd:about { t args } {
  global JSTOOLS_VERSION
  set about_editor [j:ldb 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]
  j:about:button .about JEabout:donations [j:about_donations]
  
  tkwait window .about
}

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

j:command:register jedit:cmd:new_window {New Window}
proc jedit:cmd:new_window { args } {
  jedit:jedit
}

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

j: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 [j:prompt -text JEprompt:mode]
  if {$prompt_result != {}} then {
    jedit:set_mode $t $prompt_result
    jedit:apply_mode $window
  }
}

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

j:command:register jedit:cmd:close {Close Window}
proc jedit:cmd:close { t args } {
  global JEDIT_WINDOW_COUNT
  
  if {$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 [j:confirm -text JEconfirm:close_window] {
        incr JEDIT_WINDOW_COUNT -1	;# one fewer window
        destroy [jedit:text_to_top $t]
      }
    } else {
      mode:$mode:close $t
    }
  }
}

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

j:command:register jedit:cmd:quit {Quit}
proc jedit:cmd:quit { t args } {
  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 [j:confirm -text JEconfirm:quit] {
      exit 0
    }
  } else {
    mode:$mode:quit $t
  }
}

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

j:command:register jedit:cmd:load {Load...}
proc jedit:cmd:load { t args } {
  jedit:save_checkpoint $t	;# save undo information

  set filename [j:fs -prompt "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
######################################################################

j: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 [j: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
######################################################################

j:command:register jedit:cmd:saveas {Save As...}
proc jedit:cmd:saveas { t args } {
  set filename [j:fs -prompt JEprompt:saveas]
  if {"x$filename" != "x" && \
     ( ! [file exists $filename] || \
      [j:confirm -text 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
######################################################################

j:command:register jedit:cmd:print {Print...}
proc jedit:cmd:print { t args } {
  global J_PREFS
  if [j:confirm -priority 24 \
    -text JEconfirm:print_to...] {
    exec lpr -P$J_PREFS(printer) << [$t get 1.0 end]
  }
}

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

j:command:register jedit:cmd:print_postscript {Print PostScript}
proc jedit:cmd:print_postscript { t args } {
  global J_PREFS
  if [j:confirm -priority 24 \
    -text JEconfirm:print_ps_to...] {
    exec lpr -P$J_PREFS(printer) << [j:tc:ps:convert_text $t]
  }
}

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

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

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

j:command:register jedit:cmd:cut {Cut}
proc jedit:cmd:cut { t args } {
  global CUTBUFFER

  jedit:save_checkpoint $t			;# save undo information

  set CUTBUFFER [$t get sel.first sel.last]
  j:text:delete $t sel.first sel.last
}

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

j:command:register jedit:cmd:copy {Copy}
proc jedit:cmd:copy { t args } {
  global CUTBUFFER

  set CUTBUFFER [$t get sel.first sel.last]
}

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

j: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:text:insert_string $t $CUTBUFFER

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

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

j:command:register jedit:cmd:note {Note}
proc jedit:cmd:note { t args } {
  j:more -title JEtitle:note -text [$t get sel.first sel.last]
}

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

j: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
######################################################################

j:command:register jedit:cmd:run_pipe {Pipe Through...}
proc jedit:cmd:run_pipe { t args } {
  global UNIX_PIPE; append UNIX_PIPE {}

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

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

j: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 [j:prompt -text JEprompt:unix_cmd -default $UNIX_COMMAND]
  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_string $t $result
    }
  }
}

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

j: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
######################################################################

j: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
######################################################################

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

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

j: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!
######################################################################

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

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

j: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]
  j:alert -title "Notice" \
    -text JEmsg:at_line...column...
}

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

j: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_string $t [j:selection_if_any]

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

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

j:command:register jedit:cmd:find {Find...}
proc jedit:cmd:find { t args } {
  jedit:save_checkpoint $t
  j:find $t
}

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

j:command:register jedit:cmd:find_again {Find Again}
proc jedit:cmd:find_again { t args } {
  jedit:save_checkpoint $t
  j:find:again $t
}

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

j: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 [j: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
######################################################################

j:command:register jedit:cmd:char_panel {Select Character}
proc jedit:cmd:char_panel { t args } {
  set tl [j:new_toplevel .high_bit]
  wm title $tl [j:ldb JEtitle:characters]
  
  message $tl.m -aspect 400 \
    -text [j:ldb 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 j:buttonbar for visual consistency:  
  j: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_string $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>
  } {
    j:tk3 {
      bind $tl.t $event {;}
    }
    j:tk4 {
      bind $tl.t $event {break}
    }
  }
}

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

j:command:register jedit:cmd:hyphen {Insert Hyphen}
proc jedit:cmd:hyphen { t args } {
  j:text:insert_string $t "\xad"
}

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

j:command:register jedit:cmd:copyright {Insert Copyright Symbol}
proc jedit:cmd:copyright { t args } {
  j:text:insert_string $t "\xa9"
}

######################################################################
# rich-text cut
######################################################################

j:command:register jedit:cmd:rich_cut {Rich Cut}
proc jedit:cmd:rich_cut { t } {
  jedit:cmd:rich_copy $t			;# (saves checkpoint)
  $t delete sel.first sel.last
}

######################################################################
# rich-text copy
######################################################################

j:command:register jedit:cmd:rich_copy {Rich Copy}
proc jedit:cmd:rich_copy { t } {
  global RICHBUFFER
  
  jedit:save_checkpoint $t			;# save undo information
  
  set RICHBUFFER {}
  set curstring {}
  set curtags [$t tag names sel.first]
  
  $t mark set richptr sel.first
  
  while {[$t compare richptr < sel.last]} {
    set tags [$t tag names richptr]
    set char [$t get richptr]
    if {"x$tags" != "x$curtags"} {	;# new "range" of text
      lappend RICHBUFFER [list $curstring $curtags]
      set curstring $char
      set curtags $tags
    } else {
      append curstring $char
    }
    $t mark set richptr {richptr+1c}
  }
  lappend RICHBUFFER [list $curstring $curtags]
  return
}

######################################################################
# rich-text paste
#   partly lifted from insertWithTags in mkStyles.tcl demo
######################################################################

j:command:register jedit:cmd:rich_paste {Rich Paste}
proc jedit:cmd:rich_paste { t } {
  global RICHBUFFER
  
  jedit:save_checkpoint $t			;# save undo information
  
  lappend RICHBUFFER {}			;# make sure it's defined
  
  foreach pair $RICHBUFFER {
    set text [lindex $pair 0]
    set tags [lindex $pair 1]
    
    set start [$t index insert]
    $t insert insert $text
    foreach tag [$t tag names $start] {
      $t tag remove $tag $start insert	;# clear tags inherited from left
    }
    foreach tag $tags {	
      $t tag add $tag $start insert	;# add new tags
    }
  }
  $t tag remove sel 1.0 end		;# clear selection (guaranteed in text)
  return
}

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

j:command:register jedit:cmd:rich_saveas {Rich Save As...}
proc jedit:cmd:rich_saveas { w args } {
  j:tc:saveas $w
}

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

j:command:register jedit:cmd:fmt {Format Lines with `fmt'}
proc jedit:cmd:fmt { w args } {
  jedit:pipe $w {fmt}
}

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

j: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> }
}

j: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}
}

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

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

j: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]}}
}

j:command:register jedit:cmd:sort {Sort by Character Codes}
proc jedit:cmd:sort { w args } {
  jedit:pipe $w {sort}
}

j:command:register jedit:cmd:sort-n {Sort Numerically}
proc jedit:cmd:sort-n { w args } {
  jedit:pipe $w {sort -n}
}

j:command:register jedit:cmd:sort-if {Sort Alphabetically}
proc jedit:cmd:sort-if { w args } {
  jedit:pipe $w {sort -if}
}

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

j:command:register jedit:cmd:edit_prefs {Editor Preferences...}
j:command:register jedit:cmd:mode_prefs {Mode Preferences...}
j:command:register jedit:cmd:save_checkpoint {Checkpoint}
j:command:register jedit:cmd:undo {Undo}
j:command:register jedit:cmd:redo {Redo}
j:command:register jedit:font:roman {Roman}
j:command:register jedit:font:italic {Italic}
j:command:register jedit:font:bold {Bold}
j:command:register jedit:font:bolditalic {Bold Italic}
j:command:register jedit:font:typewriter {Typewriter}
j:command:register jedit:font:heading0 {Level 0 Heading (Title)}
j:command:register jedit:font:heading1 {Level 1 Heading}
j:command:register jedit:font:heading2 {Level 2 Heading}
j:command:register jedit:font:heading3 {Level 3 Heading}
j:command:register jedit:font:heading4 {Level 4 Heading}
j:command:register jedit:font:heading5 {Level 5 Heading}
j:command:register jedit:font:plain {Plain Font}
j:command:register jedit:format:background:clear {Plain Background}
j:command:register jedit:format:foreground:clear {Plain Foreground}

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

proc jedit:register_commands {} {}

