nimrepl.nim 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. #
  2. #
  3. # Nim REPL
  4. # (c) Copyright 2012 Dominik Picheta
  5. #
  6. # See the file "copying.txt", included in this
  7. # distribution, for details about the copyright.
  8. #
  9. import glib2, gtk2, gdk2, os, osproc, dialogs, strutils
  10. when defined(tinyc):
  11. const runCmd = "run"
  12. else:
  13. const runCmd = "c -r"
  14. var nimExe = findExe("nim")
  15. if nimExe.len == 0: nimExe = "../bin" / addFileExt("nim", os.ExeExt)
  16. proc execCode(code: string): string =
  17. var f: File
  18. if open(f, "temp.nim", fmWrite):
  19. f.write(code)
  20. f.close()
  21. result = osproc.execProcess(
  22. "$# $# --verbosity:0 --hint[Conf]:off temp.nim" % [nimExe, runCmd],
  23. options = {poStdErrToStdOut})
  24. else:
  25. result = "cannot open file 'temp.nim'"
  26. var shiftPressed = false
  27. var w: gtk2.PWindow
  28. var inputTextBuffer: PTextBuffer
  29. var outputTextBuffer: PTextBuffer
  30. proc destroy(widget: PWidget, data: pointer){.cdecl.} =
  31. main_quit()
  32. proc fileOpenClicked(menuitem: PMenuItem, userdata: pointer) {.cdecl.} =
  33. var path = chooseFileToOpen(w)
  34. if path != "":
  35. var file = readFile(path)
  36. if file != nil:
  37. set_text(inputTextBuffer, file, len(file).gint)
  38. else:
  39. error(w, "Unable to read from file")
  40. proc fileSaveClicked(menuitem: PMenuItem, userdata: pointer) {.cdecl.} =
  41. var path = chooseFileToSave(w)
  42. if path == "": return
  43. var startIter: TTextIter
  44. var endIter: TTextIter
  45. get_start_iter(inputTextBuffer, addr(startIter))
  46. get_end_iter(inputTextBuffer, addr(endIter))
  47. var inputText = get_text(inputTextBuffer, addr(startIter),
  48. addr(endIter), false)
  49. var f: File
  50. if open(f, path, fmWrite):
  51. f.write(inputText)
  52. f.close()
  53. else:
  54. error(w, "Unable to write to file")
  55. proc inputKeyPressed(widget: PWidget, event: PEventKey,
  56. userdata: pointer): bool {.cdecl.} =
  57. if ($keyval_name(event.keyval)).tolower() == "shift_l":
  58. # SHIFT is pressed
  59. shiftPressed = true
  60. proc setError(msg: string) =
  61. outputTextBuffer.setText(msg, msg.len.gint)
  62. proc inputKeyReleased(widget: PWidget, event: PEventKey,
  63. userdata: pointer): bool {.cdecl.} =
  64. #echo(keyval_name(event.keyval))
  65. if ($keyval_name(event.keyval)).tolower() == "shift_l":
  66. # SHIFT is released
  67. shiftPressed = false
  68. if ($keyval_name(event.keyval)).tolower() == "return":
  69. #echo($keyval_name(event.keyval), "Shift_L")
  70. # Enter pressed
  71. if not shiftPressed:
  72. var startIter: TTextIter
  73. var endIter: TTextIter
  74. get_start_iter(inputTextBuffer, addr(startIter))
  75. get_end_iter(inputTextBuffer, addr(endIter))
  76. var inputText = get_text(inputTextBuffer, addr(startIter),
  77. addr(endIter), false)
  78. try:
  79. var r = execCode($inputText)
  80. set_text(outputTextBuffer, r, len(r).gint)
  81. except IOError:
  82. setError("Error: Could not open file temp.nim")
  83. proc initControls() =
  84. w = window_new(gtk2.WINDOW_TOPLEVEL)
  85. set_default_size(w, 500, 600)
  86. set_title(w, "Nim REPL")
  87. discard signal_connect(w, "destroy", SIGNAL_FUNC(nimrepl.destroy), nil)
  88. # MainBox (vbox)
  89. var mainBox = vbox_new(false, 0)
  90. add(w, mainBox)
  91. # TopMenu (MenuBar)
  92. var topMenu = menu_bar_new()
  93. show(topMenu)
  94. var fileMenu = menu_new()
  95. var openMenuItem = menu_item_new("Open")
  96. append(fileMenu, openMenuItem)
  97. show(openMenuItem)
  98. discard signal_connect(openMenuItem, "activate",
  99. SIGNAL_FUNC(fileOpenClicked), nil)
  100. var saveMenuItem = menu_item_new("Save...")
  101. append(fileMenu, saveMenuItem)
  102. show(saveMenuItem)
  103. discard signal_connect(saveMenuItem, "activate",
  104. SIGNAL_FUNC(fileSaveClicked), nil)
  105. var fileMenuItem = menu_item_new("File")
  106. set_submenu(fileMenuItem, fileMenu)
  107. show(fileMenuItem)
  108. append(topMenu, fileMenuItem)
  109. pack_start(mainBox, topMenu, false, false, 0)
  110. # VPaned - Separates the InputTextView and the OutputTextView
  111. var paned = vpaned_new()
  112. set_position(paned, 450)
  113. pack_start(mainBox, paned, true, true, 0)
  114. show(paned)
  115. # Init the TextBuffers
  116. inputTextBuffer = text_buffer_new(nil)
  117. outputTextBuffer = text_buffer_new(nil)
  118. # InputTextView (TextView)
  119. var inputScrolledWindow = scrolled_window_new(nil, nil)
  120. set_policy(inputScrolledWindow, POLICY_AUTOMATIC, POLICY_AUTOMATIC)
  121. var inputTextView = text_view_new(inputTextBuffer)
  122. add_with_viewport(inputScrolledWindow, inputTextView)
  123. add1(paned, inputScrolledWindow)
  124. show(inputScrolledWindow)
  125. show(inputTextView)
  126. discard signal_connect(inputTextView, "key-release-event",
  127. SIGNAL_FUNC(inputKeyReleased), nil)
  128. discard signal_connect(inputTextView, "key-press-event",
  129. SIGNAL_FUNC(inputKeyPressed), nil)
  130. # OutputTextView (TextView)
  131. var outputScrolledWindow = scrolled_window_new(nil, nil)
  132. set_policy(outputScrolledWindow, POLICY_AUTOMATIC, POLICY_AUTOMATIC)
  133. var outputTextView = text_view_new(outputTextBuffer)
  134. add_with_viewport(outputScrolledWindow, outputTextView)
  135. add2(paned, outputScrolledWindow)
  136. show(outputScrolledWindow)
  137. show(outputTextView)
  138. show(w)
  139. show(mainBox)
  140. nim_init()
  141. initControls()
  142. main()