Golang Playground ACE editor

Make golang play editor usable. With format and theme support.

  1. // ==UserScript==
  2. // @name Golang Playground ACE editor
  3. // @namespace http://masoudd.ir/
  4. // @version 0.5.1
  5. // @description Make golang play editor usable. With format and theme support.
  6. // @author masoud_dot_naservand on google's email
  7. // @match https://play.golang.org/
  8. // @match https://play.golang.org/p/*
  9. // @grant GM_addStyle
  10. // @grant GM_getValue
  11. // @grant GM_setValue
  12. // @license GPL-3.0
  13. // @supportURL https://codeberg.org/masoudd/Golang_Playground_ACE_editor
  14. // @copyright 2020, masoudd (https://greatest.deepsurf.us/en/users/506611-masoudd)
  15. // @copyright 2018, Teeed (https://openuserjs.org/users/Teeed)
  16. // ==/UserScript==
  17.  
  18. /*
  19. 0.5.1:
  20. - Fix the things play.golang.org broke
  21. 0.5:
  22. - Devided themes to Bright and Dark groups
  23. - Changed default theme to solarized_light so it looks like the default go playground theme
  24.  
  25. 0.4:
  26. - Updated the ace.js from 1.3.3 to 1.4.9
  27. - Format button now functions
  28. - Added theme support
  29.  
  30. 0.3:
  31. Also applies to code posted on playground.
  32.  
  33. 0.2:
  34. Ctrl + Enter executes script.
  35. */
  36.  
  37. (function() {
  38. 'use strict';
  39. var themes = {"Bright": ["chrome", "clouds", "crimson_editor", "dawn", "dreamweaver",
  40. "eclipse", "github", "iplastic", "solarized_light", "textmate",
  41. "tomorrow", "xcode", "kuroir", "katzenmilch", "sqlserver"],
  42.  
  43. "Dark" : ["ambiance", "chaos", "clouds_midnight", "cobalt","dracula",
  44. "gob", "gruvbox", "idle_fingers", "kr_theme", "merbivore",
  45. "merbivore_soft", "mono_industrial", "monokai", "nord_dark",
  46. "pastel_on_dark", "solarized_dark", "terminal", "tomorrow_night",
  47. "tomorrow_night_blue", "tomorrow_night_bright",
  48. "tomorrow_night_eighties","twilight", "vibrant_ink"],
  49. };
  50. var scrpt = document.createElement('script');
  51. scrpt.src = 'https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.9/ace.min.js'
  52. scrpt.type = 'text/javascript';
  53. scrpt.async = true;
  54. scrpt.onload = function() {
  55. // need to set basePath because ace.js can't find it in it's own if we are
  56. // loading it as ace.min.js
  57. ace.config.set("basePath", "https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.9");
  58. var wrap = document.getElementById("wrap")
  59.  
  60. var linedTextarea = document.querySelector(".linedtextarea");
  61. linedTextarea.style.display = 'none'
  62.  
  63. var codeArea = document.getElementById("code");
  64. var currentCode = codeArea.value;
  65.  
  66. var editorDiv = document.createElement('div')
  67. editorDiv.id = "newNiceEditorDiv"
  68. editorDiv.style.width = '100%'
  69. editorDiv.style.height = '100%'
  70. wrap.appendChild(editorDiv);
  71.  
  72. var editor = ace.edit("newNiceEditorDiv");
  73. editor.session.setValue(currentCode);
  74. editor.session.on('change', function(){
  75. codeArea.value = editor.session.getValue();
  76. });
  77.  
  78. // need to intercept the call to .val on the textArea
  79. // in ajax callback for format button to update the contents
  80. // of editor by the formatted code returned
  81. const originalVal = $.fn.val;
  82. $.fn.val = function(x) {
  83. if (this[0].id === 'code' && x) {
  84. editor.session.setValue(x);
  85. }
  86. return originalVal.apply(this, arguments);
  87. };
  88.  
  89. var savedTheme = GM_getValue('theme', false);
  90. if (!savedTheme) {
  91. savedTheme = 'solarized_light';
  92. GM_setValue('theme', savedTheme);
  93. }
  94. var themeLabel = document.createElement('label');
  95. themeLabel.setAttribute('title', 'Theme');
  96. var select = document.createElement('select');
  97. select.setAttribute('id', 'themeSelect');
  98. for (var group in themes) {
  99. var optGroup = document.createElement('optgroup');
  100. optGroup.setAttribute('label', group);
  101. themes[group].forEach(function(theme) {
  102. var opt = document.createElement('option');
  103. opt.setAttribute('value', theme);
  104. if (theme === savedTheme) {
  105. opt.setAttribute('selected', 'true');
  106. }
  107. opt.text = theme.replace(/_/g, ' ');
  108. optGroup.appendChild(opt);
  109. });
  110. select.appendChild(optGroup);
  111. }
  112.  
  113. themeLabel.appendChild(select);
  114. document.getElementById('aboutButton').before(themeLabel);
  115. select.addEventListener('change', function(e) {
  116. editor.setTheme(`ace/theme/${this.value}`);
  117. GM_setValue('theme', this.value);
  118. });
  119. // observe the editorDiv element for class attribute change, to catch
  120. // when the new themes apply and set the color and background-color
  121. // for #output
  122. const observeConf = {
  123. attributes: true,
  124. attributeFilter: ['class'],
  125. };
  126. // the closure
  127. const observer = new MutationObserver(function(mlist, obs) {
  128. var color = '';
  129. var backgroundColor = '';
  130. const output = document.getElementById('output');
  131. return function(mlist, obs) {
  132. var cs = getComputedStyle(editorDiv);
  133. if (color !== cs.color || backgroundColor !== cs.backgroundColor) {
  134. color = cs.color;
  135. backgroundColor = cs.backgroundColor;
  136. output.setAttribute('style', `color: ${color}; background-color: ${backgroundColor}`);
  137. }
  138. }
  139. }());
  140. observer.observe(editorDiv, observeConf);
  141.  
  142.  
  143.  
  144. editor.setTheme(`ace/theme/${savedTheme}`);
  145. editor.session.setMode("ace/mode/golang");
  146.  
  147. editorDiv.style.fontSize='16px';
  148.  
  149. function doSubmit() {
  150. document.getElementById('run').click()
  151. }
  152.  
  153. window.addEventListener("keypress", function(e) {
  154. if(e.ctrlKey && e.key == 'Enter') {
  155. doSubmit()
  156. }
  157. }, false);
  158.  
  159. }
  160. document.head.appendChild(scrpt);
  161.  
  162.  
  163.  
  164. GM_addStyle ( `
  165. #wrap {
  166. padding: 0;
  167. background: none;
  168. }
  169. select {
  170. height: 30px;
  171. border: 1px solid #375EAB;
  172. font-size: 16px;
  173. font-family: sans-serif;
  174. background: #375EAB;
  175. color: white;
  176. position: static;
  177. top: 1px;
  178. border-radius: 5px;
  179. padding-left: 1em;
  180. }
  181. `);
  182. })();