Skip to content

Commit

Permalink
feat(tidy-up): remove unnecessary brackets from tags in Go
Browse files Browse the repository at this point in the history
  • Loading branch information
andreoliwa committed Dec 30, 2024
1 parent 9673709 commit 761c11a
Show file tree
Hide file tree
Showing 7 changed files with 125 additions and 31 deletions.
3 changes: 3 additions & 0 deletions cmd/testdata/graph/pages/tag-brackets.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
- here is some #[[tag]]
- and here is one #[[tag with spaces]]
- text before #[[some-tag]] then after
3 changes: 3 additions & 0 deletions cmd/testdata/graph/pages/tag-brackets.md.golden
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
- here is some #tag
- and here is one #[[tag with spaces]]
- text before #some-tag then after
101 changes: 79 additions & 22 deletions cmd/tidy_up.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,48 @@ var tidyUpCmd = &cobra.Command{ //nolint:exhaustruct,gochecknoglobals
}

transaction := graph.NewTransaction()
shouldSave := false
commit := false

exitCode := 0
for _, path := range args {
if !isValidMarkdownFile(path) {
fmt.Printf("%s: skipping, not a Markdown file\n", path)
} else {
// Some fixes still need modifications directly on the file contents.
// We will do them first, and apply each function on top of the previously modified contents.
bytes, err := os.ReadFile(path)
if err != nil {
log.Fatalf("%s: error reading file contents: %s\n", path, err)
}
currentFileContents := string(bytes)

fileInfo, err := os.Stat(path)
if err != nil {
log.Fatalf("%s: error getting file info: %s\n", path, err)
}

messages := make([]string, 0)

write := false
for _, f := range []func(string) changedContents{
removeUnnecessaryBracketsFromTags,
} {
result := f(currentFileContents)
if result.msg != "" {
messages = append(messages, result.msg)
// Pass the new contents to the next function.
currentFileContents = result.newContents
write = true
}
}
if write {
err := os.WriteFile(path, []byte(currentFileContents), fileInfo.Mode())
if err != nil {
log.Fatalf("%s: error writing file contents: %s\n", path, err)
}
}

// Now we will apply the functions that modify the Markdown through a Page and a transaction.
page, err := transaction.OpenViaPath(path)
if err != nil {
log.Fatalf("%s: error opening file via path: %s\n", path, err)
Expand All @@ -52,17 +87,15 @@ var tidyUpCmd = &cobra.Command{ //nolint:exhaustruct,gochecknoglobals
log.Fatalf("%s: error opening file via path: page is nil\n", path)
}

messages := make([]string, 0)

functions := []func(logseq.Page) tidyInfo{
checkForbiddenReferences, checkRunningTasks, removeDoubleSpaces}
for _, f := range functions {
info := f(page)
if info.msg != "" {
messages = append(messages, info.msg)
for _, f := range []func(logseq.Page) changedPage{
checkForbiddenReferences, checkRunningTasks, removeDoubleSpaces,
} {
result := f(page)
if result.msg != "" {
messages = append(messages, result.msg)
}
if info.changed {
shouldSave = true
if result.changed {
commit = true
}
}

Expand All @@ -74,7 +107,7 @@ var tidyUpCmd = &cobra.Command{ //nolint:exhaustruct,gochecknoglobals
}
}
}
if shouldSave {
if commit {
err = transaction.Save()
if err != nil {
log.Fatalf("error saving transaction: %s\n", err)
Expand Down Expand Up @@ -106,13 +139,20 @@ func isValidMarkdownFile(filePath string) bool {
return !info.IsDir()
}

type tidyInfo struct {
// changedContents is the result of a check function that modifies file contents directly without a transaction.
type changedContents struct {
msg string
newContents string
}

// changedPage is the result of a check function that modifies Markdown through a Page and a transaction.
type changedPage struct {
msg string
changed bool
}

// checkForbiddenReferences checks if a page has forbidden references to other pages or tags.
func checkForbiddenReferences(page logseq.Page) tidyInfo {
func checkForbiddenReferences(page logseq.Page) changedPage {
all := make([]string, 0)

for _, block := range page.Blocks() {
Expand Down Expand Up @@ -145,11 +185,11 @@ func checkForbiddenReferences(page logseq.Page) tidyInfo {
if count := len(all); count > 0 {
unique := sortAndRemoveDuplicates(all)

return tidyInfo{fmt.Sprintf("remove %d forbidden references to pages/tags: %s",
return changedPage{fmt.Sprintf("remove %d forbidden references to pages/tags: %s",
count, strings.Join(unique, ", ")), false}
}

return tidyInfo{"", false}
return changedPage{"", false}
}

func sortAndRemoveDuplicates(elements []string) []string {
Expand All @@ -170,7 +210,7 @@ func sortAndRemoveDuplicates(elements []string) []string {
}

// checkRunningTasks checks if a page has running tasks (DOING, etc.).
func checkRunningTasks(page logseq.Page) tidyInfo {
func checkRunningTasks(page logseq.Page) changedPage {
all := make([]string, 0)

for _, block := range page.Blocks() {
Expand All @@ -194,13 +234,13 @@ func checkRunningTasks(page logseq.Page) tidyInfo {
if count := len(all); count > 0 {
unique := sortAndRemoveDuplicates(all)

return tidyInfo{fmt.Sprintf("stop %d running task(s): %s", count, strings.Join(unique, ", ")), false}
return changedPage{fmt.Sprintf("stop %d running task(s): %s", count, strings.Join(unique, ", ")), false}
}

return tidyInfo{"", false}
return changedPage{"", false}
}

func removeDoubleSpaces(page logseq.Page) tidyInfo {
func removeDoubleSpaces(page logseq.Page) changedPage {
all := make([]string, 0)
doubleSpaceRegex := regexp.MustCompile(`\s{2,}`)
fixed := false
Expand Down Expand Up @@ -238,8 +278,25 @@ func removeDoubleSpaces(page logseq.Page) tidyInfo {
if count := len(all); count > 0 {
unique := sortAndRemoveDuplicates(all)

return tidyInfo{fmt.Sprintf("fixed %d double spaces: %s", count, strings.Join(unique, ", ")), fixed}
return changedPage{fmt.Sprintf("fixed %d double spaces: %s", count, strings.Join(unique, ", ")), fixed}
}

return changedPage{"", fixed}
}

// removeUnnecessaryBracketsFromTags removes unnecessary brackets from hashtags.
// logseq-go rewrites tags correctly when saving the transaction, removing unnecessary brackets.
// But, when reading the file, the AST doesn't provide the information if a tag has brackets or not.
// So I would have to rewrite the file to fix them, and I don't want to do it every time there is a tag without spaces.
// Also, as of 2024-12-30, logseq-go has a bug when reading properties with spaces in values,
// which causes them to be partially removed from the file, destroying data. I will report it soon.
func removeUnnecessaryBracketsFromTags(oldContents string) changedContents {
re := regexp.MustCompile(`#\[\[([^ ]*?)]]`)

newContents := re.ReplaceAllString(oldContents, "#$1")
if newContents != oldContents {
return changedContents{"removed unnecessary brackets from tags", newContents}
}

return tidyInfo{"", fixed}
return changedContents{"", ""}
}
42 changes: 36 additions & 6 deletions cmd/tidy_up_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (

"github.com/andreoliwa/logseq-go"
"github.com/stretchr/testify/assert"
"gotest.tools/v3/golden"
)

func TestSortAndRemoveDuplicates(t *testing.T) {
Expand Down Expand Up @@ -91,27 +92,46 @@ func setupPage(t *testing.T, name string) logseq.Page {
return page
}

type resultSetupFileContents struct {
oldContents string
goldenPath string
}

func setupFileContents(t *testing.T, name string) resultSetupFileContents {
t.Helper()

subdir := filepath.Join("graph", "pages", name+".md")
path := filepath.Join("testdata", subdir)

bytes, err := os.ReadFile(path)
if err != nil {
t.Fatal(err)
}

return resultSetupFileContents{string(bytes), subdir + ".golden"}
}

func TestCheckForbiddenReferences(t *testing.T) {
invalid := setupPage(t, "forbidden")
assert.Equal(t, tidyInfo{"remove 4 forbidden references to pages/tags: Inbox, quick capture", false},
assert.Equal(t, changedPage{"remove 4 forbidden references to pages/tags: Inbox, quick capture", false},
checkForbiddenReferences(invalid))

valid := setupPage(t, "valid")
assert.Equal(t, tidyInfo{"", false}, checkForbiddenReferences(valid))
assert.Equal(t, changedPage{"", false}, checkForbiddenReferences(valid))
}

func TestCheckRunningTasks(t *testing.T) {
invalid := setupPage(t, "running")
assert.Equal(t, tidyInfo{"stop 2 running task(s): DOING, IN-PROGRESS", false}, checkRunningTasks(invalid))
assert.Equal(t, changedPage{"stop 2 running task(s): DOING, IN-PROGRESS", false}, checkRunningTasks(invalid))

valid := setupPage(t, "valid")
assert.Equal(t, tidyInfo{"", false}, checkRunningTasks(valid))
assert.Equal(t, changedPage{"", false}, checkRunningTasks(valid))
}

func TestRemoveDoubleSpaces(t *testing.T) {
invalid := setupPage(t, "spaces")
assert.Equal(t,
tidyInfo{"fixed 4 double spaces: 'Link With Spaces ', 'Regular text with spaces'," +
changedPage{"fixed 4 double spaces: 'Link With Spaces ', 'Regular text with spaces'," +
" 'some page title with spaces', 'some tag with spaces'", true},
removeDoubleSpaces(invalid))

Expand All @@ -122,5 +142,15 @@ func TestRemoveDoubleSpaces(t *testing.T) {
// assert.Equal(t, expected, actual)

valid := setupPage(t, "valid")
assert.Equal(t, tidyInfo{"", false}, removeDoubleSpaces(valid))
assert.Equal(t, changedPage{"", false}, removeDoubleSpaces(valid))
}

func TestRemoveUnnecessaryBracketsFromTags(t *testing.T) {
invalid := setupFileContents(t, "tag-brackets")
changed := removeUnnecessaryBracketsFromTags(invalid.oldContents)
assert.Equal(t, "removed unnecessary brackets from tags", changed.msg)
golden.Assert(t, changed.newContents, invalid.goldenPath)

valid := setupFileContents(t, "valid")
assert.Equal(t, changedContents{"", ""}, removeUnnecessaryBracketsFromTags(valid.oldContents))
}
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ require (
github.com/andreoliwa/logseq-go v0.0.0-20241228161444-32088a5a9491
github.com/spf13/cobra v1.8.1
github.com/stretchr/testify v1.10.0
gotest.tools/v3 v3.5.1
)

require (
Expand All @@ -28,6 +29,7 @@ require (
github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140 // indirect
github.com/fsnotify/fsnotify v1.8.0 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/kamstrup/intmap v0.5.1 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,8 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU=
gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=
olympos.io/encoding/edn v0.0.0-20201019073823-d3554ca0b0a3 h1:slmdOY3vp8a7KQbHkL+FLbvbkgMqmXojpFUO/jENuqQ=
olympos.io/encoding/edn v0.0.0-20201019073823-d3554ca0b0a3/go.mod h1:oVgVk4OWVDi43qWBEyGhXgYxt7+ED4iYNpTngSLX2Iw=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
3 changes: 0 additions & 3 deletions python/logseq_doctor/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,9 +124,6 @@ def tidy_up(
changed.append("empty bullets")
each_file.write_text(rm_empty_bullets)

if rust_ext.tidy_up(each_file):
changed.append("brackets")

if changed:
if not exit_code:
exit_code = 1
Expand Down

0 comments on commit 761c11a

Please sign in to comment.