Skip to content

Commit

Permalink
Only append ConjureSchool lessons if they aren't already there
Browse files Browse the repository at this point in the history
Also explain to the user that they've already run a lesson if they try
again and they can undo to reset it. Fixes #355
  • Loading branch information
Olical committed May 28, 2022
1 parent ace0350 commit 2c42367
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 51 deletions.
63 changes: 36 additions & 27 deletions fnl/conjure/school.fnl
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,15 @@
(buffer.upsert-hidden buf-name))

(defn- append [lines]
(let [buf (upsert-buf)]
(nvim.buf_set_lines
buf
(if (buffer.empty? buf) 0 -1)
-1 false lines)))
(let [buf (upsert-buf)
current-buf-str (str.join "\n" (nvim.buf_get_lines 0 0 -1 true))
to-insert-str (str.join "\n" lines)]
(when (not (string.find current-buf-str to-insert-str 0 true))
(nvim.buf_set_lines
buf
(if (buffer.empty? buf) 0 -1)
-1 false lines)
true)))

(defn- map-str [m]
(.. (config.get-in [:mapping :prefix])
Expand All @@ -25,6 +29,11 @@
(defn- progress [n]
(.. "Lesson ["n "/7] complete!"))

(defn- append-or-warn [current-progress lines]
(if (append lines)
(progress current-progress)
"You've already completed this lesson! You can (u)ndo and run it again though if you'd like."))

(defn start []
(when (not (editor.has-filetype? :fennel))
(nvim.echo
Expand Down Expand Up @@ -68,7 +77,8 @@
["(school.lesson-1)"]))))

(defn lesson-1 []
(append
(append-or-warn
1
[""
";; Good job!"
";; You'll notice the heads up display (HUD) appeared showing the result of the evaluation."
Expand All @@ -92,49 +102,49 @@
";; Next, we have a form inside a comment. We want to evaluate that inner form, not the comment."
(.. ";; Place your cursor on the inner form (the one inside the comment) and use " (map-str :eval_current_form) " to evaluate it.")
"(comment"
" (school.lesson-2))"])
(progress 1))
" (school.lesson-2))"]))

(defn lesson-2 []
(append
(append-or-warn
2
[""
";; Awesome! You evaluated the inner form under your cursor."
(.. ";; If we want to evaluate the outermost form under our cursor, we can use " (map-str :eval_root_form) " instead.")
";; Try that below to print some output and advance to the next lesson."
";; You can place your cursor anywhere inside the (do ...) form or it's children."
"(do"
" (print \"Hello, World!\")"
" (school.lesson-3))"])
(progress 2))
" (print \"Hello, World!\")"
" (school.lesson-3))"]))

(defn lesson-3 []
(append
(append-or-warn
3
[""
";; You evaluated the outermost form! Nice!"
";; Notice that the print output was captured and displayed in the log too."
";; The result of every evaluation is stored in a Neovim register as well as the log."
(.. ";; Try pressing \"" (config.get-in [:eval :result_register]) "p to paste the contents of the register into your buffer.")
(.. ";; We can also evaluate a form and replace it with the result of the evaluation with " (map-str :eval_replace_form))
(.. ";; We'll try that in the next lesson, place your cursor inside the form below and press " (map-str :eval_replace_form))
"(school.lesson-4)"])
(progress 3))
"(school.lesson-4)"]))

(defn lesson-4 []
(append
(append-or-warn
4
[""
";; Well done! Notice how the resulting string in the log also replaced the form in the buffer!"
";; Next let's try evaluating a form at a mark."
";; Place your cursor on the next lesson form below and use mf to set the f mark at that location."
(.. ";; Now move your cursor elsewhere in the buffer and use " (map-str :eval_marked_form) "f to evaluate it.")
";; If you use a capital letter like mF you can even open a different file and evaluate that marked form without changing buffers!"
"(school.lesson-5)"])
(progress 4))
"(school.lesson-5)"]))

(def lesson-5-message
"This is the contents of school.lesson-5-message!")

(defn lesson-5 []
(append
(append-or-warn
5
[""
";; Excellent!"
";; This is extremely useful when you want to evaluate a specific form repeatedly as you change code elsewhere in the file or project."
Expand All @@ -145,14 +155,14 @@
""
(.. ";; You can evaluate visual selections with " (map-str :eval_visual))
";; Try evaluating the form below using a visual selection."
"(school.lesson-6)"])
(progress 5))
"(school.lesson-6)"]))

(def lesson-6-message
"This is the contents of school.lesson-6-message!")

