cosmos 3.5.1 → 3.5.2

Sign up to get free protection for your applications and to get access to all the features.
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