1package main
2
3import (
4	"fmt"
5	"strings"
6
7	"github.com/xyproto/env"
8	"github.com/xyproto/mode"
9	"github.com/xyproto/vt100"
10)
11
12// TemplateProgram represents a string and cursor movement up, and then to the right
13// which can be used to position the cursor after inserting a string.
14type TemplateProgram struct {
15	text  string
16	right int
17	up    int
18}
19
20var templatePrograms = map[mode.Mode]TemplateProgram{
21	mode.C: {
22		"#include <stdio.h>\n#include <stdlib.h>\n\nint main(int argc, char* argv[])\n{\n\tprintf(\"%s\\n\", \"Hello, World!\");\n\treturn EXIT_SUCCESS;\n}\n",
23		8,
24		3,
25	},
26	mode.Cpp: {
27		"#include <cstdlib>\n#include <iostream>\n#include <string>\n\nusing namespace std::string_literals;\n\nint main(int argc, char** argv)\n{\n    std::cout << \"Hello, World!\"s << std::endl;\n    return EXIT_SUCCESS;\n}\n",
28		14,
29		3,
30	},
31	mode.Clojure: {
32		"(ns example.hello\n  (:gen-class))\n\n(defn hello-world []\n  (println \"Hello, World!\"))\n\n(hello-world)\n",
33		10,
34		3,
35	},
36	mode.Crystal: {
37		"class Greeter\n  def initialize(@name : String)\n  end\n\n  def greet\n    puts \"Hello, #{@name}!\"\n  end\nend\n\nGreeter.new(\"World\").greet\n",
38		6,
39		5,
40	},
41	mode.CS: {
42		"using System;\n\nclass Greeter {\n    public static void Main(string[] args) {\n        Console.WriteLine(\"Hello, World!\");\n    }\n}\n",
43		19,
44		3,
45	},
46	mode.D: {
47		"module main;\n\nimport std.stdio;\n\nvoid main(string[] args) {\n    writeln(\"Hello, World!\");\n}\n",
48		2,
49		1,
50	},
51	mode.Go: {
52		"package main\n\nimport (\n\t\"fmt\"\n)\n\nfunc main() {\n\tfmt.Println(\"Hello, World!\")\n}\n",
53		13,
54		2,
55	},
56	mode.HTML: {
57		"<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n    <title>Hello</title>\n    <meta name=\"description\" content=\"Hello\">\n    <link rel=\"shortcut icon\" href=\"https://www.iconsdb.com/icons/download/orange/teapot-16.png\">\n    <link rel=\"stylesheet\" href=\"https://unpkg.com/@picocss/pico@latest/css/pico.classless.min.css\">\n  </head>\n  <body>\n    <header>\n      <hgroup>\n        <h1>Greetings</h1>\n        <h2>About to greet <code>the world</code></h2>\n      </hgroup>\n    </header>\n    <main>\n      <section id=\"hello\">\n        <h2>Hello, World!</h2>\n        Task completed.\n      </section>\n    </main>\n    <footer>\n      All done.\n    </footer>\n  </body>\n</html>\n",
58		4,
59		9,
60	},
61	mode.Java: {
62		"class Greeter {\n    public static void main(String[] args) {\n        System.out.println(\"Hello, World!\");\n    }\n}\n",
63		20,
64		3,
65	},
66	mode.JavaScript: {
67		"console.log('Hello, World!');\n",
68		13,
69		1,
70	},
71	mode.Haskell: {
72		"main :: IO ()\nmain = putStrLn \"Hello, World!\"\n",
73		17,
74		1,
75	},
76	mode.Kotlin: {
77		"fun main() {\n    println(\"Hello, World!\")\n}\n",
78		9,
79		2,
80	},
81	mode.Lua: {
82		"print(\"Hello, World!\")\n",
83		7,
84		1,
85	},
86	mode.Nim: {
87		"echo \"Hello, World!\"\n",
88		6,
89		1,
90	},
91	mode.ObjectPascal: {
92		"program Hello;\nconst\n  greeting = 'Hello, World!';\nbegin\n  writeln(greeting);\nend.\n",
93		12,
94		4,
95	},
96	mode.Odin: {
97		"package main\n\nimport \"core:fmt\"\n\nmain :: proc() {\n    fmt.println(\"Hello, World!\");\n}\n",
98		13,
99		2,
100	},
101	mode.Python: {
102		"#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\ndef main():\n    print(\"Hello, World!\")\n\n\nif __name__ == \"__main__\":\n    main()\n",
103		7,
104		5,
105	},
106	mode.Rust: {
107		"fn main() {\n    println!(\"Hello, World!\");\n}\n",
108		10,
109		2,
110	},
111	mode.Scala: {
112		"object Hello {\n\tdef main(args: Array[String]) = {\n\t\tprintln(\"Hello, World!\")\n\t}\n}\n",
113		9,
114		3,
115	},
116	mode.Shell: {
117		"# Maintainer: " + strings.Title(env.Str("LOGNAME", "name")) + " <" + env.Str("EMAIL", "email") + ">\n\npkgname=\npkgver=1.0.0\npkgrel=1\npkgdesc='Example application'\narch=(x86_64)\nurl='https://github.com/example/application'\nlicense=(BSD3)\nmakedepends=(git go)\nsource=(\"git+$url#commit=asdf\") # tag: v1.0.0\nb2sums=(SKIP)\n\nbuild() {\n  cd $pkgname\n  go build -v -mod=vendor -buildmode=pie -trimpath -ldflags=\"-s -w -extldflags \\\"${LDFLAGS}\\\"\"\n}\n\npackage() {\n  install -Dm755 $pkgname/$pkgname \"$pkgdir/usr/bin/$pkgname\"\n  install -Dm644 $pkgname/LICENSE \"$pkgdir/usr/share/licenses/$pkgname/LICENSE\"\n}\n",
118		8,
119		20,
120	},
121	mode.StandardML: {
122		"let\n  val name = \"World\"\nin\n  map (fn x => (print (\"Hello, \" ^ x ^ \"!\\n\"))) [name]\nend;",
123		22,
124		1,
125	},
126	mode.TypeScript: {
127		"console.log('Hello, World!');\n",
128		13,
129		1,
130	},
131	mode.V: {
132		"fn main() {\n    name := 'World'\n    println('Hello, $name!')\n}\n",
133		9,
134		2,
135	},
136	mode.Zig: {
137		"const std = @import(\"std\");\n\npub fn main() !void {\n    const stdout = std.io.getStdOut().writer();\n    try stdout.print(\"Hello, World!\\n\", .{});\n}\n",
138		18,
139		2,
140	},
141}
142
143// HasTemplateProgram checks if a template is available for the current
144// programming language, by looking at e.mode.
145func (e *Editor) HasTemplateProgram() bool {
146	_, found := templatePrograms[e.mode]
147	return found
148}
149
150// InsertTemplateProgram will insert a template program at the current cursor position,
151// if available. It will then reposition the cursor at an appropriate place in the template.
152func (e *Editor) InsertTemplateProgram(c *vt100.Canvas) error {
153	prog, found := templatePrograms[e.mode]
154	if !found {
155		return fmt.Errorf("could not find a template program for %s", e.mode)
156	}
157
158	// Insert the template program
159	e.InsertStringAndMove(c, prog.text)
160
161	// Move the cursor up and to the right
162	for x := 0; x < prog.up; x++ {
163		e.Up(c, nil)
164	}
165	for x := 0; x < prog.right; x++ {
166		e.Next(c)
167	}
168
169	return nil
170}
171