(defn lesson-6 []
(append
(append-or-warn
6
[""
";; Wonderful!"
";; Visual evaluation is great for specific sections of a form."
Expand All @@ -161,16 +171,15 @@
"school.lesson-6-message"
""
(.. ";; Use " (map-str :eval_motion) "a( to evaluate the lesson form.")
"(school.lesson-7)"])
(progress 6))
"(school.lesson-7)"]))

(defn lesson-7 []
(append
(append-or-warn
7
[""
";; Excellent job, you made it to the end!"
";; To learn more about configuring Conjure, install the plugin and check out :help conjure"
";; You can learn about specific languages with :help conjure-client- and then tab completion."
";; For example, conjure-client-fennel-aniseed or conjure-client-clojure-nrepl."
""
";; I hope you have a wonderful time in Conjure!"])
(progress 7))
";; I hope you have a wonderful time in Conjure!"]))
56 changes: 32 additions & 24 deletions lua/conjure/school.lua
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,20 @@ end
_2amodule_locals_2a["upsert-buf"] = upsert_buf
local function append(lines)
local buf = upsert_buf()
local _1_
if buffer["empty?"](buf) then
_1_ = 0
local current_buf_str = str.join("\n", nvim.buf_get_lines(0, 0, -1, true))
local to_insert_str = str.join("\n", lines)
if not string.find(current_buf_str, to_insert_str, 0, true) then
local _1_
if buffer["empty?"](buf) then
_1_ = 0
else
_1_ = -1
end
nvim.buf_set_lines(buf, _1_, -1, false, lines)
return true
else
_1_ = -1
return nil
end
return nvim.buf_set_lines(buf, _1_, -1, false, lines)
end
_2amodule_locals_2a["append"] = append
local function map_str(m)
Expand All @@ -43,6 +50,14 @@ local function progress(n)
return ("Lesson [" .. n .. "/7] complete!")
end
_2amodule_locals_2a["progress"] = progress
local function append_or_warn(current_progress, lines)
if append(lines) then
return progress(current_progress)
else
return "You've already completed this lesson! You can (u)ndo and run it again though if you'd like."
end
end
_2amodule_locals_2a["append-or-warn"] = append_or_warn
local function start()
if not editor["has-filetype?"]("fennel") then
nvim.echo("Warning: No Fennel filetype found, falling back to Clojure syntax.", "Install https://github.com/Olical/aniseed for better Fennel support.")
Expand All @@ -56,58 +71,51 @@ local function start()
local buf = upsert_buf()
nvim.ex.edit(buf_name)
nvim.buf_set_lines(buf, 0, -1, false, {})
local _4_
local _6_
if ("<localleader>" == config["get-in"]({"mapping", "prefix"})) then
if a["empty?"](nvim.g.maplocalleader) then
nvim.g.maplocalleader = ","
nvim.ex.edit()
_4_ = {";; Your <localleader> wasn't configured so I've defaulted it to comma (,) for now.", ";; See :help localleader for more information. (let maplocalleader=\",\")"}
_6_ = {";; Your <localleader> wasn't configured so I've defaulted it to comma (,) for now.", ";; See :help localleader for more information. (let maplocalleader=\",\")"}
else
_4_ = {(";; Your <localleader> is currently mapped to \"" .. nvim.g.maplocalleader .. "\"")}
_6_ = {(";; Your <localleader> is currently mapped to \"" .. nvim.g.maplocalleader .. "\"")}
end
else
_4_ = nil
_6_ = nil
end
return append(a.concat({"(module user.conjure-school", " {require {school conjure.school}})", "", ";; Welcome to Conjure school!", ";; Grab yourself a nice beverage and let's get evaluating. I hope you enjoy!", "", ";; This language is Fennel, it's quite similar to Clojure.", ";; Conjure is written in Fennel, it's compiled to Lua and executed inside Neovim itself.", ";; This means we can work with a Lisp without installing or running anything else.", "", ";; Note: Some colorschemes will make the HUD unreadable, see here for more: https://git.io/JJ1Hl", "", ";; Let's learn how to evaluate it using Conjure's assortment of mappings.", ";; You can learn how to change these mappings with :help conjure-mappings", "", (";; Let's begin by evaluating the whole buffer using " .. map_str("eval_buf"))}, _4_, {"(school.lesson-1)"}))
return append(a.concat({"(module user.conjure-school", " {require {school conjure.school}})", "", ";; Welcome to Conjure school!", ";; Grab yourself a nice beverage and let's get evaluating. I hope you enjoy!", "", ";; This language is Fennel, it's quite similar to Clojure.", ";; Conjure is written in Fennel, it's compiled to Lua and executed inside Neovim itself.", ";; This means we can work with a Lisp without installing or running anything else.", "", ";; Note: Some colorschemes will make the HUD unreadable, see here for more: https://git.io/JJ1Hl", "", ";; Let's learn how to evaluate it using Conjure's assortment of mappings.", ";; You can learn how to change these mappings with :help conjure-mappings", "", (";; Let's begin by evaluating the whole buffer using " .. map_str("eval_buf"))}, _6_, {"(school.lesson-1)"}))
end
_2amodule_2a["start"] = start
local function lesson_1()
append({"", ";; Good job!", ";; You'll notice the heads up display (HUD) appeared showing the result of the evaluation.", ";; All results are appended to a log buffer. If that log is not open, the HUD will appear.", ";; The HUD closes automatically when you move your cursor.", "", ";; You can open the log buffer in a few ways:", (";; * Horizontally - " .. map_str("log_split")), (";; * Vertically - " .. map_str("log_vsplit")), (";; * New tab - " .. map_str("log_tab")), "", (";; All visible log windows (including the HUD) can be closed with " .. map_str("log_close_visible")), ";; Try opening and closing the log window to get the hang of those key mappings.", ";; It's a regular window and buffer, so you can edit and close it however you want.", ";; Feel free to leave the log open in a split for the next lesson to see how it behaves.", "", ";; If you ever need to clear your log you can use the reset mappings:", (";; * Soft reset (leaves windows open) - " .. map_str("log_reset_soft")), (";; * Hard reset (closes windows, deletes the buffer) - " .. map_str("log_reset_hard")), "", ";; Next, we have a form inside a comment. We want to evaluate that inner form, not the comment.", (";; Place your cursor on the inner form (the one inside the comment) and use " .. map_str("eval_current_form") .. " to evaluate it."), "(comment", " (school.lesson-2))"})
return progress(1)
return append_or_warn(1, {"", ";; Good job!", ";; You'll notice the heads up display (HUD) appeared showing the result of the evaluation.", ";; All results are appended to a log buffer. If that log is not open, the HUD will appear.", ";; The HUD closes automatically when you move your cursor.", "", ";; You can open the log buffer in a few ways:", (";; * Horizontally - " .. map_str("log_split")), (";; * Vertically - " .. map_str("log_vsplit")), (";; * New tab - " .. map_str("log_tab")), "", (";; All visible log windows (including the HUD) can be closed with " .. map_str("log_close_visible")), ";; Try opening and closing the log window to get the hang of those key mappings.", ";; It's a regular window and buffer, so you can edit and close it however you want.", ";; Feel free to leave the log open in a split for the next lesson to see how it behaves.", "", ";; If you ever need to clear your log you can use the reset mappings:", (";; * Soft reset (leaves windows open) - " .. map_str("log_reset_soft")), (";; * Hard reset (closes windows, deletes the buffer) - " .. map_str("log_reset_hard")), "", ";; Next, we have a form inside a comment. We want to evaluate that inner form, not the comment.", (";; Place your cursor on the inner form (the one inside the comment) and use " .. map_str("eval_current_form") .. " to evaluate it."), "(comment", " (school.lesson-2))"})
end
_2amodule_2a["lesson-1"] = lesson_1
local function lesson_2()
append({"", ";; Awesome! You evaluated the inner form under your cursor.", (";; If we want to evaluate the outermost form under our cursor, we can use " .. map_str("eval_root_form") .. " instead."), ";; Try that below to print some output and advance to the next lesson.", ";; You can place your cursor anywhere inside the (do ...) form or it's children.", "(do", " (print \"Hello, World!\")", " (school.lesson-3))"})
return progress(2)
return append_or_warn(2, {"", ";; Awesome! You evaluated the inner form under your cursor.", (";; If we want to evaluate the outermost form under our cursor, we can use " .. map_str("eval_root_form") .. " instead."), ";; Try that below to print some output and advance to the next lesson.", ";; You can place your cursor anywhere inside the (do ...) form or it's children.", "(do", " (print \"Hello, World!\")", " (school.lesson-3))"})
end
_2amodule_2a["lesson-2"] = lesson_2
local function lesson_3()
append({"", ";; You evaluated the outermost form! Nice!", ";; Notice that the print output was captured and displayed in the log too.", ";; The result of every evaluation is stored in a Neovim register as well as the log.", (";; Try pressing \"" .. config["get-in"]({"eval", "result_register"}) .. "p to paste the contents of the register into your buffer."), (";; We can also evaluate a form and replace it with the result of the evaluation with " .. map_str("eval_replace_form")), (";; We'll try that in the next lesson, place your cursor inside the form below and press " .. map_str("eval_replace_form")), "(school.lesson-4)"})
return progress(3)
return append_or_warn(3, {"", ";; You evaluated the outermost form! Nice!", ";; Notice that the print output was captured and displayed in the log too.", ";; The result of every evaluation is stored in a Neovim register as well as the log.", (";; Try pressing \"" .. config["get-in"]({"eval", "result_register"}) .. "p to paste the contents of the register into your buffer."), (";; We can also evaluate a form and replace it with the result of the evaluation with " .. map_str("eval_replace_form")), (";; We'll try that in the next lesson, place your cursor inside the form below and press " .. map_str("eval_replace_form")), "(school.lesson-4)"})
end
_2amodule_2a["lesson-3"] = lesson_3
local function lesson_4()
append({"", ";; Well done! Notice how the resulting string in the log also replaced the form in the buffer!", ";; Next let's try evaluating a form at a mark.", ";; Place your cursor on the next lesson form below and use mf to set the f mark at that location.", (";; Now move your cursor elsewhere in the buffer and use " .. map_str("eval_marked_form") .. "f to evaluate it."), ";; If you use a capital letter like mF you can even open a different file and evaluate that marked form without changing buffers!", "(school.lesson-5)"})
return progress(4)
return append_or_warn(4, {"", ";; Well done! Notice how the resulting string in the log also replaced the form in the buffer!", ";; Next let's try evaluating a form at a mark.", ";; Place your cursor on the next lesson form below and use mf to set the f mark at that location.", (";; Now move your cursor elsewhere in the buffer and use " .. map_str("eval_marked_form") .. "f to evaluate it."), ";; If you use a capital letter like mF you can even open a different file and evaluate that marked form without changing buffers!", "(school.lesson-5)"})
end
_2amodule_2a["lesson-4"] = lesson_4
local lesson_5_message = "This is the contents of school.lesson-5-message!"
_2amodule_2a["lesson-5-message"] = lesson_5_message
local function lesson_5()
append({"", ";; Excellent!", ";; This is extremely useful when you want to evaluate a specific form repeatedly as you change code elsewhere in the file or project.", (";; Try inspecting the contents of the variable below by placing your cursor on it and pressing " .. map_str("eval_word")), "school.lesson-5-message", "", ";; You should see the contents in the HUD or log.", "", (";; You can evaluate visual selections with " .. map_str("eval_visual")), ";; Try evaluating the form below using a visual selection.", "(school.lesson-6)"})
return progress(5)
return append_or_warn(5, {"", ";; Excellent!", ";; This is extremely useful when you want to evaluate a specific form repeatedly as you change code elsewhere in the file or project.", (";; Try inspecting the contents of the variable below by placing your cursor on it and pressing " .. map_str("eval_word")), "school.lesson-5-message", "", ";; You should see the contents in the HUD or log.", "", (";; You can evaluate visual selections with " .. map_str("eval_visual")), ";; Try evaluating the form below using a visual selection.", "(school.lesson-6)"})
end
_2amodule_2a["lesson-5"] = lesson_5
local lesson_6_message = "This is the contents of school.lesson-6-message!"
_2amodule_2a["lesson-6-message"] = lesson_6_message
local function lesson_6()
append({"", ";; Wonderful!", ";; Visual evaluation is great for specific sections of a form.", (";; You can also evaluate a given motion with " .. map_str("eval_motion")), (";; Try " .. map_str("eval_motion") .. "iw below to evaluate the word."), "school.lesson-6-message", "", (";; Use " .. map_str("eval_motion") .. "a( to evaluate the lesson form."), "(school.lesson-7)"})
return progress(6)
return append_or_warn(6, {"", ";; Wonderful!", ";; Visual evaluation is great for specific sections of a form.", (";; You can also evaluate a given motion with " .. map_str("eval_motion")), (";; Try " .. map_str("eval_motion") .. "iw below to evaluate the word."), "school.lesson-6-message", "", (";; Use " .. map_str("eval_motion") .. "a( to evaluate the lesson form."), "(school.lesson-7)"})
end
_2amodule_2a["lesson-6"] = lesson_6
local function lesson_7()
append({"", ";; Excellent job, you made it to the end!", ";; To learn more about configuring Conjure, install the plugin and check out :help conjure", ";; You can learn about specific languages with :help conjure-client- and then tab completion.", ";; For example, conjure-client-fennel-aniseed or conjure-client-clojure-nrepl.", "", ";; I hope you have a wonderful time in Conjure!"})
return progress(7)
return append_or_warn(7, {"", ";; Excellent job, you made it to the end!", ";; To learn more about configuring Conjure, install the plugin and check out :help conjure", ";; You can learn about specific languages with :help conjure-client- and then tab completion.", ";; For example, conjure-client-fennel-aniseed or conjure-client-clojure-nrepl.", "", ";; I hope you have a wonderful time in Conjure!"})
end
_2amodule_2a["lesson-7"] = lesson_7
return _2amodule_2a

0 comments on commit 2c42367

Please sign in to comment.