diff --git a/http_mutators.go b/http_mutators.go
index d7569f5..31f9915 100644
--- a/http_mutators.go
+++ b/http_mutators.go
@@ -39,7 +39,11 @@ func handlerRenameConfirm(w http.ResponseWriter, rq *http.Request) {
hyphaData, isOld = HyphaStorage[hyphaName]
newName = CanonicalName(rq.PostFormValue("new-name"))
_, newNameIsUsed = HyphaStorage[newName]
+ recursive bool
)
+ if rq.PostFormValue("recursive") == "true" {
+ recursive = true
+ }
switch {
case newNameIsUsed:
HttpErr(w, http.StatusBadRequest, hyphaName, "Error: hypha exists",
@@ -54,7 +58,7 @@ func handlerRenameConfirm(w http.ResponseWriter, rq *http.Request) {
HttpErr(w, http.StatusBadRequest, hyphaName, "Error: invalid name",
"Invalid new name. Names cannot contain characters If you rename this hypha, all incoming links and all relative outcoming links will break. You will also lose all history for the new name. Rename carefully.^?!:#@><*|\"\\'&%
")
default:
- if hop := hyphaData.RenameHypha(hyphaName, newName); len(hop.Errs) == 0 {
+ if hop := hyphaData.RenameHypha(hyphaName, newName, recursive); len(hop.Errs) == 0 {
http.Redirect(w, rq, "/page/"+newName, http.StatusSeeOther)
} else {
HttpErr(w, http.StatusInternalServerError, hyphaName,
diff --git a/hypha.go b/hypha.go
index d6920a3..74a8685 100644
--- a/hypha.go
+++ b/hypha.go
@@ -11,6 +11,7 @@ import (
"github.com/bouncepaw/mycorrhiza/gemtext"
"github.com/bouncepaw/mycorrhiza/history"
+ "github.com/bouncepaw/mycorrhiza/util"
)
func init() {
@@ -52,25 +53,61 @@ func (hd *HyphaData) DeleteHypha(hyphaName string) *history.HistoryOp {
return hop
}
-// RenameHypha renames hypha from old name `hyphaName` to `newName` and makes a history record about that.
-func (hd *HyphaData) RenameHypha(hyphaName, newName string) *history.HistoryOp {
+func findHyphaeToRename(hyphaName string, recursive bool) []string {
+ hyphae := []string{hyphaName}
+ if recursive {
+ hyphae = append(hyphae, util.FindSubhyphae(hyphaName, IterateHyphaNamesWith)...)
+ }
+ return hyphae
+}
+
+func renamingPairs(hyphaNames []string, replaceName func(string) string) map[string]string {
+ renameMap := make(map[string]string)
+ for _, hn := range hyphaNames {
+ if hd, ok := HyphaStorage[hn]; ok {
+ if hd.textPath != "" {
+ renameMap[hd.textPath] = replaceName(hd.textPath)
+ }
+ if hd.binaryPath != "" {
+ renameMap[hd.binaryPath] = replaceName(hd.binaryPath)
+ }
+ }
+ }
+ return renameMap
+}
+
+// word Data is plural here
+func relocateHyphaData(hyphaNames []string, replaceName func(string) string) {
+ for _, hyphaName := range hyphaNames {
+ if hd, ok := HyphaStorage[hyphaName]; ok {
+ hd.textPath = replaceName(hd.textPath)
+ hd.binaryPath = replaceName(hd.binaryPath)
+ HyphaStorage[replaceName(hyphaName)] = hd
+ delete(HyphaStorage, hyphaName)
+ }
+ }
+}
+
+// RenameHypha renames hypha from old name `hyphaName` to `newName` and makes a history record about that. If `recursive` is `true`, its subhyphae will be renamed the same way.
+func (hd *HyphaData) RenameHypha(hyphaName, newName string, recursive bool) *history.HistoryOp {
var (
- newTextPath = strings.Replace(hd.textPath, hyphaName, newName, 1)
- newBinaryPath = strings.Replace(hd.binaryPath, hyphaName, newName, 1)
- hop = history.Operation(history.TypeRenameHypha).
- WithFilesRenamed(map[string]string{
- hd.textPath: newTextPath,
- hd.binaryPath: newBinaryPath,
- }).
- WithMsg(fmt.Sprintf("Rename ‘%s’ to ‘%s’", hyphaName, newName)).
- WithSignature("anon").
- Apply()
+ replaceName = func(str string) string {
+ return strings.Replace(str, hyphaName, newName, 1)
+ }
+ hyphaNames = findHyphaeToRename(hyphaName, recursive)
+ renameMap = renamingPairs(hyphaNames, replaceName)
+ renameMsg = "Rename ‘%s’ to ‘%s’"
+ hop = history.Operation(history.TypeRenameHypha)
)
+ if recursive {
+ renameMsg += " recursively"
+ }
+ hop.WithFilesRenamed(renameMap).
+ WithMsg(fmt.Sprintf(renameMsg, hyphaName, newName)).
+ WithSignature("anon").
+ Apply()
if len(hop.Errs) == 0 {
- hd.textPath = newTextPath
- hd.binaryPath = newBinaryPath
- HyphaStorage[newName] = hd
- delete(HyphaStorage, hyphaName)
+ relocateHyphaData(hyphaNames, replaceName)
}
return hop
}
diff --git a/templates/rename.qtpl b/templates/rename.qtpl
index 64d20e8..77e4e56 100644
--- a/templates/rename.qtpl
+++ b/templates/rename.qtpl
@@ -6,11 +6,20 @@ This dialog is to be shown to a user when they try to rename a hypha.
Rename {%s hyphaName %}
-
If you rename this hypha, all incoming links and all relative outcoming links will break. You will also lose all history for the new name. Rename carefully.
-If you rename this hypha, all incoming links and all relative outcoming links will break. You will also lose all history for the new name. Rename carefully.
`) -//line templates/rename.qtpl:15 +//line templates/rename.qtpl:24 } else { -//line templates/rename.qtpl:15 +//line templates/rename.qtpl:24 qw422016.N().S(` `) -//line templates/rename.qtpl:16 +//line templates/rename.qtpl:25 streamcannotRenameDueToNonExistence(qw422016, hyphaName) -//line templates/rename.qtpl:16 +//line templates/rename.qtpl:25 qw422016.N().S(` `) -//line templates/rename.qtpl:17 +//line templates/rename.qtpl:26 } -//line templates/rename.qtpl:17 +//line templates/rename.qtpl:26 qw422016.N().S(` `) -//line templates/rename.qtpl:19 +//line templates/rename.qtpl:28 } -//line templates/rename.qtpl:19 +//line templates/rename.qtpl:28 func WriteRenameAskHTML(qq422016 qtio422016.Writer, hyphaName string, isOld bool) { -//line templates/rename.qtpl:19 +//line templates/rename.qtpl:28 qw422016 := qt422016.AcquireWriter(qq422016) -//line templates/rename.qtpl:19 +//line templates/rename.qtpl:28 StreamRenameAskHTML(qw422016, hyphaName, isOld) -//line templates/rename.qtpl:19 +//line templates/rename.qtpl:28 qt422016.ReleaseWriter(qw422016) -//line templates/rename.qtpl:19 +//line templates/rename.qtpl:28 } -//line templates/rename.qtpl:19 +//line templates/rename.qtpl:28 func RenameAskHTML(hyphaName string, isOld bool) string { -//line templates/rename.qtpl:19 +//line templates/rename.qtpl:28 qb422016 := qt422016.AcquireByteBuffer() -//line templates/rename.qtpl:19 +//line templates/rename.qtpl:28 WriteRenameAskHTML(qb422016, hyphaName, isOld) -//line templates/rename.qtpl:19 +//line templates/rename.qtpl:28 qs422016 := string(qb422016.B) -//line templates/rename.qtpl:19 +//line templates/rename.qtpl:28 qt422016.ReleaseByteBuffer(qb422016) -//line templates/rename.qtpl:19 +//line templates/rename.qtpl:28 return qs422016 -//line templates/rename.qtpl:19 +//line templates/rename.qtpl:28 } -//line templates/rename.qtpl:21 +//line templates/rename.qtpl:30 func streamcannotRenameDueToNonExistence(qw422016 *qt422016.Writer, hyphaName string) { -//line templates/rename.qtpl:21 +//line templates/rename.qtpl:30 qw422016.N().S(`This hypha does not exist.