Merge branch 'master' into editor-flag-fix
This commit is contained in:
commit
06f9a46403
4
go.mod
4
go.mod
@ -3,7 +3,7 @@ module github.com/bouncepaw/mycorrhiza
|
|||||||
go 1.16
|
go 1.16
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/bouncepaw/mycomarkup v1.0.1
|
github.com/bouncepaw/mycomarkup v1.0.3
|
||||||
github.com/go-ini/ini v1.62.0
|
github.com/go-ini/ini v1.62.0
|
||||||
github.com/gorilla/feeds v1.1.1
|
github.com/gorilla/feeds v1.1.1
|
||||||
github.com/gorilla/mux v1.8.0
|
github.com/gorilla/mux v1.8.0
|
||||||
@ -17,4 +17,4 @@ require (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Use this trick to test mycomarkup:
|
// Use this trick to test mycomarkup:
|
||||||
// replace github.com/bouncepaw/mycomarkup v1.0.1 => "/Users/bouncepaw/GolandProjects/mycomarkup"
|
// replace github.com/bouncepaw/mycomarkup v1.0.3 => "/Users/bouncepaw/GolandProjects/mycomarkup"
|
||||||
|
|||||||
4
go.sum
4
go.sum
@ -1,6 +1,6 @@
|
|||||||
github.com/andybalholm/brotli v1.0.0/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
|
github.com/andybalholm/brotli v1.0.0/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
|
||||||
github.com/bouncepaw/mycomarkup v1.0.1 h1:6GEpc49KtoCoP9XMn4hLq4FJrGK8r2NJ3yXHmS0qTRs=
|
github.com/bouncepaw/mycomarkup v1.0.3 h1:FrL7VxS9wZDE+E0ROimf/fDgqUSvMJ2CIX1eKTdmAPQ=
|
||||||
github.com/bouncepaw/mycomarkup v1.0.1/go.mod h1:0n6thlGGgrx2Y/2NaaUH4qHW4v1xJ+EpW7yMFUxNRIg=
|
github.com/bouncepaw/mycomarkup v1.0.3/go.mod h1:0n6thlGGgrx2Y/2NaaUH4qHW4v1xJ+EpW7yMFUxNRIg=
|
||||||
github.com/go-ini/ini v1.62.0 h1:7VJT/ZXjzqSrvtraFp4ONq80hTcRQth1c9ZnQ3uNQvU=
|
github.com/go-ini/ini v1.62.0 h1:7VJT/ZXjzqSrvtraFp4ONq80hTcRQth1c9ZnQ3uNQvU=
|
||||||
github.com/go-ini/ini v1.62.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
|
github.com/go-ini/ini v1.62.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package shroom
|
package shroom
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/bouncepaw/mycorrhiza/hyphae"
|
"github.com/bouncepaw/mycorrhiza/hyphae"
|
||||||
@ -11,11 +12,33 @@ func YieldHyphaNamesContainingString(query string) <-chan string {
|
|||||||
query = util.CanonicalName(query)
|
query = util.CanonicalName(query)
|
||||||
out := make(chan string)
|
out := make(chan string)
|
||||||
go func() {
|
go func() {
|
||||||
|
// To make it unicode-friendly and lean, we cast every string into rune slices, sort, and only then cast them back
|
||||||
|
raw := make([][]rune, 0)
|
||||||
for h := range hyphae.YieldExistingHyphae() {
|
for h := range hyphae.YieldExistingHyphae() {
|
||||||
if hyphaNameMatchesString(h.Name, query) {
|
if hyphaNameMatchesString(h.Name, query) {
|
||||||
out <- h.Name
|
raw = append(raw, []rune(h.Name))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
sort.Slice(raw, func(i, j int) bool {
|
||||||
|
const slash rune = 47 // == '/'
|
||||||
|
// Classic lexicographical sort with a twist
|
||||||
|
c := 0
|
||||||
|
for {
|
||||||
|
if c == len(raw[i]) { return true }
|
||||||
|
if c == len(raw[j]) { return false }
|
||||||
|
if raw[i][c] == raw[j][c] {
|
||||||
|
c++
|
||||||
|
} else {
|
||||||
|
// The twist: subhyphae-awareness is about pushing slash upwards
|
||||||
|
if raw[i][c] == slash { return true }
|
||||||
|
if raw[j][c] == slash { return false }
|
||||||
|
return raw[i][c] < raw[j][c]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
for _, name := range raw {
|
||||||
|
out <- string(name)
|
||||||
|
}
|
||||||
close(out)
|
close(out)
|
||||||
}()
|
}()
|
||||||
return out
|
return out
|
||||||
|
|||||||
@ -5,6 +5,11 @@ function placeCursor(position, el = editTextarea) {
|
|||||||
el.selectionStart = el.selectionEnd
|
el.selectionStart = el.selectionEnd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function selectRange(left, right, el = editTextarea) {
|
||||||
|
el.selectionEnd = right
|
||||||
|
el.selectionStart = left
|
||||||
|
}
|
||||||
|
|
||||||
function getSelectedText(el = editTextarea) {
|
function getSelectedText(el = editTextarea) {
|
||||||
const [start, end] = [el.selectionStart, el.selectionEnd]
|
const [start, end] = [el.selectionStart, el.selectionEnd]
|
||||||
const text = el.value
|
const text = el.value
|
||||||
@ -13,7 +18,7 @@ function getSelectedText(el = editTextarea) {
|
|||||||
|
|
||||||
function textInserter(text, cursorPosition = null, el = editTextarea) {
|
function textInserter(text, cursorPosition = null, el = editTextarea) {
|
||||||
return function() {
|
return function() {
|
||||||
window.hyphaChanged = true;
|
window.hyphaChanged = true
|
||||||
const [start, end] = [el.selectionStart, el.selectionEnd]
|
const [start, end] = [el.selectionStart, el.selectionEnd]
|
||||||
el.setRangeText(text, start, end, 'select')
|
el.setRangeText(text, start, end, 'select')
|
||||||
el.focus()
|
el.focus()
|
||||||
@ -27,16 +32,36 @@ function textInserter(text, cursorPosition = null, el = editTextarea) {
|
|||||||
|
|
||||||
function selectionWrapper(cursorPosition, prefix, postfix = null, el = editTextarea) {
|
function selectionWrapper(cursorPosition, prefix, postfix = null, el = editTextarea) {
|
||||||
return function() {
|
return function() {
|
||||||
window.hyphaChanged = true;
|
window.hyphaChanged = true
|
||||||
const [start, end] = [el.selectionStart, el.selectionEnd]
|
let [start, end] = [el.selectionStart, el.selectionEnd]
|
||||||
if (postfix == null) {
|
if (postfix == null) {
|
||||||
postfix = prefix
|
postfix = prefix
|
||||||
}
|
}
|
||||||
let text = getSelectedText(el)
|
let text = getSelectedText(el)
|
||||||
let result = prefix + text + postfix
|
let removing = false
|
||||||
|
let result
|
||||||
|
if (text.startsWith(prefix) && text.endsWith(postfix)) {
|
||||||
|
// selection is decorated, so we just cut it
|
||||||
|
removing = true
|
||||||
|
result = text.substring(cursorPosition, text.length - cursorPosition)
|
||||||
|
} else if ( (prefix == el.value.slice(start-cursorPosition, start)) &&
|
||||||
|
(postfix == el.value.slice(end, end+cursorPosition)) ) {
|
||||||
|
// selection is surrounded by decorations
|
||||||
|
removing = true
|
||||||
|
result = text
|
||||||
|
start -= cursorPosition
|
||||||
|
end += cursorPosition
|
||||||
|
} else {
|
||||||
|
// no decorations, so we add them
|
||||||
|
result = prefix + text + postfix
|
||||||
|
}
|
||||||
el.setRangeText(result, start, end, 'select')
|
el.setRangeText(result, start, end, 'select')
|
||||||
el.focus()
|
el.focus()
|
||||||
placeCursor(end + cursorPosition)
|
if (removing) {
|
||||||
|
selectRange(start, end-cursorPosition*2)
|
||||||
|
} else {
|
||||||
|
selectRange(start+cursorPosition, end+cursorPosition)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user