cosmos 3.5.1 → 3.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1158) hide show
  1. checksums.yaml +4 -4
  2. data/.coveralls.yml +1 -1
  3. data/.gitattributes +3 -3
  4. data/.gitignore +48 -48
  5. data/.travis.yml +8 -8
  6. data/CONTRIBUTING.txt +50 -50
  7. data/Gemfile +10 -10
  8. data/Guardfile +27 -27
  9. data/LICENSE.txt +879 -879
  10. data/Manifest.txt +1414 -1414
  11. data/README.md +111 -111
  12. data/Rakefile +218 -214
  13. data/autohotkey/config/data/diamond.STL +57 -57
  14. data/autohotkey/config/system/system.txt +34 -34
  15. data/autohotkey/config/targets/COSMOS/cmd_tlm/cosmos_server_cmds.txt +41 -41
  16. data/autohotkey/config/targets/COSMOS/cmd_tlm/cosmos_server_tlm.txt +15 -15
  17. data/autohotkey/config/targets/COSMOS/cmd_tlm_server.txt +6 -6
  18. data/autohotkey/config/targets/COSMOS/target.txt +5 -5
  19. data/autohotkey/config/targets/INST/cmd_tlm/inst_cmds.txt +121 -121
  20. data/autohotkey/config/targets/INST/cmd_tlm/inst_tlm.txt +270 -270
  21. data/autohotkey/config/targets/INST/cmd_tlm_server.txt +5 -5
  22. data/autohotkey/config/targets/INST/lib/example_limits_response.rb +30 -30
  23. data/autohotkey/config/targets/INST/lib/sim_inst.rb +305 -305
  24. data/autohotkey/config/targets/INST/screens/adcs.txt +46 -46
  25. data/autohotkey/config/targets/INST/screens/array.txt +7 -7
  26. data/autohotkey/config/targets/INST/screens/block.txt +8 -8
  27. data/autohotkey/config/targets/INST/screens/commanding.txt +30 -30
  28. data/autohotkey/config/targets/INST/screens/graphs.txt +14 -14
  29. data/autohotkey/config/targets/INST/screens/ground.txt +25 -25
  30. data/autohotkey/config/targets/INST/screens/health_status.txt +33 -33
  31. data/autohotkey/config/targets/INST/screens/hs.txt +49 -49
  32. data/autohotkey/config/targets/INST/screens/image.txt +21 -21
  33. data/autohotkey/config/targets/INST/screens/latest.txt +23 -23
  34. data/autohotkey/config/targets/INST/screens/mech.txt +25 -25
  35. data/autohotkey/config/targets/INST/screens/other.txt +25 -25
  36. data/autohotkey/config/targets/INST/screens/params.txt +25 -25
  37. data/autohotkey/config/targets/INST/screens/tabs.txt +68 -68
  38. data/autohotkey/config/targets/INST/target.txt +26 -26
  39. data/autohotkey/config/targets/META/cmd_tlm/meta_cmd.txt +10 -10
  40. data/autohotkey/config/targets/META/cmd_tlm/meta_tlm.txt +9 -9
  41. data/autohotkey/config/targets/SYSTEM/cmd_tlm/limits_groups.txt +7 -7
  42. data/autohotkey/config/targets/SYSTEM/screens/error.txt +11 -11
  43. data/autohotkey/config/tools/cmd_tlm_server/cmd_tlm_server.txt +22 -22
  44. data/autohotkey/config/tools/data_viewer/data_viewer.txt +11 -11
  45. data/autohotkey/config/tools/handbook_creator/handbook_creator.txt +49 -49
  46. data/autohotkey/config/tools/handbook_creator/templates/command_packets.html.erb +86 -86
  47. data/autohotkey/config/tools/handbook_creator/templates/command_toc.html.erb +38 -38
  48. data/autohotkey/config/tools/handbook_creator/templates/footer.html.erb +9 -9
  49. data/autohotkey/config/tools/handbook_creator/templates/header.html.erb +25 -25
  50. data/autohotkey/config/tools/handbook_creator/templates/limits_groups.html.erb +13 -13
  51. data/autohotkey/config/tools/handbook_creator/templates/nav.html.erb +27 -27
  52. data/autohotkey/config/tools/handbook_creator/templates/overview.html.erb +1 -1
  53. data/autohotkey/config/tools/handbook_creator/templates/pdf_cover.html.erb +23 -23
  54. data/autohotkey/config/tools/handbook_creator/templates/pdf_footer.html.erb +33 -33
  55. data/autohotkey/config/tools/handbook_creator/templates/pdf_header.html.erb +41 -41
  56. data/autohotkey/config/tools/handbook_creator/templates/telemetry_packets.html.erb +80 -80
  57. data/autohotkey/config/tools/handbook_creator/templates/telemetry_toc.html.erb +38 -38
  58. data/autohotkey/config/tools/handbook_creator/templates/title.html.erb +1 -1
  59. data/autohotkey/config/tools/launcher/launcher.txt +38 -38
  60. data/autohotkey/config/tools/script_runner/script_runner.txt +3 -3
  61. data/autohotkey/config/tools/table_manager/ConfigTables_def.txt +8 -8
  62. data/autohotkey/config/tools/table_manager/OneDimensionalTable_def.txt +19 -19
  63. data/autohotkey/config/tools/table_manager/TwoDimensionalTable_def.txt +248 -248
  64. data/autohotkey/config/tools/test_runner/test_runner.txt +8 -8
  65. data/autohotkey/config/tools/test_runner/test_runner2.txt +11 -11
  66. data/autohotkey/config/tools/test_runner/test_runner3.txt +6 -6
  67. data/autohotkey/config/tools/test_runner/test_runner4.txt +1 -1
  68. data/autohotkey/config/tools/tlm_extractor/tlm_extractor.txt +13 -13
  69. data/autohotkey/config/tools/tlm_extractor/tlm_extractor2.txt +9 -9
  70. data/autohotkey/config/tools/tlm_grapher/bad.txt +50 -50
  71. data/autohotkey/config/tools/tlm_grapher/temp1-4.txt +51 -51
  72. data/autohotkey/config/tools/tlm_grapher/test2.txt +111 -111
  73. data/autohotkey/config/tools/tlm_viewer/tlm_viewer.txt +24 -24
  74. data/autohotkey/config/tools/tlm_viewer/tlm_viewer2.txt +4 -4
  75. data/autohotkey/config/tools/tlm_viewer/tlm_viewer3.txt +3 -3
  76. data/autohotkey/lib/example_background_task.rb +42 -42
  77. data/autohotkey/lib/user_version.rb +3 -3
  78. data/autohotkey/procedures/clear_util.rb +7 -7
  79. data/autohotkey/procedures/collect_util.rb +14 -14
  80. data/autohotkey/procedures/example_test.rb +67 -67
  81. data/autohotkey/procedures/example_test2.rb +74 -74
  82. data/autohotkey/procedures/script_test.rb +17 -17
  83. data/autohotkey/procedures/syntax_error.rb +18 -18
  84. data/autohotkey/tools/CmdExtractorAHK +16 -16
  85. data/autohotkey/tools/CmdSender +14 -14
  86. data/autohotkey/tools/CmdSenderAHK +18 -18
  87. data/autohotkey/tools/CmdTlmServer +14 -14
  88. data/autohotkey/tools/CmdTlmServerAHK +28 -28
  89. data/autohotkey/tools/CmdTlmServerAHK2 +17 -17
  90. data/autohotkey/tools/DataViewer +14 -14
  91. data/autohotkey/tools/DataViewerAHK +17 -17
  92. data/autohotkey/tools/HandbookCreatorAHK +20 -20
  93. data/autohotkey/tools/LauncherAHK +17 -17
  94. data/autohotkey/tools/LimitsMonitorAHK +20 -20
  95. data/autohotkey/tools/OpenGLBuilderAHK +24 -24
  96. data/autohotkey/tools/PacketViewer +14 -14
  97. data/autohotkey/tools/PacketViewerAHK +18 -18
  98. data/autohotkey/tools/PacketViewerAHK2 +17 -17
  99. data/autohotkey/tools/Replay +14 -14
  100. data/autohotkey/tools/ReplayAHK +17 -17
  101. data/autohotkey/tools/ScriptRunner +14 -14
  102. data/autohotkey/tools/ScriptRunnerAHK +20 -20
  103. data/autohotkey/tools/ScriptRunnerAHK2 +17 -17
  104. data/autohotkey/tools/TableManager +14 -14
  105. data/autohotkey/tools/TableManagerAHK +30 -30
  106. data/autohotkey/tools/TestRunner +15 -15
  107. data/autohotkey/tools/TestRunnerAHK +17 -17
  108. data/autohotkey/tools/TestRunnerAHK2 +17 -17
  109. data/autohotkey/tools/TestRunnerAHK3 +17 -17
  110. data/autohotkey/tools/TestRunnerAHK4 +17 -17
  111. data/autohotkey/tools/TestRunnerAHK5 +17 -17
  112. data/autohotkey/tools/TestRunnerAHK6 +17 -17
  113. data/autohotkey/tools/TlmExtractor +15 -15
  114. data/autohotkey/tools/TlmExtractorAHK +19 -19
  115. data/autohotkey/tools/TlmExtractorAHK2 +16 -16
  116. data/autohotkey/tools/TlmExtractorAHK3 +16 -16
  117. data/autohotkey/tools/TlmGrapher +14 -14
  118. data/autohotkey/tools/TlmGrapherAHK +19 -19
  119. data/autohotkey/tools/TlmGrapherAHK2 +23 -23
  120. data/autohotkey/tools/TlmGrapherAHK3 +17 -17
  121. data/autohotkey/tools/TlmGrapherAHK4 +17 -17
  122. data/autohotkey/tools/TlmViewer +14 -14
  123. data/autohotkey/tools/TlmViewerAHK +28 -28
  124. data/autohotkey/tools/TlmViewerAHK2 +22 -22
  125. data/autohotkey/tools/TlmViewerAHK3 +23 -23
  126. data/autohotkey/tools/TlmViewerAHK4 +22 -22
  127. data/autohotkey/tools/TlmViewerAHK5 +18 -18
  128. data/autohotkey/tools/autohotkey.rb +37 -37
  129. data/autohotkey/tools/cmd_extractor.ahk +33 -33
  130. data/autohotkey/tools/cmd_sender.ahk +182 -182
  131. data/autohotkey/tools/cmd_tlm_server.ahk +90 -90
  132. data/autohotkey/tools/cmd_tlm_server2.ahk +45 -45
  133. data/autohotkey/tools/data_viewer.ahk +141 -141
  134. data/autohotkey/tools/handbook_creator.ahk +32 -32
  135. data/autohotkey/tools/launcher.ahk +41 -41
  136. data/autohotkey/tools/limits_monitor.ahk +123 -123
  137. data/autohotkey/tools/open_gl_builder.ahk +134 -134
  138. data/autohotkey/tools/packet_viewer.ahk +196 -196
  139. data/autohotkey/tools/packet_viewer2.ahk +9 -9
  140. data/autohotkey/tools/replay.ahk +104 -104
  141. data/autohotkey/tools/script_runner.ahk +589 -589
  142. data/autohotkey/tools/script_runner2.ahk +38 -38
  143. data/autohotkey/tools/table_manager.ahk +220 -220
  144. data/autohotkey/tools/test_runner.ahk +262 -262
  145. data/autohotkey/tools/test_runner2.ahk +53 -53
  146. data/autohotkey/tools/test_runner3.ahk +13 -13
  147. data/autohotkey/tools/test_runner5.ahk +8 -8
  148. data/autohotkey/tools/test_runner6.ahk +5 -5
  149. data/autohotkey/tools/tlm_extractor.ahk +296 -296
  150. data/autohotkey/tools/tlm_grapher.ahk +660 -660
  151. data/autohotkey/tools/tlm_grapher2.ahk +115 -115
  152. data/autohotkey/tools/tlm_grapher3.ahk +24 -24
  153. data/autohotkey/tools/tlm_viewer.ahk +133 -133
  154. data/autohotkey/tools/tlm_viewer2.ahk +50 -50
  155. data/autohotkey/tools/tlm_viewer4.ahk +4 -4
  156. data/autohotkey/tools/tlm_viewer5.ahk +20 -20
  157. data/bin/cosmos +96 -96
  158. data/bin/cstol_converter +1166 -1166
  159. data/bin/rubysloc +85 -85
  160. data/cosmos.gemspec +99 -99
  161. data/data/about.txt +4 -4
  162. data/data/crc.txt +326 -326
  163. data/data/diamond.STL +57 -57
  164. data/data/legal.txt +9 -9
  165. data/demo/Gemfile +10 -10
  166. data/demo/Launcher +16 -16
  167. data/demo/Launcher.bat +0 -0
  168. data/demo/Rakefile +77 -77
  169. data/demo/config/data/crc.txt +224 -226
  170. data/demo/config/data/diamond.STL +57 -57
  171. data/demo/config/data/meta_init.txt +4 -4
  172. data/demo/config/system/system.txt +35 -35
  173. data/demo/config/system/system2.txt +33 -33
  174. data/demo/config/targets/COSMOS/cmd_tlm/cosmos_server_cmds.txt +41 -41
  175. data/demo/config/targets/COSMOS/cmd_tlm/cosmos_server_tlm.txt +15 -15
  176. data/demo/config/targets/COSMOS/cmd_tlm_server.txt +6 -6
  177. data/demo/config/targets/COSMOS/screens/limits_change.txt +20 -20
  178. data/demo/config/targets/COSMOS/screens/version.txt +19 -19
  179. data/demo/config/targets/COSMOS/target.txt +11 -11
  180. data/demo/config/targets/EXAMPLE/cmd_tlm/example_cmds.txt +2 -2
  181. data/demo/config/targets/EXAMPLE/cmd_tlm/example_tlm.txt +5 -5
  182. data/demo/config/targets/EXAMPLE/cmd_tlm_server.txt +6 -6
  183. data/demo/config/targets/EXAMPLE/lib/example_interface.rb +22 -22
  184. data/demo/config/targets/EXAMPLE/target.txt +6 -6
  185. data/demo/config/targets/INST/cmd_tlm/inst_cmds.txt +121 -121
  186. data/demo/config/targets/INST/cmd_tlm/inst_tlm.txt +247 -247
  187. data/demo/config/targets/INST/cmd_tlm_server.txt +5 -5
  188. data/demo/config/targets/INST/lib/example_limits_response.rb +30 -30
  189. data/demo/config/targets/INST/lib/sim_inst.rb +305 -305
  190. data/demo/config/targets/INST/screens/adcs.txt +46 -46
  191. data/demo/config/targets/INST/screens/array.txt +15 -15
  192. data/demo/config/targets/INST/screens/block.txt +8 -8
  193. data/demo/config/targets/INST/screens/commanding.txt +30 -30
  194. data/demo/config/targets/INST/screens/graphs.txt +14 -14
  195. data/demo/config/targets/INST/screens/ground.txt +25 -25
  196. data/demo/config/targets/INST/screens/hs.txt +44 -44
  197. data/demo/config/targets/INST/screens/latest.txt +23 -23
  198. data/demo/config/targets/INST/screens/other.txt +29 -29
  199. data/demo/config/targets/INST/screens/tabs.txt +70 -70
  200. data/demo/config/targets/INST/target.txt +33 -33
  201. data/demo/config/targets/META/cmd_tlm/meta_cmd.txt +10 -10
  202. data/demo/config/targets/META/cmd_tlm/meta_tlm.txt +13 -13
  203. data/demo/config/targets/SYSTEM/cmd_tlm/limits_groups.txt +7 -7
  204. data/demo/config/targets/SYSTEM/cmd_tlm/override.txt +29 -29
  205. data/demo/config/targets/SYSTEM/screens/status.txt +12 -12
  206. data/demo/config/targets/TEMPLATED/cmd_tlm/templated_cmds.txt +13 -13
  207. data/demo/config/targets/TEMPLATED/cmd_tlm/templated_tlm.txt +3 -3
  208. data/demo/config/targets/TEMPLATED/cmd_tlm_server.txt +6 -6
  209. data/demo/config/targets/TEMPLATED/lib/templated_interface.rb +56 -56
  210. data/demo/config/targets/TEMPLATED/target.txt +6 -6
  211. data/demo/config/tools/cmd_tlm_server/cmd_tlm_server.txt +39 -39
  212. data/demo/config/tools/cmd_tlm_server/cmd_tlm_server2.txt +34 -34
  213. data/demo/config/tools/data_viewer/data_viewer.txt +11 -11
  214. data/demo/config/tools/handbook_creator/handbook_creator.txt +66 -66
  215. data/demo/config/tools/handbook_creator/templates/command_packets.html.erb +88 -88
  216. data/demo/config/tools/handbook_creator/templates/command_toc.html.erb +38 -38
  217. data/demo/config/tools/handbook_creator/templates/footer.html.erb +9 -9
  218. data/demo/config/tools/handbook_creator/templates/header.html.erb +25 -25
  219. data/demo/config/tools/handbook_creator/templates/limits_groups.html.erb +13 -13
  220. data/demo/config/tools/handbook_creator/templates/nav.html.erb +27 -27
  221. data/demo/config/tools/handbook_creator/templates/overview.html.erb +1 -1
  222. data/demo/config/tools/handbook_creator/templates/pdf_cover.html.erb +23 -23
  223. data/demo/config/tools/handbook_creator/templates/pdf_footer.html.erb +33 -33
  224. data/demo/config/tools/handbook_creator/templates/pdf_header.html.erb +41 -41
  225. data/demo/config/tools/handbook_creator/templates/telemetry_packets.html.erb +82 -82
  226. data/demo/config/tools/handbook_creator/templates/telemetry_toc.html.erb +38 -38
  227. data/demo/config/tools/handbook_creator/templates/title.html.erb +1 -1
  228. data/demo/config/tools/launcher/launcher.txt +45 -45
  229. data/demo/config/tools/launcher/launcher2.txt +45 -45
  230. data/demo/config/tools/script_runner/script_runner.txt +3 -3
  231. data/demo/config/tools/table_manager/ConfigTables_def.txt +8 -8
  232. data/demo/config/tools/table_manager/ExampleTableDefinition.txt +24 -24
  233. data/demo/config/tools/table_manager/MCConfigurationTable_fsw1_def.txt +25 -25
  234. data/demo/config/tools/table_manager/MCConfigurationTable_fsw2_def.txt +25 -25
  235. data/demo/config/tools/table_manager/PPSSelectionTable_def.txt +8 -8
  236. data/demo/config/tools/table_manager/TLMMonitoringTable_def.txt +248 -248
  237. data/demo/config/tools/test_runner/test_runner.txt +17 -17
  238. data/demo/config/tools/tlm_extractor/tlm_extractor.txt +13 -13
  239. data/demo/config/tools/tlm_extractor/tlm_extractor2.txt +2 -2
  240. data/demo/config/tools/tlm_extractor/tlm_extractor3.txt +2 -2
  241. data/demo/config/tools/tlm_extractor/tlm_extractor4.txt +2 -2
  242. data/demo/config/tools/tlm_viewer/tlm_viewer.txt +41 -41
  243. data/demo/lib/example_background_task.rb +57 -57
  244. data/demo/lib/example_target.rb +113 -113
  245. data/demo/lib/scpi_target.rb +74 -74
  246. data/demo/lib/user_version.rb +3 -3
  247. data/demo/procedures/checks.rb +11 -11
  248. data/demo/procedures/clear_util.rb +7 -7
  249. data/demo/procedures/collect.rb +18 -18
  250. data/demo/procedures/collect_util.rb +14 -14
  251. data/demo/procedures/cosmos_api_test.rb +293 -293
  252. data/demo/procedures/disconnect.rb +29 -29
  253. data/demo/procedures/example_test.rb +183 -183
  254. data/demo/procedures/plot_test.rb +8 -8
  255. data/demo/procedures/run_example_test.rb +3 -3
  256. data/demo/procedures/test.rb +51 -51
  257. data/demo/tools/CmdExtractor +16 -16
  258. data/demo/tools/CmdExtractor.bat +0 -0
  259. data/demo/tools/CmdSender +16 -16
  260. data/demo/tools/CmdSender.bat +0 -0
  261. data/demo/tools/CmdTlmServer +16 -16
  262. data/demo/tools/CmdTlmServer.bat +0 -0
  263. data/demo/tools/DataViewer +16 -16
  264. data/demo/tools/DataViewer.bat +0 -0
  265. data/demo/tools/ExampleTarget +16 -16
  266. data/demo/tools/ExampleTarget.bat +0 -0
  267. data/demo/tools/HandbookCreator +16 -16
  268. data/demo/tools/HandbookCreator.bat +0 -0
  269. data/demo/tools/Launcher +16 -16
  270. data/demo/tools/Launcher.bat +0 -0
  271. data/demo/tools/LimitsMonitor +16 -16
  272. data/demo/tools/LimitsMonitor.bat +0 -0
  273. data/demo/tools/OpenGLBuilder +16 -16
  274. data/demo/tools/OpenGLBuilder.bat +0 -0
  275. data/demo/tools/PacketViewer +16 -16
  276. data/demo/tools/PacketViewer.bat +0 -0
  277. data/demo/tools/Replay +16 -16
  278. data/demo/tools/Replay.bat +0 -0
  279. data/demo/tools/ScpiTarget +16 -16
  280. data/demo/tools/ScpiTarget.bat +0 -0
  281. data/demo/tools/ScriptRunner +16 -16
  282. data/demo/tools/ScriptRunner.bat +0 -0
  283. data/demo/tools/TableManager +16 -16
  284. data/demo/tools/TableManager.bat +0 -0
  285. data/demo/tools/TestRunner +16 -16
  286. data/demo/tools/TestRunner.bat +0 -0
  287. data/demo/tools/TlmExtractor +16 -16
  288. data/demo/tools/TlmExtractor.bat +0 -0
  289. data/demo/tools/TlmGrapher +16 -16
  290. data/demo/tools/TlmGrapher.bat +0 -0
  291. data/demo/tools/TlmViewer +16 -16
  292. data/demo/tools/TlmViewer.bat +0 -0
  293. data/demo/tools/ToolLaunch.bat +14 -5
  294. data/demo/tools/mac/CmdExtractor.app/Contents/Info.plist +38 -38
  295. data/demo/tools/mac/CmdExtractor.app/Contents/MacOS/CmdExtractor.rb +16 -16
  296. data/demo/tools/mac/CmdExtractor.app/Contents/MacOS/main.sh +10 -10
  297. data/demo/tools/mac/CmdExtractor.app/Contents/MacOS/tool_launch.rb +38 -38
  298. data/demo/tools/mac/CmdSender.app/Contents/Info.plist +38 -38
  299. data/demo/tools/mac/CmdSender.app/Contents/MacOS/CmdSender.rb +16 -16
  300. data/demo/tools/mac/CmdSender.app/Contents/MacOS/main.sh +10 -10
  301. data/demo/tools/mac/CmdSender.app/Contents/MacOS/tool_launch.rb +38 -38
  302. data/demo/tools/mac/CmdTlmServer.app/Contents/Info.plist +38 -38
  303. data/demo/tools/mac/CmdTlmServer.app/Contents/MacOS/CmdTlmServer.rb +16 -16
  304. data/demo/tools/mac/CmdTlmServer.app/Contents/MacOS/main.sh +10 -10
  305. data/demo/tools/mac/CmdTlmServer.app/Contents/MacOS/tool_launch.rb +38 -38
  306. data/demo/tools/mac/DataViewer.app/Contents/Info.plist +38 -38
  307. data/demo/tools/mac/DataViewer.app/Contents/MacOS/DataViewer.rb +16 -16
  308. data/demo/tools/mac/DataViewer.app/Contents/MacOS/main.sh +10 -10
  309. data/demo/tools/mac/DataViewer.app/Contents/MacOS/tool_launch.rb +38 -38
  310. data/demo/tools/mac/HandbookCreator.app/Contents/Info.plist +38 -38
  311. data/demo/tools/mac/HandbookCreator.app/Contents/MacOS/HandbookCreator.rb +16 -16
  312. data/demo/tools/mac/HandbookCreator.app/Contents/MacOS/main.sh +10 -10
  313. data/demo/tools/mac/HandbookCreator.app/Contents/MacOS/tool_launch.rb +38 -38
  314. data/demo/tools/mac/Launcher.app/Contents/Info.plist +38 -38
  315. data/demo/tools/mac/Launcher.app/Contents/MacOS/Launcher.rb +16 -16
  316. data/demo/tools/mac/Launcher.app/Contents/MacOS/main.sh +10 -10
  317. data/demo/tools/mac/Launcher.app/Contents/MacOS/tool_launch.rb +38 -38
  318. data/demo/tools/mac/LimitsMonitor.app/Contents/Info.plist +38 -38
  319. data/demo/tools/mac/LimitsMonitor.app/Contents/MacOS/LimitsMonitor.rb +16 -16
  320. data/demo/tools/mac/LimitsMonitor.app/Contents/MacOS/main.sh +10 -10
  321. data/demo/tools/mac/LimitsMonitor.app/Contents/MacOS/tool_launch.rb +38 -38
  322. data/demo/tools/mac/OpenGLBuilder.app/Contents/Info.plist +38 -38
  323. data/demo/tools/mac/OpenGLBuilder.app/Contents/MacOS/OpenGLBuilder.rb +16 -16
  324. data/demo/tools/mac/OpenGLBuilder.app/Contents/MacOS/main.sh +10 -10
  325. data/demo/tools/mac/OpenGLBuilder.app/Contents/MacOS/tool_launch.rb +38 -38
  326. data/demo/tools/mac/PacketViewer.app/Contents/Info.plist +38 -38
  327. data/demo/tools/mac/PacketViewer.app/Contents/MacOS/PacketViewer.rb +16 -16
  328. data/demo/tools/mac/PacketViewer.app/Contents/MacOS/main.sh +10 -10
  329. data/demo/tools/mac/PacketViewer.app/Contents/MacOS/tool_launch.rb +38 -38
  330. data/demo/tools/mac/Replay.app/Contents/Info.plist +38 -38
  331. data/demo/tools/mac/Replay.app/Contents/MacOS/Replay.rb +16 -16
  332. data/demo/tools/mac/Replay.app/Contents/MacOS/main.sh +10 -10
  333. data/demo/tools/mac/Replay.app/Contents/MacOS/tool_launch.rb +38 -38
  334. data/demo/tools/mac/ScriptRunner.app/Contents/Info.plist +38 -38
  335. data/demo/tools/mac/ScriptRunner.app/Contents/MacOS/ScriptRunner.rb +16 -16
  336. data/demo/tools/mac/ScriptRunner.app/Contents/MacOS/main.sh +10 -10
  337. data/demo/tools/mac/ScriptRunner.app/Contents/MacOS/tool_launch.rb +38 -38
  338. data/demo/tools/mac/TableManager.app/Contents/Info.plist +38 -38
  339. data/demo/tools/mac/TableManager.app/Contents/MacOS/TableManager.rb +16 -16
  340. data/demo/tools/mac/TableManager.app/Contents/MacOS/main.sh +10 -10
  341. data/demo/tools/mac/TableManager.app/Contents/MacOS/tool_launch.rb +38 -38
  342. data/demo/tools/mac/TestRunner.app/Contents/Info.plist +38 -38
  343. data/demo/tools/mac/TestRunner.app/Contents/MacOS/TestRunner.rb +16 -16
  344. data/demo/tools/mac/TestRunner.app/Contents/MacOS/main.sh +10 -10
  345. data/demo/tools/mac/TestRunner.app/Contents/MacOS/tool_launch.rb +38 -38
  346. data/demo/tools/mac/TlmExtractor.app/Contents/Info.plist +38 -38
  347. data/demo/tools/mac/TlmExtractor.app/Contents/MacOS/TlmExtractor.rb +16 -16
  348. data/demo/tools/mac/TlmExtractor.app/Contents/MacOS/main.sh +10 -10
  349. data/demo/tools/mac/TlmExtractor.app/Contents/MacOS/tool_launch.rb +38 -38
  350. data/demo/tools/mac/TlmGrapher.app/Contents/Info.plist +38 -38
  351. data/demo/tools/mac/TlmGrapher.app/Contents/MacOS/TlmGrapher.rb +16 -16
  352. data/demo/tools/mac/TlmGrapher.app/Contents/MacOS/main.sh +10 -10
  353. data/demo/tools/mac/TlmGrapher.app/Contents/MacOS/tool_launch.rb +38 -38
  354. data/demo/tools/mac/TlmViewer.app/Contents/Info.plist +38 -38
  355. data/demo/tools/mac/TlmViewer.app/Contents/MacOS/TlmViewer.rb +16 -16
  356. data/demo/tools/mac/TlmViewer.app/Contents/MacOS/main.sh +10 -10
  357. data/demo/tools/mac/TlmViewer.app/Contents/MacOS/tool_launch.rb +38 -38
  358. data/demo/tools/tool_launch.rb +38 -38
  359. data/ext/cosmos/ext/array/array.c +111 -111
  360. data/ext/cosmos/ext/array/extconf.rb +13 -13
  361. data/ext/cosmos/ext/buffered_file/buffered_file.c +167 -167
  362. data/ext/cosmos/ext/buffered_file/extconf.rb +13 -13
  363. data/ext/cosmos/ext/config_parser/config_parser.c +237 -237
  364. data/ext/cosmos/ext/config_parser/extconf.rb +13 -13
  365. data/ext/cosmos/ext/cosmos_io/cosmos_io.c +117 -117
  366. data/ext/cosmos/ext/cosmos_io/extconf.rb +13 -13
  367. data/ext/cosmos/ext/crc/crc.c +341 -341
  368. data/ext/cosmos/ext/crc/extconf.rb +12 -12
  369. data/ext/cosmos/ext/line_graph/extconf.rb +13 -13
  370. data/ext/cosmos/ext/line_graph/line_graph.c +501 -501
  371. data/ext/cosmos/ext/low_fragmentation_array/extconf.rb +12 -12
  372. data/ext/cosmos/ext/low_fragmentation_array/low_fragmentation_array.c +265 -265
  373. data/ext/cosmos/ext/packet/extconf.rb +13 -13
  374. data/ext/cosmos/ext/packet/packet.c +339 -339
  375. data/ext/cosmos/ext/platform/extconf.rb +13 -13
  376. data/ext/cosmos/ext/platform/platform.c +101 -101
  377. data/ext/cosmos/ext/polynomial_conversion/extconf.rb +13 -13
  378. data/ext/cosmos/ext/polynomial_conversion/polynomial_conversion.c +73 -73
  379. data/ext/cosmos/ext/string/extconf.rb +13 -13
  380. data/ext/cosmos/ext/string/string.c +49 -49
  381. data/ext/cosmos/ext/structure/structure.c +1428 -1428
  382. data/ext/cosmos/ext/tabbed_plots_config/extconf.rb +13 -13
  383. data/ext/cosmos/ext/tabbed_plots_config/tabbed_plots_config.c +51 -51
  384. data/ext/cosmos/ext/telemetry/extconf.rb +13 -13
  385. data/ext/cosmos/ext/telemetry/telemetry.c +307 -307
  386. data/ext/mkrf_conf.rb +40 -40
  387. data/install/Gemfile +10 -10
  388. data/install/Launcher +16 -16
  389. data/install/Launcher.bat +0 -0
  390. data/install/Rakefile +77 -77
  391. data/install/config/data/crc.txt +151 -151
  392. data/install/config/system/system.txt +29 -29
  393. data/install/config/targets/COSMOS/cmd_tlm/cosmos_server_cmds.txt +41 -41
  394. data/install/config/targets/COSMOS/cmd_tlm/cosmos_server_tlm.txt +15 -15
  395. data/install/config/targets/COSMOS/cmd_tlm_server.txt +6 -6
  396. data/install/config/targets/COSMOS/screens/limits_change.txt +20 -20
  397. data/install/config/targets/COSMOS/screens/version.txt +19 -19
  398. data/install/config/targets/COSMOS/target.txt +8 -8
  399. data/install/config/tools/cmd_tlm_server/cmd_tlm_server.txt +2 -2
  400. data/install/config/tools/data_viewer/data_viewer.txt +3 -3
  401. data/install/config/tools/handbook_creator/handbook_creator.txt +49 -49
  402. data/install/config/tools/handbook_creator/templates/command_packets.html.erb +86 -86
  403. data/install/config/tools/handbook_creator/templates/command_toc.html.erb +38 -38
  404. data/install/config/tools/handbook_creator/templates/footer.html.erb +9 -9
  405. data/install/config/tools/handbook_creator/templates/header.html.erb +25 -25
  406. data/install/config/tools/handbook_creator/templates/limits_groups.html.erb +13 -13
  407. data/install/config/tools/handbook_creator/templates/nav.html.erb +27 -27
  408. data/install/config/tools/handbook_creator/templates/overview.html.erb +1 -1
  409. data/install/config/tools/handbook_creator/templates/pdf_cover.html.erb +23 -23
  410. data/install/config/tools/handbook_creator/templates/pdf_footer.html.erb +33 -33
  411. data/install/config/tools/handbook_creator/templates/pdf_header.html.erb +41 -41
  412. data/install/config/tools/handbook_creator/templates/telemetry_packets.html.erb +80 -80
  413. data/install/config/tools/handbook_creator/templates/telemetry_toc.html.erb +38 -38
  414. data/install/config/tools/handbook_creator/templates/title.html.erb +1 -1
  415. data/install/config/tools/launcher/launcher.txt +40 -40
  416. data/install/config/tools/script_runner/script_runner.txt +3 -3
  417. data/install/config/tools/test_runner/test_runner.txt +8 -8
  418. data/install/config/tools/tlm_viewer/tlm_viewer.txt +5 -5
  419. data/install/lib/user_version.rb +3 -3
  420. data/install/tools/CmdExtractor +16 -16
  421. data/install/tools/CmdExtractor.bat +0 -0
  422. data/install/tools/CmdSender +16 -16
  423. data/install/tools/CmdSender.bat +0 -0
  424. data/install/tools/CmdTlmServer +16 -16
  425. data/install/tools/CmdTlmServer.bat +0 -0
  426. data/install/tools/DataViewer +16 -16
  427. data/install/tools/DataViewer.bat +0 -0
  428. data/install/tools/HandbookCreator +16 -16
  429. data/install/tools/HandbookCreator.bat +0 -0
  430. data/install/tools/Launcher +16 -16
  431. data/install/tools/Launcher.bat +0 -0
  432. data/install/tools/LimitsMonitor +16 -16
  433. data/install/tools/LimitsMonitor.bat +0 -0
  434. data/install/tools/OpenGLBuilder +16 -16
  435. data/install/tools/OpenGLBuilder.bat +0 -0
  436. data/install/tools/PacketViewer +16 -16
  437. data/install/tools/PacketViewer.bat +0 -0
  438. data/install/tools/Replay +16 -16
  439. data/install/tools/Replay.bat +0 -0
  440. data/install/tools/ScriptRunner +16 -16
  441. data/install/tools/ScriptRunner.bat +0 -0
  442. data/install/tools/TableManager +16 -16
  443. data/install/tools/TableManager.bat +0 -0
  444. data/install/tools/TestRunner +16 -16
  445. data/install/tools/TestRunner.bat +0 -0
  446. data/install/tools/TlmExtractor +16 -16
  447. data/install/tools/TlmExtractor.bat +0 -0
  448. data/install/tools/TlmGrapher +16 -16
  449. data/install/tools/TlmGrapher.bat +0 -0
  450. data/install/tools/TlmViewer +16 -16
  451. data/install/tools/TlmViewer.bat +0 -0
  452. data/install/tools/ToolLaunch.bat +14 -5
  453. data/install/tools/mac/CmdExtractor.app/Contents/Info.plist +38 -38
  454. data/install/tools/mac/CmdExtractor.app/Contents/MacOS/CmdExtractor.rb +16 -16
  455. data/install/tools/mac/CmdExtractor.app/Contents/MacOS/main.sh +10 -10
  456. data/install/tools/mac/CmdExtractor.app/Contents/MacOS/tool_launch.rb +38 -38
  457. data/install/tools/mac/CmdSender.app/Contents/Info.plist +38 -38
  458. data/install/tools/mac/CmdSender.app/Contents/MacOS/CmdSender.rb +16 -16
  459. data/install/tools/mac/CmdSender.app/Contents/MacOS/main.sh +10 -10
  460. data/install/tools/mac/CmdSender.app/Contents/MacOS/tool_launch.rb +38 -38
  461. data/install/tools/mac/CmdTlmServer.app/Contents/Info.plist +38 -38
  462. data/install/tools/mac/CmdTlmServer.app/Contents/MacOS/CmdTlmServer.rb +16 -16
  463. data/install/tools/mac/CmdTlmServer.app/Contents/MacOS/main.sh +10 -10
  464. data/install/tools/mac/CmdTlmServer.app/Contents/MacOS/tool_launch.rb +38 -38
  465. data/install/tools/mac/DataViewer.app/Contents/Info.plist +38 -38
  466. data/install/tools/mac/DataViewer.app/Contents/MacOS/DataViewer.rb +16 -16
  467. data/install/tools/mac/DataViewer.app/Contents/MacOS/main.sh +10 -10
  468. data/install/tools/mac/DataViewer.app/Contents/MacOS/tool_launch.rb +38 -38
  469. data/install/tools/mac/HandbookCreator.app/Contents/Info.plist +38 -38
  470. data/install/tools/mac/HandbookCreator.app/Contents/MacOS/HandbookCreator.rb +16 -16
  471. data/install/tools/mac/HandbookCreator.app/Contents/MacOS/main.sh +10 -10
  472. data/install/tools/mac/HandbookCreator.app/Contents/MacOS/tool_launch.rb +38 -38
  473. data/install/tools/mac/Launcher.app/Contents/Info.plist +38 -38
  474. data/install/tools/mac/Launcher.app/Contents/MacOS/Launcher.rb +16 -16
  475. data/install/tools/mac/Launcher.app/Contents/MacOS/main.sh +10 -10
  476. data/install/tools/mac/Launcher.app/Contents/MacOS/tool_launch.rb +38 -38
  477. data/install/tools/mac/LimitsMonitor.app/Contents/Info.plist +38 -38
  478. data/install/tools/mac/LimitsMonitor.app/Contents/MacOS/LimitsMonitor.rb +16 -16
  479. data/install/tools/mac/LimitsMonitor.app/Contents/MacOS/main.sh +10 -10
  480. data/install/tools/mac/LimitsMonitor.app/Contents/MacOS/tool_launch.rb +38 -38
  481. data/install/tools/mac/OpenGLBuilder.app/Contents/Info.plist +38 -38
  482. data/install/tools/mac/OpenGLBuilder.app/Contents/MacOS/OpenGLBuilder.rb +16 -16
  483. data/install/tools/mac/OpenGLBuilder.app/Contents/MacOS/main.sh +10 -10
  484. data/install/tools/mac/OpenGLBuilder.app/Contents/MacOS/tool_launch.rb +38 -38
  485. data/install/tools/mac/PacketViewer.app/Contents/Info.plist +38 -38
  486. data/install/tools/mac/PacketViewer.app/Contents/MacOS/PacketViewer.rb +16 -16
  487. data/install/tools/mac/PacketViewer.app/Contents/MacOS/main.sh +10 -10
  488. data/install/tools/mac/PacketViewer.app/Contents/MacOS/tool_launch.rb +38 -38
  489. data/install/tools/mac/Replay.app/Contents/Info.plist +38 -38
  490. data/install/tools/mac/Replay.app/Contents/MacOS/Replay.rb +16 -16
  491. data/install/tools/mac/Replay.app/Contents/MacOS/main.sh +10 -10
  492. data/install/tools/mac/Replay.app/Contents/MacOS/tool_launch.rb +38 -38
  493. data/install/tools/mac/ScriptRunner.app/Contents/Info.plist +38 -38
  494. data/install/tools/mac/ScriptRunner.app/Contents/MacOS/ScriptRunner.rb +16 -16
  495. data/install/tools/mac/ScriptRunner.app/Contents/MacOS/main.sh +10 -10
  496. data/install/tools/mac/ScriptRunner.app/Contents/MacOS/tool_launch.rb +38 -38
  497. data/install/tools/mac/TableManager.app/Contents/Info.plist +38 -38
  498. data/install/tools/mac/TableManager.app/Contents/MacOS/TableManager.rb +16 -16
  499. data/install/tools/mac/TableManager.app/Contents/MacOS/main.sh +10 -10
  500. data/install/tools/mac/TableManager.app/Contents/MacOS/tool_launch.rb +38 -38
  501. data/install/tools/mac/TestRunner.app/Contents/Info.plist +38 -38
  502. data/install/tools/mac/TestRunner.app/Contents/MacOS/TestRunner.rb +16 -16
  503. data/install/tools/mac/TestRunner.app/Contents/MacOS/main.sh +10 -10
  504. data/install/tools/mac/TestRunner.app/Contents/MacOS/tool_launch.rb +38 -38
  505. data/install/tools/mac/TlmExtractor.app/Contents/Info.plist +38 -38
  506. data/install/tools/mac/TlmExtractor.app/Contents/MacOS/TlmExtractor.rb +16 -16
  507. data/install/tools/mac/TlmExtractor.app/Contents/MacOS/main.sh +10 -10
  508. data/install/tools/mac/TlmExtractor.app/Contents/MacOS/tool_launch.rb +38 -38
  509. data/install/tools/mac/TlmGrapher.app/Contents/Info.plist +38 -38
  510. data/install/tools/mac/TlmGrapher.app/Contents/MacOS/TlmGrapher.rb +16 -16
  511. data/install/tools/mac/TlmGrapher.app/Contents/MacOS/main.sh +10 -10
  512. data/install/tools/mac/TlmGrapher.app/Contents/MacOS/tool_launch.rb +38 -38
  513. data/install/tools/mac/TlmViewer.app/Contents/Info.plist +38 -38
  514. data/install/tools/mac/TlmViewer.app/Contents/MacOS/TlmViewer.rb +16 -16
  515. data/install/tools/mac/TlmViewer.app/Contents/MacOS/main.sh +10 -10
  516. data/install/tools/mac/TlmViewer.app/Contents/MacOS/tool_launch.rb +38 -38
  517. data/install/tools/tool_launch.rb +38 -38
  518. data/lib/cosmos.rb +63 -63
  519. data/lib/cosmos/ccsds/ccsds_packet.rb +63 -63
  520. data/lib/cosmos/ccsds/ccsds_parser.rb +143 -143
  521. data/lib/cosmos/config/config_parser.rb +324 -324
  522. data/lib/cosmos/conversions.rb +13 -13
  523. data/lib/cosmos/conversions/conversion.rb +47 -47
  524. data/lib/cosmos/conversions/generic_conversion.rb +55 -55
  525. data/lib/cosmos/conversions/new_packet_log_conversion.rb +45 -45
  526. data/lib/cosmos/conversions/polynomial_conversion.rb +57 -57
  527. data/lib/cosmos/conversions/processor_conversion.rb +46 -46
  528. data/lib/cosmos/conversions/received_count_conversion.rb +33 -33
  529. data/lib/cosmos/conversions/received_time_formatted_conversion.rb +37 -37
  530. data/lib/cosmos/conversions/received_time_seconds_conversion.rb +37 -37
  531. data/lib/cosmos/conversions/segmented_polynomial_conversion.rb +128 -128
  532. data/lib/cosmos/conversions/unix_time_conversion.rb +50 -50
  533. data/lib/cosmos/conversions/unix_time_formatted_conversion.rb +44 -44
  534. data/lib/cosmos/conversions/unix_time_seconds_conversion.rb +44 -44
  535. data/lib/cosmos/core_ext.rb +18 -18
  536. data/lib/cosmos/core_ext/array.rb +354 -354
  537. data/lib/cosmos/core_ext/class.rb +51 -51
  538. data/lib/cosmos/core_ext/cosmos_io.rb +29 -29
  539. data/lib/cosmos/core_ext/exception.rb +52 -52
  540. data/lib/cosmos/core_ext/file.rb +75 -75
  541. data/lib/cosmos/core_ext/hash.rb +28 -28
  542. data/lib/cosmos/core_ext/io.rb +75 -75
  543. data/lib/cosmos/core_ext/kernel.rb +38 -38
  544. data/lib/cosmos/core_ext/math.rb +119 -119
  545. data/lib/cosmos/core_ext/matrix.rb +146 -146
  546. data/lib/cosmos/core_ext/objectspace.rb +29 -29
  547. data/lib/cosmos/core_ext/range.rb +22 -22
  548. data/lib/cosmos/core_ext/socket.rb +32 -32
  549. data/lib/cosmos/core_ext/string.rb +311 -311
  550. data/lib/cosmos/core_ext/stringio.rb +24 -24
  551. data/lib/cosmos/core_ext/time.rb +448 -448
  552. data/lib/cosmos/gui/choosers/combobox_chooser.rb +130 -130
  553. data/lib/cosmos/gui/choosers/file_chooser.rb +68 -68
  554. data/lib/cosmos/gui/choosers/float_chooser.rb +82 -82
  555. data/lib/cosmos/gui/choosers/integer_chooser.rb +80 -80
  556. data/lib/cosmos/gui/choosers/string_chooser.rb +53 -53
  557. data/lib/cosmos/gui/choosers/telemetry_chooser.rb +326 -326
  558. data/lib/cosmos/gui/dialogs/about_dialog.rb +137 -137
  559. data/lib/cosmos/gui/dialogs/calendar_dialog.rb +136 -136
  560. data/lib/cosmos/gui/dialogs/cmd_details_dialog.rb +52 -52
  561. data/lib/cosmos/gui/dialogs/cmd_tlm_raw_dialog.rb +149 -149
  562. data/lib/cosmos/gui/dialogs/details_dialog.rb +174 -174
  563. data/lib/cosmos/gui/dialogs/exception_dialog.rb +97 -97
  564. data/lib/cosmos/gui/dialogs/exception_list_dialog.rb +59 -59
  565. data/lib/cosmos/gui/dialogs/find_replace_dialog.rb +260 -260
  566. data/lib/cosmos/gui/dialogs/legal_dialog.rb +169 -169
  567. data/lib/cosmos/gui/dialogs/packet_log_dialog.rb +118 -118
  568. data/lib/cosmos/gui/dialogs/progress_dialog.rb +276 -276
  569. data/lib/cosmos/gui/dialogs/pry_dialog.rb +165 -165
  570. data/lib/cosmos/gui/dialogs/scroll_text_dialog.rb +37 -37
  571. data/lib/cosmos/gui/dialogs/select_dialog.rb +54 -54
  572. data/lib/cosmos/gui/dialogs/set_tlm_dialog.rb +131 -131
  573. data/lib/cosmos/gui/dialogs/splash.rb +135 -135
  574. data/lib/cosmos/gui/dialogs/tlm_details_dialog.rb +206 -206
  575. data/lib/cosmos/gui/dialogs/tlm_edit_dialog.rb +81 -81
  576. data/lib/cosmos/gui/line_graph/line_graph.rb +456 -456
  577. data/lib/cosmos/gui/line_graph/line_graph_dialog.rb +34 -34
  578. data/lib/cosmos/gui/line_graph/line_graph_drawing.rb +473 -473
  579. data/lib/cosmos/gui/line_graph/line_graph_popups.rb +116 -116
  580. data/lib/cosmos/gui/line_graph/line_graph_scaling.rb +451 -451
  581. data/lib/cosmos/gui/line_graph/line_graph_script.rb +26 -26
  582. data/lib/cosmos/gui/line_graph/lines.rb +290 -290
  583. data/lib/cosmos/gui/line_graph/overview_graph.rb +469 -469
  584. data/lib/cosmos/gui/opengl/earth_model.rb +22 -22
  585. data/lib/cosmos/gui/opengl/gl_bounds.rb +67 -67
  586. data/lib/cosmos/gui/opengl/gl_light.rb +39 -39
  587. data/lib/cosmos/gui/opengl/gl_material.rb +29 -29
  588. data/lib/cosmos/gui/opengl/gl_scene.rb +72 -72
  589. data/lib/cosmos/gui/opengl/gl_shape.rb +146 -146
  590. data/lib/cosmos/gui/opengl/gl_viewer.rb +724 -724
  591. data/lib/cosmos/gui/opengl/gl_viewport.rb +35 -35
  592. data/lib/cosmos/gui/opengl/moon_model.rb +22 -22
  593. data/lib/cosmos/gui/opengl/opengl.rb +8 -8
  594. data/lib/cosmos/gui/opengl/stl_reader.rb +211 -211
  595. data/lib/cosmos/gui/opengl/stl_shape.rb +124 -124
  596. data/lib/cosmos/gui/opengl/texture_mapped_sphere.rb +202 -202
  597. data/lib/cosmos/gui/qt.rb +860 -860
  598. data/lib/cosmos/gui/qt_tool.rb +380 -380
  599. data/lib/cosmos/gui/text/completion.rb +381 -381
  600. data/lib/cosmos/gui/text/completion_line_edit.rb +30 -30
  601. data/lib/cosmos/gui/text/completion_text_edit.rb +179 -179
  602. data/lib/cosmos/gui/text/ruby_editor.rb +415 -415
  603. data/lib/cosmos/gui/utilities/screenshot.rb +25 -25
  604. data/lib/cosmos/gui/utilities/script_module_gui.rb +330 -330
  605. data/lib/cosmos/gui/widgets/full_text_search_line_edit.rb +161 -161
  606. data/lib/cosmos/gui/widgets/packet_log_frame.rb +305 -305
  607. data/lib/cosmos/gui/widgets/realtime_button_bar.rb +98 -98
  608. data/lib/cosmos/interfaces.rb +11 -11
  609. data/lib/cosmos/interfaces/cmd_tlm_server_interface.rb +153 -153
  610. data/lib/cosmos/interfaces/interface.rb +225 -225
  611. data/lib/cosmos/interfaces/linc_interface.rb +360 -360
  612. data/lib/cosmos/interfaces/serial_interface.rb +76 -76
  613. data/lib/cosmos/interfaces/simulated_target_interface.rb +129 -129
  614. data/lib/cosmos/interfaces/stream_interface.rb +136 -136
  615. data/lib/cosmos/interfaces/tcpip_client_interface.rb +60 -60
  616. data/lib/cosmos/interfaces/tcpip_server_interface.rb +164 -164
  617. data/lib/cosmos/interfaces/udp_interface.rb +161 -161
  618. data/lib/cosmos/io/buffered_file.rb +11 -11
  619. data/lib/cosmos/io/cosmos_snmp.rb +50 -50
  620. data/lib/cosmos/io/io_multiplexer.rb +89 -89
  621. data/lib/cosmos/io/json_drb.rb +376 -376
  622. data/lib/cosmos/io/json_drb_object.rb +198 -198
  623. data/lib/cosmos/io/json_rpc.rb +365 -365
  624. data/lib/cosmos/io/posix_serial_driver.rb +145 -145
  625. data/lib/cosmos/io/raw_logger.rb +174 -174
  626. data/lib/cosmos/io/raw_logger_pair.rb +71 -71
  627. data/lib/cosmos/io/serial_driver.rb +85 -85
  628. data/lib/cosmos/io/stderr.rb +36 -36
  629. data/lib/cosmos/io/stdout.rb +36 -36
  630. data/lib/cosmos/io/tcpip_server.rb +571 -571
  631. data/lib/cosmos/io/udp_sockets.rb +152 -152
  632. data/lib/cosmos/io/win32_serial_driver.rb +145 -145
  633. data/lib/cosmos/packet_logs.rb +7 -7
  634. data/lib/cosmos/packet_logs/ccsds_log_reader.rb +104 -104
  635. data/lib/cosmos/packet_logs/meta_packet_log_writer.rb +107 -107
  636. data/lib/cosmos/packet_logs/packet_log_reader.rb +450 -450
  637. data/lib/cosmos/packet_logs/packet_log_writer.rb +323 -323
  638. data/lib/cosmos/packet_logs/packet_log_writer_pair.rb +30 -30
  639. data/lib/cosmos/packets/binary_accessor.rb +634 -634
  640. data/lib/cosmos/packets/commands.rb +293 -293
  641. data/lib/cosmos/packets/limits.rb +267 -267
  642. data/lib/cosmos/packets/limits_response.rb +38 -38
  643. data/lib/cosmos/packets/packet.rb +786 -786
  644. data/lib/cosmos/packets/packet_config.rb +482 -482
  645. data/lib/cosmos/packets/packet_item.rb +317 -317
  646. data/lib/cosmos/packets/packet_item_limits.rb +128 -128
  647. data/lib/cosmos/packets/parsers/format_string_parser.rb +58 -58
  648. data/lib/cosmos/packets/parsers/limits_parser.rb +146 -146
  649. data/lib/cosmos/packets/parsers/limits_response_parser.rb +52 -52
  650. data/lib/cosmos/packets/parsers/macro_parser.rb +116 -116
  651. data/lib/cosmos/packets/parsers/packet_item_parser.rb +215 -215
  652. data/lib/cosmos/packets/parsers/packet_parser.rb +123 -123
  653. data/lib/cosmos/packets/parsers/processor_parser.rb +63 -63
  654. data/lib/cosmos/packets/parsers/state_parser.rb +116 -116
  655. data/lib/cosmos/packets/structure.rb +458 -458
  656. data/lib/cosmos/packets/structure_item.rb +233 -233
  657. data/lib/cosmos/packets/telemetry.rb +350 -350
  658. data/lib/cosmos/processors.rb +6 -6
  659. data/lib/cosmos/processors/new_packet_log_processor.rb +34 -34
  660. data/lib/cosmos/processors/processor.rb +71 -71
  661. data/lib/cosmos/processors/statistics_processor.rb +65 -65
  662. data/lib/cosmos/processors/watermark_processor.rb +44 -44
  663. data/lib/cosmos/script.rb +9 -9
  664. data/lib/cosmos/script/cmd_tlm_server.rb +110 -110
  665. data/lib/cosmos/script/commands.rb +184 -184
  666. data/lib/cosmos/script/extract.rb +123 -123
  667. data/lib/cosmos/script/limits.rb +114 -114
  668. data/lib/cosmos/script/script.rb +76 -76
  669. data/lib/cosmos/script/scripting.rb +897 -897
  670. data/lib/cosmos/script/telemetry.rb +174 -174
  671. data/lib/cosmos/script/tools.rb +138 -138
  672. data/lib/cosmos/streams/burst_stream_protocol.rb +25 -25
  673. data/lib/cosmos/streams/fixed_stream_protocol.rb +111 -111
  674. data/lib/cosmos/streams/length_stream_protocol.rb +140 -140
  675. data/lib/cosmos/streams/preidentified_stream_protocol.rb +118 -118
  676. data/lib/cosmos/streams/serial_stream.rb +157 -157
  677. data/lib/cosmos/streams/stream.rb +63 -63
  678. data/lib/cosmos/streams/stream_protocol.rb +373 -373
  679. data/lib/cosmos/streams/tcpip_client_stream.rb +113 -113
  680. data/lib/cosmos/streams/tcpip_socket_stream.rb +143 -143
  681. data/lib/cosmos/streams/template_stream_protocol.rb +140 -140
  682. data/lib/cosmos/streams/terminated_stream_protocol.rb +81 -81
  683. data/lib/cosmos/system.rb +4 -4
  684. data/lib/cosmos/system/system.rb +618 -618
  685. data/lib/cosmos/system/target.rb +197 -197
  686. data/lib/cosmos/tools/cmd_extractor/cmd_extractor.rb +255 -255
  687. data/lib/cosmos/tools/cmd_sender/cmd_sender.rb +717 -717
  688. data/lib/cosmos/tools/cmd_sender/cmd_sender_item_delegate.rb +77 -77
  689. data/lib/cosmos/tools/cmd_sender/cmd_sender_text_edit.rb +70 -70
  690. data/lib/cosmos/tools/cmd_tlm_server/api.rb +1034 -1034
  691. data/lib/cosmos/tools/cmd_tlm_server/background_task.rb +46 -46
  692. data/lib/cosmos/tools/cmd_tlm_server/background_tasks.rb +67 -67
  693. data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server.rb +515 -515
  694. data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server_config.rb +253 -253
  695. data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server_gui.rb +408 -408
  696. data/lib/cosmos/tools/cmd_tlm_server/commanding.rb +112 -112
  697. data/lib/cosmos/tools/cmd_tlm_server/connections.rb +175 -175
  698. data/lib/cosmos/tools/cmd_tlm_server/gui/interfaces_tab.rb +200 -200
  699. data/lib/cosmos/tools/cmd_tlm_server/gui/logging_tab.rb +176 -176
  700. data/lib/cosmos/tools/cmd_tlm_server/gui/packets_tab.rb +150 -150
  701. data/lib/cosmos/tools/cmd_tlm_server/gui/status_tab.rb +244 -244
  702. data/lib/cosmos/tools/cmd_tlm_server/gui/targets_tab.rb +90 -90
  703. data/lib/cosmos/tools/cmd_tlm_server/interface_thread.rb +266 -266
  704. data/lib/cosmos/tools/cmd_tlm_server/interfaces.rb +127 -127
  705. data/lib/cosmos/tools/cmd_tlm_server/packet_logging.rb +132 -132
  706. data/lib/cosmos/tools/cmd_tlm_server/router_thread.rb +66 -66
  707. data/lib/cosmos/tools/cmd_tlm_server/routers.rb +97 -97
  708. data/lib/cosmos/tools/data_viewer/data_viewer.rb +621 -621
  709. data/lib/cosmos/tools/data_viewer/data_viewer_component.rb +134 -134
  710. data/lib/cosmos/tools/data_viewer/dump_component.rb +40 -40
  711. data/lib/cosmos/tools/handbook_creator/handbook_creator.rb +156 -156
  712. data/lib/cosmos/tools/handbook_creator/handbook_creator_config.rb +382 -382
  713. data/lib/cosmos/tools/launcher/launcher.rb +188 -188
  714. data/lib/cosmos/tools/launcher/launcher_config.rb +256 -256
  715. data/lib/cosmos/tools/launcher/launcher_multitool.rb +40 -40
  716. data/lib/cosmos/tools/launcher/launcher_tool.rb +116 -116
  717. data/lib/cosmos/tools/limits_monitor/limits_monitor.rb +837 -837
  718. data/lib/cosmos/tools/opengl_builder/opengl_builder.rb +416 -416
  719. data/lib/cosmos/tools/opengl_builder/scene_config.rb +118 -118
  720. data/lib/cosmos/tools/packet_viewer/packet_viewer.rb +542 -542
  721. data/lib/cosmos/tools/replay/replay.rb +501 -501
  722. data/lib/cosmos/tools/replay/replay_server.rb +91 -91
  723. data/lib/cosmos/tools/script_runner/script_audit.rb +147 -147
  724. data/lib/cosmos/tools/script_runner/script_runner.rb +922 -922
  725. data/lib/cosmos/tools/script_runner/script_runner_config.rb +40 -40
  726. data/lib/cosmos/tools/script_runner/script_runner_frame.rb +1798 -1798
  727. data/lib/cosmos/tools/table_manager/table.rb +70 -70
  728. data/lib/cosmos/tools/table_manager/table_config.rb +764 -764
  729. data/lib/cosmos/tools/table_manager/table_item.rb +74 -74
  730. data/lib/cosmos/tools/table_manager/table_manager.rb +1065 -1065
  731. data/lib/cosmos/tools/table_manager/table_manager_core.rb +539 -539
  732. data/lib/cosmos/tools/test_runner/results_writer.rb +283 -283
  733. data/lib/cosmos/tools/test_runner/test.rb +539 -539
  734. data/lib/cosmos/tools/test_runner/test_runner.rb +1189 -1189
  735. data/lib/cosmos/tools/test_runner/test_runner_chooser.rb +341 -341
  736. data/lib/cosmos/tools/tlm_extractor/text_item_chooser.rb +60 -60
  737. data/lib/cosmos/tools/tlm_extractor/tlm_extractor.rb +1016 -1016
  738. data/lib/cosmos/tools/tlm_extractor/tlm_extractor_config.rb +371 -371
  739. data/lib/cosmos/tools/tlm_extractor/tlm_extractor_processor.rb +60 -60
  740. data/lib/cosmos/tools/tlm_grapher/data_object_adders/housekeeping_data_object_adder.rb +75 -75
  741. data/lib/cosmos/tools/tlm_grapher/data_object_adders/singlexy_data_object_adder.rb +44 -44
  742. data/lib/cosmos/tools/tlm_grapher/data_object_adders/xy_data_object_adder.rb +95 -95
  743. data/lib/cosmos/tools/tlm_grapher/data_object_editors/data_object_editor.rb +61 -61
  744. data/lib/cosmos/tools/tlm_grapher/data_object_editors/housekeeping_data_object_editor.rb +181 -181
  745. data/lib/cosmos/tools/tlm_grapher/data_object_editors/linegraph_data_object_editor.rb +141 -141
  746. data/lib/cosmos/tools/tlm_grapher/data_object_editors/singlexy_data_object_editor.rb +30 -30
  747. data/lib/cosmos/tools/tlm_grapher/data_object_editors/xy_data_object_editor.rb +174 -174
  748. data/lib/cosmos/tools/tlm_grapher/data_objects/data_object.rb +193 -193
  749. data/lib/cosmos/tools/tlm_grapher/data_objects/housekeeping_data_object.rb +407 -407
  750. data/lib/cosmos/tools/tlm_grapher/data_objects/linegraph_data_object.rb +176 -176
  751. data/lib/cosmos/tools/tlm_grapher/data_objects/singlexy_data_object.rb +25 -25
  752. data/lib/cosmos/tools/tlm_grapher/data_objects/xy_data_object.rb +323 -323
  753. data/lib/cosmos/tools/tlm_grapher/plot_editors/linegraph_plot_editor.rb +181 -181
  754. data/lib/cosmos/tools/tlm_grapher/plot_editors/plot_editor.rb +28 -28
  755. data/lib/cosmos/tools/tlm_grapher/plot_editors/singlexy_plot_editor.rb +30 -30
  756. data/lib/cosmos/tools/tlm_grapher/plot_editors/xy_plot_editor.rb +59 -59
  757. data/lib/cosmos/tools/tlm_grapher/plot_gui_objects/linegraph_plot_gui_object.rb +172 -172
  758. data/lib/cosmos/tools/tlm_grapher/plot_gui_objects/singlexy_plot_gui_object.rb +27 -27
  759. data/lib/cosmos/tools/tlm_grapher/plot_gui_objects/xy_plot_gui_object.rb +74 -74
  760. data/lib/cosmos/tools/tlm_grapher/plots/linegraph_plot.rb +201 -201
  761. data/lib/cosmos/tools/tlm_grapher/plots/plot.rb +69 -69
  762. data/lib/cosmos/tools/tlm_grapher/plots/singlexy_plot.rb +20 -20
  763. data/lib/cosmos/tools/tlm_grapher/plots/xy_plot.rb +61 -61
  764. data/lib/cosmos/tools/tlm_grapher/tabbed_plots/overview_tabbed_plots.rb +1291 -1291
  765. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_config.rb +430 -430
  766. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_data_object_editor.rb +107 -107
  767. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_logfile_thread.rb +114 -114
  768. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_plot_editor.rb +101 -101
  769. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_realtime_thread.rb +78 -78
  770. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_tab.rb +57 -57
  771. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_tool.rb +1004 -1004
  772. data/lib/cosmos/tools/tlm_grapher/tlm_grapher.rb +87 -87
  773. data/lib/cosmos/tools/tlm_viewer/screen.rb +486 -486
  774. data/lib/cosmos/tools/tlm_viewer/tlm_viewer.rb +561 -561
  775. data/lib/cosmos/tools/tlm_viewer/tlm_viewer_config.rb +290 -290
  776. data/lib/cosmos/tools/tlm_viewer/widgets.rb +53 -53
  777. data/lib/cosmos/tools/tlm_viewer/widgets/aging_widget.rb +110 -110
  778. data/lib/cosmos/tools/tlm_viewer/widgets/array_widget.rb +66 -66
  779. data/lib/cosmos/tools/tlm_viewer/widgets/block_widget.rb +57 -57
  780. data/lib/cosmos/tools/tlm_viewer/widgets/button_widget.rb +39 -39
  781. data/lib/cosmos/tools/tlm_viewer/widgets/canvas_widget.rb +62 -62
  782. data/lib/cosmos/tools/tlm_viewer/widgets/canvasimage_widget.rb +41 -41
  783. data/lib/cosmos/tools/tlm_viewer/widgets/canvasimagevalue_widget.rb +57 -57
  784. data/lib/cosmos/tools/tlm_viewer/widgets/canvaslabel_widget.rb +37 -37
  785. data/lib/cosmos/tools/tlm_viewer/widgets/canvaslabelvalue_widget.rb +56 -56
  786. data/lib/cosmos/tools/tlm_viewer/widgets/canvasline_widget.rb +55 -55
  787. data/lib/cosmos/tools/tlm_viewer/widgets/canvaslinevalue_widget.rb +66 -66
  788. data/lib/cosmos/tools/tlm_viewer/widgets/canvasvalue_widget.rb +124 -124
  789. data/lib/cosmos/tools/tlm_viewer/widgets/checkbutton_widget.rb +31 -31
  790. data/lib/cosmos/tools/tlm_viewer/widgets/combobox_widget.rb +30 -30
  791. data/lib/cosmos/tools/tlm_viewer/widgets/formatfontvalue_widget.rb +36 -36
  792. data/lib/cosmos/tools/tlm_viewer/widgets/formatvalue_widget.rb +35 -35
  793. data/lib/cosmos/tools/tlm_viewer/widgets/horizontal_widget.rb +27 -27
  794. data/lib/cosmos/tools/tlm_viewer/widgets/horizontalbox_widget.rb +31 -31
  795. data/lib/cosmos/tools/tlm_viewer/widgets/horizontalline_widget.rb +26 -26
  796. data/lib/cosmos/tools/tlm_viewer/widgets/label_widget.rb +29 -29
  797. data/lib/cosmos/tools/tlm_viewer/widgets/labelformatvalue_widget.rb +39 -39
  798. data/lib/cosmos/tools/tlm_viewer/widgets/labelprogressbar_widget.rb +38 -38
  799. data/lib/cosmos/tools/tlm_viewer/widgets/labeltrendlimitsbar_widget.rb +38 -38
  800. data/lib/cosmos/tools/tlm_viewer/widgets/labelvalue_widget.rb +39 -39
  801. data/lib/cosmos/tools/tlm_viewer/widgets/labelvaluedesc_widget.rb +42 -42
  802. data/lib/cosmos/tools/tlm_viewer/widgets/labelvaluelimitsbar_widget.rb +37 -37
  803. data/lib/cosmos/tools/tlm_viewer/widgets/labelvaluerangebar_widget.rb +37 -37
  804. data/lib/cosmos/tools/tlm_viewer/widgets/layout_widget.rb +34 -34
  805. data/lib/cosmos/tools/tlm_viewer/widgets/limitsbar_widget.rb +178 -178
  806. data/lib/cosmos/tools/tlm_viewer/widgets/linegraph_widget.rb +54 -54
  807. data/lib/cosmos/tools/tlm_viewer/widgets/matrixbycolumns_widget.rb +47 -47
  808. data/lib/cosmos/tools/tlm_viewer/widgets/multi_widget.rb +116 -116
  809. data/lib/cosmos/tools/tlm_viewer/widgets/progressbar_widget.rb +34 -34
  810. data/lib/cosmos/tools/tlm_viewer/widgets/radiobutton_widget.rb +30 -30
  811. data/lib/cosmos/tools/tlm_viewer/widgets/rangebar_widget.rb +57 -57
  812. data/lib/cosmos/tools/tlm_viewer/widgets/screenshotbutton_widget.rb +34 -34
  813. data/lib/cosmos/tools/tlm_viewer/widgets/scrollwindow_widget.rb +35 -35
  814. data/lib/cosmos/tools/tlm_viewer/widgets/sectionheader_widget.rb +33 -33
  815. data/lib/cosmos/tools/tlm_viewer/widgets/tabbook_widget.rb +26 -26
  816. data/lib/cosmos/tools/tlm_viewer/widgets/tabitem_widget.rb +28 -28
  817. data/lib/cosmos/tools/tlm_viewer/widgets/textbox_widget.rb +47 -47
  818. data/lib/cosmos/tools/tlm_viewer/widgets/textfield_widget.rb +26 -26
  819. data/lib/cosmos/tools/tlm_viewer/widgets/timegraph_widget.rb +88 -88
  820. data/lib/cosmos/tools/tlm_viewer/widgets/title_widget.rb +27 -27
  821. data/lib/cosmos/tools/tlm_viewer/widgets/trendbar_widget.rb +130 -130
  822. data/lib/cosmos/tools/tlm_viewer/widgets/trendlimitsbar_widget.rb +46 -46
  823. data/lib/cosmos/tools/tlm_viewer/widgets/value_widget.rb +43 -43
  824. data/lib/cosmos/tools/tlm_viewer/widgets/valuelimitsbar_widget.rb +37 -37
  825. data/lib/cosmos/tools/tlm_viewer/widgets/valuerangebar_widget.rb +37 -37
  826. data/lib/cosmos/tools/tlm_viewer/widgets/vertical_widget.rb +35 -35
  827. data/lib/cosmos/tools/tlm_viewer/widgets/verticalbox_widget.rb +37 -37
  828. data/lib/cosmos/tools/tlm_viewer/widgets/widget.rb +257 -257
  829. data/lib/cosmos/top_level.rb +759 -759
  830. data/lib/cosmos/utilities.rb +11 -11
  831. data/lib/cosmos/utilities/crc.rb +166 -166
  832. data/lib/cosmos/utilities/csv.rb +83 -83
  833. data/lib/cosmos/utilities/logger.rb +137 -137
  834. data/lib/cosmos/utilities/low_fragmentation_array.rb +11 -11
  835. data/lib/cosmos/utilities/message_log.rb +79 -79
  836. data/lib/cosmos/utilities/quaternion.rb +258 -258
  837. data/lib/cosmos/utilities/ruby_lex_utils.rb +313 -313
  838. data/lib/cosmos/utilities/simulated_target.rb +99 -99
  839. data/lib/cosmos/utilities/sleeper.rb +44 -44
  840. data/lib/cosmos/version.rb +12 -12
  841. data/lib/cosmos/win32/excel.rb +66 -66
  842. data/lib/cosmos/win32/win32.rb +387 -387
  843. data/lib/cosmos/win32/win32_main.rb +321 -321
  844. data/roodi.yml +24 -24
  845. data/run_gui_tests.bat +0 -0
  846. data/spec/ccsds/ccsds_packet_spec.rb +67 -67
  847. data/spec/ccsds/ccsds_parser_spec.rb +148 -148
  848. data/spec/config/config_parser_spec.rb +322 -322
  849. data/spec/conversions/conversion_spec.rb +31 -31
  850. data/spec/conversions/generic_conversion_spec.rb +45 -45
  851. data/spec/conversions/new_packet_log_conversion_spec.rb +39 -39
  852. data/spec/conversions/polynomial_conversion_spec.rb +40 -40
  853. data/spec/conversions/processor_conversion_spec.rb +45 -45
  854. data/spec/conversions/received_count_conversion_spec.rb +43 -43
  855. data/spec/conversions/received_time_formatted_conversion_spec.rb +49 -49
  856. data/spec/conversions/received_time_seconds_conversion_spec.rb +50 -50
  857. data/spec/conversions/segmented_polynomial_conversion_spec.rb +51 -51
  858. data/spec/conversions/unix_time_formatted_conversion_spec.rb +74 -74
  859. data/spec/conversions/unix_time_seconds_conversion_spec.rb +76 -76
  860. data/spec/core_ext/array_spec.rb +186 -186
  861. data/spec/core_ext/class_spec.rb +36 -36
  862. data/spec/core_ext/cosmos_io_spec.rb +77 -77
  863. data/spec/core_ext/exception_spec.rb +91 -91
  864. data/spec/core_ext/file_spec.rb +72 -72
  865. data/spec/core_ext/hash_spec.rb +24 -24
  866. data/spec/core_ext/io_spec.rb +46 -46
  867. data/spec/core_ext/kernel_spec.rb +54 -54
  868. data/spec/core_ext/math_spec.rb +116 -116
  869. data/spec/core_ext/matrix_spec.rb +66 -66
  870. data/spec/core_ext/objectspace_spec.rb +29 -29
  871. data/spec/core_ext/range_spec.rb +21 -21
  872. data/spec/core_ext/socket_spec.rb +32 -32
  873. data/spec/core_ext/string_spec.rb +223 -223
  874. data/spec/core_ext/stringio_spec.rb +21 -21
  875. data/spec/core_ext/time_spec.rb +202 -202
  876. data/spec/gui/line_graph/line_clip_spec.rb +322 -322
  877. data/spec/gui/qt_spec.rb +102 -102
  878. data/spec/install/config/system/system.txt +33 -33
  879. data/spec/install/config/targets/COSMOS/cmd_tlm/cosmos_server_cmds.txt +41 -41
  880. data/spec/install/config/targets/COSMOS/cmd_tlm/cosmos_server_tlm.txt +15 -15
  881. data/spec/install/config/targets/COSMOS/cmd_tlm_server.txt +6 -6
  882. data/spec/install/config/targets/COSMOS/screens/limits_change.txt +20 -20
  883. data/spec/install/config/targets/COSMOS/screens/version.txt +19 -19
  884. data/spec/install/config/targets/COSMOS/target.txt +5 -5
  885. data/spec/install/config/targets/INST/cmd_tlm/inst_cmd_linc.txt +30 -30
  886. data/spec/install/config/targets/INST/cmd_tlm/inst_cmds.txt +111 -111
  887. data/spec/install/config/targets/INST/cmd_tlm/inst_tlm.txt +236 -236
  888. data/spec/install/config/targets/INST/cmd_tlm/inst_tlm_linc.txt +25 -25
  889. data/spec/install/config/targets/INST/cmd_tlm_server.txt +5 -5
  890. data/spec/install/config/targets/INST/lib/sim_inst.rb +305 -305
  891. data/spec/install/config/targets/INST/target.txt +10 -10
  892. data/spec/install/config/targets/META/cmd_tlm/meta_cmd.txt +4 -4
  893. data/spec/install/config/targets/META/cmd_tlm/meta_tlm.txt +4 -4
  894. data/spec/install/config/targets/SYSTEM/cmd_tlm/limits_groups.txt +7 -7
  895. data/spec/interfaces/cmd_tlm_server_interface_spec.rb +150 -150
  896. data/spec/interfaces/interface_spec.rb +130 -130
  897. data/spec/interfaces/linc_interface_spec.rb +259 -259
  898. data/spec/interfaces/serial_interface_spec.rb +56 -56
  899. data/spec/interfaces/simulated_target_interface_spec.rb +128 -128
  900. data/spec/interfaces/stream_interface_spec.rb +157 -157
  901. data/spec/interfaces/tcpip_client_interface_spec.rb +55 -55
  902. data/spec/interfaces/tcpip_server_interface_spec.rb +160 -160
  903. data/spec/interfaces/udp_interface_spec.rb +175 -175
  904. data/spec/io/buffered_file_spec.rb +113 -113
  905. data/spec/io/io_multiplexer_spec.rb +94 -94
  906. data/spec/io/json_drb_object_spec.rb +119 -119
  907. data/spec/io/json_drb_spec.rb +311 -311
  908. data/spec/io/json_rpc_spec.rb +264 -264
  909. data/spec/io/raw_logger_pair_spec.rb +76 -76
  910. data/spec/io/raw_logger_spec.rb +133 -133
  911. data/spec/io/serial_driver_spec.rb +60 -60
  912. data/spec/io/stderr_spec.rb +32 -32
  913. data/spec/io/stdout_spec.rb +32 -32
  914. data/spec/io/tcpip_server_spec.rb +338 -338
  915. data/spec/io/udp_sockets_spec.rb +94 -94
  916. data/spec/io/win32_serial_driver_spec.rb +88 -88
  917. data/spec/packet_logs/meta_packet_log_writer_spec.rb +170 -170
  918. data/spec/packet_logs/packet_log_reader_spec.rb +468 -468
  919. data/spec/packet_logs/packet_log_writer_pair_spec.rb +30 -30
  920. data/spec/packet_logs/packet_log_writer_spec.rb +225 -225
  921. data/spec/packets/binary_accessor_spec.rb +2326 -2326
  922. data/spec/packets/commands_spec.rb +369 -369
  923. data/spec/packets/limits_response_spec.rb +25 -25
  924. data/spec/packets/limits_spec.rb +344 -344
  925. data/spec/packets/packet_config_spec.rb +805 -805
  926. data/spec/packets/packet_item_limits_spec.rb +161 -161
  927. data/spec/packets/packet_item_spec.rb +386 -386
  928. data/spec/packets/packet_spec.rb +1317 -1317
  929. data/spec/packets/parsers/format_string_parser_spec.rb +122 -122
  930. data/spec/packets/parsers/limits_parser_spec.rb +282 -282
  931. data/spec/packets/parsers/limits_response_parser_spec.rb +149 -149
  932. data/spec/packets/parsers/macro_parser_spec.rb +212 -212
  933. data/spec/packets/parsers/packet_item_parser_spec.rb +306 -306
  934. data/spec/packets/parsers/packet_parser_spec.rb +99 -99
  935. data/spec/packets/parsers/processor_parser_spec.rb +114 -114
  936. data/spec/packets/parsers/state_parser_spec.rb +156 -156
  937. data/spec/packets/structure_item_spec.rb +195 -195
  938. data/spec/packets/structure_spec.rb +565 -565
  939. data/spec/packets/telemetry_spec.rb +578 -578
  940. data/spec/processors/new_packet_log_processor_spec.rb +39 -39
  941. data/spec/processors/processor_spec.rb +55 -55
  942. data/spec/processors/statistics_processor_spec.rb +60 -60
  943. data/spec/processors/watermark_processor_spec.rb +51 -51
  944. data/spec/script/cmd_tlm_server_spec.rb +110 -110
  945. data/spec/script/commands_disconnect_spec.rb +270 -270
  946. data/spec/script/commands_spec.rb +302 -302
  947. data/spec/script/limits_spec.rb +153 -153
  948. data/spec/script/script_spec.rb +86 -86
  949. data/spec/script/scripting_spec.rb +440 -440
  950. data/spec/script/telemetry_spec.rb +165 -165
  951. data/spec/script/tools_spec.rb +117 -117
  952. data/spec/spec_helper.rb +190 -190
  953. data/spec/streams/burst_stream_protocol_spec.rb +32 -32
  954. data/spec/streams/fixed_stream_protocol_spec.rb +113 -113
  955. data/spec/streams/length_stream_protocol_spec.rb +300 -300
  956. data/spec/streams/preidentified_stream_protocol_spec.rb +121 -121
  957. data/spec/streams/serial_stream_spec.rb +117 -117
  958. data/spec/streams/stream_protocol_spec.rb +346 -346
  959. data/spec/streams/stream_spec.rb +30 -30
  960. data/spec/streams/tcpip_client_stream_spec.rb +57 -57
  961. data/spec/streams/tcpip_socket_stream_spec.rb +193 -193
  962. data/spec/streams/template_stream_protocol_spec.rb +156 -156
  963. data/spec/streams/terminated_stream_protocol_spec.rb +127 -127
  964. data/spec/system/system_spec.rb +665 -665
  965. data/spec/system/target_spec.rb +250 -250
  966. data/spec/tools/cmd_tlm_server/api_spec.rb +1117 -1117
  967. data/spec/tools/cmd_tlm_server/background_task_spec.rb +32 -32
  968. data/spec/tools/cmd_tlm_server/background_tasks_spec.rb +81 -81
  969. data/spec/tools/cmd_tlm_server/cmd_tlm_server_config_spec.rb +453 -453
  970. data/spec/tools/cmd_tlm_server/cmd_tlm_server_spec.rb +415 -415
  971. data/spec/tools/cmd_tlm_server/commanding_spec.rb +151 -151
  972. data/spec/tools/cmd_tlm_server/connections_spec.rb +235 -235
  973. data/spec/tools/cmd_tlm_server/interface_thread_spec.rb +306 -306
  974. data/spec/tools/cmd_tlm_server/interfaces_spec.rb +252 -252
  975. data/spec/tools/cmd_tlm_server/packet_logging_spec.rb +143 -143
  976. data/spec/tools/cmd_tlm_server/router_thread_spec.rb +151 -151
  977. data/spec/tools/cmd_tlm_server/routers_spec.rb +223 -223
  978. data/spec/tools/launcher/launcher_config_spec.rb +464 -464
  979. data/spec/top_level/top_level_spec.rb +334 -334
  980. data/spec/utilities/crc_spec.rb +45 -45
  981. data/spec/utilities/csv_spec.rb +97 -97
  982. data/spec/utilities/logger_spec.rb +102 -102
  983. data/spec/utilities/message_log_spec.rb +89 -89
  984. data/spec/utilities/quaternion_spec.rb +107 -107
  985. data/spec/utilities/ruby_lex_utils_spec.rb +86 -86
  986. data/tasks/manifest.rake +22 -22
  987. data/tasks/spec.rake +23 -23
  988. data/test/benchmarks/binary_accessor_benchmark.rb +14 -14
  989. data/test/benchmarks/gsub_benchmark.rb +152 -152
  990. data/test/benchmarks/is_a_benchmark.rb +34 -34
  991. data/test/performance/PACKETS.bat +0 -0
  992. data/test/performance/Rakefile +77 -77
  993. data/test/performance/THREADS.bat +0 -0
  994. data/test/performance/config/data/crc.txt +196 -196
  995. data/test/performance/config/data/diamond.STL +57 -57
  996. data/test/performance/config/data/meta_init.txt +4 -4
  997. data/test/performance/config/system/system_packets.txt +39 -39
  998. data/test/performance/config/system/system_threads.txt +59 -59
  999. data/test/performance/config/targets/COSMOS/cmd_tlm/cosmos_server_cmds.txt +46 -46
  1000. data/test/performance/config/targets/COSMOS/cmd_tlm/cosmos_server_tlm.txt +15 -15
  1001. data/test/performance/config/targets/COSMOS/cmd_tlm_server.txt +6 -6
  1002. data/test/performance/config/targets/COSMOS/screens/limits_change.txt +20 -20
  1003. data/test/performance/config/targets/COSMOS/screens/version.txt +19 -19
  1004. data/test/performance/config/targets/COSMOS/target.txt +11 -11
  1005. data/test/performance/config/targets/PACKET/cmd_tlm/packet_cmds.txt +20 -20
  1006. data/test/performance/config/targets/PACKET/cmd_tlm/packet_tlm.txt +98 -98
  1007. data/test/performance/config/targets/PACKET/cmd_tlm_server.txt +6 -6
  1008. data/test/performance/config/targets/PACKET/lib/packet_interface.rb +22 -22
  1009. data/test/performance/config/targets/PACKET/lib/packet_limits_response.rb +24 -24
  1010. data/test/performance/config/targets/PACKET/screens/status.txt +25 -25
  1011. data/test/performance/config/targets/PACKET/target.txt +28 -28
  1012. data/test/performance/config/targets/SYSTEM/screens/status.txt +12 -12
  1013. data/test/performance/config/targets/THREAD/cmd_tlm/thread_cmds.txt +17 -17
  1014. data/test/performance/config/targets/THREAD/cmd_tlm/thread_tlm.txt +18 -18
  1015. data/test/performance/config/targets/THREAD/cmd_tlm_server.txt +6 -6
  1016. data/test/performance/config/targets/THREAD/lib/thread_interface.rb +22 -22
  1017. data/test/performance/config/targets/THREAD/screens/status.txt +25 -25
  1018. data/test/performance/config/targets/THREAD/target.txt +6 -6
  1019. data/test/performance/config/tools/cmd_tlm_server/cmd_tlm_server_packets.txt +28 -28
  1020. data/test/performance/config/tools/cmd_tlm_server/cmd_tlm_server_threads.txt +68 -68
  1021. data/test/performance/config/tools/data_viewer/data_viewer.txt +11 -11
  1022. data/test/performance/config/tools/handbook_creator/handbook_creator.txt +66 -66
  1023. data/test/performance/config/tools/handbook_creator/templates/command_packets.html.erb +86 -86
  1024. data/test/performance/config/tools/handbook_creator/templates/command_toc.html.erb +38 -38
  1025. data/test/performance/config/tools/handbook_creator/templates/footer.html.erb +9 -9
  1026. data/test/performance/config/tools/handbook_creator/templates/header.html.erb +25 -25
  1027. data/test/performance/config/tools/handbook_creator/templates/limits_groups.html.erb +13 -13
  1028. data/test/performance/config/tools/handbook_creator/templates/nav.html.erb +27 -27
  1029. data/test/performance/config/tools/handbook_creator/templates/overview.html.erb +1 -1
  1030. data/test/performance/config/tools/handbook_creator/templates/pdf_cover.html.erb +23 -23
  1031. data/test/performance/config/tools/handbook_creator/templates/pdf_footer.html.erb +33 -33
  1032. data/test/performance/config/tools/handbook_creator/templates/pdf_header.html.erb +41 -41
  1033. data/test/performance/config/tools/handbook_creator/templates/telemetry_packets.html.erb +80 -80
  1034. data/test/performance/config/tools/handbook_creator/templates/telemetry_toc.html.erb +38 -38
  1035. data/test/performance/config/tools/handbook_creator/templates/title.html.erb +1 -1
  1036. data/test/performance/config/tools/launcher/launcher_packets.txt +34 -34
  1037. data/test/performance/config/tools/launcher/launcher_threads.txt +83 -83
  1038. data/test/performance/config/tools/script_runner/script_runner.txt +3 -3
  1039. data/test/performance/config/tools/table_manager/ConfigTables_def.txt +8 -8
  1040. data/test/performance/config/tools/table_manager/ExampleTableDefinition.txt +24 -24
  1041. data/test/performance/config/tools/table_manager/MCConfigurationTable_fsw1_def.txt +25 -25
  1042. data/test/performance/config/tools/table_manager/MCConfigurationTable_fsw2_def.txt +25 -25
  1043. data/test/performance/config/tools/table_manager/PPSSelectionTable_def.txt +8 -8
  1044. data/test/performance/config/tools/table_manager/TLMMonitoringTable_def.txt +248 -248
  1045. data/test/performance/config/tools/test_runner/test_runner.txt +17 -17
  1046. data/test/performance/config/tools/tlm_extractor/tlm_extractor.txt +13 -13
  1047. data/test/performance/config/tools/tlm_extractor/tlm_extractor2.txt +2 -2
  1048. data/test/performance/config/tools/tlm_extractor/tlm_extractor3.txt +2 -2
  1049. data/test/performance/config/tools/tlm_extractor/tlm_extractor4.txt +2 -2
  1050. data/test/performance/config/tools/tlm_grapher/tlm_grapher.txt +204 -204
  1051. data/test/performance/config/tools/tlm_viewer/tlm_viewer.txt +13 -13
  1052. data/test/performance/lib/packet_target.rb +126 -126
  1053. data/test/performance/lib/thread_target.rb +120 -120
  1054. data/test/performance/lib/user_version.rb +3 -3
  1055. data/test/performance/procedures/checks.rb +11 -11
  1056. data/test/performance/procedures/clear_util.rb +7 -7
  1057. data/test/performance/procedures/collect.rb +18 -18
  1058. data/test/performance/procedures/collect_util.rb +14 -14
  1059. data/test/performance/procedures/cosmos_api_test.rb +293 -293
  1060. data/test/performance/procedures/disconnect.rb +29 -29
  1061. data/test/performance/procedures/example_test.rb +182 -182
  1062. data/test/performance/procedures/plot_test.rb +8 -8
  1063. data/test/performance/procedures/procedure.rb +2 -2
  1064. data/test/performance/procedures/run_example_test.rb +3 -3
  1065. data/test/performance/procedures/test.rb +51 -51
  1066. data/test/performance/tools/CmdExtractor +14 -14
  1067. data/test/performance/tools/CmdExtractor.bat +0 -0
  1068. data/test/performance/tools/CmdSender +14 -14
  1069. data/test/performance/tools/CmdSender.bat +0 -0
  1070. data/test/performance/tools/CmdTlmServer +16 -16
  1071. data/test/performance/tools/CmdTlmServer.bat +0 -0
  1072. data/test/performance/tools/CmdTlmServerMemProf +20 -20
  1073. data/test/performance/tools/CmdTlmServerMemProf.bat +0 -0
  1074. data/test/performance/tools/DataViewer +14 -14
  1075. data/test/performance/tools/DataViewer.bat +0 -0
  1076. data/test/performance/tools/HandbookCreator +14 -14
  1077. data/test/performance/tools/HandbookCreator.bat +0 -0
  1078. data/test/performance/tools/Launcher +14 -14
  1079. data/test/performance/tools/Launcher.bat +0 -0
  1080. data/test/performance/tools/LimitsMonitor +14 -14
  1081. data/test/performance/tools/LimitsMonitor.bat +0 -0
  1082. data/test/performance/tools/OpenGLBuilder +14 -14
  1083. data/test/performance/tools/OpenGLBuilder.bat +0 -0
  1084. data/test/performance/tools/PacketTarget +14 -14
  1085. data/test/performance/tools/PacketTarget.bat +0 -0
  1086. data/test/performance/tools/PacketViewer +14 -14
  1087. data/test/performance/tools/PacketViewer.bat +0 -0
  1088. data/test/performance/tools/Replay +14 -14
  1089. data/test/performance/tools/Replay.bat +0 -0
  1090. data/test/performance/tools/ScpiTarget +14 -14
  1091. data/test/performance/tools/ScpiTarget.bat +0 -0
  1092. data/test/performance/tools/ScriptRunner +14 -14
  1093. data/test/performance/tools/ScriptRunner.bat +0 -0
  1094. data/test/performance/tools/TableManager +14 -14
  1095. data/test/performance/tools/TableManager.bat +0 -0
  1096. data/test/performance/tools/TestRunner +14 -14
  1097. data/test/performance/tools/TestRunner.bat +0 -0
  1098. data/test/performance/tools/ThreadTarget +14 -14
  1099. data/test/performance/tools/ThreadTarget.bat +0 -0
  1100. data/test/performance/tools/TlmExtractor +14 -14
  1101. data/test/performance/tools/TlmExtractor.bat +0 -0
  1102. data/test/performance/tools/TlmGrapher +14 -14
  1103. data/test/performance/tools/TlmGrapher.bat +0 -0
  1104. data/test/performance/tools/TlmGrapherMemProf +19 -19
  1105. data/test/performance/tools/TlmGrapherMemProf.bat +0 -0
  1106. data/test/performance/tools/TlmViewer +14 -14
  1107. data/test/performance/tools/TlmViewer.bat +0 -0
  1108. data/test/performance/tools/TlmViewerMemProf +19 -19
  1109. data/test/performance/tools/TlmViewerMemProf.bat +0 -0
  1110. data/test/performance/tools/mac/CmdExtractor.app/Contents/Info.plist +38 -38
  1111. data/test/performance/tools/mac/CmdExtractor.app/Contents/MacOS/CmdExtractor.rb +15 -15
  1112. data/test/performance/tools/mac/CmdExtractor.app/Contents/MacOS/main.sh +6 -6
  1113. data/test/performance/tools/mac/CmdSender.app/Contents/Info.plist +38 -38
  1114. data/test/performance/tools/mac/CmdSender.app/Contents/MacOS/CmdSender.rb +15 -15
  1115. data/test/performance/tools/mac/CmdSender.app/Contents/MacOS/main.sh +6 -6
  1116. data/test/performance/tools/mac/CmdTlmServer.app/Contents/Info.plist +38 -38
  1117. data/test/performance/tools/mac/CmdTlmServer.app/Contents/MacOS/CmdTlmServer.rb +15 -15
  1118. data/test/performance/tools/mac/CmdTlmServer.app/Contents/MacOS/main.sh +6 -6
  1119. data/test/performance/tools/mac/DataViewer.app/Contents/Info.plist +38 -38
  1120. data/test/performance/tools/mac/DataViewer.app/Contents/MacOS/DataViewer.rb +15 -15
  1121. data/test/performance/tools/mac/DataViewer.app/Contents/MacOS/main.sh +6 -6
  1122. data/test/performance/tools/mac/HandbookCreator.app/Contents/Info.plist +38 -38
  1123. data/test/performance/tools/mac/HandbookCreator.app/Contents/MacOS/HandbookCreator.rb +15 -15
  1124. data/test/performance/tools/mac/HandbookCreator.app/Contents/MacOS/main.sh +6 -6
  1125. data/test/performance/tools/mac/Launcher.app/Contents/Info.plist +38 -38
  1126. data/test/performance/tools/mac/Launcher.app/Contents/MacOS/Launcher.rb +15 -15
  1127. data/test/performance/tools/mac/Launcher.app/Contents/MacOS/main.sh +6 -6
  1128. data/test/performance/tools/mac/LimitsMonitor.app/Contents/Info.plist +38 -38
  1129. data/test/performance/tools/mac/LimitsMonitor.app/Contents/MacOS/LimitsMonitor.rb +15 -15
  1130. data/test/performance/tools/mac/LimitsMonitor.app/Contents/MacOS/main.sh +6 -6
  1131. data/test/performance/tools/mac/OpenGLBuilder.app/Contents/Info.plist +38 -38
  1132. data/test/performance/tools/mac/OpenGLBuilder.app/Contents/MacOS/OpenGLBuilder.rb +15 -15
  1133. data/test/performance/tools/mac/OpenGLBuilder.app/Contents/MacOS/main.sh +6 -6
  1134. data/test/performance/tools/mac/PacketViewer.app/Contents/Info.plist +38 -38
  1135. data/test/performance/tools/mac/PacketViewer.app/Contents/MacOS/PacketViewer.rb +15 -15
  1136. data/test/performance/tools/mac/PacketViewer.app/Contents/MacOS/main.sh +6 -6
  1137. data/test/performance/tools/mac/Replay.app/Contents/Info.plist +38 -38
  1138. data/test/performance/tools/mac/Replay.app/Contents/MacOS/Replay.rb +15 -15
  1139. data/test/performance/tools/mac/Replay.app/Contents/MacOS/main.sh +6 -6
  1140. data/test/performance/tools/mac/ScriptRunner.app/Contents/Info.plist +38 -38
  1141. data/test/performance/tools/mac/ScriptRunner.app/Contents/MacOS/ScriptRunner.rb +15 -15
  1142. data/test/performance/tools/mac/ScriptRunner.app/Contents/MacOS/main.sh +6 -6
  1143. data/test/performance/tools/mac/TableManager.app/Contents/Info.plist +38 -38
  1144. data/test/performance/tools/mac/TableManager.app/Contents/MacOS/TableManager.rb +15 -15
  1145. data/test/performance/tools/mac/TableManager.app/Contents/MacOS/main.sh +6 -6
  1146. data/test/performance/tools/mac/TestRunner.app/Contents/Info.plist +38 -38
  1147. data/test/performance/tools/mac/TestRunner.app/Contents/MacOS/TestRunner.rb +15 -15
  1148. data/test/performance/tools/mac/TestRunner.app/Contents/MacOS/main.sh +6 -6
  1149. data/test/performance/tools/mac/TlmExtractor.app/Contents/Info.plist +38 -38
  1150. data/test/performance/tools/mac/TlmExtractor.app/Contents/MacOS/TlmExtractor.rb +15 -15
  1151. data/test/performance/tools/mac/TlmExtractor.app/Contents/MacOS/main.sh +6 -6
  1152. data/test/performance/tools/mac/TlmGrapher.app/Contents/Info.plist +38 -38
  1153. data/test/performance/tools/mac/TlmGrapher.app/Contents/MacOS/TlmGrapher.rb +15 -15
  1154. data/test/performance/tools/mac/TlmGrapher.app/Contents/MacOS/main.sh +6 -6
  1155. data/test/performance/tools/mac/TlmViewer.app/Contents/Info.plist +38 -38
  1156. data/test/performance/tools/mac/TlmViewer.app/Contents/MacOS/TlmViewer.rb +15 -15
  1157. data/test/performance/tools/mac/TlmViewer.app/Contents/MacOS/main.sh +6 -6
  1158. metadata +3 -3
