1
0

action.go 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. package editor
  2. import(
  3. "strings"
  4. "strconv"
  5. "slices"
  6. "os"
  7. "github.com/zyedidia/rope"
  8. "golang.design/x/clipboard"
  9. "moose/internal/util"
  10. )
  11. type ActionManager = struct {
  12. Common []Action
  13. Normal []Action
  14. Insert []Action
  15. Palette []Action
  16. }
  17. type Action = struct {
  18. Binding []string
  19. Command []string
  20. AskArgs bool
  21. Callback func(*Model, []string)
  22. }
  23. func DefaultActionManager() ActionManager {
  24. return ActionManager{
  25. Common: []Action{
  26. Action{
  27. Binding: []string{"f12"},
  28. Callback: func(m *Model, args []string) {
  29. m.Mode = ModeNormal
  30. },
  31. },
  32. Action{
  33. Binding: []string{"ctrl+q"},
  34. Command: []string{"q", "quit"},
  35. AskArgs: true,
  36. Callback: func(m *Model, args []string) {
  37. m.Quit()
  38. },
  39. },
  40. Action{
  41. Binding: []string{"ctrl+s"},
  42. Command: []string{"s", "save"},
  43. AskArgs: false,
  44. Callback: func(m *Model, args []string) {
  45. path := ""
  46. if len(args) < 1 || args[0] == "" {
  47. if m.BM.Current().Path == "" {
  48. m.Mode = ModeNormal
  49. m.BM.PaletteBuffer.Clear()
  50. m.BM.PaletteBuffer.Insert("moose.error:Missing filename argument for save")
  51. return
  52. }
  53. }
  54. if len(args) > 0 && args[0] != "" {
  55. m.BM.Current().Path = args[0]
  56. }
  57. path = m.BM.Current().Path
  58. data := []byte(m.BM.Current().String())
  59. err := os.WriteFile(path, data, 0644)
  60. if err != nil {
  61. m.Mode = ModeNormal
  62. m.BM.PaletteBuffer.Clear()
  63. m.BM.PaletteBuffer.Insert("moose.error:Could not save to file \"" + path + "\": " + err.Error())
  64. return
  65. }
  66. m.BM.PaletteBuffer.Clear()
  67. m.BM.PaletteBuffer.Insert("moose.info:Wrote " + strconv.Itoa(len(data)) + " bytes to \"" + path + "\"")
  68. return
  69. },
  70. },
  71. Action{
  72. Binding: []string{"shift+ctrl+Rune[s]"},
  73. Command: []string{"s", "save"},
  74. AskArgs: true,
  75. },
  76. Action{
  77. Binding: []string{"ctrl+e"},
  78. Command: []string{"e", "edit"},
  79. AskArgs: true,
  80. Callback: func(m *Model, args []string) {
  81. if len(args) < 1 {
  82. m.Mode = ModeNormal
  83. m.BM.PaletteBuffer.Clear()
  84. m.BM.PaletteBuffer.Insert("moose.error:Did not specify path for edit")
  85. return
  86. }
  87. content, err := os.ReadFile(args[0])
  88. if err != nil {
  89. m.Mode = ModeNormal
  90. m.BM.PaletteBuffer.Clear()
  91. m.BM.PaletteBuffer.Insert("moose.error:Could not edit file \"" + args[0] + "\": " + err.Error())
  92. return
  93. }
  94. m.BM.Current().Clear()
  95. m.BM.Current().Rope = rope.New(content)
  96. m.BM.Current().LI.Rebuild(m.BM.Current().Rope)
  97. m.BM.Current().Path = args[0]
  98. },
  99. },
  100. Action{
  101. Binding: []string{"left"},
  102. Callback: func(m *Model, args []string) {
  103. if m.Mode == ModePalette {
  104. m.BM.PaletteBuffer.MoveHoriz(-1)
  105. } else {
  106. m.BM.Current().MoveHoriz(-1)
  107. }
  108. },
  109. },
  110. Action{
  111. Binding: []string{"right"},
  112. Callback: func(m *Model, args []string) {
  113. if m.Mode == ModePalette {
  114. m.BM.PaletteBuffer.MoveHoriz(1)
  115. } else {
  116. m.BM.Current().MoveHoriz(1)
  117. }
  118. },
  119. },
  120. Action{
  121. Binding: []string{"up"},
  122. Callback: func(m *Model, args []string) {
  123. if m.Mode != ModePalette {
  124. m.BM.Current().MoveVert(-1)
  125. }
  126. },
  127. },
  128. Action{
  129. Binding: []string{"down"},
  130. Callback: func(m *Model, args []string) {
  131. if m.Mode != ModePalette {
  132. m.BM.Current().MoveVert(1)
  133. }
  134. },
  135. },
  136. Action{
  137. Binding: []string{"shift+left"},
  138. AskArgs: false,
  139. Callback: func(m *Model, args []string) {
  140. if m.Mode == ModePalette {
  141. m.BM.PaletteBuffer.MoveWordHoriz(-1)
  142. } else {
  143. m.BM.Current().MoveWordHoriz(-1)
  144. }
  145. },
  146. },
  147. Action{
  148. Binding: []string{"shift+right"},
  149. AskArgs: false,
  150. Callback: func(m *Model, args []string) {
  151. if m.Mode == ModePalette {
  152. m.BM.PaletteBuffer.MoveWordHoriz(1)
  153. } else {
  154. m.BM.Current().MoveWordHoriz(1)
  155. }
  156. },
  157. },
  158. },
  159. Normal: []Action{
  160. Action{
  161. Binding: []string{"Rune[w]"},
  162. Callback: func(m *Model, args []string) {
  163. m.Mode = ModeWrite
  164. },
  165. },
  166. Action{
  167. Binding: []string{"Rune[q]"},
  168. Callback: func(m *Model, args []string) {
  169. m.Mode = ModePalette
  170. m.BM.PaletteBuffer.Clear()
  171. m.BM.PaletteBuffer.Insert("/")
  172. },
  173. },
  174. Action{
  175. Binding: []string{"Rune[f]"},
  176. AskArgs: true,
  177. Callback: func(m *Model, args []string) {
  178. m.Mode = ModePalette
  179. m.BM.PaletteBuffer.Clear()
  180. m.BM.PaletteBuffer.Insert("?")
  181. },
  182. },
  183. Action{
  184. Binding: []string{"Rune[v]"},
  185. Command: []string{"p", "paste"},
  186. AskArgs: false,
  187. Callback: func(m *Model, args []string) {
  188. text := clipboard.Read(clipboard.FmtText)
  189. if string(text) != "" {
  190. if m.Mode == ModePalette {
  191. m.BM.PaletteBuffer.Insert(string(text))
  192. } else {
  193. m.BM.Current().Insert(string(text))
  194. }
  195. }
  196. },
  197. },
  198. Action{
  199. Binding: []string{"Rune[j]"},
  200. Callback: func(m *Model, args []string) {
  201. if m.Mode == ModePalette {
  202. m.BM.PaletteBuffer.MoveHoriz(-1)
  203. } else {
  204. m.BM.Current().MoveHoriz(-1)
  205. }
  206. },
  207. },
  208. },
  209. Insert: []Action{
  210. Action{
  211. Binding: []string{"shift+up"},
  212. Command: []string{"TODO:"},
  213. AskArgs: false,
  214. Callback: func(m *Model, args []string) {
  215. m.BM.Current().AddCursorVert(-1)
  216. },
  217. },
  218. Action{
  219. Binding: []string{"shift+down"},
  220. Command: []string{"TODO:"},
  221. AskArgs: false,
  222. Callback: func(m *Model, args []string) {
  223. m.BM.Current().AddCursorVert(1)
  224. },
  225. },
  226. Action{
  227. Binding: []string{"esc"},
  228. Command: []string{"clrc", "clearcursors"},
  229. AskArgs: false,
  230. Callback: func(m *Model, args []string) {
  231. m.BM.Current().ClearCursors()
  232. },
  233. },
  234. Action{
  235. Binding: []string{"tab"},
  236. Command: []string{"TODO:"},
  237. AskArgs: false,
  238. Callback: func(m *Model, args []string) {
  239. for _ = range 4 {
  240. m.BM.Current().Insert(" ")
  241. }
  242. },
  243. },
  244. Action{
  245. Binding: []string{"shift+tab"},
  246. Command: []string{"TODO:"},
  247. AskArgs: false,
  248. Callback: func(m *Model, args []string) {
  249. // TODO: implement m.BM.Current().remove...
  250. },
  251. },
  252. Action{
  253. Binding: []string{"backspace"},
  254. Callback: func(m *Model, args []string) {
  255. m.BM.Current().Delete()
  256. },
  257. },
  258. Action{
  259. Binding: []string{"enter"},
  260. Callback: func(m *Model, args []string) {
  261. m.BM.Current().Insert("\n")
  262. },
  263. },
  264. },
  265. Palette: []Action{
  266. Action{
  267. Binding: []string{"backspace"},
  268. Callback: func(m *Model, args []string) {
  269. m.BM.PaletteBuffer.Delete()
  270. },
  271. },
  272. Action{
  273. Binding: []string{"enter"},
  274. Callback: func(m *Model, _ []string) {
  275. input := m.BM.PaletteBuffer.String()
  276. args := strings.Split(input, " ")
  277. if args[0] == "" {
  278. m.Mode = ModeNormal
  279. return
  280. }
  281. cmd := string([]rune(args[0])[1:])
  282. if strings.HasPrefix(args[0], "/") {
  283. for _, action := range append(m.AM.Common, append(m.AM.Normal, m.AM.Insert...)...) {
  284. if action.Callback == nil { continue }
  285. if len(action.Command) > 0 && slices.Contains(util.StandardizeBindingsArray(action.Command), util.StandardizeBinding(cmd)) {
  286. m.Mode = ModeNormal
  287. action.Callback(m, args[1:])
  288. return
  289. }
  290. }
  291. m.Mode = ModeNormal
  292. m.BM.PaletteBuffer.Clear()
  293. m.BM.PaletteBuffer.Insert("moose.error:Unknown command \"" + cmd + "\"")
  294. } else if strings.HasPrefix(args[0], "?") {
  295. m.Mode = ModeFind
  296. m.BM.PaletteBuffer.Clear()
  297. m.BM.PaletteBuffer.Insert("moose.error:Find mode unimplemented \"" + cmd + "\"")
  298. } else {
  299. m.Mode = ModeNormal
  300. m.BM.PaletteBuffer.Clear()
  301. m.BM.PaletteBuffer.Insert("moose.error:Unknown palette input \"" + cmd + "\"")
  302. }
  303. },
  304. },
  305. },
  306. }
  307. }