Skip to content

Commit

Permalink
feat: consider uris with custom schemes as bookmarks
Browse files Browse the repository at this point in the history
  • Loading branch information
dhth committed Jul 31, 2024
1 parent 44aeaa2 commit de6c86b
Show file tree
Hide file tree
Showing 13 changed files with 175 additions and 74 deletions.
23 changes: 14 additions & 9 deletions cmd/assets/guide/domain-task-bookmarks.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
Sometimes you'll add URLs to a task's summary or its context.
Sometimes you'll add URIs to a task's summary or its context.

Such URLs (eg. https://github.com/dhth/omm, https://tools.dhruvs.space,
https://c.xkcd.com/random/comic) could be placed anywhere in the
summary/context.
Such URIs could be placed anywhere in the summary/context. For example:

omm lets you open these URLs via a single keypress. You can either press `b` to
open up a list of all URLs, and then open one of them by pressing `` or open
all of them by pressing `B`.
- https://c.xkcd.com/random/comic
- spotify:track:4fVBFyglBhMf0erfF7pBJp
- obsidian://open?vault=VAULT&file=FILE
- mailto:example@example.com
- slack://channel?team=TEAM_ID&id=ID

Note: If a task has a single URL added to it, pressing `b` will skip showing the
list, and open the URL directly.
omm lets you open these URIs via a single keypress. You can either press `b` to
open up a list of all URIs, and then open one of them by pressing `` or open
all of them by pressing `B` (some of them will fail to be opened on your machine
since they point to non-existent resources, but you get the point).

Note: If a task has a single URI added to it, pressing `b` will skip showing the
list, and open the URI directly.

Try both approaches now.
20 changes: 20 additions & 0 deletions internal/types/colors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package types

var (
colors = []string{
"#d3869b",
"#b5e48c",
"#90e0ef",
"#ca7df9",
"#ada7ff",
"#bbd0ff",
"#48cae4",
"#8187dc",
"#ffb4a2",
"#b8bb26",
"#ffc6ff",
"#4895ef",
"#83a598",
"#fabd2f",
}
)
20 changes: 2 additions & 18 deletions internal/types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,23 +26,7 @@ const (
var (
createdAtColor = "#928374"
hasContextColor = "#928374"
taskColors = []string{
"#d3869b",
"#b5e48c",
"#90e0ef",
"#ca7df9",
"#ada7ff",
"#bbd0ff",
"#48cae4",
"#8187dc",
"#ffb4a2",
"#b8bb26",
"#ffc6ff",
"#4895ef",
"#83a598",
"#fabd2f",
}
createdAtStyle = lipgloss.NewStyle().
createdAtStyle = lipgloss.NewStyle().
Foreground(lipgloss.Color(createdAtColor))

hasContextStyle = lipgloss.NewStyle().
Expand Down Expand Up @@ -155,7 +139,7 @@ func GetDynamicStyle(str string) lipgloss.Style {
h.Write([]byte(str))
hash := h.Sum32()

color := taskColors[int(hash)%len(taskColors)]
color := colors[int(hash)%len(colors)]
return lipgloss.NewStyle().
Foreground(lipgloss.Color(color))
}
Expand Down
2 changes: 1 addition & 1 deletion internal/ui/assets/help.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,5 +84,5 @@ B open all bookmarks added to current task
### Task Bookmarks List

```text
⏎ open URL in browser
⏎ open URI in browser
```
12 changes: 6 additions & 6 deletions internal/ui/cmds.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ func openTextEditor(fPath string, editorCmd []string, taskIndex int, taskId uint
})
}

func openURL(url string) tea.Cmd {
func openURI(uri string) tea.Cmd {
var cmd string
var args []string
switch runtime.GOOS {
Expand All @@ -104,16 +104,16 @@ func openURL(url string) tea.Cmd {
default:
cmd = "xdg-open"
}
c := exec.Command(cmd, append(args, url)...)
c := exec.Command(cmd, append(args, uri)...)
return tea.ExecProcess(c, func(err error) tea.Msg {
return urlOpenedMsg{url, err}
return uriOpenedMsg{uri, err}
})
}

func openURLsDarwin(urls []string) tea.Cmd {
c := exec.Command("open", urls...)
func openURIsDarwin(uris []string) tea.Cmd {
c := exec.Command("open", uris...)
return tea.ExecProcess(c, func(err error) tea.Msg {
return urlsOpenedDarwinMsg{urls, err}
return urisOpenedDarwinMsg{uris, err}
})
}

Expand Down
3 changes: 1 addition & 2 deletions internal/ui/initial.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"github.com/charmbracelet/lipgloss"
"github.com/dhth/omm/internal/types"
"github.com/dhth/omm/internal/utils"
"mvdan.cc/xurls/v2"
)

func InitialModel(db *sql.DB, config Config) model {
Expand Down Expand Up @@ -135,7 +134,7 @@ func InitialModel(db *sql.DB, config Config) model {
atlSelStyle: atlSelItemStyle,
contextVPTaskId: 0,
rtos: runtime.GOOS,
urlRegex: xurls.Strict(),
uriRegex: utils.GetURIRegex(),
taskDetailsMdRenderer: tr,
}

Expand Down
2 changes: 1 addition & 1 deletion internal/ui/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ type model struct {
terminalHeight int
contextVPTaskId uint64
rtos string
urlRegex *regexp.Regexp
uriRegex *regexp.Regexp
shortenedListHt int
contextMdRenderer *glamour.TermRenderer
taskDetailsMdRenderer *glamour.TermRenderer
Expand Down
4 changes: 2 additions & 2 deletions internal/ui/msgs.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,12 @@ type textEditorClosed struct {
err error
}

type urlOpenedMsg struct {
type uriOpenedMsg struct {
url string
err error
}

type urlsOpenedDarwinMsg struct {
type urisOpenedDarwinMsg struct {
urls []string
err error
}
Expand Down
50 changes: 25 additions & 25 deletions internal/ui/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -873,8 +873,8 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
m.archivedTaskList.Select(listIndex)

case contextBookmarksView:
url := m.taskBMList.SelectedItem().FilterValue()
cmds = append(cmds, openURL(url))
uri := m.taskBMList.SelectedItem().FilterValue()
cmds = append(cmds, openURI(uri))
case prefixSelectionView:
prefix := m.prefixSearchList.SelectedItem().FilterValue()

Expand Down Expand Up @@ -1155,24 +1155,24 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
break
}

urls, ok := m.getTaskUrls()
uris, ok := m.getTaskURIs()
if !ok {
break
}

if len(urls) == 0 {
if len(uris) == 0 {
m.errorMsg = "No bookmarks for this task"
break
}

if len(urls) == 1 {
cmds = append(cmds, openURL(urls[0]))
if len(uris) == 1 {
cmds = append(cmds, openURI(uris[0]))
break
}

bmItems := make([]list.Item, len(urls))
for i, url := range urls {
bmItems[i] = list.Item(types.ContextBookmark(url))
bmItems := make([]list.Item, len(uris))
for i, uri := range uris {
bmItems[i] = list.Item(types.ContextBookmark(uri))
}
m.taskBMList.SetItems(bmItems)
switch m.activeView {
Expand All @@ -1189,28 +1189,28 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
break
}

urls, ok := m.getTaskUrls()
uris, ok := m.getTaskURIs()
if !ok {
break
}

if len(urls) == 0 {
if len(uris) == 0 {
m.errorMsg = "No bookmarks for this task"
break
}

if len(urls) == 1 {
cmds = append(cmds, openURL(urls[0]))
if len(uris) == 1 {
cmds = append(cmds, openURI(uris[0]))
break
}

if m.rtos == types.GOOSDarwin {
cmds = append(cmds, openURLsDarwin(urls))
cmds = append(cmds, openURIsDarwin(uris))
break
}

for _, url := range urls {
cmds = append(cmds, openURL(url))
for _, uri := range uris {
cmds = append(cmds, openURI(uri))
}

case "y":
Expand Down Expand Up @@ -1451,13 +1451,13 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
}

cmds = append(cmds, updateTaskContext(m.db, msg.taskIndex, msg.taskId, string(context), m.activeTaskList))
case urlOpenedMsg:
case uriOpenedMsg:
if msg.err != nil {
m.errorMsg = fmt.Sprintf("Error opening url: %s", msg.err)
m.errorMsg = fmt.Sprintf("Error opening uri: %s", msg.err)
}
case urlsOpenedDarwinMsg:
case urisOpenedDarwinMsg:
if msg.err != nil {
m.errorMsg = fmt.Sprintf("Error opening urls: %s", msg.err)
m.errorMsg = fmt.Sprintf("Error opening uris: %s", msg.err)
}

case contextWrittenToCBMsg:
Expand Down Expand Up @@ -1627,7 +1627,7 @@ func (m *model) setContextFSContent(task types.Task) {
m.taskDetailsVP.SetContent(details)
}

func (m model) getTaskUrls() ([]string, bool) {
func (m model) getTaskURIs() ([]string, bool) {
var t types.Task
var ok bool

Expand All @@ -1648,11 +1648,11 @@ func (m model) getTaskUrls() ([]string, bool) {
return nil, false
}

var urls []string
urls = append(urls, utils.ExtractURLs(m.urlRegex, t.Summary)...)
var uris []string
uris = append(uris, utils.ExtractURIs(m.uriRegex, t.Summary)...)
if t.Context != nil {
urls = append(urls, utils.ExtractURLs(m.urlRegex, *t.Context)...)
uris = append(uris, utils.ExtractURIs(m.uriRegex, *t.Context)...)
}

return urls, true
return uris, true
}
2 changes: 1 addition & 1 deletion internal/utils/assets/gruvbox.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@
"block_prefix": ". "
},
"task": {
"ticked": "[] ",
"ticked": "[] ",
"unticked": "[ ] "
},
"link": {
Expand Down
53 changes: 53 additions & 0 deletions internal/utils/urls.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package utils

import (
"regexp"
"strings"

"mvdan.cc/xurls/v2"
)

// duplicated from https://github.com/mvdan/xurls/blob/master/xurls.go#L83-L88 as xurls doesn't let the user extend or
// override SchemesNoAuthority
var (
knownSchemes = []string{
`cid`,
`file`,
`magnet`,
`mailto`,
`mid`,
`sms`,
`tel`,
`xmpp`,
`spotify`,
`facetime`,
`facetime-audio`,
}
anyScheme = `(?:[a-zA-Z][a-zA-Z.\-+]*://|` + anyOf(knownSchemes...) + `:)`
)

func anyOf(strs ...string) string {
var b strings.Builder
b.WriteString("(?:")
for i, s := range strs {
if i != 0 {
b.WriteByte('|')
}
b.WriteString(regexp.QuoteMeta(s))
}
b.WriteByte(')')
return b.String()
}

func GetURIRegex() *regexp.Regexp {
rgx, err := xurls.StrictMatchingScheme(anyScheme)
if err != nil {
return xurls.Strict()
}

return rgx
}

func ExtractURIs(rg *regexp.Regexp, text string) []string {
return rg.FindAllString(text, -1)
}
Loading

0 comments on commit de6c86b

Please sign in to comment.