PageRenderTime 44ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/share/tk8.3/console.tcl

https://github.com/rogerz/sourcenav-enhance
TCL | 485 lines | 350 code | 43 blank | 92 comment | 51 complexity | 35ba9757f163a4453a83743b6ab1b711 MD5 | raw file
  1. # console.tcl --
  2. #
  3. # This code constructs the console window for an application. It
  4. # can be used by non-unix systems that do not have built-in support
  5. # for shells.
  6. #
  7. # RCS: @(#) $Id: console.tcl 144 2003-02-05 10:56:26Z mdejong $
  8. #
  9. # Copyright (c) 1998-1999 Scriptics Corp.
  10. # Copyright (c) 1995-1997 Sun Microsystems, Inc.
  11. #
  12. # See the file "license.terms" for information on usage and redistribution
  13. # of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  14. #
  15. # TODO: history - remember partially written command
  16. # tkConsoleInit --
  17. # This procedure constructs and configures the console windows.
  18. #
  19. # Arguments:
  20. # None.
  21. proc tkConsoleInit {} {
  22. global tcl_platform
  23. if {![consoleinterp eval {set tcl_interactive}]} {
  24. wm withdraw .
  25. }
  26. if {[string compare $tcl_platform(platform) "macintosh"]} {
  27. set mod "Ctrl"
  28. } else {
  29. set mod "Cmd"
  30. }
  31. menu .menubar
  32. .menubar add cascade -label File -menu .menubar.file -underline 0
  33. .menubar add cascade -label Edit -menu .menubar.edit -underline 0
  34. menu .menubar.file -tearoff 0
  35. .menubar.file add command -label "Source..." -underline 0 \
  36. -command tkConsoleSource
  37. .menubar.file add command -label "Hide Console" -underline 0 \
  38. -command {wm withdraw .}
  39. if {[string compare $tcl_platform(platform) "macintosh"]} {
  40. .menubar.file add command -label "Exit" -underline 1 -command exit
  41. } else {
  42. .menubar.file add command -label "Quit" -command exit -accel Cmd-Q
  43. }
  44. menu .menubar.edit -tearoff 0
  45. .menubar.edit add command -label "Cut" -underline 2 \
  46. -command { event generate .console <<Cut>> } -accel "$mod+X"
  47. .menubar.edit add command -label "Copy" -underline 0 \
  48. -command { event generate .console <<Copy>> } -accel "$mod+C"
  49. .menubar.edit add command -label "Paste" -underline 1 \
  50. -command { event generate .console <<Paste>> } -accel "$mod+V"
  51. if {[string compare $tcl_platform(platform) "windows"]} {
  52. .menubar.edit add command -label "Clear" -underline 2 \
  53. -command { event generate .console <<Clear>> }
  54. } else {
  55. .menubar.edit add command -label "Delete" -underline 0 \
  56. -command { event generate .console <<Clear>> } -accel "Del"
  57. .menubar add cascade -label Help -menu .menubar.help -underline 0
  58. menu .menubar.help -tearoff 0
  59. .menubar.help add command -label "About..." -underline 0 \
  60. -command tkConsoleAbout
  61. }
  62. . configure -menu .menubar
  63. text .console -yscrollcommand ".sb set" -setgrid true
  64. scrollbar .sb -command ".console yview"
  65. pack .sb -side right -fill both
  66. pack .console -fill both -expand 1 -side left
  67. switch -exact $tcl_platform(platform) {
  68. "macintosh" {
  69. .console configure -font {Monaco 9 normal} -highlightthickness 0
  70. }
  71. "windows" {
  72. .console configure -font systemfixed
  73. }
  74. }
  75. tkConsoleBind .console
  76. .console tag configure stderr -foreground red
  77. .console tag configure stdin -foreground blue
  78. focus .console
  79. wm protocol . WM_DELETE_WINDOW { wm withdraw . }
  80. wm title . "Console"
  81. flush stdout
  82. .console mark set output [.console index "end - 1 char"]
  83. tkTextSetCursor .console end
  84. .console mark set promptEnd insert
  85. .console mark gravity promptEnd left
  86. }
  87. # tkConsoleSource --
  88. #
  89. # Prompts the user for a file to source in the main interpreter.
  90. #
  91. # Arguments:
  92. # None.
  93. proc tkConsoleSource {} {
  94. set filename [tk_getOpenFile -defaultextension .tcl -parent . \
  95. -title "Select a file to source" \
  96. -filetypes {{"Tcl Scripts" .tcl} {"All Files" *}}]
  97. if {[string compare $filename ""]} {
  98. set cmd [list source $filename]
  99. if {[catch {consoleinterp eval $cmd} result]} {
  100. tkConsoleOutput stderr "$result\n"
  101. }
  102. }
  103. }
  104. # tkConsoleInvoke --
  105. # Processes the command line input. If the command is complete it
  106. # is evaled in the main interpreter. Otherwise, the continuation
  107. # prompt is added and more input may be added.
  108. #
  109. # Arguments:
  110. # None.
  111. proc tkConsoleInvoke {args} {
  112. set ranges [.console tag ranges input]
  113. set cmd ""
  114. if {[llength $ranges]} {
  115. set pos 0
  116. while {[string compare [lindex $ranges $pos] ""]} {
  117. set start [lindex $ranges $pos]
  118. set end [lindex $ranges [incr pos]]
  119. append cmd [.console get $start $end]
  120. incr pos
  121. }
  122. }
  123. if {[string equal $cmd ""]} {
  124. tkConsolePrompt
  125. } elseif {[info complete $cmd]} {
  126. .console mark set output end
  127. .console tag delete input
  128. set result [consoleinterp record $cmd]
  129. if {[string compare $result ""]} {
  130. puts $result
  131. }
  132. tkConsoleHistory reset
  133. tkConsolePrompt
  134. } else {
  135. tkConsolePrompt partial
  136. }
  137. .console yview -pickplace insert
  138. }
  139. # tkConsoleHistory --
  140. # This procedure implements command line history for the
  141. # console. In general is evals the history command in the
  142. # main interpreter to obtain the history. The global variable
  143. # histNum is used to store the current location in the history.
  144. #
  145. # Arguments:
  146. # cmd - Which action to take: prev, next, reset.
  147. set histNum 1
  148. proc tkConsoleHistory {cmd} {
  149. global histNum
  150. switch $cmd {
  151. prev {
  152. incr histNum -1
  153. if {$histNum == 0} {
  154. set cmd {history event [expr {[history nextid] -1}]}
  155. } else {
  156. set cmd "history event $histNum"
  157. }
  158. if {[catch {consoleinterp eval $cmd} cmd]} {
  159. incr histNum
  160. return
  161. }
  162. .console delete promptEnd end
  163. .console insert promptEnd $cmd {input stdin}
  164. }
  165. next {
  166. incr histNum
  167. if {$histNum == 0} {
  168. set cmd {history event [expr {[history nextid] -1}]}
  169. } elseif {$histNum > 0} {
  170. set cmd ""
  171. set histNum 1
  172. } else {
  173. set cmd "history event $histNum"
  174. }
  175. if {[string compare $cmd ""]} {
  176. catch {consoleinterp eval $cmd} cmd
  177. }
  178. .console delete promptEnd end
  179. .console insert promptEnd $cmd {input stdin}
  180. }
  181. reset {
  182. set histNum 1
  183. }
  184. }
  185. }
  186. # tkConsolePrompt --
  187. # This procedure draws the prompt. If tcl_prompt1 or tcl_prompt2
  188. # exists in the main interpreter it will be called to generate the
  189. # prompt. Otherwise, a hard coded default prompt is printed.
  190. #
  191. # Arguments:
  192. # partial - Flag to specify which prompt to print.
  193. proc tkConsolePrompt {{partial normal}} {
  194. if {[string equal $partial "normal"]} {
  195. set temp [.console index "end - 1 char"]
  196. .console mark set output end
  197. if {[consoleinterp eval "info exists tcl_prompt1"]} {
  198. consoleinterp eval "eval \[set tcl_prompt1\]"
  199. } else {
  200. puts -nonewline "% "
  201. }
  202. } else {
  203. set temp [.console index output]
  204. .console mark set output end
  205. if {[consoleinterp eval "info exists tcl_prompt2"]} {
  206. consoleinterp eval "eval \[set tcl_prompt2\]"
  207. } else {
  208. puts -nonewline "> "
  209. }
  210. }
  211. flush stdout
  212. .console mark set output $temp
  213. tkTextSetCursor .console end
  214. .console mark set promptEnd insert
  215. .console mark gravity promptEnd left
  216. }
  217. # tkConsoleBind --
  218. # This procedure first ensures that the default bindings for the Text
  219. # class have been defined. Then certain bindings are overridden for
  220. # the class.
  221. #
  222. # Arguments:
  223. # None.
  224. proc tkConsoleBind {win} {
  225. bindtags $win "$win Text . all"
  226. # Ignore all Alt, Meta, and Control keypresses unless explicitly bound.
  227. # Otherwise, if a widget binding for one of these is defined, the
  228. # <KeyPress> class binding will also fire and insert the character,
  229. # which is wrong. Ditto for <Escape>.
  230. bind $win <Alt-KeyPress> {# nothing }
  231. bind $win <Meta-KeyPress> {# nothing}
  232. bind $win <Control-KeyPress> {# nothing}
  233. bind $win <Escape> {# nothing}
  234. bind $win <KP_Enter> {# nothing}
  235. bind $win <Tab> {
  236. tkConsoleInsert %W \t
  237. focus %W
  238. break
  239. }
  240. bind $win <Return> {
  241. %W mark set insert {end - 1c}
  242. tkConsoleInsert %W "\n"
  243. tkConsoleInvoke
  244. break
  245. }
  246. bind $win <Delete> {
  247. if {[string compare [%W tag nextrange sel 1.0 end] ""]} {
  248. %W tag remove sel sel.first promptEnd
  249. } elseif {[%W compare insert < promptEnd]} {
  250. break
  251. }
  252. }
  253. bind $win <BackSpace> {
  254. if {[string compare [%W tag nextrange sel 1.0 end] ""]} {
  255. %W tag remove sel sel.first promptEnd
  256. } elseif {[%W compare insert <= promptEnd]} {
  257. break
  258. }
  259. }
  260. foreach left {Control-a Home} {
  261. bind $win <$left> {
  262. if {[%W compare insert < promptEnd]} {
  263. tkTextSetCursor %W {insert linestart}
  264. } else {
  265. tkTextSetCursor %W promptEnd
  266. }
  267. break
  268. }
  269. }
  270. foreach right {Control-e End} {
  271. bind $win <$right> {
  272. tkTextSetCursor %W {insert lineend}
  273. break
  274. }
  275. }
  276. bind $win <Control-d> {
  277. if {[%W compare insert < promptEnd]} {
  278. break
  279. }
  280. }
  281. bind $win <Control-k> {
  282. if {[%W compare insert < promptEnd]} {
  283. %W mark set insert promptEnd
  284. }
  285. }
  286. bind $win <Control-t> {
  287. if {[%W compare insert < promptEnd]} {
  288. break
  289. }
  290. }
  291. bind $win <Meta-d> {
  292. if {[%W compare insert < promptEnd]} {
  293. break
  294. }
  295. }
  296. bind $win <Meta-BackSpace> {
  297. if {[%W compare insert <= promptEnd]} {
  298. break
  299. }
  300. }
  301. bind $win <Control-h> {
  302. if {[%W compare insert <= promptEnd]} {
  303. break
  304. }
  305. }
  306. foreach prev {Control-p Up} {
  307. bind $win <$prev> {
  308. tkConsoleHistory prev
  309. break
  310. }
  311. }
  312. foreach prev {Control-n Down} {
  313. bind $win <$prev> {
  314. tkConsoleHistory next
  315. break
  316. }
  317. }
  318. bind $win <Insert> {
  319. catch {tkConsoleInsert %W [selection get -displayof %W]}
  320. break
  321. }
  322. bind $win <KeyPress> {
  323. tkConsoleInsert %W %A
  324. break
  325. }
  326. foreach left {Control-b Left} {
  327. bind $win <$left> {
  328. if {[%W compare insert == promptEnd]} {
  329. break
  330. }
  331. tkTextSetCursor %W insert-1c
  332. break
  333. }
  334. }
  335. foreach right {Control-f Right} {
  336. bind $win <$right> {
  337. tkTextSetCursor %W insert+1c
  338. break
  339. }
  340. }
  341. bind $win <F9> {
  342. eval destroy [winfo child .]
  343. if {[string equal $tcl_platform(platform) "macintosh"]} {
  344. source -rsrc Console
  345. } else {
  346. source [file join $tk_library console.tcl]
  347. }
  348. }
  349. bind $win <<Cut>> {
  350. # Same as the copy event
  351. if {![catch {set data [%W get sel.first sel.last]}]} {
  352. clipboard clear -displayof %W
  353. clipboard append -displayof %W $data
  354. }
  355. break
  356. }
  357. bind $win <<Copy>> {
  358. if {![catch {set data [%W get sel.first sel.last]}]} {
  359. clipboard clear -displayof %W
  360. clipboard append -displayof %W $data
  361. }
  362. break
  363. }
  364. bind $win <<Paste>> {
  365. catch {
  366. set clip [selection get -displayof %W -selection CLIPBOARD]
  367. set list [split $clip \n\r]
  368. tkConsoleInsert %W [lindex $list 0]
  369. foreach x [lrange $list 1 end] {
  370. %W mark set insert {end - 1c}
  371. tkConsoleInsert %W "\n"
  372. tkConsoleInvoke
  373. tkConsoleInsert %W $x
  374. }
  375. }
  376. break
  377. }
  378. }
  379. # tkConsoleInsert --
  380. # Insert a string into a text at the point of the insertion cursor.
  381. # If there is a selection in the text, and it covers the point of the
  382. # insertion cursor, then delete the selection before inserting. Insertion
  383. # is restricted to the prompt area.
  384. #
  385. # Arguments:
  386. # w - The text window in which to insert the string
  387. # s - The string to insert (usually just a single character)
  388. proc tkConsoleInsert {w s} {
  389. if {[string equal $s ""]} {
  390. return
  391. }
  392. catch {
  393. if {[$w compare sel.first <= insert]
  394. && [$w compare sel.last >= insert]} {
  395. $w tag remove sel sel.first promptEnd
  396. $w delete sel.first sel.last
  397. }
  398. }
  399. if {[$w compare insert < promptEnd]} {
  400. $w mark set insert end
  401. }
  402. $w insert insert $s {input stdin}
  403. $w see insert
  404. }
  405. # tkConsoleOutput --
  406. #
  407. # This routine is called directly by ConsolePutsCmd to cause a string
  408. # to be displayed in the console.
  409. #
  410. # Arguments:
  411. # dest - The output tag to be used: either "stderr" or "stdout".
  412. # string - The string to be displayed.
  413. proc tkConsoleOutput {dest string} {
  414. .console insert output $string $dest
  415. .console see insert
  416. }
  417. # tkConsoleExit --
  418. #
  419. # This routine is called by ConsoleEventProc when the main window of
  420. # the application is destroyed. Don't call exit - that probably already
  421. # happened. Just delete our window.
  422. #
  423. # Arguments:
  424. # None.
  425. proc tkConsoleExit {} {
  426. destroy .
  427. }
  428. # tkConsoleAbout --
  429. #
  430. # This routine displays an About box to show Tcl/Tk version info.
  431. #
  432. # Arguments:
  433. # None.
  434. proc tkConsoleAbout {} {
  435. global tk_patchLevel
  436. tk_messageBox -type ok -message "Tcl for Windows
  437. Copyright \251 2000 Scriptics Corporation
  438. Tcl [info patchlevel]
  439. Tk $tk_patchLevel"
  440. }
  441. # now initialize the console
  442. tkConsoleInit