Guest User

Untitled

a guest
Jul 18th, 2018
109
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.25 KB | None | 0 0
  1. package main
  2.  
  3. import (
  4. "container/vector";
  5. "fmt";
  6. "go/ast";
  7. "go/token";
  8. "go/parser";
  9. "go/printer";
  10. "io";
  11. "os";
  12. "path";
  13. "regexp";
  14. "strings";
  15.  
  16. . "./html";
  17. )
  18.  
  19.  
  20. type HTMLStyler struct {
  21. comment *ast.Comment;
  22. comment_text []string;
  23. comment_offset int;
  24. prev *history;
  25. }
  26.  
  27. type history struct {
  28. val interface {};
  29. prev *history;
  30. }
  31.  
  32. type collector struct {
  33. contents *vector.StringVector;
  34. }
  35.  
  36. func (self *collector) Write(p []byte) (n int, err os.Error) {
  37. self.contents.Push(string(p));
  38. return len(p), nil;
  39. }
  40.  
  41.  
  42. func (self *HTMLStyler) LineTag(line int) ([]byte, printer.HTMLTag) {
  43. return []byte{}, printer.HTMLTag{}
  44. }
  45.  
  46. func (self *HTMLStyler) Comment(comment *ast.Comment, line []byte) ([]byte, printer.HTMLTag) {
  47. if self.comment == comment {
  48. self.comment_offset++;
  49. if self.comment_text[self.comment_offset] == "" {
  50. self.comment_offset++;
  51. }
  52. } else {
  53. self.comment = comment;
  54. self.comment_text = strings.Split(string(comment.Text), "\r\n", 0);
  55. self.comment_offset = 0;
  56. }
  57.  
  58. self.prev = &history{comment, self.prev};
  59.  
  60. return strings.Bytes(self.comment_text[self.comment_offset]), printer.HTMLTag{
  61. Start: "<span class=\"go-comment\">",
  62. End: "</span>",
  63. };
  64. }
  65.  
  66. func (self *HTMLStyler) BasicLit(x *ast.BasicLit) ([]byte, printer.HTMLTag) {
  67. kind := "other";
  68. switch x.Kind {
  69. case token.INT:
  70. kind = "int"
  71. case token.FLOAT:
  72. kind = "float"
  73. case token.CHAR:
  74. kind = "char"
  75. case token.STRING:
  76. kind = "string"
  77. }
  78.  
  79. if x.Value[0] == '`' {
  80. kind = "string go-raw-string";
  81. }
  82.  
  83. self.prev = &history{x, self.prev};
  84.  
  85. return x.Value, printer.HTMLTag{
  86. Start: "<span class=\"go-basiclit go-" + kind + "\">",
  87. End: "</span>",
  88. };
  89. }
  90.  
  91. func (self *HTMLStyler) Ident(id *ast.Ident) ([]byte, printer.HTMLTag) {
  92. classes := "go-local";
  93. if id.IsExported() {
  94. classes = "go-exported"
  95. }
  96.  
  97. switch id.String() {
  98. case "bool", "uint8", "uint16", "uint32", "uint64", "int8", "int16", "int32", "int64", "float32", "float64", "byte", "uint", "int", "float", "uintptr", "string":
  99. classes += " go-prim-ident";
  100. default:
  101. if tok, ok := self.prev.val.(token.Token); ok && tok.String() == "func" || tok.String() == ")" {
  102. classes += " go-func-ident";
  103. }
  104. }
  105.  
  106. self.prev = &history{id, self.prev};
  107.  
  108. return strings.Bytes(id.String()), printer.HTMLTag{
  109. Start: "<span class=\"go-ident " + classes + "\">",
  110. End: "</span>",
  111. };
  112. }
  113.  
  114. func (self *HTMLStyler) Token(tok token.Token) ([]byte, printer.HTMLTag) {
  115. extra := "";
  116.  
  117. if tok.IsKeyword() {
  118. extra += " go-keyword"
  119. }
  120.  
  121. if tok.IsLiteral() {
  122. extra += " go-literal"
  123. }
  124.  
  125. if tok.IsOperator() {
  126. extra += " go-operator"
  127. }
  128.  
  129. self.prev = &history{tok, self.prev};
  130.  
  131. return strings.Bytes(tok.String()), printer.HTMLTag{
  132. Start: "<span class=\"go-token" + extra + "\">",
  133. End: "</span>",
  134. };
  135. }
  136.  
  137. func Print(filename string, source interface{}) (pretty string, ok os.Error) {
  138. fileAst, ok := parser.ParseFile(filename, source, 4);
  139.  
  140. // Make common corrections for snippet pastes
  141. if ok != nil && source != nil {
  142. src := source.(string);
  143.  
  144. if m, _ := regexp.MatchString(`^package`, src); !m {
  145. src = "package main\n\n" + src
  146. }
  147.  
  148. if fileAst, ok = parser.ParseFile(filename, src, 4); ok != nil {
  149. return
  150. }
  151. }
  152.  
  153. coll := new(collector);
  154. coll.contents = vector.NewStringVector(0);
  155.  
  156. (&printer.Config{
  157. Mode: 5,
  158. Tabwidth: 4,
  159. Styler: new(HTMLStyler),
  160. }).Fprint(coll, fileAst);
  161.  
  162. pretty = strings.Join(coll.contents.Data(), "");
  163.  
  164. return;
  165. }
  166.  
  167. func prettyPaste(id string, limit int) (code []string, err os.Error) {
  168. source, err := io.ReadFile("pastes" + path.Clean("/"+id));
  169. if err != nil {
  170. return
  171. }
  172.  
  173. multi := strings.Split(string(source), "\n---", 0);
  174.  
  175. allCode := make([]string, len(multi));
  176. results := make(chan int);
  177. for i := 0; i < len(multi); i++ {
  178. go func(i int) {
  179. allCode[i], _ = prettySource(id, multi[i], limit);
  180. results <- i
  181. }(i);
  182. }
  183.  
  184. for i := 0; i < len(multi); i++ {
  185. <-results;
  186. }
  187.  
  188. code = allCode;
  189.  
  190. return;
  191. }
  192.  
  193. func prettySource(filename string, source string, limit int) (code string, err os.Error) {
  194. prettyCode, ok := Print(filename, source);
  195. if ok != nil { // If it fails to parse, just serve it raw.
  196. prettyCode = source
  197. }
  198.  
  199. linesPre := Pre().Attrs(As{"class": "line-numbers"});
  200. codePre := Pre().Attrs(As{"class": "code-lines"});
  201.  
  202. stopped := false;
  203. for i, code := range strings.Split(prettyCode, "\n", 0) {
  204. line := i + 1;
  205. linesPre.Append(
  206. fmt.Sprintf(
  207. A("%d").Attrs(As{
  208. "rel": "#L%d",
  209. "href": "#LC%d",
  210. "id": "LID%d",
  211. }).Out()+"\n",
  212. line, line, line, line));
  213. codePre.Append(
  214. Div(code).Attrs(As{
  215. "class": "line",
  216. "id": "LC" + fmt.Sprint(line),
  217. }).Out());
  218.  
  219. if limit != 0 && i == limit {
  220. stopped = true;
  221. break;
  222. }
  223. }
  224.  
  225. if stopped {
  226. linesPre.Append("\n");
  227. codePre.Append(
  228. Div(
  229. A("\n...").Attrs(As{
  230. "href": "/{@|url+html}",
  231. "class": "go-comment",
  232. })).Attrs(As{
  233. "class": "line",
  234. }).Out());
  235. }
  236.  
  237. code = Table(
  238. Tbody(
  239. Tr(
  240. Td(linesPre).Attrs(As{"width": "1%", "valign": "top"}),
  241. Td(codePre).Attrs(As{"valign": "top"})))).Attrs(As{
  242. "class": "code",
  243. "cellspacing": "0",
  244. "cellpadding": "0",
  245. }).Out();
  246.  
  247. return;
  248. }
Add Comment
Please, Sign In to add comment