@@ -1,40 +1,40 @@
1
- # encoding: ascii-8bit
2
-
3
- # Copyright 2014 Ball Aerospace & Technologies Corp.
4
- # All Rights Reserved.
5
- #
6
- # This program is free software; you can modify and/or redistribute it
7
- # under the terms of the GNU General Public License
8
- # as published by the Free Software Foundation; version 3 with
9
- # attribution addendums as found in the LICENSE.txt
10
-
11
- require 'cosmos'
12
-
13
- module Cosmos
14
-
15
- # This class reads the Script Runner configuration file
16
- class ScriptRunnerConfig
17
- # Processes the config file
18
- def initialize(filename)
19
- parser = ConfigParser.new
20
- parser.parse_file(filename) do |keyword, params|
21
- case keyword
22
- when 'LINE_DELAY'
23
- parser.verify_num_parameters(1, 1, "#{keyword} <Delay in Seconds>")
24
- ScriptRunnerFrame.line_delay = params[0].to_f
25
- when 'MONITOR_LIMITS'
26
- parser.verify_num_parameters(0, 0, keyword)
27
- ScriptRunnerFrame.monitor_limits = true
28
- when 'PAUSE_ON_RED'
29
- parser.verify_num_parameters(0, 0, keyword)
30
- ScriptRunnerFrame.monitor_limits = true
31
- ScriptRunnerFrame.pause_on_red = true
32
- else
33
- # blank config.lines will have a nil keyword and should not raise an exception
34
- raise parser.error("Unknown keyword '#{keyword}'") if keyword
35
- end
36
- end
37
- end
38
- end # class ScriptRunnerConfig
39
-
40
- end # module Cosmos
1
+ # encoding: ascii-8bit
2
+
3
+ # Copyright 2014 Ball Aerospace & Technologies Corp.
4
+ # All Rights Reserved.
5
+ #
6
+ # This program is free software; you can modify and/or redistribute it
7
+ # under the terms of the GNU General Public License
8
+ # as published by the Free Software Foundation; version 3 with
9
+ # attribution addendums as found in the LICENSE.txt
10
+
11
+ require 'cosmos'
12
+
13
+ module Cosmos
14
+
15
+ # This class reads the Script Runner configuration file
16
+ class ScriptRunnerConfig
17
+ # Processes the config file
18
+ def initialize(filename)
19
+ parser = ConfigParser.new
20
+ parser.parse_file(filename) do |keyword, params|
21
+ case keyword
22
+ when 'LINE_DELAY'
23
+ parser.verify_num_parameters(1, 1, "#{keyword} <Delay in Seconds>")
24
+ ScriptRunnerFrame.line_delay = params[0].to_f
25
+ when 'MONITOR_LIMITS'
26
+ parser.verify_num_parameters(0, 0, keyword)
27
+ ScriptRunnerFrame.monitor_limits = true
28
+ when 'PAUSE_ON_RED'
29
+ parser.verify_num_parameters(0, 0, keyword)
30
+ ScriptRunnerFrame.monitor_limits = true
31
+ ScriptRunnerFrame.pause_on_red = true
32
+ else
33
+ # blank config.lines will have a nil keyword and should not raise an exception
34
+ raise parser.error("Unknown keyword '#{keyword}'") if keyword
35
+ end
36
+ end
37
+ end
38
+ end # class ScriptRunnerConfig
39
+
40
+ end # module Cosmos
@@ -1,1798 +1,1798 @@
1
- # encoding: ascii-8bit
2
-
3
- # Copyright 2014 Ball Aerospace & Technologies Corp.
4
- # All Rights Reserved.
5
- #
6
- # This program is free software; you can modify and/or redistribute it
7
- # under the terms of the GNU General Public License
8
- # as published by the Free Software Foundation; version 3 with
9
- # attribution addendums as found in the LICENSE.txt
10
-
11
- require 'cosmos'
12
- require 'cosmos/script'
13
- require 'cosmos/gui/utilities/script_module_gui'
14
- require 'cosmos/gui/dialogs/splash'
15
- require 'cosmos/gui/dialogs/exception_dialog'
16
- require 'cosmos/gui/text/completion'
17
- require 'cosmos/gui/text/completion_line_edit'
18
- require 'cosmos/gui/text/ruby_editor'
19
- require 'cosmos/gui/dialogs/progress_dialog'
20
- require 'cosmos/gui/widgets/realtime_button_bar'
21
- require 'cosmos/gui/dialogs/find_replace_dialog'
22
- require 'cosmos/gui/choosers/file_chooser'
23
- require 'cosmos/io/stdout'
24
- require 'cosmos/io/stderr'
25
-
26
- module Cosmos
27
-
28
- Cosmos.disable_warnings do
29
- module Script
30
- def prompt_for_script_abort
31
- ScriptRunnerFrame.instance.perform_pause
32
- return false # Not aborted - Retry
33
- end
34
- end
35
- end
36
-
37
- class ScriptRunnerDialog < Qt::Dialog
38
- attr_reader :script_runner_frame
39
-
40
- def initialize(parent,
41
- title,
42
- default_tab_text = 'Untitled')
43
- super(parent)
44
- setWindowTitle(title)
45
- setMinimumWidth(parent.width * 0.8)
46
- setMinimumHeight(parent.height * 0.6)
47
-
48
- # Create script runner frame
49
- @script_runner_frame = ScriptRunnerFrame.new(self, default_tab_text)
50
- layout = Qt::VBoxLayout.new
51
- layout.addWidget(@script_runner_frame)
52
- setLayout(layout)
53
- end
54
-
55
- # Executes the given text and closes when complete
56
- def execute_text_and_close_on_complete(text, text_binding = nil)
57
- @script_runner_frame.set_text(text)
58
- @script_runner_frame.run_and_close_on_complete(text_binding)
59
- exec
60
- dispose
61
- end
62
-
63
- def reject
64
- # Don't allow the dialog to close if we're running
65
- return if @script_runner_frame.running?
66
- super
67
- end
68
- end # class ScriptRunnerDialog
69
-
70
- class ScriptRunnerFrame < Qt::Widget
71
- slots 'context_menu(const QPoint&)'
72
- slots 'undo_available(bool)'
73
- slots 'breakpoint_set(int)'
74
- slots 'breakpoint_cleared(int)'
75
- slots 'breakpoints_cleared()'
76
- signals 'undoAvailable(bool)'
77
- signals 'modificationChanged(bool)'
78
-
79
- CMD_KEYWORDS = %w(cmd cmd_no_range_check cmd_no_hazardous_check cmd_no_checks)
80
- TLM_KEYWORDS = %w(tlm tlm_raw tlm_formatted tlm_with_units limits_enabled? \
81
- enable_limits disable_limits wait_tolerance wait_tolerance_raw \
82
- check_tolerance check_tolerance_raw wait_check_tolerance \
83
- wait_check_tolerance_raw)
84
- SET_TLM_KEYWORDS = %w(set_tlm set_tlm_raw)
85
- CHECK_KEYWORDS = %w(check check_raw wait wait_raw wait_check wait_check_raw)
86
-
87
- attr_accessor :use_instrumentation
88
- attr_accessor :change_callback
89
- attr_accessor :run_callback
90
- attr_accessor :stop_callback
91
- attr_accessor :error_callback
92
- attr_accessor :pause_callback
93
- attr_reader :filename
94
- attr_accessor :continue_after_error
95
- attr_accessor :exceptions
96
- attr_accessor :script_binding
97
- attr_accessor :inline_return
98
- attr_accessor :inline_return_params
99
- attr_reader :message_log
100
- attr_reader :script_class
101
- attr_reader :top_level_instrumented_cache
102
- attr_accessor :stdout_max_lines
103
- attr_reader :script
104
-
105
- @@instance = nil
106
- @@run_thread = nil
107
- @@breakpoints = {}
108
- @@step_mode = false
109
- @@line_delay = 0.1
110
- @@instrumented_cache = {}
111
- @@file_cache = {}
112
- @@output_thread = nil
113
- @@limits_monitor_thread = nil
114
- @@pause_on_error = true
115
- @@monitor_limits = false
116
- @@pause_on_red = false
117
- @@show_backtrace = false
118
- @@error = nil
119
- @@output_sleeper = Sleeper.new
120
- @@limits_sleeper = Sleeper.new
121
- @@cancel_output = false
122
- @@cancel_limits = false
123
-
124
- def initialize(parent, default_tab_text = 'Untitled')
125
- super(parent)
126
- @default_tab_text = ' ' + default_tab_text + ' '
127
- # Keep track of whether this frame has been fully initialized
128
- @initialized = false
129
- @debug_frame = nil
130
-
131
- @layout = Qt::VBoxLayout.new
132
- @layout.setContentsMargins(0,0,0,0)
133
-
134
- # Add Realtime Button Bar
135
- @realtime_button_bar = RealtimeButtonBar.new(self)
136
- @realtime_button_bar.state = 'Stopped'
137
- @realtime_button_bar.start_callback = method(:handle_start_go_button)
138
- @realtime_button_bar.pause_callback = method(:handle_pause_retry_button)
139
- @realtime_button_bar.stop_callback = method(:handle_stop_button)
140
- @layout.addWidget(@realtime_button_bar)
141
-
142
- # Create a splitter to hold the script text area and the script output text area.
143
- @splitter = Qt::Splitter.new(Qt::Vertical, self)
144
- @layout.addWidget(@splitter)
145
- @top_widget = Qt::Widget.new(@splitter)
146
- @top_widget.setContentsMargins(0,0,0,0)
147
- @top_frame = Qt::VBoxLayout.new(@top_widget)
148
- @top_frame.setContentsMargins(0,0,0,0)
149
-
150
- # Add Initial Text Window
151
- @script = create_ruby_editor()
152
- @script.connect(SIGNAL('modificationChanged(bool)')) do |changed|
153
- emit modificationChanged(changed)
154
- end
155
- @top_frame.addWidget(@script)
156
-
157
- # Set self as the gui window to allow prompts and other popups to appear
158
- set_cmd_tlm_gui_window(self)
159
-
160
- # Add change handlers
161
- connect(@script,
162
- SIGNAL('undoAvailable(bool)'),
163
- self,
164
- SLOT('undo_available(bool)'))
165
-
166
- # Add Output Text
167
- @bottom_frame = Qt::Widget.new
168
- @bottom_layout = Qt::VBoxLayout.new
169
- @bottom_layout.setContentsMargins(0,0,0,0)
170
- @bottom_layout_label = Qt::Label.new("Script Output:")
171
- @bottom_layout.addWidget(@bottom_layout_label)
172
- @output = Qt::PlainTextEdit.new
173
- @output.setReadOnly(true)
174
- @output.setMaximumBlockCount(100)
175
- @bottom_layout.addWidget(@output)
176
- @bottom_frame.setLayout(@bottom_layout)
177
- @splitter.addWidget(@bottom_frame)
178
- @splitter.setStretchFactor(0,10)
179
- @splitter.setStretchFactor(1,1)
180
-
181
- setLayout(@layout)
182
-
183
- # Configure Variables
184
- @line_offset = 0
185
- @filename = ''
186
- @output_io = StringIO.new('', 'r+')
187
- @output_io_mutex = Mutex.new
188
- @change_callback = nil
189
- @run_callback = nil
190
- @stop_callback = nil
191
- @error_callback = nil
192
- @pause_callback = nil
193
- @key_press_callback = nil
194
- @allow_start = true
195
- @continue_after_error = true
196
- @debug_text = nil
197
- @debug_history = []
198
- @debug_code_completion = nil
199
- @top_level_instrumented_cache = nil
200
- @output_time = Time.now
201
- initialize_variables()
202
-
203
- # Redirect $stdout and $stderr
204
- redirect_io()
205
-
206
- # Create Tabbook
207
- @tab_book = Qt::TabWidget.new
208
- @tab_book_shown = false
209
-
210
- @find_dialog = nil
211
- @replace_dialog = nil
212
-
213
- mark_breakpoints('')
214
- end
215
-
216
- def current_tab_filename
217
- if @tab_book_shown
218
- filename = @tab_book.tabText(@tab_book.currentIndex)
219
- if filename == @default_tab_text
220
- return ''
221
- else
222
- return filename.strip
223
- end
224
- else
225
- return @filename
226
- end
227
- end
228
-
229
- def create_ruby_editor
230
- # Add Initial Text Window
231
- script = RubyEditor.new(self)
232
- script.enable_breakpoints = true if @debug_frame
233
- connect(script,
234
- SIGNAL('breakpoint_set(int)'),
235
- self,
236
- SLOT('breakpoint_set(int)'))
237
- connect(script,
238
- SIGNAL('breakpoint_cleared(int)'),
239
- self,
240
- SLOT('breakpoint_cleared(int)'))
241
- connect(script,
242
- SIGNAL('breakpoints_cleared()'),
243
- self,
244
- SLOT('breakpoints_cleared()'))
245
-
246
- # Add right click menu
247
- script.setContextMenuPolicy(Qt::CustomContextMenu)
248
- connect(script,
249
- SIGNAL('customContextMenuRequested(const QPoint&)'),
250
- self,
251
- SLOT('context_menu(const QPoint&)'))
252
-
253
- return script
254
- end
255
-
256
- def stop_message_log
257
- @message_log.stop if @message_log
258
- @message_log = nil
259
- end
260
-
261
- def filename=(filename)
262
- # Stop the message log so a new one will be created with the new filename
263
- stop_message_log()
264
- @filename = filename
265
- mark_breakpoints(filename)
266
- end
267
-
268
- def modified
269
- @script.document.isModified()
270
- end
271
-
272
- def modified=(bool)
273
- @script.document.setModified(bool)
274
- end
275
-
276
- def undo_available(bool)
277
- emit undoAvailable(bool)
278
- end
279
-
280
- def key_press_callback=(callback)
281
- @script.keyPressCallback = callback
282
- end
283
-
284
- def setFocus
285
- @script.setFocus
286
- end
287
-
288
- def allow_start=(value)
289
- @allow_start = value
290
- if @allow_start
291
- @realtime_button_bar.start_button.setEnabled(true)
292
- elsif not running?
293
- @realtime_button_bar.start_button.setEnabled(false)
294
- @script.setReadOnly(true)
295
- end
296
- end
297
-
298
- def clear
299
- self.set_text('')
300
- self.filename = ''
301
- self.modified = false
302
- end
303
-
304
- def self.instance
305
- @@instance
306
- end
307
-
308
- def self.instance=(value)
309
- @@instance = value
310
- end
311
-
312
- def self.step_mode
313
- @@step_mode
314
- end
315
-
316
- def self.step_mode=(value)
317
- @@step_mode = value
318
- if self.instance
319
- if value
320
- self.instance.pause
321
- else
322
- self.instance.go
323
- end
324
- end
325
- end
326
-
327
- def self.line_delay
328
- @@line_delay
329
- end
330
-
331
- def self.line_delay=(value)
332
- @@line_delay = value
333
- end
334
-
335
- def self.instrumented_cache
336
- @@instrumented_cache
337
- end
338
-
339
- def self.instrumented_cache=(value)
340
- @@instrumented_cache = value
341
- end
342
-
343
- def self.pause_on_error
344
- @@pause_on_error
345
- end
346
-
347
- def self.pause_on_error=(value)
348
- @@pause_on_error = value
349
- end
350
-
351
- def self.monitor_limits
352
- @@monitor_limits
353
- end
354
-
355
- def self.monitor_limits=(value)
356
- @@monitor_limits = value
357
- end
358
-
359
- def self.pause_on_red
360
- @@pause_on_red
361
- end
362
-
363
- def self.pause_on_red=(value)
364
- @@pause_on_red = value
365
- end
366
-
367
- def self.show_backtrace
368
- @@show_backtrace
369
- end
370
-
371
- def self.show_backtrace=(value)
372
- @@show_backtrace = value
373
- if @@show_backtrace and @@error
374
- puts Time.now.formatted + " (SCRIPTRUNNER): " + "Most recent exception:\n" + @@error.formatted
375
- end
376
- end
377
-
378
- def text
379
- @script.toPlainText.gsub("\r", '')
380
- end
381
-
382
- def set_text(text, filename = '')
383
- unless running?()
384
- @script.setPlainText(text)
385
- @script.stop_highlight
386
- @filename = filename
387
- mark_breakpoints(filename)
388
- end
389
- end
390
-
391
- def set_text_from_file(filename)
392
- unless running?()
393
- @@file_cache[filename] = nil
394
- load_file_into_script(filename)
395
- @filename = filename
396
- end
397
- end
398
-
399
- def self.running?
400
- if @@run_thread then true else false end
401
- end
402
-
403
- def running?
404
- if @@instance == self and ScriptRunnerFrame.running?() then true else false end
405
- end
406
-
407
- def go
408
- @go = true
409
- @pause = false unless @@step_mode
410
- end
411
-
412
- def go?
413
- temp = @go
414
- @go = false
415
- temp
416
- end
417
-
418
- def pause
419
- @pause = true
420
- @go = false
421
- end
422
-
423
- def pause?
424
- @pause
425
- end
426
-
427
- def self.stop!
428
- if @@run_thread
429
- Cosmos.kill_thread(nil, @@run_thread)
430
- @@run_thread = nil
431
- end
432
- end
433
-
434
- def stop?
435
- @stop
436
- end
437
-
438
- def retry_needed?
439
- @retry_needed
440
- end
441
-
442
- def retry_needed
443
- @retry_needed = true
444
- end
445
-
446
- def disable_retry
447
- @realtime_button_bar.start_button.setText('Skip')
448
- @realtime_button_bar.pause_button.setDisabled(true)
449
- end
450
-
451
- def enable_retry
452
- @realtime_button_bar.start_button.setText('Go')
453
- @realtime_button_bar.pause_button.setDisabled(false)
454
- end
455
-
456
- def run
457
- unless self.class.running?()
458
- run_text(@script.toPlainText)
459
- end
460
- end
461
-
462
- def run_and_close_on_complete(text_binding = nil)
463
- run_text(@script.toPlainText, 0, text_binding, true)
464
- end
465
-
466
- def self.instrument_script(text, filename, mark_private = false)
467
- if filename and !filename.empty?
468
- @@file_cache[filename] = text.clone
469
- end
470
-
471
- ruby_lex_utils = RubyLexUtils.new
472
- instrumented_text = ''
473
-
474
- Qt.execute_in_main_thread(true) do
475
- window = Qt::CoreApplication.instance.activeWindow
476
- @cancel_instrumentation = false
477
- ProgressDialog.execute(window, # parent
478
- "Instrumenting: #{File.basename(filename.to_s)}",
479
- 500, # width
480
- 100, # height
481
- true, # show overall progress
482
- false, # don't show step progress
483
- false, # don't show text
484
- false, # don't show done
485
- true) do |progress_dialog| # show cancel
486
- progress_dialog.cancel_callback = lambda {|dialog| @cancel_instrumentation = true; [true, false]}
487
- progress_dialog.enable_cancel_button
488
- comments_removed_text = ruby_lex_utils.remove_comments(text)
489
- num_lines = comments_removed_text.num_lines.to_f
490
- num_lines = 1 if num_lines < 1
491
- instrumented_text =
492
- instrument_script_implementation(ruby_lex_utils,
493
- comments_removed_text,
494
- num_lines,
495
- progress_dialog,
496
- filename,
497
- mark_private)
498
- progress_dialog.close_done
499
- end
500
- end
501
-
502
- Kernel.raise StopScript if @cancel_instrumentation or ProgressDialog.canceled?
503
- instrumented_text
504
- end
505
-
506
- def self.instrument_script_implementation(ruby_lex_utils,
507
- comments_removed_text,
508
- num_lines,
509
- progress_dialog,
510
- filename,
511
- mark_private = false)
512
- if mark_private
513
- instrumented_text = 'private; '
514
- else
515
- instrumented_text = ''
516
- end
517
-
518
- ruby_lex_utils.each_lexed_segment(comments_removed_text) do |segment, instrumentable, inside_begin, line_no|
519
- return nil if @cancel_instrumentation
520
- instrumented_line = ''
521
- if instrumentable
522
- # If not inside a begin block then create one to catch exceptions
523
- unless inside_begin
524
- instrumented_line << 'begin; '
525
- end
526
-
527
- # Add preline instrumentation
528
- instrumented_line << "ScriptRunnerFrame.instance.script_binding = binding(); if ScriptRunnerFrame.instance.inline_return then ScriptRunnerFrame.instance.inline_return = nil; return ScriptRunnerFrame.instance.inline_return_params; end; ScriptRunnerFrame.instance.pre_line_instrumentation('#{filename}', #{line_no}); "
529
-
530
- # Add the actual line
531
- instrumented_line << segment
532
- instrumented_line.chomp!
533
-
534
- # Add postline instrumentation
535
- instrumented_line << "; ScriptRunnerFrame.instance.post_line_instrumentation('#{filename}', #{line_no})"
536
-
537
- # Complete begin block to catch exceptions
538
- unless inside_begin
539
- instrumented_line << "; rescue Exception => eval_error; retry if ScriptRunnerFrame.instance.exception_instrumentation(eval_error, '#{filename}', #{line_no}); end"
540
- end
541
-
542
- instrumented_line << "\n"
543
- else
544
- unless segment =~ /^\s*end\s*$/ or segment =~ /^\s*when .*$/
545
- num_left_brackets = segment.count('{')
546
- num_right_brackets = segment.count('}')
547
- num_left_square_brackets = segment.count('[')
548
- num_right_square_brackets = segment.count(']')
549
-
550
- if (num_right_brackets > num_left_brackets) ||
551
- (num_right_square_brackets > num_left_square_brackets)
552
- instrumented_line = segment
553
- else
554
- instrumented_line = "ScriptRunnerFrame.instance.pre_line_instrumentation('#{filename}', #{line_no}); " + segment
555
- end
556
- else
557
- instrumented_line = segment
558
- end
559
- end
560
-
561
- instrumented_text << instrumented_line
562
-
563
- progress_dialog.set_overall_progress(line_no / num_lines) if progress_dialog and line_no
564
- end
565
- instrumented_text
566
- end
567
-
568
- def pre_line_instrumentation(filename, line_number)
569
- @current_filename = filename
570
- @current_line_number = line_number
571
- if @use_instrumentation
572
- # Clear go
573
- @go = false
574
-
575
- # Handle stopping mid-script if necessary
576
- Kernel.raise StopScript if @stop
577
-
578
- # Handle needing to change tabs
579
- handle_potential_tab_change(filename)
580
-
581
- # Adjust line number for offset in main script
582
- line_number = line_number + @line_offset if @active_script.object_id == @script.object_id
583
- detail_string = nil
584
- if filename
585
- detail_string = File.basename(filename) << ':' << line_number.to_s
586
- end
587
- Logger.detail_string = detail_string
588
-
589
- # Highlight the line that is about to run
590
- Qt.execute_in_main_thread(true) {@active_script.highlight_line(line_number)}
591
-
592
- # Handle pausing the script
593
- handle_pause(filename, line_number)
594
-
595
- # Handle delay between lines
596
- handle_line_delay()
597
- end
598
- end
599
-
600
- def post_line_instrumentation(filename, line_number)
601
- if @use_instrumentation
602
- line_number = line_number + @line_offset if @active_script.object_id == @script.object_id
603
- handle_output_io(filename, line_number)
604
- end
605
- end
606
-
607
- def exception_instrumentation(error, filename, line_number)
608
- if error.class == StopScript || error.class == SkipTestCase || !@use_instrumentation
609
- Kernel.raise error
610
- else
611
- line_number = line_number + @line_offset if @active_script.object_id == @script.object_id
612
- handle_exception(error, false, filename, line_number)
613
- end
614
- end
615
-
616
- def perform_pause
617
- mark_paused()
618
- wait_for_go_or_stop()
619
- end
620
-
621
- def perform_breakpoint(filename, line_number)
622
- mark_breakpoint()
623
- scriptrunner_puts "Hit Breakpoint at #{filename}:#{line_number}"
624
- handle_output_io(filename, line_number)
625
- wait_for_go_or_stop()
626
- end
627
-
628
- # Prompts the user that a script is running before they close the app
629
- def prompt_if_running_on_close
630
- safe_to_continue = true
631
- if running?
632
- case Qt::MessageBox.warning(
633
- self, # parent
634
- 'Warning', # title
635
- 'A Script is Running! Close Anyways?', # text
636
- Qt::MessageBox::Yes | Qt::MessageBox::No, # buttons
637
- Qt::MessageBox::No) # default button
638
- when Qt::MessageBox::Yes
639
- safe_to_continue = true
640
- ScriptRunnerFrame.stop!
641
- else
642
- safe_to_continue = false
643
- end
644
- end
645
- return safe_to_continue
646
- end
647
-
648
- ######################################
649
- # Implement the breakpoint callbacks from the RubyEditor
650
- ######################################
651
- def breakpoint_set(line)
652
- ScriptRunnerFrame.set_breakpoint(current_tab_filename(), line)
653
- end
654
-
655
- def breakpoint_cleared(line)
656
- ScriptRunnerFrame.clear_breakpoint(current_tab_filename(), line)
657
- end
658
-
659
- def breakpoints_cleared
660
- ScriptRunnerFrame.clear_breakpoints(current_tab_filename())
661
- end
662
-
663
- ######################################
664
- # Implement edit functionality in the frame (cut, copy, paste, etc)
665
- ######################################
666
- def undo
667
- @script.undo unless running?()
668
- end
669
-
670
- def redo
671
- @script.redo unless running?()
672
- end
673
-
674
- def cut
675
- @script.cut unless running?()
676
- end
677
-
678
- def copy
679
- @script.copy unless running?()
680
- end
681
-
682
- def paste
683
- @script.paste unless running?()
684
- end
685
-
686
- def select_all
687
- @script.select_all unless running?()
688
- end
689
-
690
- def comment_or_uncomment_lines
691
- @script.comment_or_uncomment_lines unless running?()
692
- end
693
-
694
- ##################################################################################
695
- # Implement Script functionality in the frame (run selection, run from cursor, etc
696
- ##################################################################################
697
- def run_selection
698
- unless self.class.running?()
699
- selection = @script.selected_lines
700
- if selection
701
- start_line_number = @script.selection_start_line
702
- end_line_number = @script.selection_end_line
703
- scriptrunner_puts "Running script lines #{start_line_number+1}-#{end_line_number+1}: #{File.basename(@filename)}"
704
- handle_output_io()
705
- run_text(selection, start_line_number)
706
- end
707
- end
708
- end
709
-
710
- def run_selection_while_paused
711
- current_script = @tab_book.tab(@tab_book.currentIndex)
712
- selection = current_script.selected_lines
713
- if selection
714
- start_line_number = current_script.selection_start_line
715
- end_line_number = current_script.selection_end_line
716
- scriptrunner_puts "Debug: Running selected lines #{start_line_number+1}-#{end_line_number+1}: #{@tab_book.tabText(@tab_book.currentIndex)}"
717
- handle_output_io()
718
- dialog = ScriptRunnerDialog.new(self, 'Executing Selected Lines While Paused')
719
- dialog.execute_text_and_close_on_complete(selection, @script_binding)
720
- handle_output_io()
721
- end
722
- end
723
-
724
- def run_from_cursor
725
- unless self.class.running?()
726
- line_number = @script.selection_start_line
727
- text = @script.toPlainText.split("\n")[line_number..-1].join("\n")
728
- scriptrunner_puts "Running script from line #{line_number}: #{File.basename(@filename)}"
729
- handle_output_io()
730
- run_text(text, line_number)
731
- end
732
- end
733
-
734
- def ruby_syntax_check_selection
735
- unless self.class.running?()
736
- selection = @script.selected_lines
737
- ruby_syntax_check_text(selection) if selection
738
- end
739
- end
740
-
741
- def ruby_syntax_check_text(selection = nil)
742
- unless self.class.running?()
743
- selection = text() unless selection
744
- check_process = IO.popen("ruby -c -rubygems 2>&1", 'r+')
745
- check_process.write("require 'cosmos'; require 'cosmos/script'; " + selection)
746
- check_process.close_write
747
- results = check_process.gets
748
- check_process.close
749
- if results
750
- if results =~ /Syntax OK/
751
- Qt::MessageBox.information(self, 'Syntax Check Successful', results)
752
- else
753
- # Results is a string like this: ":2: syntax error ..."
754
- # Normally the procedure comes before the first colon but since we
755
- # are writing to the process this is blank so we throw it away
756
- _, line_no, error = results.split(':')
757
- Qt::MessageBox.warning(self,
758
- 'Syntax Check Failed',
759
- "Error on line #{line_no}: #{error.strip}")
760
- end
761
- else
762
- Qt::MessageBox.critical(self,
763
- 'Syntax Check Exception',
764
- 'Ruby syntax check unexpectedly returned nil')
765
- end
766
- end
767
- end
768
-
769
- def mnemonic_check_selection
770
- unless self.class.running?()
771
- selection = @script.selected_lines
772
- mnemonic_check_text(selection, @script.selection_start_line+1) if selection
773
- end
774
- end
775
-
776
- def mnemonic_check_text(text, start_line_number = 1)
777
- results = []
778
- line_number = start_line_number
779
- text.each_line do |line|
780
- if line =~ /\(/
781
- result = nil
782
- keyword = line.split('(')[0].split[-1]
783
- if CMD_KEYWORDS.include? keyword
784
- result = mnemonic_check_cmd_line(keyword, line_number, line)
785
- elsif TLM_KEYWORDS.include? keyword
786
- result = mnemonic_check_tlm_line(keyword, line_number, line)
787
- elsif SET_TLM_KEYWORDS.include? keyword
788
- result = mnemonic_check_set_tlm_line(keyword, line_number, line)
789
- elsif CHECK_KEYWORDS.include? keyword
790
- result = mnemonic_check_check_line(keyword, line_number, line)
791
- end
792
- results << result if result
793
- end
794
- line_number += 1
795
- end
796
-
797
- if results.empty?
798
- Qt::MessageBox.information(self,
799
- 'Mnemonic Check Successful',
800
- 'Mnemonic Check Found No Errors')
801
- else
802
- dialog = Qt::Dialog.new(self) do |box|
803
- box.setWindowTitle('Mnemonic Check Failed')
804
- text = Qt::PlainTextEdit.new
805
- text.setReadOnly(true)
806
- text.setPlainText(results.join("\n"))
807
- frame = Qt::VBoxLayout.new(box)
808
- ok = Qt::PushButton.new('Ok')
809
- ok.setDefault(true)
810
- ok.connect(SIGNAL('clicked(bool)')) { box.accept }
811
- frame.addWidget(text)
812
- frame.addWidget(ok)
813
- end
814
- dialog.exec
815
- dialog.dispose
816
- end
817
- end
818
-
819
- ######################################################
820
- # Implement the debug capability
821
- ######################################################
822
- def toggle_debug(debug = nil)
823
- if debug.nil?
824
- if @debug_frame
825
- hide_debug()
826
- else
827
- show_debug()
828
- end
829
- else
830
- if debug
831
- if !@debug_frame
832
- show_debug()
833
- end
834
- else
835
- if @debug_frame
836
- hide_debug()
837
- end
838
- end
839
- end
840
- end
841
-
842
- def show_debug
843
- unless @debug_frame
844
- @script.enable_breakpoints = true
845
- if @tab_book_shown
846
- if @tab_book.count > 0
847
- (0..(@tab_book.count - 1)).each do |index|
848
- @tab_book.tab(index).enable_breakpoints = true
849
- end
850
- end
851
- end
852
-
853
- @debug_frame = Qt::HBoxLayout.new
854
- @debug_frame.setContentsMargins(0,0,0,0)
855
- @debug_frame_label = Qt::Label.new("Debug:")
856
- @debug_frame.addWidget(@debug_frame_label)
857
- @debug_text = CompletionLineEdit.new(self)
858
- @debug_text.setFocus(Qt::OtherFocusReason)
859
- @debug_text.keyPressCallback = lambda { |event|
860
- case event.key
861
- when Qt::Key_Return, Qt::Key_Enter
862
- begin
863
- debug_text = @debug_text.toPlainText
864
- @debug_history.unshift(debug_text)
865
- @debug_history_index = 0
866
- @debug_text.setPlainText('')
867
- scriptrunner_puts "Debug: #{debug_text}"
868
- handle_output_io()
869
- if not running?
870
- # Capture STDOUT and STDERR
871
- $stdout.add_stream(@output_io)
872
- $stderr.add_stream(@output_io)
873
- end
874
-
875
- if @script_binding
876
- eval(debug_text, @script_binding, 'debug', 1)
877
- else
878
- Object.class_eval(debug_text, 'debug', 1)
879
- end
880
- handle_output_io()
881
- rescue Exception => error
882
- if error.class == DRb::DRbConnError
883
- Logger.error("Error Connecting to Command and Telemetry Server")
884
- else
885
- Logger.error(error.class.to_s.split('::')[-1] + ' : ' + error.message)
886
- end
887
- handle_output_io()
888
- ensure
889
- if not running?
890
- # Capture STDOUT and STDERR
891
- $stdout.remove_stream(@output_io)
892
- $stderr.remove_stream(@output_io)
893
- end
894
- end
895
- when Qt::Key_Up
896
- if @debug_history.length > 0
897
- @debug_text.setPlainText(@debug_history[@debug_history_index])
898
- @debug_history_index += 1
899
- if @debug_history_index == @debug_history.length
900
- @debug_history_index = @debug_history.length-1
901
- end
902
- end
903
- when Qt::Key_Down
904
- if @debug_history.length > 0
905
- @debug_text.setPlainText(@debug_history[@debug_history_index])
906
- @debug_history_index -= 1
907
- @debug_history_index = 0 if @debug_history_index < 0
908
- end
909
- when Qt::Key_Escape
910
- @debug_text.setPlainText("")
911
- end
912
- }
913
-
914
- @debug_frame.addWidget(@debug_text)
915
-
916
- @toggle_button = Qt::PushButton.new('Toggle Run/Step')
917
- @debug_frame.addWidget(@toggle_button)
918
- @toggle_button.connect(SIGNAL('clicked(bool)')) do
919
- if @@step_mode
920
- scriptrunner_puts "Debug: run_mode"
921
- handle_output_io()
922
- self.class.step_mode = false
923
- else
924
- scriptrunner_puts "Debug: step_mode"
925
- handle_output_io()
926
- self.class.step_mode = true
927
- end
928
- end
929
-
930
- @return_button = Qt::PushButton.new('Insert Return')
931
- @debug_frame.addWidget(@return_button)
932
- @return_button.connect(SIGNAL('clicked(bool)')) do
933
- scriptrunner_puts "Debug: insert_return(); ScriptRunnerFrame.instance.go()"
934
- handle_output_io()
935
- insert_return()
936
- go()
937
- end
938
-
939
- @bottom_frame.layout.addLayout(@debug_frame)
940
- end
941
- end
942
-
943
- def hide_debug
944
- # Since we're disabling debug, clear the breakpoints and disable them
945
- ScriptRunnerFrame.clear_breakpoints()
946
- @script.clear_breakpoints
947
- @script.enable_breakpoints = false
948
- if @tab_book_shown
949
- if @tab_book.count > 0
950
- (0..(@tab_book.count - 1)).each do |index|
951
- @tab_book.tab(index).enable_breakpoints = false
952
- end
953
- end
954
- end
955
- # Remove the debug frame
956
- @bottom_frame.layout.takeAt(@bottom_frame.layout.count - 1) if @debug_frame
957
- @debug_frame.removeAll
958
- @debug_frame.dispose
959
- @debug_frame = nil
960
- end
961
-
962
- def self.set_breakpoint(filename, line_number)
963
- filename = File.basename(filename)
964
- @@breakpoints[filename] ||= {}
965
- @@breakpoints[filename][line_number] = true
966
- end
967
-
968
- def self.clear_breakpoint(filename, line_number)
969
- filename = File.basename(filename)
970
- @@breakpoints[filename] ||= {}
971
- @@breakpoints[filename].delete(line_number) if @@breakpoints[filename][line_number]
972
- end
973
-
974
- def self.clear_breakpoints(filename = nil)
975
- filename = File.basename(filename) unless filename.nil?
976
- if filename == nil or filename.empty?
977
- @@breakpoints = {}
978
- else
979
- @@breakpoints[filename] = {}
980
- end
981
- end
982
-
983
- def select_tab_and_destroy_tabs_after_index(index)
984
- Qt.execute_in_main_thread(true) do
985
- if @tab_book_shown
986
- @tab_book.setCurrentIndex(index)
987
- @active_script = @tab_book.tab(@tab_book.currentIndex)
988
-
989
- first_to_remove = index + 1
990
- last_to_remove = @call_stack.length - 1
991
-
992
- last_to_remove.downto(first_to_remove) do |tab_index|
993
- tab = @tab_book.tab(tab_index)
994
- @tab_book.removeTab(tab_index)
995
- tab.dispose
996
- end
997
-
998
- @call_stack = @call_stack[0..index]
999
- @current_file = @call_stack[index]
1000
- end
1001
- end
1002
- end
1003
-
1004
- def toggle_disconnect(config_file)
1005
- if get_cmd_tlm_disconnect
1006
- set_cmd_tlm_disconnect(false)
1007
- self.parent.setPalette(Cosmos::DEFAULT_PALETTE)
1008
- else
1009
- dialog = Qt::Dialog.new(self, Qt::WindowTitleHint | Qt::WindowSystemMenuHint)
1010
- dialog.setWindowTitle(tr("Server Config File"))
1011
- dialog_layout = Qt::VBoxLayout.new
1012
-
1013
- chooser = FileChooser.new(self, "Config File", config_file, 'Select',
1014
- File.join('config', 'tools', 'cmd_tlm_server', config_file))
1015
- chooser.callback = lambda do |filename|
1016
- chooser.filename = File.basename(filename)
1017
- end
1018
- dialog_layout.addWidget(chooser)
1019
-
1020
- button_layout = Qt::HBoxLayout.new
1021
- ok = Qt::PushButton.new("Ok")
1022
- ok.setDefault(true)
1023
- ok.connect(SIGNAL('clicked()')) do
1024
- dialog.accept()
1025
- end
1026
- button_layout.addWidget(ok)
1027
- cancel = Qt::PushButton.new("Cancel")
1028
- cancel.connect(SIGNAL('clicked()')) do
1029
- dialog.reject()
1030
- end
1031
- button_layout.addWidget(cancel)
1032
- dialog_layout.addLayout(button_layout)
1033
-
1034
- dialog.setLayout(dialog_layout)
1035
- if dialog.exec == Qt::Dialog::Accepted
1036
- config_file = chooser.filename
1037
- self.parent.setPalette(Cosmos::RED_PALETTE)
1038
- Splash.execute(self) do |splash|
1039
- ConfigParser.splash = splash
1040
- splash.message = "Initializing Command and Telemetry Server"
1041
- set_cmd_tlm_disconnect(true, config_file)
1042
- ConfigParser.splash = nil
1043
- end
1044
- end
1045
- dialog.dispose
1046
- end
1047
- config_file
1048
- end
1049
-
1050
- def current_backtrace
1051
- trace = []
1052
- Qt.execute_in_main_thread(true) do
1053
- if @@run_thread
1054
- temp_trace = @@run_thread.backtrace
1055
- cosmos_lib = Regexp.new(File.join(Cosmos::PATH, 'lib'))
1056
- temp_trace.each do |line|
1057
- next if line =~ cosmos_lib
1058
- trace << line
1059
- end
1060
- end
1061
- end
1062
- trace
1063
- end
1064
-
1065
- def scriptrunner_puts(string)
1066
- puts Time.now.formatted + " (SCRIPTRUNNER): " + string
1067
- end
1068
-
1069
- def handle_output_io(filename = @current_filename, line_number = @current_line_number)
1070
- @output_time = Time.now
1071
- Qt.execute_in_main_thread(true) do
1072
- if @output_io.string[-1..-1] == "\n"
1073
- time_formatted = Time.now.formatted
1074
- lines_to_write = ''
1075
- out_line_number = line_number.to_s
1076
- out_filename = File.basename(filename) if filename
1077
-
1078
- # Build each line to write
1079
- string = @output_io.string.clone
1080
- @output_io.string = @output_io.string[string.length..-1]
1081
- line_count = 0
1082
- string.each_line do |out_line|
1083
- color = nil
1084
- if out_line[0..1] == '20' and out_line[10] == ' ' and out_line[23..24] == ' ('
1085
- line_to_write = out_line
1086
- else
1087
- if filename
1088
- line_to_write = time_formatted + " (#{out_filename}:#{out_line_number}): " + out_line
1089
- else
1090
- line_to_write = time_formatted + " (SCRIPTRUNNER): " + out_line
1091
- color = Cosmos::BLUE
1092
- end
1093
- end
1094
- @output.add_formatted_text(line_to_write, color)
1095
- lines_to_write << line_to_write
1096
-
1097
- line_count += 1
1098
- if line_count > @stdout_max_lines
1099
- out_line = "ERROR: Too much written to stdout. Truncating output to #{@stdout_max_lines} lines.\n"
1100
- if filename
1101
- line_to_write = time_formatted + " (#{out_filename}:#{out_line_number}): " + out_line
1102
- else
1103
- line_to_write = time_formatted + " (SCRIPTRUNNER): " + out_line
1104
- end
1105
- @output.addText(line_to_write, Cosmos::RED)
1106
- lines_to_write << line_to_write
1107
- break
1108
- end
1109
- end # string.each_line
1110
-
1111
- # Actually add to the GUI
1112
- @output.flush
1113
-
1114
- # Add to the message log
1115
- if @filename.empty?
1116
- @message_log ||= MessageLog.new("sr_untitled")
1117
- else
1118
- @message_log ||= MessageLog.new("sr_#{File.basename(@filename).split('.')[0]}")
1119
- end
1120
- @message_log.write(lines_to_write)
1121
- end
1122
- end
1123
- end
1124
-
1125
- def graceful_kill
1126
- # Just to avoid warning
1127
- end
1128
-
1129
- protected
1130
-
1131
- def initialize_variables
1132
- @@file_cache = {}
1133
- @@error = nil
1134
- @go = false
1135
- if @@step_mode
1136
- @pause = true
1137
- else
1138
- @pause = false
1139
- end
1140
- @stop = false
1141
- @retry_needed = false
1142
- @use_instrumentation = true
1143
- @active_script = @script
1144
- @call_stack = []
1145
- @pre_line_time = Time.now
1146
- @current_file = @filename
1147
- @exceptions = nil
1148
- @script_binding = nil
1149
- @inline_eval = nil
1150
- @current_filename = nil
1151
- @current_line_number = 0
1152
- @stdout_max_lines = 1000
1153
-
1154
- @script.stop_highlight
1155
- @call_stack.push(@current_file.dup)
1156
- end
1157
-
1158
- def wait_for_go_or_stop(error = nil)
1159
- @go = false
1160
- sleep(0.01) until @go or @stop
1161
- @go = false
1162
- mark_running()
1163
- Kernel.raise StopScript if @stop
1164
- Kernel.raise error if error and !@continue_after_error
1165
- end
1166
-
1167
- def wait_for_go_or_stop_or_retry(error = nil)
1168
- @go = false
1169
- sleep(0.01) until @go or @stop or @retry_needed
1170
- @go = false
1171
- mark_running()
1172
- Kernel.raise StopScript if @stop
1173
- Kernel.raise error if error and !@continue_after_error
1174
- end
1175
-
1176
- def mark_running
1177
- Qt.execute_in_main_thread(true) do
1178
- @run_callback.call(self) if @run_callback
1179
- @active_script.rehighlight
1180
- @realtime_button_bar.state = 'Running'
1181
- @realtime_button_bar.start_button.setText('Go')
1182
- @realtime_button_bar.pause_button.setText('Pause')
1183
- end
1184
- end
1185
-
1186
- def mark_paused
1187
- Qt.execute_in_main_thread(true) do
1188
- @pause_callback.call(self) if @pause_callback
1189
- @active_script.rehighlight('lightblue')
1190
- @realtime_button_bar.state = 'Paused'
1191
- end
1192
- end
1193
-
1194
- def mark_error
1195
- Qt.execute_in_main_thread(true) do
1196
- @error_callback.call(self) if @error_callback
1197
- @active_script.rehighlight('pink')
1198
- @realtime_button_bar.state = 'Error'
1199
- @realtime_button_bar.pause_button.setText('Retry')
1200
- end
1201
- end
1202
-
1203
- def mark_stopped
1204
- stop_message_log()
1205
- Qt.execute_in_main_thread(true) do
1206
- @realtime_button_bar.start_button.setText('Start')
1207
- @realtime_button_bar.pause_button.setText('Pause')
1208
- @realtime_button_bar.state = 'Stopped'
1209
- @stop_callback.call(self) if @stop_callback
1210
- end
1211
- end
1212
-
1213
- def mark_breakpoint
1214
- Qt.execute_in_main_thread(true) do
1215
- @active_script.rehighlight('tan')
1216
- @realtime_button_bar.state = 'Breakpoint'
1217
- end
1218
- end
1219
-
1220
- def run_text(text,
1221
- line_offset = 0,
1222
- text_binding = nil,
1223
- close_on_complete = false)
1224
- @run_callback.call(self) if @run_callback
1225
- @realtime_button_bar.start_button.setEnabled(true)
1226
- initialize_variables()
1227
- create_tabs()
1228
- @line_offset = line_offset
1229
- @script.setReadOnly(true)
1230
- @realtime_button_bar.start_button.setText(' Go ')
1231
- @realtime_button_bar.state = 'Running'
1232
-
1233
- saved_instance = @@instance
1234
- saved_run_thread = @@run_thread
1235
- @@instance = self
1236
- @@run_thread = Thread.new do
1237
- uncaught_exception = false
1238
- begin
1239
- # Capture STDOUT and STDERR
1240
- $stdout.add_stream(@output_io)
1241
- $stderr.add_stream(@output_io)
1242
-
1243
- scriptrunner_puts "Starting script: #{File.basename(@filename)}" unless close_on_complete
1244
- handle_output_io()
1245
-
1246
- # Start Limits Monitoring
1247
- @@limits_monitor_thread = Thread.new { limits_monitor_thread() } if @@monitor_limits and !@@limits_monitor_thread
1248
-
1249
- # Start Output Thread
1250
- @@output_thread = Thread.new { output_thread() } unless @@output_thread
1251
-
1252
- # Check top level cache
1253
- if @top_level_instrumented_cache &&
1254
- (@top_level_instrumented_cache[1] == line_offset) &&
1255
- (@top_level_instrumented_cache[2] == @filename) &&
1256
- (@top_level_instrumented_cache[0] == text)
1257
- # Use the instrumented cache
1258
- instrumented_script = @top_level_instrumented_cache[3]
1259
- else
1260
- # Instrument the script
1261
- if text_binding
1262
- instrumented_script = self.class.instrument_script(text, @filename, false)
1263
- else
1264
- instrumented_script = self.class.instrument_script(text, @filename, true)
1265
- end
1266
- @top_level_instrumented_cache = [text, line_offset, @filename, instrumented_script]
1267
- end
1268
-
1269
- # Execute the script with warnings disabled
1270
- Cosmos.disable_warnings do
1271
- @pre_line_time = Time.now
1272
- Cosmos.set_working_dir do
1273
- if text_binding
1274
- eval(instrumented_script, text_binding, @filename, 1)
1275
- else
1276
- Object.class_eval(instrumented_script, @filename, 1)
1277
- end
1278
- end
1279
- end
1280
-
1281
- scriptrunner_puts "Script completed: #{File.basename(@filename)}" unless close_on_complete
1282
- handle_output_io()
1283
-
1284
- rescue Exception => error
1285
- if error.class == StopScript or error.class == SkipTestCase
1286
- scriptrunner_puts "Script stopped: #{File.basename(@filename)}"
1287
- handle_output_io()
1288
- else
1289
- uncaught_exception = true
1290
- filename, line_number = error.source
1291
- handle_exception(error, true, filename, line_number)
1292
- scriptrunner_puts "Exception in Control Statement - Script stopped: #{File.basename(@filename)}"
1293
- handle_output_io()
1294
- Qt.execute_in_main_thread(true) {@script.rehighlight('red') }
1295
- end
1296
- ensure
1297
- # Change Go Button to Start Button and remove highlight
1298
- Qt.execute_in_main_thread(true) do
1299
- # Stop Capturing STDOUT and STDERR
1300
- # Check for remove_stream because if the tool is quitting the
1301
- # Cosmos::restore_io may have been called which sets $stdout and
1302
- # $stderr to the IO constant
1303
- $stdout.remove_stream(@output_io) if $stdout.respond_to? :remove_stream
1304
- $stderr.remove_stream(@output_io) if $stderr.respond_to? :remove_stream
1305
-
1306
- # Clear run thread and instance to indicate we are no longer running
1307
- @@instance = saved_instance
1308
- @@run_thread = saved_run_thread
1309
- @active_script = @script
1310
- @script_binding = nil
1311
- @current_filename = nil
1312
- @current_line_number = 0
1313
- if @@limits_monitor_thread and not @@instance
1314
- @@cancel_limits = true
1315
- @@limits_sleeper.cancel
1316
- Qt::CoreApplication.processEvents()
1317
- Cosmos.kill_thread(self, @@limits_monitor_thread)
1318
- @@limits_monitor_thread = nil
1319
- end
1320
- if @@output_thread and not @@instance
1321
- @@cancel_output = true
1322
- @@output_sleeper.cancel
1323
- Qt::CoreApplication.processEvents()
1324
- Cosmos.kill_thread(self, @@output_thread)
1325
- @@output_thread = nil
1326
- end
1327
-
1328
- @script.setReadOnly(false)
1329
- @script.stop_highlight unless uncaught_exception
1330
- select_tab_and_destroy_tabs_after_index(0)
1331
- remove_tabs()
1332
- unless @allow_start
1333
- @realtime_button_bar.start_button.setEnabled(false)
1334
- @script.setReadOnly(true)
1335
- end
1336
- mark_stopped()
1337
- if close_on_complete
1338
- self.parent.done(0)
1339
- end
1340
- end
1341
- end
1342
- end
1343
- end
1344
-
1345
- def handle_potential_tab_change(filename)
1346
- # Make sure the correct file is shown in script runner
1347
- if @current_file != filename and @tab_book_shown
1348
- Qt.execute_in_main_thread(true) do
1349
- if @call_stack.include?(filename)
1350
- index = @call_stack.index(filename)
1351
- select_tab_and_destroy_tabs_after_index(index)
1352
- else # new file
1353
- # Create new tab
1354
- new_script = create_ruby_editor()
1355
- @tab_book.addTab(new_script, ' ' + File.basename(filename) + ' ')
1356
-
1357
- @call_stack.push(filename.dup)
1358
-
1359
- # Switch to new tab
1360
- @tab_book.setCurrentIndex(@tab_book.count - 1)
1361
- @active_script = new_script
1362
- load_file_into_script(filename)
1363
- new_script.setReadOnly(true)
1364
- end
1365
-
1366
- @current_file = filename
1367
- end
1368
- end
1369
- end
1370
-
1371
- def show_active_tab
1372
- @tab_book.setCurrentIndex(@call_stack.length - 1) if @tab_book_shown
1373
- end
1374
-
1375
- def handle_pause(filename, line_number)
1376
- filename = File.basename(filename)
1377
- breakpoint = false
1378
- breakpoint = true if @@breakpoints[filename] and @@breakpoints[filename][line_number]
1379
- if @pause
1380
- @pause = false unless @@step_mode
1381
- if breakpoint
1382
- perform_breakpoint(filename, line_number)
1383
- else
1384
- perform_pause()
1385
- end
1386
- else
1387
- perform_breakpoint(filename, line_number) if breakpoint
1388
- end
1389
- end
1390
-
1391
- def handle_line_delay
1392
- if @@line_delay > 0.0
1393
- sleep_time = @@line_delay - (Time.now - @pre_line_time)
1394
- sleep(sleep_time) if sleep_time > 0.0
1395
- end
1396
- @pre_line_time = Time.now
1397
- end
1398
-
1399
- def continue_without_pausing_on_errors?
1400
- if !@@pause_on_error
1401
- if Qt::MessageBox.warning(self, "Warning", "If an error occurs, the script will not pause and will run to completion. Continue?", Qt::MessageBox::Yes | Qt::MessageBox::No, Qt::MessageBox::Yes) == Qt::MessageBox::No
1402
- return false
1403
- end
1404
- end
1405
- true
1406
- end
1407
-
1408
- def handle_start_go_button
1409
- scriptrunner_puts "User pressed #{@realtime_button_bar.start_button.text.strip}"
1410
- handle_output_io()
1411
- @realtime_button_bar.start_button.clear_focus()
1412
-
1413
- if running?()
1414
- show_active_tab()
1415
- go()
1416
- else
1417
- if @allow_start
1418
- run() if continue_without_pausing_on_errors?()
1419
- end
1420
- end
1421
- end
1422
-
1423
- def handle_pause_retry_button
1424
- scriptrunner_puts "User pressed #{@realtime_button_bar.pause_button.text.strip}"
1425
- handle_output_io()
1426
- @realtime_button_bar.pause_button.clear_focus()
1427
- show_active_tab() if running?
1428
- if @realtime_button_bar.pause_button.text.to_s == 'Pause'
1429
- pause()
1430
- else
1431
- retry_needed()
1432
- end
1433
- end
1434
-
1435
- def handle_stop_button
1436
- scriptrunner_puts "User pressed #{@realtime_button_bar.stop_button.text.strip}"
1437
- handle_output_io()
1438
- @realtime_button_bar.stop_button.clear_focus()
1439
-
1440
- if @stop
1441
- # If we're already stopped and they click Stop again, kill the run
1442
- # thread. This will break any ruby sleeps or other code blocks.
1443
- ScriptRunnerFrame.stop!
1444
- handle_output_io()
1445
- else
1446
- @stop = true
1447
- end
1448
- if !running?()
1449
- # Stop highlight if there was a red syntax error
1450
- @script.stop_highlight
1451
- end
1452
- end
1453
-
1454
- def handle_exception(error, fatal, filename = nil, line_number = 0)
1455
- @error_callback.call(self) if @error_callback
1456
-
1457
- @exceptions ||= []
1458
- @exceptions << error
1459
- @@error = error
1460
-
1461
- if error.class == DRb::DRbConnError
1462
- Logger.error("Error Connecting to Command and Telemetry Server")
1463
- elsif error.class == CheckError
1464
- Logger.error(error.message)
1465
- else
1466
- Logger.error(error.class.to_s.split('::')[-1] + ' : ' + error.message)
1467
- end
1468
- Logger.error(error.backtrace.join("\n")) if @@show_backtrace
1469
- handle_output_io(filename, line_number)
1470
-
1471
- Kernel.raise error if !@@pause_on_error and !@continue_after_error and !fatal
1472
-
1473
- if !fatal and @@pause_on_error
1474
- mark_error()
1475
- wait_for_go_or_stop_or_retry(error)
1476
- end
1477
-
1478
- if @retry_needed
1479
- @retry_needed = false
1480
- true
1481
- else
1482
- false
1483
- end
1484
- end
1485
-
1486
- # Right click context_menu for the script
1487
- def context_menu(point)
1488
- if @tab_book_shown
1489
- current_script = @tab_book.tab(@tab_book.currentIndex)
1490
- else
1491
- current_script = @script
1492
- end
1493
- menu = current_script.context_menu(point)
1494
- menu.addSeparator()
1495
- if not self.class.running?
1496
- exec_selected_action = Qt::Action.new(tr("Execute Selected Lines"), self)
1497
- exec_selected_action.statusTip = tr("Execute the selected lines as a standalone script")
1498
- exec_selected_action.connect(SIGNAL('triggered()')) { run_selection() }
1499
- menu.addAction(exec_selected_action)
1500
-
1501
- exec_cursor_action = Qt::Action.new(tr("Execute From Cursor"), self)
1502
- exec_cursor_action.statusTip = tr("Execute the script starting at the line containing the cursor")
1503
- exec_cursor_action.connect(SIGNAL('triggered()')) { run_from_cursor() }
1504
- menu.addAction(exec_cursor_action)
1505
-
1506
- menu.addSeparator()
1507
-
1508
- if RUBY_VERSION.split('.')[0].to_i > 1
1509
- syntax_action = Qt::Action.new(tr("Ruby Syntax Check Selected Lines"), self)
1510
- syntax_action.statusTip = tr("Check the selected lines for valid Ruby syntax")
1511
- syntax_action.connect(SIGNAL('triggered()')) { ruby_syntax_check_selection() }
1512
- menu.addAction(syntax_action)
1513
- end
1514
-
1515
- mnemonic_action = Qt::Action.new(tr("Mnemonic Check Selected Lines"), self)
1516
- mnemonic_action.statusTip = tr("Check the selected lines for valid targets, packets, mnemonics and parameters")
1517
- mnemonic_action.connect(SIGNAL('triggered()')) { mnemonic_check_selection() }
1518
- menu.addAction(mnemonic_action)
1519
-
1520
- elsif running?() and @realtime_button_bar.state != 'Running'
1521
- exec_selected_action = Qt::Action.new(tr("Execute Selected Lines While Paused"), self)
1522
- exec_selected_action.statusTip = tr("Execute the selected lines as a standalone script")
1523
- exec_selected_action.connect(SIGNAL('triggered()')) { run_selection_while_paused() }
1524
- menu.addAction(exec_selected_action)
1525
- end
1526
- menu.exec(current_script.mapToGlobal(point))
1527
- menu.dispose
1528
- end
1529
-
1530
- def load_file_into_script(filename)
1531
- cached = @@file_cache[filename]
1532
- if cached
1533
- @active_script.setPlainText(cached.gsub("\r", ''))
1534
- else
1535
- @active_script.setPlainText(File.read(filename).gsub("\r", ''))
1536
- end
1537
- mark_breakpoints(filename)
1538
-
1539
- @active_script.stop_highlight
1540
- end
1541
-
1542
- def mark_breakpoints(filename)
1543
- @active_script.clear_breakpoints
1544
- breakpoints = @@breakpoints[File.basename(filename)]
1545
- if breakpoints
1546
- breakpoints.each do |line_number, present|
1547
- @active_script.add_breakpoint(line_number) if present
1548
- end
1549
- end
1550
- end
1551
-
1552
- def redirect_io
1553
- # Redirect Standard Output and Standard Error
1554
- $stdout = Stdout.instance
1555
- $stderr = Stderr.instance
1556
-
1557
- # Disable outputting to default io file descriptors
1558
- $stdout.remove_default_io
1559
- $stderr.remove_default_io
1560
-
1561
- Logger.level = Logger::INFO
1562
- Logger::INFO_SEVERITY_STRING.replace('')
1563
- Logger::WARN_SEVERITY_STRING.replace('<Y> WARN:')
1564
- Logger::ERROR_SEVERITY_STRING.replace('<R> ERROR:')
1565
- end
1566
-
1567
- def create_tabs
1568
- tab_text = @default_tab_text
1569
- tab_text = ' ' + File.basename(@filename) + ' ' unless @filename.empty?
1570
- @tab_book.addTab(@script, tab_text)
1571
- @top_frame.insertWidget(0, @tab_book)
1572
- @tab_book_shown = true
1573
- end
1574
-
1575
- def remove_tabs
1576
- @top_frame.takeAt(0) # Remove the @tab_book from the layout
1577
- @top_frame.addWidget(@script) # Add back the script
1578
- @script.show
1579
- @tab_book_shown = false
1580
- end
1581
-
1582
- def isolate_string(keyword, line)
1583
- found_string = nil
1584
-
1585
- # Find keyword
1586
- keyword_index = line.index(keyword)
1587
-
1588
- # Remove keyword from line
1589
- line = line[(keyword_index + keyword.length)..-1]
1590
-
1591
- # Find start parens
1592
- start_parens = line.index('(')
1593
- if start_parens
1594
- end_parens = line[start_parens..-1].index(')')
1595
- found_string = line[(start_parens + 1)..(end_parens + start_parens - 1)].remove_quotes if end_parens
1596
- if keyword == 'wait' or keyword == 'wait_check'
1597
- quote_index = found_string.rindex('"')
1598
- quote_index = found_string.rindex("'") unless quote_index
1599
- if quote_index
1600
- found_string = found_string[0..quote_index].remove_quotes
1601
- else
1602
- found_string = nil
1603
- end
1604
- end
1605
- end
1606
- found_string
1607
- end
1608
-
1609
- def mnemonic_check_cmd_line(keyword, line_number, line)
1610
- result = nil
1611
-
1612
- # Isolate the string
1613
- string = isolate_string(keyword, line)
1614
- if string
1615
- begin
1616
- target_name, cmd_name, cmd_params = extract_fields_from_cmd_text(string)
1617
- result = "At line #{line_number}: Unknown command: #{target_name} #{cmd_name}"
1618
- packet = System.commands.packet(target_name, cmd_name)
1619
- Kernel.raise "Command not found" unless packet
1620
- cmd_params.each do |param_name, param_value|
1621
- result = "At line #{line_number}: Unknown command parameter: #{target_name} #{cmd_name} #{param_name}"
1622
- packet.get_item(param_name)
1623
- end
1624
- result = nil
1625
- rescue
1626
- if result
1627
- if string.index('=>')
1628
- # Assume alternative syntax
1629
- result = nil
1630
- end
1631
- else
1632
- result = "At line #{line_number}: Potentially malformed command: #{line}"
1633
- end
1634
- end
1635
- end
1636
-
1637
- result
1638
- end
1639
-
1640
- def _mnemonic_check_tlm_line(keyword, line_number, line)
1641
- result = nil
1642
-
1643
- # Isolate the string
1644
- string = isolate_string(keyword, line)
1645
- if string
1646
- begin
1647
- target_name, packet_name, item_name = yield string
1648
- result = "At line #{line_number}: Unknown telemetry item: #{target_name} #{packet_name} #{item_name}"
1649
- System.telemetry.packet_and_item(target_name, packet_name, item_name)
1650
- result = nil
1651
- rescue
1652
- if result
1653
- if string.index(',')
1654
- # Assume alternative syntax
1655
- result = nil
1656
- end
1657
- else
1658
- result = "At line #{line_number}: Potentially malformed telemetry: #{line}"
1659
- end
1660
- end
1661
- end
1662
-
1663
- result
1664
- end
1665
-
1666
- def mnemonic_check_tlm_line(keyword, line_number, line)
1667
- _mnemonic_check_tlm_line(keyword, line_number, line) do |string|
1668
- extract_fields_from_tlm_text(string)
1669
- end
1670
- end
1671
-
1672
- def mnemonic_check_set_tlm_line(keyword, line_number, line)
1673
- _mnemonic_check_tlm_line(keyword, line_number, line) do |string|
1674
- extract_fields_from_set_tlm_text(string)
1675
- end
1676
- end
1677
-
1678
- def mnemonic_check_check_line(keyword, line_number, line)
1679
- _mnemonic_check_tlm_line(keyword, line_number, line) do |string|
1680
- extract_fields_from_check_text(string)
1681
- end
1682
- end
1683
-
1684
- def output_thread
1685
- @@cancel_output = false
1686
- @@output_sleeper = Sleeper.new
1687
- begin
1688
- loop do
1689
- break if @@cancel_output
1690
- handle_output_io() if (Time.now - @output_time) > 5.0
1691
- break if @@cancel_output
1692
- break if @@output_sleeper.sleep(1.0)
1693
- end # loop
1694
- rescue => error
1695
- Qt.execute_in_main_thread(true) do
1696
- ExceptionDialog.new(self, error, "Output Thread")
1697
- end
1698
- end
1699
- end
1700
-
1701
- def limits_monitor_thread
1702
- @@cancel_limits = false
1703
- @@limits_sleeper = Sleeper.new
1704
- queue_id = nil
1705
- begin
1706
- loop do
1707
- break if @@cancel_limits
1708
- begin
1709
- # Subscribe to limits notifications
1710
- queue_id = subscribe_limits_events(100000) unless queue_id
1711
-
1712
- # Get the next limits event
1713
- break if @@cancel_limits
1714
- begin
1715
- type, data = get_limits_event(queue_id, true)
1716
- rescue ThreadError
1717
- break if @@cancel_limits
1718
- break if @@limits_sleeper.sleep(0.5)
1719
- next
1720
- end
1721
-
1722
- break if @@cancel_limits
1723
-
1724
- # Display limits state changes
1725
- if type == :LIMITS_CHANGE
1726
- target_name = data[0]
1727
- packet_name = data[1]
1728
- item_name = data[2]
1729
- old_limits_state = data[3]
1730
- new_limits_state = data[4]
1731
-
1732
- if old_limits_state == nil # Changing from nil
1733
- if (new_limits_state != :GREEN) &&
1734
- (new_limits_state != :GREEN_LOW) &&
1735
- (new_limits_state != :GREEN_HIGH) &&
1736
- (new_limits_state != :BLUE)
1737
- msg = "#{target_name} #{packet_name} #{item_name} is #{new_limits_state.to_s}"
1738
- case new_limits_state
1739
- when :YELLOW, :YELLOW_LOW, :YELLOW_HIGH
1740
- scriptrunner_puts "<Y>#{msg}"
1741
- when :RED, :RED_LOW, :RED_HIGH
1742
- scriptrunner_puts "<R>#{msg}"
1743
- else
1744
- # Print nothing
1745
- end
1746
- handle_output_io()
1747
- end
1748
- else # changing from a color
1749
- msg = "#{target_name} #{packet_name} #{item_name} is #{new_limits_state.to_s}"
1750
- case new_limits_state
1751
- when :BLUE
1752
- scriptrunner_puts "<B>#{msg}"
1753
- when :GREEN, :GREEN_LOW, :GREEN_HIGH
1754
- scriptrunner_puts "<G>#{msg}"
1755
- when :YELLOW, :YELLOW_LOW, :YELLOW_HIGH
1756
- scriptrunner_puts "<Y>#{msg}"
1757
- when :RED, :RED_LOW, :RED_HIGH
1758
- scriptrunner_puts "<R>#{msg}"
1759
- else
1760
- # Print nothing
1761
- end
1762
- break if @@cancel_limits
1763
- handle_output_io()
1764
- break if @@cancel_limits
1765
- end
1766
-
1767
- if @@pause_on_red && (new_limits_state == :RED ||
1768
- new_limits_state == :RED_LOW ||
1769
- new_limits_state == :RED_HIGH)
1770
- break if @@cancel_limits
1771
- pause()
1772
- break if @@cancel_limits
1773
- end
1774
- end
1775
-
1776
- rescue DRb::DRbConnError
1777
- queue_id = nil
1778
- break if @@cancel_limits
1779
- break if @@limits_sleeper.sleep(1)
1780
- end
1781
-
1782
- end # loop
1783
- rescue => error
1784
- Qt.execute_in_main_thread(true) do
1785
- ExceptionDialog.new(self, error, "Limits Monitor Thread")
1786
- end
1787
- end
1788
- ensure
1789
- begin
1790
- unsubscribe_limits_events(queue_id) if queue_id
1791
- rescue
1792
- # Oh Well
1793
- end
1794
- end
1795
-
1796
- end # class ScriptRunnerFrame
1797
-
1798
- end # module Cosmos
1
+ # encoding: ascii-8bit
2
+
3
+ # Copyright 2014 Ball Aerospace & Technologies Corp.
4
+ # All Rights Reserved.
5
+ #
6
+ # This program is free software; you can modify and/or redistribute it
7
+ # under the terms of the GNU General Public License
8
+ # as published by the Free Software Foundation; version 3 with
9
+ # attribution addendums as found in the LICENSE.txt
10
+
11
+ require 'cosmos'
12
+ require 'cosmos/script'
13
+ require 'cosmos/gui/utilities/script_module_gui'
14
+ require 'cosmos/gui/dialogs/splash'
15
+ require 'cosmos/gui/dialogs/exception_dialog'
16
+ require 'cosmos/gui/text/completion'
17
+ require 'cosmos/gui/text/completion_line_edit'
18
+ require 'cosmos/gui/text/ruby_editor'
19
+ require 'cosmos/gui/dialogs/progress_dialog'
20
+ require 'cosmos/gui/widgets/realtime_button_bar'
21
+ require 'cosmos/gui/dialogs/find_replace_dialog'
22
+ require 'cosmos/gui/choosers/file_chooser'
23
+ require 'cosmos/io/stdout'
24
+ require 'cosmos/io/stderr'
25
+
26
+ module Cosmos
27
+
28
+ Cosmos.disable_warnings do
29
+ module Script
30
+ def prompt_for_script_abort
31
+ ScriptRunnerFrame.instance.perform_pause
32
+ return false # Not aborted - Retry
33
+ end
34
+ end
35
+ end
36
+
37
+ class ScriptRunnerDialog < Qt::Dialog
38
+ attr_reader :script_runner_frame
39
+
40
+ def initialize(parent,
41
+ title,
42
+ default_tab_text = 'Untitled')
43
+ super(parent)
44
+ setWindowTitle(title)
45
+ setMinimumWidth(parent.width * 0.8)
46
+ setMinimumHeight(parent.height * 0.6)
47
+
48
+ # Create script runner frame
49
+ @script_runner_frame = ScriptRunnerFrame.new(self, default_tab_text)
50
+ layout = Qt::VBoxLayout.new
51
+ layout.addWidget(@script_runner_frame)
52
+ setLayout(layout)
53
+ end
54
+
55
+ # Executes the given text and closes when complete
56
+ def execute_text_and_close_on_complete(text, text_binding = nil)
57
+ @script_runner_frame.set_text(text)
58
+ @script_runner_frame.run_and_close_on_complete(text_binding)
59
+ exec
60
+ dispose
61
+ end
62
+
63
+ def reject
64
+ # Don't allow the dialog to close if we're running
65
+ return if @script_runner_frame.running?
66
+ super
67
+ end
68
+ end # class ScriptRunnerDialog
69
+
70
+ class ScriptRunnerFrame < Qt::Widget
71
+ slots 'context_menu(const QPoint&)'
72
+ slots 'undo_available(bool)'
73
+ slots 'breakpoint_set(int)'
74
+ slots 'breakpoint_cleared(int)'
75
+ slots 'breakpoints_cleared()'
76
+ signals 'undoAvailable(bool)'
77
+ signals 'modificationChanged(bool)'
78
+
79
+ CMD_KEYWORDS = %w(cmd cmd_no_range_check cmd_no_hazardous_check cmd_no_checks)
80
+ TLM_KEYWORDS = %w(tlm tlm_raw tlm_formatted tlm_with_units limits_enabled? \
81
+ enable_limits disable_limits wait_tolerance wait_tolerance_raw \
82
+ check_tolerance check_tolerance_raw wait_check_tolerance \
83
+ wait_check_tolerance_raw)
84
+ SET_TLM_KEYWORDS = %w(set_tlm set_tlm_raw)
85
+ CHECK_KEYWORDS = %w(check check_raw wait wait_raw wait_check wait_check_raw)
86
+
87
+ attr_accessor :use_instrumentation
88
+ attr_accessor :change_callback
89
+ attr_accessor :run_callback
90
+ attr_accessor :stop_callback
91
+ attr_accessor :error_callback
92
+ attr_accessor :pause_callback
93
+ attr_reader :filename
94
+ attr_accessor :continue_after_error
95
+ attr_accessor :exceptions
96
+ attr_accessor :script_binding
97
+ attr_accessor :inline_return
98
+ attr_accessor :inline_return_params
99
+ attr_reader :message_log
100
+ attr_reader :script_class
101
+ attr_reader :top_level_instrumented_cache
102
+ attr_accessor :stdout_max_lines
103
+ attr_reader :script
104
+
105
+ @@instance = nil
106
+ @@run_thread = nil
107
+ @@breakpoints = {}
108
+ @@step_mode = false
109
+ @@line_delay = 0.1
110
+ @@instrumented_cache = {}
111
+ @@file_cache = {}
112
+ @@output_thread = nil
113
+ @@limits_monitor_thread = nil
114
+ @@pause_on_error = true
115
+ @@monitor_limits = false
116
+ @@pause_on_red = false
117
+ @@show_backtrace = false
118
+ @@error = nil
119
+ @@output_sleeper = Sleeper.new
120
+ @@limits_sleeper = Sleeper.new
121
+ @@cancel_output = false
122
+ @@cancel_limits = false
123
+
124
+ def initialize(parent, default_tab_text = 'Untitled')
125
+ super(parent)
126
+ @default_tab_text = ' ' + default_tab_text + ' '
127
+ # Keep track of whether this frame has been fully initialized
128
+ @initialized = false
129
+ @debug_frame = nil
130
+
131
+ @layout = Qt::VBoxLayout.new
132
+ @layout.setContentsMargins(0,0,0,0)
133
+
134
+ # Add Realtime Button Bar
135
+ @realtime_button_bar = RealtimeButtonBar.new(self)
136
+ @realtime_button_bar.state = 'Stopped'
137
+ @realtime_button_bar.start_callback = method(:handle_start_go_button)
138
+ @realtime_button_bar.pause_callback = method(:handle_pause_retry_button)
139
+ @realtime_button_bar.stop_callback = method(:handle_stop_button)
140
+ @layout.addWidget(@realtime_button_bar)
141
+
142
+ # Create a splitter to hold the script text area and the script output text area.
143
+ @splitter = Qt::Splitter.new(Qt::Vertical, self)
144
+ @layout.addWidget(@splitter)
145
+ @top_widget = Qt::Widget.new(@splitter)
146
+ @top_widget.setContentsMargins(0,0,0,0)
147
+ @top_frame = Qt::VBoxLayout.new(@top_widget)
148
+ @top_frame.setContentsMargins(0,0,0,0)
149
+
150
+ # Add Initial Text Window
151
+ @script = create_ruby_editor()
152
+ @script.connect(SIGNAL('modificationChanged(bool)')) do |changed|
153
+ emit modificationChanged(changed)
154
+ end
155
+ @top_frame.addWidget(@script)
156
+
157
+ # Set self as the gui window to allow prompts and other popups to appear
158
+ set_cmd_tlm_gui_window(self)
159
+
160
+ # Add change handlers
161
+ connect(@script,
162
+ SIGNAL('undoAvailable(bool)'),
163
+ self,
164
+ SLOT('undo_available(bool)'))
165
+
166
+ # Add Output Text
167
+ @bottom_frame = Qt::Widget.new
168
+ @bottom_layout = Qt::VBoxLayout.new
169
+ @bottom_layout.setContentsMargins(0,0,0,0)
170
+ @bottom_layout_label = Qt::Label.new("Script Output:")
171
+ @bottom_layout.addWidget(@bottom_layout_label)
172
+ @output = Qt::PlainTextEdit.new
173
+ @output.setReadOnly(true)
174
+ @output.setMaximumBlockCount(100)
175
+ @bottom_layout.addWidget(@output)
176
+ @bottom_frame.setLayout(@bottom_layout)
177
+ @splitter.addWidget(@bottom_frame)
178
+ @splitter.setStretchFactor(0,10)
179
+ @splitter.setStretchFactor(1,1)
180
+
181
+ setLayout(@layout)
182
+
183
+ # Configure Variables
184
+ @line_offset = 0
185
+ @filename = ''
186
+ @output_io = StringIO.new('', 'r+')
187
+ @output_io_mutex = Mutex.new
188
+ @change_callback = nil
189
+ @run_callback = nil
190
+ @stop_callback = nil
191
+ @error_callback = nil
192
+ @pause_callback = nil
193
+ @key_press_callback = nil
194
+ @allow_start = true
195
+ @continue_after_error = true
196
+ @debug_text = nil
197
+ @debug_history = []
198
+ @debug_code_completion = nil
199
+ @top_level_instrumented_cache = nil
200
+ @output_time = Time.now
201
+ initialize_variables()
202
+
203
+ # Redirect $stdout and $stderr
204
+ redirect_io()
205
+
206
+ # Create Tabbook
207
+ @tab_book = Qt::TabWidget.new
208
+ @tab_book_shown = false
209
+
210
+ @find_dialog = nil
211
+ @replace_dialog = nil
212
+
213
+ mark_breakpoints('')
214
+ end
215
+
216
+ def current_tab_filename
217
+ if @tab_book_shown
218
+ filename = @tab_book.tabText(@tab_book.currentIndex)
219
+ if filename == @default_tab_text
220
+ return ''
221
+ else
222
+ return filename.strip
223
+ end
224
+ else
225
+ return @filename
226
+ end
227
+ end
228
+
229
+ def create_ruby_editor
230
+ # Add Initial Text Window
231
+ script = RubyEditor.new(self)
232
+ script.enable_breakpoints = true if @debug_frame
233
+ connect(script,
234
+ SIGNAL('breakpoint_set(int)'),
235
+ self,
236
+ SLOT('breakpoint_set(int)'))
237
+ connect(script,
238
+ SIGNAL('breakpoint_cleared(int)'),
239
+ self,
240
+ SLOT('breakpoint_cleared(int)'))
241
+ connect(script,
242
+ SIGNAL('breakpoints_cleared()'),
243
+ self,
244
+ SLOT('breakpoints_cleared()'))
245
+
246
+ # Add right click menu
247
+ script.setContextMenuPolicy(Qt::CustomContextMenu)
248
+ connect(script,
249
+ SIGNAL('customContextMenuRequested(const QPoint&)'),
250
+ self,
251
+ SLOT('context_menu(const QPoint&)'))
252
+
253
+ return script
254
+ end
255
+
256
+ def stop_message_log
257
+ @message_log.stop if @message_log
258
+ @message_log = nil
259
+ end
260
+
261
+ def filename=(filename)
262
+ # Stop the message log so a new one will be created with the new filename
263
+ stop_message_log()
264
+ @filename = filename
265
+ mark_breakpoints(filename)
266
+ end
267
+
268
+ def modified
269
+ @script.document.isModified()
270
+ end
271
+
272
+ def modified=(bool)
273
+ @script.document.setModified(bool)
274
+ end
275
+
276
+ def undo_available(bool)
277
+ emit undoAvailable(bool)
278
+ end
279
+
280
+ def key_press_callback=(callback)
281
+ @script.keyPressCallback = callback
282
+ end
283
+
284
+ def setFocus
285
+ @script.setFocus
286
+ end
287
+
288
+ def allow_start=(value)
289
+ @allow_start = value
290
+ if @allow_start
291
+ @realtime_button_bar.start_button.setEnabled(true)
292
+ elsif not running?
293
+ @realtime_button_bar.start_button.setEnabled(false)
294
+ @script.setReadOnly(true)
295
+ end
296
+ end
297
+
298
+ def clear
299
+ self.set_text('')
300
+ self.filename = ''
301
+ self.modified = false
302
+ end
303
+
304
+ def self.instance
305
+ @@instance
306
+ end
307
+
308
+ def self.instance=(value)
309
+ @@instance = value
310
+ end
311
+
312
+ def self.step_mode
313
+ @@step_mode
314
+ end
315
+
316
+ def self.step_mode=(value)
317
+ @@step_mode = value
318
+ if self.instance
319
+ if value
320
+ self.instance.pause
321
+ else
322
+ self.instance.go
323
+ end
324
+ end
325
+ end
326
+
327
+ def self.line_delay
328
+ @@line_delay
329
+ end
330
+
331
+ def self.line_delay=(value)
332
+ @@line_delay = value
333
+ end
334
+
335
+ def self.instrumented_cache
336
+ @@instrumented_cache
337
+ end
338
+
339
+ def self.instrumented_cache=(value)
340
+ @@instrumented_cache = value
341
+ end
342
+
343
+ def self.pause_on_error
344
+ @@pause_on_error
345
+ end
346
+
347
+ def self.pause_on_error=(value)
348
+ @@pause_on_error = value
349
+ end
350
+
351
+ def self.monitor_limits
352
+ @@monitor_limits
353
+ end
354
+
355
+ def self.monitor_limits=(value)
356
+ @@monitor_limits = value
357
+ end
358
+
359
+ def self.pause_on_red
360
+ @@pause_on_red
361
+ end
362
+
363
+ def self.pause_on_red=(value)
364
+ @@pause_on_red = value
365
+ end
366
+
367
+ def self.show_backtrace
368
+ @@show_backtrace
369
+ end
370
+
371
+ def self.show_backtrace=(value)
372
+ @@show_backtrace = value
373
+ if @@show_backtrace and @@error
374
+ puts Time.now.formatted + " (SCRIPTRUNNER): " + "Most recent exception:\n" + @@error.formatted
375
+ end
376
+ end
377
+
378
+ def text
379
+ @script.toPlainText.gsub("\r", '')
380
+ end
381
+
382
+ def set_text(text, filename = '')
383
+ unless running?()
384
+ @script.setPlainText(text)
385
+ @script.stop_highlight
386
+ @filename = filename
387
+ mark_breakpoints(filename)
388
+ end
389
+ end
390
+
391
+ def set_text_from_file(filename)
392
+ unless running?()
393
+ @@file_cache[filename] = nil
394
+ load_file_into_script(filename)
395
+ @filename = filename
396
+ end
397
+ end
398
+
399
+ def self.running?
400
+ if @@run_thread then true else false end
401
+ end
402
+
403
+ def running?
404
+ if @@instance == self and ScriptRunnerFrame.running?() then true else false end
405
+ end
406
+
407
+ def go
408
+ @go = true
409
+ @pause = false unless @@step_mode
410
+ end
411
+
412
+ def go?
413
+ temp = @go
414
+ @go = false
415
+ temp
416
+ end
417
+
418
+ def pause
419
+ @pause = true
420
+ @go = false
421
+ end
422
+
423
+ def pause?
424
+ @pause
425
+ end
426
+
427
+ def self.stop!
428
+ if @@run_thread
429
+ Cosmos.kill_thread(nil, @@run_thread)
430
+ @@run_thread = nil
431
+ end
432
+ end
433
+
434
+ def stop?
435
+ @stop
436
+ end
437
+
438
+ def retry_needed?
439
+ @retry_needed
440
+ end
441
+
442
+ def retry_needed
443
+ @retry_needed = true
444
+ end
445
+
446
+ def disable_retry
447
+ @realtime_button_bar.start_button.setText('Skip')
448
+ @realtime_button_bar.pause_button.setDisabled(true)
449
+ end
450
+
451
+ def enable_retry
452
+ @realtime_button_bar.start_button.setText('Go')
453
+ @realtime_button_bar.pause_button.setDisabled(false)
454
+ end
455
+
456
+ def run
457
+ unless self.class.running?()
458
+ run_text(@script.toPlainText)
459
+ end
460
+ end
461
+
462
+ def run_and_close_on_complete(text_binding = nil)
463
+ run_text(@script.toPlainText, 0, text_binding, true)
464
+ end
465
+
466
+ def self.instrument_script(text, filename, mark_private = false)
467
+ if filename and !filename.empty?
468
+ @@file_cache[filename] = text.clone
469
+ end
470
+
471
+ ruby_lex_utils = RubyLexUtils.new
472
+ instrumented_text = ''
473
+
474
+ Qt.execute_in_main_thread(true) do
475
+ window = Qt::CoreApplication.instance.activeWindow
476
+ @cancel_instrumentation = false
477
+ ProgressDialog.execute(window, # parent
478
+ "Instrumenting: #{File.basename(filename.to_s)}",
479
+ 500, # width
480
+ 100, # height
481
+ true, # show overall progress
482
+ false, # don't show step progress
483
+ false, # don't show text
484
+ false, # don't show done
485
+ true) do |progress_dialog| # show cancel
486
+ progress_dialog.cancel_callback = lambda {|dialog| @cancel_instrumentation = true; [true, false]}
487
+ progress_dialog.enable_cancel_button
488
+ comments_removed_text = ruby_lex_utils.remove_comments(text)
489
+ num_lines = comments_removed_text.num_lines.to_f
490
+ num_lines = 1 if num_lines < 1
491
+ instrumented_text =
492
+ instrument_script_implementation(ruby_lex_utils,
493
+ comments_removed_text,
494
+ num_lines,
495
+ progress_dialog,
496
+ filename,
497
+ mark_private)
498
+ progress_dialog.close_done
499
+ end
500
+ end
501
+
502
+ Kernel.raise StopScript if @cancel_instrumentation or ProgressDialog.canceled?
503
+ instrumented_text
504
+ end
505
+
506
+ def self.instrument_script_implementation(ruby_lex_utils,
507
+ comments_removed_text,
508
+ num_lines,
509
+ progress_dialog,
510
+ filename,
511
+ mark_private = false)
512
+ if mark_private
513
+ instrumented_text = 'private; '
514
+ else
515
+ instrumented_text = ''
516
+ end
517
+
518
+ ruby_lex_utils.each_lexed_segment(comments_removed_text) do |segment, instrumentable, inside_begin, line_no|
519
+ return nil if @cancel_instrumentation
520
+ instrumented_line = ''
521
+ if instrumentable
522
+ # If not inside a begin block then create one to catch exceptions
523
+ unless inside_begin
524
+ instrumented_line << 'begin; '
525
+ end
526
+
527
+ # Add preline instrumentation
528
+ instrumented_line << "ScriptRunnerFrame.instance.script_binding = binding(); if ScriptRunnerFrame.instance.inline_return then ScriptRunnerFrame.instance.inline_return = nil; return ScriptRunnerFrame.instance.inline_return_params; end; ScriptRunnerFrame.instance.pre_line_instrumentation('#{filename}', #{line_no}); "
529
+
530
+ # Add the actual line
531
+ instrumented_line << segment
532
+ instrumented_line.chomp!
533
+
534
+ # Add postline instrumentation
535
+ instrumented_line << "; ScriptRunnerFrame.instance.post_line_instrumentation('#{filename}', #{line_no})"
536
+
537
+ # Complete begin block to catch exceptions
538
+ unless inside_begin
539
+ instrumented_line << "; rescue Exception => eval_error; retry if ScriptRunnerFrame.instance.exception_instrumentation(eval_error, '#{filename}', #{line_no}); end"
540
+ end
541
+
542
+ instrumented_line << "\n"
543
+ else
544
+ unless segment =~ /^\s*end\s*$/ or segment =~ /^\s*when .*$/
545
+ num_left_brackets = segment.count('{')
546
+ num_right_brackets = segment.count('}')
547
+ num_left_square_brackets = segment.count('[')
548
+ num_right_square_brackets = segment.count(']')
549
+
550
+ if (num_right_brackets > num_left_brackets) ||
551
+ (num_right_square_brackets > num_left_square_brackets)
552
+ instrumented_line = segment
553
+ else
554
+ instrumented_line = "ScriptRunnerFrame.instance.pre_line_instrumentation('#{filename}', #{line_no}); " + segment
555
+ end
556
+ else
557
+ instrumented_line = segment
558
+ end
559
+ end
560
+
561
+ instrumented_text << instrumented_line
562
+
563
+ progress_dialog.set_overall_progress(line_no / num_lines) if progress_dialog and line_no
564
+ end
565
+ instrumented_text
566
+ end
567
+
568
+ def pre_line_instrumentation(filename, line_number)
569
+ @current_filename = filename
570
+ @current_line_number = line_number
571
+ if @use_instrumentation
572
+ # Clear go
573
+ @go = false
574
+
575
+ # Handle stopping mid-script if necessary
576
+ Kernel.raise StopScript if @stop
577
+
578
+ # Handle needing to change tabs
579
+ handle_potential_tab_change(filename)
580
+
581
+ # Adjust line number for offset in main script
582
+ line_number = line_number + @line_offset if @active_script.object_id == @script.object_id
583
+ detail_string = nil
584
+ if filename
585
+ detail_string = File.basename(filename) << ':' << line_number.to_s
586
+ end
587
+ Logger.detail_string = detail_string
588
+
589
+ # Highlight the line that is about to run
590
+ Qt.execute_in_main_thread(true) {@active_script.highlight_line(line_number)}
591
+
592
+ # Handle pausing the script
593
+ handle_pause(filename, line_number)
594
+
595
+ # Handle delay between lines
596
+ handle_line_delay()
597
+ end
598
+ end
599
+
600
+ def post_line_instrumentation(filename, line_number)
601
+ if @use_instrumentation
602
+ line_number = line_number + @line_offset if @active_script.object_id == @script.object_id
603
+ handle_output_io(filename, line_number)
604
+ end
605
+ end
606
+
607
+ def exception_instrumentation(error, filename, line_number)
608
+ if error.class == StopScript || error.class == SkipTestCase || !@use_instrumentation
609
+ Kernel.raise error
610
+ else
611
+ line_number = line_number + @line_offset if @active_script.object_id == @script.object_id
612
+ handle_exception(error, false, filename, line_number)
613
+ end
614
+ end
615
+
616
+ def perform_pause
617
+ mark_paused()
618
+ wait_for_go_or_stop()
619
+ end
620
+
621
+ def perform_breakpoint(filename, line_number)
622
+ mark_breakpoint()
623
+ scriptrunner_puts "Hit Breakpoint at #{filename}:#{line_number}"
624
+ handle_output_io(filename, line_number)
625
+ wait_for_go_or_stop()
626
+ end
627
+
628
+ # Prompts the user that a script is running before they close the app
629
+ def prompt_if_running_on_close
630
+ safe_to_continue = true
631
+ if running?
632
+ case Qt::MessageBox.warning(
633
+ self, # parent
634
+ 'Warning', # title
635
+ 'A Script is Running! Close Anyways?', # text
636
+ Qt::MessageBox::Yes | Qt::MessageBox::No, # buttons
637
+ Qt::MessageBox::No) # default button
638
+ when Qt::MessageBox::Yes
639
+ safe_to_continue = true
640
+ ScriptRunnerFrame.stop!
641
+ else
642
+ safe_to_continue = false
643
+ end
644
+ end
645
+ return safe_to_continue
646
+ end
647
+
648
+ ######################################
649
+ # Implement the breakpoint callbacks from the RubyEditor
650
+ ######################################
651
+ def breakpoint_set(line)
652
+ ScriptRunnerFrame.set_breakpoint(current_tab_filename(), line)
653
+ end
654
+
655
+ def breakpoint_cleared(line)
656
+ ScriptRunnerFrame.clear_breakpoint(current_tab_filename(), line)
657
+ end
658
+
659
+ def breakpoints_cleared
660
+ ScriptRunnerFrame.clear_breakpoints(current_tab_filename())
661
+ end
662
+
663
+ ######################################
664
+ # Implement edit functionality in the frame (cut, copy, paste, etc)
665
+ ######################################
666
+ def undo
667
+ @script.undo unless running?()
668
+ end
669
+
670
+ def redo
671
+ @script.redo unless running?()
672
+ end
673
+
674
+ def cut
675
+ @script.cut unless running?()
676
+ end
677
+
678
+ def copy
679
+ @script.copy unless running?()
680
+ end
681
+
682
+ def paste
683
+ @script.paste unless running?()
684
+ end
685
+
686
+ def select_all
687
+ @script.select_all unless running?()
688
+ end
689
+
690
+ def comment_or_uncomment_lines
691
+ @script.comment_or_uncomment_lines unless running?()
692
+ end
693
+
694
+ ##################################################################################
695
+ # Implement Script functionality in the frame (run selection, run from cursor, etc
696
+ ##################################################################################
697
+ def run_selection
698
+ unless self.class.running?()
699
+ selection = @script.selected_lines
700
+ if selection
701
+ start_line_number = @script.selection_start_line
702
+ end_line_number = @script.selection_end_line
703
+ scriptrunner_puts "Running script lines #{start_line_number+1}-#{end_line_number+1}: #{File.basename(@filename)}"
704
+ handle_output_io()
705
+ run_text(selection, start_line_number)
706
+ end
707
+ end
708
+ end
709
+
710
+ def run_selection_while_paused
711
+ current_script = @tab_book.tab(@tab_book.currentIndex)
712
+ selection = current_script.selected_lines
713
+ if selection
714
+ start_line_number = current_script.selection_start_line
715
+ end_line_number = current_script.selection_end_line
716
+ scriptrunner_puts "Debug: Running selected lines #{start_line_number+1}-#{end_line_number+1}: #{@tab_book.tabText(@tab_book.currentIndex)}"
717
+ handle_output_io()
718
+ dialog = ScriptRunnerDialog.new(self, 'Executing Selected Lines While Paused')
719
+ dialog.execute_text_and_close_on_complete(selection, @script_binding)
720
+ handle_output_io()
721
+ end
722
+ end
723
+
724
+ def run_from_cursor
725
+ unless self.class.running?()
726
+ line_number = @script.selection_start_line
727
+ text = @script.toPlainText.split("\n")[line_number..-1].join("\n")
728
+ scriptrunner_puts "Running script from line #{line_number}: #{File.basename(@filename)}"
729
+ handle_output_io()
730
+ run_text(text, line_number)
731
+ end
732
+ end
733
+
734
+ def ruby_syntax_check_selection
735
+ unless self.class.running?()
736
+ selection = @script.selected_lines
737
+ ruby_syntax_check_text(selection) if selection
738
+ end
739
+ end
740
+
741
+ def ruby_syntax_check_text(selection = nil)
742
+ unless self.class.running?()
743
+ selection = text() unless selection
744
+ check_process = IO.popen("ruby -c -rubygems 2>&1", 'r+')
745
+ check_process.write("require 'cosmos'; require 'cosmos/script'; " + selection)
746
+ check_process.close_write
747
+ results = check_process.gets
748
+ check_process.close
749
+ if results
750
+ if results =~ /Syntax OK/
751
+ Qt::MessageBox.information(self, 'Syntax Check Successful', results)
752
+ else
753
+ # Results is a string like this: ":2: syntax error ..."
754
+ # Normally the procedure comes before the first colon but since we
755
+ # are writing to the process this is blank so we throw it away
756
+ _, line_no, error = results.split(':')
757
+ Qt::MessageBox.warning(self,
758
+ 'Syntax Check Failed',
759
+ "Error on line #{line_no}: #{error.strip}")
760
+ end
761
+ else
762
+ Qt::MessageBox.critical(self,
763
+ 'Syntax Check Exception',
764
+ 'Ruby syntax check unexpectedly returned nil')
765
+ end
766
+ end
767
+ end
768
+
769
+ def mnemonic_check_selection
770
+ unless self.class.running?()
771
+ selection = @script.selected_lines
772
+ mnemonic_check_text(selection, @script.selection_start_line+1) if selection
773
+ end
774
+ end
775
+
776
+ def mnemonic_check_text(text, start_line_number = 1)
777
+ results = []
778
+ line_number = start_line_number
779
+ text.each_line do |line|
780
+ if line =~ /\(/
781
+ result = nil
782
+ keyword = line.split('(')[0].split[-1]
783
+ if CMD_KEYWORDS.include? keyword
784
+ result = mnemonic_check_cmd_line(keyword, line_number, line)
785
+ elsif TLM_KEYWORDS.include? keyword
786
+ result = mnemonic_check_tlm_line(keyword, line_number, line)
787
+ elsif SET_TLM_KEYWORDS.include? keyword
788
+ result = mnemonic_check_set_tlm_line(keyword, line_number, line)
789
+ elsif CHECK_KEYWORDS.include? keyword
790
+ result = mnemonic_check_check_line(keyword, line_number, line)
791
+ end
792
+ results << result if result
793
+ end
794
+ line_number += 1
795
+ end
796
+
797
+ if results.empty?
798
+ Qt::MessageBox.information(self,
799
+ 'Mnemonic Check Successful',
800
+ 'Mnemonic Check Found No Errors')
801
+ else
802
+ dialog = Qt::Dialog.new(self) do |box|
803
+ box.setWindowTitle('Mnemonic Check Failed')
804
+ text = Qt::PlainTextEdit.new
805
+ text.setReadOnly(true)
806
+ text.setPlainText(results.join("\n"))
807
+ frame = Qt::VBoxLayout.new(box)
808
+ ok = Qt::PushButton.new('Ok')
809
+ ok.setDefault(true)
810
+ ok.connect(SIGNAL('clicked(bool)')) { box.accept }
811
+ frame.addWidget(text)
812
+ frame.addWidget(ok)
813
+ end
814
+ dialog.exec
815
+ dialog.dispose
816
+ end
817
+ end
818
+
819
+ ######################################################
820
+ # Implement the debug capability
821
+ ######################################################
822
+ def toggle_debug(debug = nil)
823
+ if debug.nil?
824
+ if @debug_frame
825
+ hide_debug()
826
+ else
827
+ show_debug()
828
+ end
829
+ else
830
+ if debug
831
+ if !@debug_frame
832
+ show_debug()
833
+ end
834
+ else
835
+ if @debug_frame
836
+ hide_debug()
837
+ end
838
+ end
839
+ end
840
+ end
841
+
842
+ def show_debug
843
+ unless @debug_frame
844
+ @script.enable_breakpoints = true
845
+ if @tab_book_shown
846
+ if @tab_book.count > 0
847
+ (0..(@tab_book.count - 1)).each do |index|
848
+ @tab_book.tab(index).enable_breakpoints = true
849
+ end
850
+ end
851
+ end
852
+
853
+ @debug_frame = Qt::HBoxLayout.new
854
+ @debug_frame.setContentsMargins(0,0,0,0)
855
+ @debug_frame_label = Qt::Label.new("Debug:")
856
+ @debug_frame.addWidget(@debug_frame_label)
857
+ @debug_text = CompletionLineEdit.new(self)
858
+ @debug_text.setFocus(Qt::OtherFocusReason)
859
+ @debug_text.keyPressCallback = lambda { |event|
860
+ case event.key
861
+ when Qt::Key_Return, Qt::Key_Enter
862
+ begin
863
+ debug_text = @debug_text.toPlainText
864
+ @debug_history.unshift(debug_text)
865
+ @debug_history_index = 0
866
+ @debug_text.setPlainText('')
867
+ scriptrunner_puts "Debug: #{debug_text}"
868
+ handle_output_io()
869
+ if not running?
870
+ # Capture STDOUT and STDERR
871
+ $stdout.add_stream(@output_io)
872
+ $stderr.add_stream(@output_io)
873
+ end
874
+
875
+ if @script_binding
876
+ eval(debug_text, @script_binding, 'debug', 1)
877
+ else
878
+ Object.class_eval(debug_text, 'debug', 1)
879
+ end
880
+ handle_output_io()
881
+ rescue Exception => error
882
+ if error.class == DRb::DRbConnError
883
+ Logger.error("Error Connecting to Command and Telemetry Server")
884
+ else
885
+ Logger.error(error.class.to_s.split('::')[-1] + ' : ' + error.message)
886
+ end
887
+ handle_output_io()
888
+ ensure
889
+ if not running?
890
+ # Capture STDOUT and STDERR
891
+ $stdout.remove_stream(@output_io)
892
+ $stderr.remove_stream(@output_io)
893
+ end
894
+ end
895
+ when Qt::Key_Up
896
+ if @debug_history.length > 0
897
+ @debug_text.setPlainText(@debug_history[@debug_history_index])
898
+ @debug_history_index += 1
899
+ if @debug_history_index == @debug_history.length
900
+ @debug_history_index = @debug_history.length-1
901
+ end
902
+ end
903
+ when Qt::Key_Down
904
+ if @debug_history.length > 0
905
+ @debug_text.setPlainText(@debug_history[@debug_history_index])
906
+ @debug_history_index -= 1
907
+ @debug_history_index = 0 if @debug_history_index < 0
908
+ end
909
+ when Qt::Key_Escape
910
+ @debug_text.setPlainText("")
911
+ end
912
+ }
913
+
914
+ @debug_frame.addWidget(@debug_text)
915
+
916
+ @toggle_button = Qt::PushButton.new('Toggle Run/Step')
917
+ @debug_frame.addWidget(@toggle_button)
918
+ @toggle_button.connect(SIGNAL('clicked(bool)')) do
919
+ if @@step_mode
920
+ scriptrunner_puts "Debug: run_mode"
921
+ handle_output_io()
922
+ self.class.step_mode = false
923
+ else
924
+ scriptrunner_puts "Debug: step_mode"
925
+ handle_output_io()
926
+ self.class.step_mode = true
927
+ end
928
+ end
929
+
930
+ @return_button = Qt::PushButton.new('Insert Return')
931
+ @debug_frame.addWidget(@return_button)
932
+ @return_button.connect(SIGNAL('clicked(bool)')) do
933
+ scriptrunner_puts "Debug: insert_return(); ScriptRunnerFrame.instance.go()"
934
+ handle_output_io()
935
+ insert_return()
936
+ go()
937
+ end
938
+
939
+ @bottom_frame.layout.addLayout(@debug_frame)
940
+ end
941
+ end
942
+
943
+ def hide_debug
944
+ # Since we're disabling debug, clear the breakpoints and disable them
945
+ ScriptRunnerFrame.clear_breakpoints()
946
+ @script.clear_breakpoints
947
+ @script.enable_breakpoints = false
948
+ if @tab_book_shown
949
+ if @tab_book.count > 0
950
+ (0..(@tab_book.count - 1)).each do |index|
951
+ @tab_book.tab(index).enable_breakpoints = false
952
+ end
953
+ end
954
+ end
955
+ # Remove the debug frame
956
+ @bottom_frame.layout.takeAt(@bottom_frame.layout.count - 1) if @debug_frame
957
+ @debug_frame.removeAll
958
+ @debug_frame.dispose
959
+ @debug_frame = nil
960
+ end
961
+
962
+ def self.set_breakpoint(filename, line_number)
963
+ filename = File.basename(filename)
964
+ @@breakpoints[filename] ||= {}
965
+ @@breakpoints[filename][line_number] = true
966
+ end
967
+
968
+ def self.clear_breakpoint(filename, line_number)
969
+ filename = File.basename(filename)
970
+ @@breakpoints[filename] ||= {}
971
+ @@breakpoints[filename].delete(line_number) if @@breakpoints[filename][line_number]
972
+ end
973
+
974
+ def self.clear_breakpoints(filename = nil)
975
+ filename = File.basename(filename) unless filename.nil?
976
+ if filename == nil or filename.empty?
977
+ @@breakpoints = {}
978
+ else
979
+ @@breakpoints[filename] = {}
980
+ end
981
+ end
982
+
983
+ def select_tab_and_destroy_tabs_after_index(index)
984
+ Qt.execute_in_main_thread(true) do
985
+ if @tab_book_shown
986
+ @tab_book.setCurrentIndex(index)
987
+ @active_script = @tab_book.tab(@tab_book.currentIndex)
988
+
989
+ first_to_remove = index + 1
990
+ last_to_remove = @call_stack.length - 1
991
+
992
+ last_to_remove.downto(first_to_remove) do |tab_index|
993
+ tab = @tab_book.tab(tab_index)
994
+ @tab_book.removeTab(tab_index)
995
+ tab.dispose
996
+ end
997
+
998
+ @call_stack = @call_stack[0..index]
999
+ @current_file = @call_stack[index]
1000
+ end
1001
+ end
1002
+ end
1003
+
1004
+ def toggle_disconnect(config_file)
1005
+ if get_cmd_tlm_disconnect
1006
+ set_cmd_tlm_disconnect(false)
1007
+ self.parent.setPalette(Cosmos::DEFAULT_PALETTE)
1008
+ else
1009
+ dialog = Qt::Dialog.new(self, Qt::WindowTitleHint | Qt::WindowSystemMenuHint)
1010
+ dialog.setWindowTitle(tr("Server Config File"))
1011
+ dialog_layout = Qt::VBoxLayout.new
1012
+
1013
+ chooser = FileChooser.new(self, "Config File", config_file, 'Select',
1014
+ File.join('config', 'tools', 'cmd_tlm_server', config_file))
1015
+ chooser.callback = lambda do |filename|
1016
+ chooser.filename = File.basename(filename)
1017
+ end
1018
+ dialog_layout.addWidget(chooser)
1019
+
1020
+ button_layout = Qt::HBoxLayout.new
1021
+ ok = Qt::PushButton.new("Ok")
1022
+ ok.setDefault(true)
1023
+ ok.connect(SIGNAL('clicked()')) do
1024
+ dialog.accept()
1025
+ end
1026
+ button_layout.addWidget(ok)
1027
+ cancel = Qt::PushButton.new("Cancel")
1028
+ cancel.connect(SIGNAL('clicked()')) do
1029
+ dialog.reject()
1030
+ end
1031
+ button_layout.addWidget(cancel)
1032
+ dialog_layout.addLayout(button_layout)
1033
+
1034
+ dialog.setLayout(dialog_layout)
1035
+ if dialog.exec == Qt::Dialog::Accepted
1036
+ config_file = chooser.filename
1037
+ self.parent.setPalette(Cosmos::RED_PALETTE)
1038
+ Splash.execute(self) do |splash|
1039
+ ConfigParser.splash = splash
1040
+ splash.message = "Initializing Command and Telemetry Server"
1041
+ set_cmd_tlm_disconnect(true, config_file)
1042
+ ConfigParser.splash = nil
1043
+ end
1044
+ end
1045
+ dialog.dispose
1046
+ end
1047
+ config_file
1048
+ end
1049
+
1050
+ def current_backtrace
1051
+ trace = []
1052
+ Qt.execute_in_main_thread(true) do
1053
+ if @@run_thread
1054
+ temp_trace = @@run_thread.backtrace
1055
+ cosmos_lib = Regexp.new(File.join(Cosmos::PATH, 'lib'))
1056
+ temp_trace.each do |line|
1057
+ next if line =~ cosmos_lib
1058
+ trace << line
1059
+ end
1060
+ end
1061
+ end
1062
+ trace
1063
+ end
1064
+
1065
+ def scriptrunner_puts(string)
1066
+ puts Time.now.formatted + " (SCRIPTRUNNER): " + string
1067
+ end
1068
+
1069
+ def handle_output_io(filename = @current_filename, line_number = @current_line_number)
1070
+ @output_time = Time.now
1071
+ Qt.execute_in_main_thread(true) do
1072
+ if @output_io.string[-1..-1] == "\n"
1073
+ time_formatted = Time.now.formatted
1074
+ lines_to_write = ''
1075
+ out_line_number = line_number.to_s
1076
+ out_filename = File.basename(filename) if filename
1077
+
1078
+ # Build each line to write
1079
+ string = @output_io.string.clone
1080
+ @output_io.string = @output_io.string[string.length..-1]
1081
+ line_count = 0
1082
+ string.each_line do |out_line|
1083
+ color = nil
1084
+ if out_line[0..1] == '20' and out_line[10] == ' ' and out_line[23..24] == ' ('
1085
+ line_to_write = out_line
1086
+ else
1087
+ if filename
1088
+ line_to_write = time_formatted + " (#{out_filename}:#{out_line_number}): " + out_line
1089
+ else
1090
+ line_to_write = time_formatted + " (SCRIPTRUNNER): " + out_line
1091
+ color = Cosmos::BLUE
1092
+ end
1093
+ end
1094
+ @output.add_formatted_text(line_to_write, color)
1095
+ lines_to_write << line_to_write
1096
+
1097
+ line_count += 1
1098
+ if line_count > @stdout_max_lines
1099
+ out_line = "ERROR: Too much written to stdout. Truncating output to #{@stdout_max_lines} lines.\n"
1100
+ if filename
1101
+ line_to_write = time_formatted + " (#{out_filename}:#{out_line_number}): " + out_line
1102
+ else
1103
+ line_to_write = time_formatted + " (SCRIPTRUNNER): " + out_line
1104
+ end
1105
+ @output.addText(line_to_write, Cosmos::RED)
1106
+ lines_to_write << line_to_write
1107
+ break
1108
+ end
1109
+ end # string.each_line
1110
+
1111
+ # Actually add to the GUI
1112
+ @output.flush
1113
+
1114
+ # Add to the message log
1115
+ if @filename.empty?
1116
+ @message_log ||= MessageLog.new("sr_untitled")
1117
+ else
1118
+ @message_log ||= MessageLog.new("sr_#{File.basename(@filename).split('.')[0]}")
1119
+ end
1120
+ @message_log.write(lines_to_write)
1121
+ end
1122
+ end
1123
+ end
1124
+
1125
+ def graceful_kill
1126
+ # Just to avoid warning
1127
+ end
1128
+
1129
+ protected
1130
+
1131
+ def initialize_variables
1132
+ @@file_cache = {}
1133
+ @@error = nil
1134
+ @go = false
1135
+ if @@step_mode
1136
+ @pause = true
1137
+ else
1138
+ @pause = false
1139
+ end
1140
+ @stop = false
1141
+ @retry_needed = false
1142
+ @use_instrumentation = true
1143
+ @active_script = @script
1144
+ @call_stack = []
1145
+ @pre_line_time = Time.now
1146
+ @current_file = @filename
1147
+ @exceptions = nil
1148
+ @script_binding = nil
1149
+ @inline_eval = nil
1150
+ @current_filename = nil
1151
+ @current_line_number = 0
1152
+ @stdout_max_lines = 1000
1153
+
1154
+ @script.stop_highlight
1155
+ @call_stack.push(@current_file.dup)
1156
+ end
1157
+
1158
+ def wait_for_go_or_stop(error = nil)
1159
+ @go = false
1160
+ sleep(0.01) until @go or @stop
1161
+ @go = false
1162
+ mark_running()
1163
+ Kernel.raise StopScript if @stop
1164
+ Kernel.raise error if error and !@continue_after_error
1165
+ end
1166
+
1167
+ def wait_for_go_or_stop_or_retry(error = nil)
1168
+ @go = false
1169
+ sleep(0.01) until @go or @stop or @retry_needed
1170
+ @go = false
1171
+ mark_running()
1172
+ Kernel.raise StopScript if @stop
1173
+ Kernel.raise error if error and !@continue_after_error
1174
+ end
1175
+
1176
+ def mark_running
1177
+ Qt.execute_in_main_thread(true) do
1178
+ @run_callback.call(self) if @run_callback
1179
+ @active_script.rehighlight
1180
+ @realtime_button_bar.state = 'Running'
1181
+ @realtime_button_bar.start_button.setText('Go')
1182
+ @realtime_button_bar.pause_button.setText('Pause')
1183
+ end
1184
+ end
1185
+
1186
+ def mark_paused
1187
+ Qt.execute_in_main_thread(true) do
1188
+ @pause_callback.call(self) if @pause_callback
1189
+ @active_script.rehighlight('lightblue')
1190
+ @realtime_button_bar.state = 'Paused'
1191
+ end
1192
+ end
1193
+
1194
+ def mark_error
1195
+ Qt.execute_in_main_thread(true) do
1196
+ @error_callback.call(self) if @error_callback
1197
+ @active_script.rehighlight('pink')
1198
+ @realtime_button_bar.state = 'Error'
1199
+ @realtime_button_bar.pause_button.setText('Retry')
1200
+ end
1201
+ end
1202
+
1203
+ def mark_stopped
1204
+ stop_message_log()
1205
+ Qt.execute_in_main_thread(true) do
1206
+ @realtime_button_bar.start_button.setText('Start')
1207
+ @realtime_button_bar.pause_button.setText('Pause')
1208
+ @realtime_button_bar.state = 'Stopped'
1209
+ @stop_callback.call(self) if @stop_callback
1210
+ end
1211
+ end
1212
+
1213
+ def mark_breakpoint
1214
+ Qt.execute_in_main_thread(true) do
1215
+ @active_script.rehighlight('tan')
1216
+ @realtime_button_bar.state = 'Breakpoint'
1217
+ end
1218
+ end
1219
+
1220
+ def run_text(text,
1221
+ line_offset = 0,
1222
+ text_binding = nil,
1223
+ close_on_complete = false)
1224
+ @run_callback.call(self) if @run_callback
1225
+ @realtime_button_bar.start_button.setEnabled(true)
1226
+ initialize_variables()
1227
+ create_tabs()
1228
+ @line_offset = line_offset
1229
+ @script.setReadOnly(true)
1230
+ @realtime_button_bar.start_button.setText(' Go ')
1231
+ @realtime_button_bar.state = 'Running'
1232
+
1233
+ saved_instance = @@instance
1234
+ saved_run_thread = @@run_thread
1235
+ @@instance = self
1236
+ @@run_thread = Thread.new do
1237
+ uncaught_exception = false
1238
+ begin
1239
+ # Capture STDOUT and STDERR
1240
+ $stdout.add_stream(@output_io)
1241
+ $stderr.add_stream(@output_io)
1242
+
1243
+ scriptrunner_puts "Starting script: #{File.basename(@filename)}" unless close_on_complete
1244
+ handle_output_io()
1245
+
1246
+ # Start Limits Monitoring
1247
+ @@limits_monitor_thread = Thread.new { limits_monitor_thread() } if @@monitor_limits and !@@limits_monitor_thread
1248
+
1249
+ # Start Output Thread
1250
+ @@output_thread = Thread.new { output_thread() } unless @@output_thread
1251
+
1252
+ # Check top level cache
1253
+ if @top_level_instrumented_cache &&
1254
+ (@top_level_instrumented_cache[1] == line_offset) &&
1255
+ (@top_level_instrumented_cache[2] == @filename) &&
1256
+ (@top_level_instrumented_cache[0] == text)
1257
+ # Use the instrumented cache
1258
+ instrumented_script = @top_level_instrumented_cache[3]
1259
+ else
1260
+ # Instrument the script
1261
+ if text_binding
1262
+ instrumented_script = self.class.instrument_script(text, @filename, false)
1263
+ else
1264
+ instrumented_script = self.class.instrument_script(text, @filename, true)
1265
+ end
1266
+ @top_level_instrumented_cache = [text, line_offset, @filename, instrumented_script]
1267
+ end
1268
+
1269
+ # Execute the script with warnings disabled
1270
+ Cosmos.disable_warnings do
1271
+ @pre_line_time = Time.now
1272
+ Cosmos.set_working_dir do
1273
+ if text_binding
1274
+ eval(instrumented_script, text_binding, @filename, 1)
1275
+ else
1276
+ Object.class_eval(instrumented_script, @filename, 1)
1277
+ end
1278
+ end
1279
+ end
1280
+
1281
+ scriptrunner_puts "Script completed: #{File.basename(@filename)}" unless close_on_complete
1282
+ handle_output_io()
1283
+
1284
+ rescue Exception => error
1285
+ if error.class == StopScript or error.class == SkipTestCase
1286
+ scriptrunner_puts "Script stopped: #{File.basename(@filename)}"
1287
+ handle_output_io()
1288
+ else
1289
+ uncaught_exception = true
1290
+ filename, line_number = error.source
1291
+ handle_exception(error, true, filename, line_number)
1292
+ scriptrunner_puts "Exception in Control Statement - Script stopped: #{File.basename(@filename)}"
1293
+ handle_output_io()
1294
+ Qt.execute_in_main_thread(true) {@script.rehighlight('red') }
1295
+ end
1296
+ ensure
1297
+ # Change Go Button to Start Button and remove highlight
1298
+ Qt.execute_in_main_thread(true) do
1299
+ # Stop Capturing STDOUT and STDERR
1300
+ # Check for remove_stream because if the tool is quitting the
1301
+ # Cosmos::restore_io may have been called which sets $stdout and
1302
+ # $stderr to the IO constant
1303
+ $stdout.remove_stream(@output_io) if $stdout.respond_to? :remove_stream
1304
+ $stderr.remove_stream(@output_io) if $stderr.respond_to? :remove_stream
1305
+
1306
+ # Clear run thread and instance to indicate we are no longer running
1307
+ @@instance = saved_instance
1308
+ @@run_thread = saved_run_thread
1309
+ @active_script = @script
1310
+ @script_binding = nil
1311
+ @current_filename = nil
1312
+ @current_line_number = 0
1313
+ if @@limits_monitor_thread and not @@instance
1314
+ @@cancel_limits = true
1315
+ @@limits_sleeper.cancel
1316
+ Qt::CoreApplication.processEvents()
1317
+ Cosmos.kill_thread(self, @@limits_monitor_thread)
1318
+ @@limits_monitor_thread = nil
1319
+ end
1320
+ if @@output_thread and not @@instance
1321
+ @@cancel_output = true
1322
+ @@output_sleeper.cancel
1323
+ Qt::CoreApplication.processEvents()
1324
+ Cosmos.kill_thread(self, @@output_thread)
1325
+ @@output_thread = nil
1326
+ end
1327
+
1328
+ @script.setReadOnly(false)
1329
+ @script.stop_highlight unless uncaught_exception
1330
+ select_tab_and_destroy_tabs_after_index(0)
1331
+ remove_tabs()
1332
+ unless @allow_start
1333
+ @realtime_button_bar.start_button.setEnabled(false)
1334
+ @script.setReadOnly(true)
1335
+ end
1336
+ mark_stopped()
1337
+ if close_on_complete
1338
+ self.parent.done(0)
1339
+ end
1340
+ end
1341
+ end
1342
+ end
1343
+ end
1344
+
1345
+ def handle_potential_tab_change(filename)
1346
+ # Make sure the correct file is shown in script runner
1347
+ if @current_file != filename and @tab_book_shown
1348
+ Qt.execute_in_main_thread(true) do
1349
+ if @call_stack.include?(filename)
1350
+ index = @call_stack.index(filename)
1351
+ select_tab_and_destroy_tabs_after_index(index)
1352
+ else # new file
1353
+ # Create new tab
1354
+ new_script = create_ruby_editor()
1355
+ @tab_book.addTab(new_script, ' ' + File.basename(filename) + ' ')
1356
+
1357
+ @call_stack.push(filename.dup)
1358
+
1359
+ # Switch to new tab
1360
+ @tab_book.setCurrentIndex(@tab_book.count - 1)
1361
+ @active_script = new_script
1362
+ load_file_into_script(filename)
1363
+ new_script.setReadOnly(true)
1364
+ end
1365
+
1366
+ @current_file = filename
1367
+ end
1368
+ end
1369
+ end
1370
+
1371
+ def show_active_tab
1372
+ @tab_book.setCurrentIndex(@call_stack.length - 1) if @tab_book_shown
1373
+ end
1374
+
1375
+ def handle_pause(filename, line_number)
1376
+ filename = File.basename(filename)
1377
+ breakpoint = false
1378
+ breakpoint = true if @@breakpoints[filename] and @@breakpoints[filename][line_number]
1379
+ if @pause
1380
+ @pause = false unless @@step_mode
1381
+ if breakpoint
1382
+ perform_breakpoint(filename, line_number)
1383
+ else
1384
+ perform_pause()
1385
+ end
1386
+ else
1387
+ perform_breakpoint(filename, line_number) if breakpoint
1388
+ end
1389
+ end
1390
+
1391
+ def handle_line_delay
1392
+ if @@line_delay > 0.0
1393
+ sleep_time = @@line_delay - (Time.now - @pre_line_time)
1394
+ sleep(sleep_time) if sleep_time > 0.0
1395
+ end
1396
+ @pre_line_time = Time.now
1397
+ end
1398
+
1399
+ def continue_without_pausing_on_errors?
1400
+ if !@@pause_on_error
1401
+ if Qt::MessageBox.warning(self, "Warning", "If an error occurs, the script will not pause and will run to completion. Continue?", Qt::MessageBox::Yes | Qt::MessageBox::No, Qt::MessageBox::Yes) == Qt::MessageBox::No
1402
+ return false
1403
+ end
1404
+ end
1405
+ true
1406
+ end
1407
+
1408
+ def handle_start_go_button
1409
+ scriptrunner_puts "User pressed #{@realtime_button_bar.start_button.text.strip}"
1410
+ handle_output_io()
1411
+ @realtime_button_bar.start_button.clear_focus()
1412
+
1413
+ if running?()
1414
+ show_active_tab()
1415
+ go()
1416
+ else
1417
+ if @allow_start
1418
+ run() if continue_without_pausing_on_errors?()
1419
+ end
1420
+ end
1421
+ end
1422
+
1423
+ def handle_pause_retry_button
1424
+ scriptrunner_puts "User pressed #{@realtime_button_bar.pause_button.text.strip}"
1425
+ handle_output_io()
1426
+ @realtime_button_bar.pause_button.clear_focus()
1427
+ show_active_tab() if running?
1428
+ if @realtime_button_bar.pause_button.text.to_s == 'Pause'
1429
+ pause()
1430
+ else
1431
+ retry_needed()
1432
+ end
1433
+ end
1434
+
1435
+ def handle_stop_button
1436
+ scriptrunner_puts "User pressed #{@realtime_button_bar.stop_button.text.strip}"
1437
+ handle_output_io()
1438
+ @realtime_button_bar.stop_button.clear_focus()
1439
+
1440
+ if @stop
1441
+ # If we're already stopped and they click Stop again, kill the run
1442
+ # thread. This will break any ruby sleeps or other code blocks.
1443
+ ScriptRunnerFrame.stop!
1444
+ handle_output_io()
1445
+ else
1446
+ @stop = true
1447
+ end
1448
+ if !running?()
1449
+ # Stop highlight if there was a red syntax error
1450
+ @script.stop_highlight
1451
+ end
1452
+ end
1453
+
1454
+ def handle_exception(error, fatal, filename = nil, line_number = 0)
1455
+ @error_callback.call(self) if @error_callback
1456
+
1457
+ @exceptions ||= []
1458
+ @exceptions << error
1459
+ @@error = error
1460
+
1461
+ if error.class == DRb::DRbConnError
1462
+ Logger.error("Error Connecting to Command and Telemetry Server")
1463
+ elsif error.class == CheckError
1464
+ Logger.error(error.message)
1465
+ else
1466
+ Logger.error(error.class.to_s.split('::')[-1] + ' : ' + error.message)
1467
+ end
1468
+ Logger.error(error.backtrace.join("\n")) if @@show_backtrace
1469
+ handle_output_io(filename, line_number)
1470
+
1471
+ Kernel.raise error if !@@pause_on_error and !@continue_after_error and !fatal
1472
+
1473
+ if !fatal and @@pause_on_error
1474
+ mark_error()
1475
+ wait_for_go_or_stop_or_retry(error)
1476
+ end
1477
+
1478
+ if @retry_needed
1479
+ @retry_needed = false
1480
+ true
1481
+ else
1482
+ false
1483
+ end
1484
+ end
1485
+
1486
+ # Right click context_menu for the script
1487
+ def context_menu(point)
1488
+ if @tab_book_shown
1489
+ current_script = @tab_book.tab(@tab_book.currentIndex)
1490
+ else
1491
+ current_script = @script
1492
+ end
1493
+ menu = current_script.context_menu(point)
1494
+ menu.addSeparator()
1495
+ if not self.class.running?
1496
+ exec_selected_action = Qt::Action.new(tr("Execute Selected Lines"), self)
1497
+ exec_selected_action.statusTip = tr("Execute the selected lines as a standalone script")
1498
+ exec_selected_action.connect(SIGNAL('triggered()')) { run_selection() }
1499
+ menu.addAction(exec_selected_action)
1500
+
1501
+ exec_cursor_action = Qt::Action.new(tr("Execute From Cursor"), self)
1502
+ exec_cursor_action.statusTip = tr("Execute the script starting at the line containing the cursor")
1503
+ exec_cursor_action.connect(SIGNAL('triggered()')) { run_from_cursor() }
1504
+ menu.addAction(exec_cursor_action)
1505
+
1506
+ menu.addSeparator()
1507
+
1508
+ if RUBY_VERSION.split('.')[0].to_i > 1
1509
+ syntax_action = Qt::Action.new(tr("Ruby Syntax Check Selected Lines"), self)
1510
+ syntax_action.statusTip = tr("Check the selected lines for valid Ruby syntax")
1511
+ syntax_action.connect(SIGNAL('triggered()')) { ruby_syntax_check_selection() }
1512
+ menu.addAction(syntax_action)
1513
+ end
1514
+
1515
+ mnemonic_action = Qt::Action.new(tr("Mnemonic Check Selected Lines"), self)
1516
+ mnemonic_action.statusTip = tr("Check the selected lines for valid targets, packets, mnemonics and parameters")
1517
+ mnemonic_action.connect(SIGNAL('triggered()')) { mnemonic_check_selection() }
1518
+ menu.addAction(mnemonic_action)
1519
+
1520
+ elsif running?() and @realtime_button_bar.state != 'Running'
1521
+ exec_selected_action = Qt::Action.new(tr("Execute Selected Lines While Paused"), self)
1522
+ exec_selected_action.statusTip = tr("Execute the selected lines as a standalone script")
1523
+ exec_selected_action.connect(SIGNAL('triggered()')) { run_selection_while_paused() }
1524
+ menu.addAction(exec_selected_action)
1525
+ end
1526
+ menu.exec(current_script.mapToGlobal(point))
1527
+ menu.dispose
1528
+ end
1529
+
1530
+ def load_file_into_script(filename)
1531
+ cached = @@file_cache[filename]
1532
+ if cached
1533
+ @active_script.setPlainText(cached.gsub("\r", ''))
1534
+ else
1535
+ @active_script.setPlainText(File.read(filename).gsub("\r", ''))
1536
+ end
1537
+ mark_breakpoints(filename)
1538
+
1539
+ @active_script.stop_highlight
1540
+ end
1541
+
1542
+ def mark_breakpoints(filename)
1543
+ @active_script.clear_breakpoints
1544
+ breakpoints = @@breakpoints[File.basename(filename)]
1545
+ if breakpoints
1546
+ breakpoints.each do |line_number, present|
1547
+ @active_script.add_breakpoint(line_number) if present
1548
+ end
1549
+ end
1550
+ end
1551
+
1552
+ def redirect_io
1553
+ # Redirect Standard Output and Standard Error
1554
+ $stdout = Stdout.instance
1555
+ $stderr = Stderr.instance
1556
+
1557
+ # Disable outputting to default io file descriptors
1558
+ $stdout.remove_default_io
1559
+ $stderr.remove_default_io
1560
+
1561
+ Logger.level = Logger::INFO
1562
+ Logger::INFO_SEVERITY_STRING.replace('')
1563
+ Logger::WARN_SEVERITY_STRING.replace('<Y> WARN:')
1564
+ Logger::ERROR_SEVERITY_STRING.replace('<R> ERROR:')
1565
+ end
1566
+
1567
+ def create_tabs
1568
+ tab_text = @default_tab_text
1569
+ tab_text = ' ' + File.basename(@filename) + ' ' unless @filename.empty?
1570
+ @tab_book.addTab(@script, tab_text)
1571
+ @top_frame.insertWidget(0, @tab_book)
1572
+ @tab_book_shown = true
1573
+ end
1574
+
1575
+ def remove_tabs
1576
+ @top_frame.takeAt(0) # Remove the @tab_book from the layout
1577
+ @top_frame.addWidget(@script) # Add back the script
1578
+ @script.show
1579
+ @tab_book_shown = false
1580
+ end
1581
+
1582
+ def isolate_string(keyword, line)
1583
+ found_string = nil
1584
+
1585
+ # Find keyword
1586
+ keyword_index = line.index(keyword)
1587
+
1588
+ # Remove keyword from line
1589
+ line = line[(keyword_index + keyword.length)..-1]
1590
+
1591
+ # Find start parens
1592
+ start_parens = line.index('(')
1593
+ if start_parens
1594
+ end_parens = line[start_parens..-1].index(')')
1595
+ found_string = line[(start_parens + 1)..(end_parens + start_parens - 1)].remove_quotes if end_parens
1596
+ if keyword == 'wait' or keyword == 'wait_check'
1597
+ quote_index = found_string.rindex('"')
1598
+ quote_index = found_string.rindex("'") unless quote_index
1599
+ if quote_index
1600
+ found_string = found_string[0..quote_index].remove_quotes
1601
+ else
1602
+ found_string = nil
1603
+ end
1604
+ end
1605
+ end
1606
+ found_string
1607
+ end
1608
+
1609
+ def mnemonic_check_cmd_line(keyword, line_number, line)
1610
+ result = nil
1611
+
1612
+ # Isolate the string
1613
+ string = isolate_string(keyword, line)
1614
+ if string
1615
+ begin
1616
+ target_name, cmd_name, cmd_params = extract_fields_from_cmd_text(string)
1617
+ result = "At line #{line_number}: Unknown command: #{target_name} #{cmd_name}"
1618
+ packet = System.commands.packet(target_name, cmd_name)
1619
+ Kernel.raise "Command not found" unless packet
1620
+ cmd_params.each do |param_name, param_value|
1621
+ result = "At line #{line_number}: Unknown command parameter: #{target_name} #{cmd_name} #{param_name}"
1622
+ packet.get_item(param_name)
1623
+ end
1624
+ result = nil
1625
+ rescue
1626
+ if result
1627
+ if string.index('=>')
1628
+ # Assume alternative syntax
1629
+ result = nil
1630
+ end
1631
+ else
1632
+ result = "At line #{line_number}: Potentially malformed command: #{line}"
1633
+ end
1634
+ end
1635
+ end
1636
+
1637
+ result
1638
+ end
1639
+
1640
+ def _mnemonic_check_tlm_line(keyword, line_number, line)
1641
+ result = nil
1642
+
1643
+ # Isolate the string
1644
+ string = isolate_string(keyword, line)
1645
+ if string
1646
+ begin
1647
+ target_name, packet_name, item_name = yield string
1648
+ result = "At line #{line_number}: Unknown telemetry item: #{target_name} #{packet_name} #{item_name}"
1649
+ System.telemetry.packet_and_item(target_name, packet_name, item_name)
1650
+ result = nil
1651
+ rescue
1652
+ if result
1653
+ if string.index(',')
1654
+ # Assume alternative syntax
1655
+ result = nil
1656
+ end
1657
+ else
1658
+ result = "At line #{line_number}: Potentially malformed telemetry: #{line}"
1659
+ end
1660
+ end
1661
+ end
1662
+
1663
+ result
1664
+ end
1665
+
1666
+ def mnemonic_check_tlm_line(keyword, line_number, line)
1667
+ _mnemonic_check_tlm_line(keyword, line_number, line) do |string|
1668
+ extract_fields_from_tlm_text(string)
1669
+ end
1670
+ end
1671
+
1672
+ def mnemonic_check_set_tlm_line(keyword, line_number, line)
1673
+ _mnemonic_check_tlm_line(keyword, line_number, line) do |string|
1674
+ extract_fields_from_set_tlm_text(string)
1675
+ end
1676
+ end
1677
+
1678
+ def mnemonic_check_check_line(keyword, line_number, line)
1679
+ _mnemonic_check_tlm_line(keyword, line_number, line) do |string|
1680
+ extract_fields_from_check_text(string)
1681
+ end
1682
+ end
1683
+
1684
+ def output_thread
1685
+ @@cancel_output = false
1686
+ @@output_sleeper = Sleeper.new
1687
+ begin
1688
+ loop do
1689
+ break if @@cancel_output
1690
+ handle_output_io() if (Time.now - @output_time) > 5.0
1691
+ break if @@cancel_output
1692
+ break if @@output_sleeper.sleep(1.0)
1693
+ end # loop
1694
+ rescue => error
1695
+ Qt.execute_in_main_thread(true) do
1696
+ ExceptionDialog.new(self, error, "Output Thread")
1697
+ end
1698
+ end
1699
+ end
1700
+
1701
+ def limits_monitor_thread
1702
+ @@cancel_limits = false
1703
+ @@limits_sleeper = Sleeper.new
1704
+ queue_id = nil
1705
+ begin
1706
+ loop do
1707
+ break if @@cancel_limits
1708
+ begin
1709
+ # Subscribe to limits notifications
1710
+ queue_id = subscribe_limits_events(100000) unless queue_id
1711
+
1712
+ # Get the next limits event
1713
+ break if @@cancel_limits
1714
+ begin
1715
+ type, data = get_limits_event(queue_id, true)
1716
+ rescue ThreadError
1717
+ break if @@cancel_limits
1718
+ break if @@limits_sleeper.sleep(0.5)
1719
+ next
1720
+ end
1721
+
1722
+ break if @@cancel_limits
1723
+
1724
+ # Display limits state changes
1725
+ if type == :LIMITS_CHANGE
1726
+ target_name = data[0]
1727
+ packet_name = data[1]
1728
+ item_name = data[2]
1729
+ old_limits_state = data[3]
1730
+ new_limits_state = data[4]
1731
+
1732
+ if old_limits_state == nil # Changing from nil
1733
+ if (new_limits_state != :GREEN) &&
1734
+ (new_limits_state != :GREEN_LOW) &&
1735
+ (new_limits_state != :GREEN_HIGH) &&
1736
+ (new_limits_state != :BLUE)
1737
+ msg = "#{target_name} #{packet_name} #{item_name} is #{new_limits_state.to_s}"
1738
+ case new_limits_state
1739
+ when :YELLOW, :YELLOW_LOW, :YELLOW_HIGH
1740
+ scriptrunner_puts "<Y>#{msg}"
1741
+ when :RED, :RED_LOW, :RED_HIGH
1742
+ scriptrunner_puts "<R>#{msg}"
1743
+ else
1744
+ # Print nothing
1745
+ end
1746
+ handle_output_io()
1747
+ end
1748
+ else # changing from a color
1749
+ msg = "#{target_name} #{packet_name} #{item_name} is #{new_limits_state.to_s}"
1750
+ case new_limits_state
1751
+ when :BLUE
1752
+ scriptrunner_puts "<B>#{msg}"
1753
+ when :GREEN, :GREEN_LOW, :GREEN_HIGH
1754
+ scriptrunner_puts "<G>#{msg}"
1755
+ when :YELLOW, :YELLOW_LOW, :YELLOW_HIGH
1756
+ scriptrunner_puts "<Y>#{msg}"
1757
+ when :RED, :RED_LOW, :RED_HIGH
1758
+ scriptrunner_puts "<R>#{msg}"
1759
+ else
1760
+ # Print nothing
1761
+ end
1762
+ break if @@cancel_limits
1763
+ handle_output_io()
1764
+ break if @@cancel_limits
1765
+ end
1766
+
1767
+ if @@pause_on_red && (new_limits_state == :RED ||
1768
+ new_limits_state == :RED_LOW ||
1769
+ new_limits_state == :RED_HIGH)
1770
+ break if @@cancel_limits
1771
+ pause()
1772
+ break if @@cancel_limits
1773
+ end
1774
+ end
1775
+
1776
+ rescue DRb::DRbConnError
1777
+ queue_id = nil
1778
+ break if @@cancel_limits
1779
+ break if @@limits_sleeper.sleep(1)
1780
+ end
1781
+
1782
+ end # loop
1783
+ rescue => error
1784
+ Qt.execute_in_main_thread(true) do
1785
+ ExceptionDialog.new(self, error, "Limits Monitor Thread")
1786
+ end
1787
+ end
1788
+ ensure
1789
+ begin
1790
+ unsubscribe_limits_events(queue_id) if queue_id
1791
+ rescue
1792
+ # Oh Well
1793
+ end
1794
+ end
1795
+
1796
+ end # class ScriptRunnerFrame
1797
+
1798
+ end # module Cosmos