Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 38 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,9 @@ notesmd-cli --help

### Editor Flag

The `search`, `search-content`, `create`, and `move` commands support the `--editor` (or `-e`) flag, which opens notes in your default text editor instead of the Obsidian application. This is useful for quick edits or when working in a terminal-only environment.
The `open`, `daily`, `search`, `search-content`, `create`, and `move` commands support the `--editor` (or `-e`) flag, which opens notes in your default text editor instead of the Obsidian application. This is useful for quick edits or when working in a terminal-only environment.

The editor is determined by the `EDITOR` environment variable. If not set, it defaults to `vim`.
The editor is determined by the `EDITOR` environment variable (e.g., `"vim"`, `"code"`, or `"code -w"`). If not set, it defaults to `vim`.

**Supported editors:**

Expand All @@ -71,20 +71,37 @@ The editor is determined by the `EDITOR` environment variable. If not set, it de
export EDITOR="code" # or "vim", "nano", "subl", etc.

# Use with supported commands
notesmd-cli open "note.md" --editor
notesmd-cli daily --editor
notesmd-cli search --editor
notesmd-cli search-content "term" --editor
notesmd-cli create "note.md" --open --editor
notesmd-cli move "old.md" "new.md" --open --editor
```

### Set Default Vault
To avoid passing `--editor` every time, configure it as the default open type once:

Defines default vault for future usage. If not set, pass `--vault` flag for other commands. You don't provide the path to vault here, just the name.
```bash
notesmd-cli set-default --open-type editor
```

### Set Default Vault and Open Type

Defines the default vault and/or open type for future usage. If no default vault is set, pass the `--vault` flag with other commands.

```bash
# Set default vault (vault name only, not the path)
notesmd-cli set-default "{vault-name}"

# Set default open type: 'obsidian' (default) or 'editor'
notesmd-cli set-default --open-type editor

# Set both at once
notesmd-cli set-default "{vault-name}" --open-type editor
```

When `default_open_type` is set to `editor`, commands that support `--open` will open notes in `$EDITOR` automatically, without needing to pass `--editor` each time.

Note: `open` and other commands in `notesmd-cli` use this vault's base directory as the working directory, not the current working directory of your terminal.

### Print Default Vault
Expand Down Expand Up @@ -112,7 +129,7 @@ Then you can use `obs_cd` to navigate to the default vault directory within your

### Open Note

Open given note name in Obsidian. Note can also be an absolute path from top level of vault.
Open given note name in Obsidian (or your default editor). Note can also be an absolute path from top level of vault.

```bash
# Opens note in obsidian vault
Expand All @@ -125,11 +142,14 @@ notesmd-cli open "{note-name}" --vault "{vault-name}"
notesmd-cli open "{note-name}" --section "{heading-text}"

notesmd-cli open "{note-name}" --vault "{vault-name}" --section "{heading-text}"

# Opens note in your default editor instead of Obsidian
notesmd-cli open "{note-name}" --editor
```

### Daily Note

Open daily note in Obsidian. It will create one (using template) if one does not exist.
Creates or opens today's daily note directly on disk — **Obsidian does not need to be running**. If `.obsidian/daily-notes.json` exists in the vault, the CLI reads `folder`, `format` (Moment.js date format, default `YYYY-MM-DD`), and `template` from it. A template file's content is used when creating a new daily note. If the config is missing or unreadable, defaults are used (vault root, `YYYY-MM-DD`, no template).

```bash
# Creates / opens daily note in obsidian vault
Expand All @@ -138,6 +158,8 @@ notesmd-cli daily
# Creates / opens daily note in specified obsidian vault
notesmd-cli daily --vault "{vault-name}"

# Creates / opens daily note in your default editor
notesmd-cli daily --editor
```

### Search Note
Expand Down Expand Up @@ -206,25 +228,27 @@ notesmd-cli print "{note-name}" --vault "{vault-name}"

### Create / Update Note

Creates note (can also be a path with name) in vault. By default, if the note exists, it will create another note but passing `--overwrite` or `--append` can be used to edit the named note.
Creates a note (can also be a path with name) directly on disk — **Obsidian does not need to be running**. If the note already exists and neither `--overwrite` nor `--append` is passed, the file is left unchanged. Intermediate directories are created automatically.

When the note name has no explicit path (no `/`), the CLI reads `.obsidian/app.json` from the vault to check for a configured default folder (`newFileLocation: "folder"` and `newFileFolderPath`). If configured, the note is placed in that folder. If the config is missing or unreadable, the note is created at the vault root.

```bash
# Creates empty note in default obsidian and opens it
# Creates empty note in default vault
notesmd-cli create "{note-name}"

# Creates empty note in given obsidian and opens it
notesmd-cli create "{note-name}" --vault "{vault-name}"
# Creates empty note in specified vault
notesmd-cli create "{note-name}" --vault "{vault-name}"

# Creates note in default obsidian with content
# Creates note with content
notesmd-cli create "{note-name}" --content "abcde"

# Creates note in default obsidian with content - overwrite existing note
# Overwrites an existing note
notesmd-cli create "{note-name}" --content "abcde" --overwrite

# Creates note in default obsidian with content - append existing note
# Appends to an existing note
notesmd-cli create "{note-name}" --content "abcde" --append

# Creates note and opens it
# Creates note and opens it in Obsidian
notesmd-cli create "{note-name}" --content "abcde" --open

# Creates note and opens it in your default editor
Expand Down
12 changes: 5 additions & 7 deletions cmd/create.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package cmd

import (
"log"

"github.com/Yakitrak/notesmd-cli/pkg/actions"
"github.com/Yakitrak/notesmd-cli/pkg/obsidian"
"github.com/spf13/cobra"
"log"
)

var shouldAppend bool
Expand All @@ -19,19 +20,16 @@ var createNoteCmd = &cobra.Command{
vault := obsidian.Vault{Name: vaultName}
uri := obsidian.Uri{}
noteName := args[0]
useEditor, err := cmd.Flags().GetBool("editor")
if err != nil {
log.Fatalf("Failed to parse --editor flag: %v", err)
}

params := actions.CreateParams{
NoteName: noteName,
Content: content,
ShouldAppend: shouldAppend,
ShouldOverwrite: shouldOverwrite,
ShouldOpen: shouldOpen,
UseEditor: useEditor,
UseEditor: resolveUseEditor(cmd, &vault),
}
err = actions.CreateNote(&vault, &uri, params)
err := actions.CreateNote(&vault, &uri, params)
if err != nil {
log.Fatal(err)
}
Expand Down
6 changes: 5 additions & 1 deletion cmd/daily.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ var DailyCmd = &cobra.Command{
Run: func(cmd *cobra.Command, args []string) {
vault := obsidian.Vault{Name: vaultName}
uri := obsidian.Uri{}
err := actions.DailyNote(&vault, &uri)

err := actions.DailyNote(&vault, &uri, actions.DailyParams{
UseEditor: resolveUseEditor(cmd, &vault),
})
if err != nil {
log.Fatal(err)
}
Expand All @@ -25,5 +28,6 @@ var DailyCmd = &cobra.Command{

func init() {
DailyCmd.Flags().StringVarP(&vaultName, "vault", "v", "", "vault name (not required if default is set)")
DailyCmd.Flags().BoolP("editor", "e", false, "open in editor instead of Obsidian")
rootCmd.AddCommand(DailyCmd)
}
25 changes: 25 additions & 0 deletions cmd/editor.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package cmd

import (
"log"

"github.com/Yakitrak/notesmd-cli/pkg/obsidian"
"github.com/spf13/cobra"
)

// resolveUseEditor returns whether the command should open in the user's editor.
// If --editor was explicitly passed, its value is used. Otherwise, the configured
// default_open_type is consulted ("editor" → true).
func resolveUseEditor(cmd *cobra.Command, vault obsidian.VaultManager) bool {
useEditor, err := cmd.Flags().GetBool("editor")
if err != nil {
log.Fatalf("Failed to parse --editor flag: %v", err)
}
if !cmd.Flags().Changed("editor") {
defaultOpenType, configErr := vault.DefaultOpenType()
if configErr == nil && defaultOpenType == "editor" {
useEditor = true
}
}
return useEditor
}
9 changes: 2 additions & 7 deletions cmd/move.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,16 @@ var moveCmd = &cobra.Command{
vault := obsidian.Vault{Name: vaultName}
note := obsidian.Note{}
uri := obsidian.Uri{}
useEditor, err := cmd.Flags().GetBool("editor")
if err != nil {
log.Fatalf("Failed to parse --editor flag: %v", err)
}
params := actions.MoveParams{
CurrentNoteName: currentName,
NewNoteName: newName,
ShouldOpen: shouldOpen,
UseEditor: useEditor,
UseEditor: resolveUseEditor(cmd, &vault),
}
err = actions.MoveNote(&vault, &note, &uri, params)
err := actions.MoveNote(&vault, &note, &uri, params)
if err != nil {
log.Fatal(err)
}

},
}

Expand Down
4 changes: 3 additions & 1 deletion cmd/open.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ var OpenVaultCmd = &cobra.Command{
vault := obsidian.Vault{Name: vaultName}
uri := obsidian.Uri{}
noteName := args[0]
params := actions.OpenParams{NoteName: noteName, Section: sectionName}

params := actions.OpenParams{NoteName: noteName, Section: sectionName, UseEditor: resolveUseEditor(cmd, &vault)}
err := actions.OpenNote(&vault, &uri, params)
if err != nil {
log.Fatal(err)
Expand All @@ -30,5 +31,6 @@ var OpenVaultCmd = &cobra.Command{
func init() {
OpenVaultCmd.Flags().StringVarP(&vaultName, "vault", "v", "", "vault name (not required if default is set)")
OpenVaultCmd.Flags().StringVarP(&sectionName, "section", "s", "", "heading text to open within the note (case-sensitive)")
OpenVaultCmd.Flags().BoolP("editor", "e", false, "open in editor instead of Obsidian")
rootCmd.AddCommand(OpenVaultCmd)
}
7 changes: 5 additions & 2 deletions cmd/print_default.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,11 @@ var printDefaultCmd = &cobra.Command{
return
}

fmt.Println("Default vault name: ", name)
fmt.Println("Default vault path: ", path)
openType, _ := vault.DefaultOpenType()

fmt.Println("Default vault name:", name)
fmt.Println("Default vault path:", path)
fmt.Println("Default open type:", openType)
},
}

Expand Down
2 changes: 1 addition & 1 deletion cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
var rootCmd = &cobra.Command{
Use: "notesmd-cli",
Short: "Interact with Obsidian vaults from the terminal",
Version: "v0.3.0",
Version: "v0.3.1",
Long: "Interact with Obsidian vaults from the terminal",
}

Expand Down
6 changes: 1 addition & 5 deletions cmd/search.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,7 @@ var searchCmd = &cobra.Command{
note := obsidian.Note{}
uri := obsidian.Uri{}
fuzzyFinder := obsidian.FuzzyFinder{}
useEditor, err := cmd.Flags().GetBool("editor")
if err != nil {
log.Fatalf("failed to retrieve 'editor' flag: %v", err)
}
err = actions.SearchNotes(&vault, &note, &uri, &fuzzyFinder, useEditor)
err := actions.SearchNotes(&vault, &note, &uri, &fuzzyFinder, resolveUseEditor(cmd, &vault))
if err != nil {
log.Fatal(err)
}
Expand Down
6 changes: 1 addition & 5 deletions cmd/search_content.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,7 @@ var searchContentCmd = &cobra.Command{
fuzzyFinder := obsidian.FuzzyFinder{}

searchTerm := args[0]
useEditor, err := cmd.Flags().GetBool("editor")
if err != nil {
log.Fatalf("Failed to parse 'editor' flag: %v", err)
}
err = actions.SearchNotesContent(&vault, &note, &uri, &fuzzyFinder, searchTerm, useEditor)
err := actions.SearchNotesContent(&vault, &note, &uri, &fuzzyFinder, searchTerm, resolveUseEditor(cmd, &vault))
if err != nil {
log.Fatal(err)
}
Expand Down
46 changes: 34 additions & 12 deletions cmd/set_default.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,55 @@ package cmd

import (
"fmt"
"log"

"github.com/Yakitrak/notesmd-cli/pkg/obsidian"
"github.com/spf13/cobra"
"log"
)

var setDefaultCmd = &cobra.Command{
Use: "set-default",
Aliases: []string{"sd"},
Short: "Sets default vault",
Args: cobra.ExactArgs(1),
Short: "Sets default vault and/or open type",
Args: cobra.RangeArgs(0, 1),
Run: func(cmd *cobra.Command, args []string) {
name := args[0]
v := obsidian.Vault{Name: name}
err := v.SetDefaultName(name)
openType, err := cmd.Flags().GetString("open-type")
if err != nil {
log.Fatal(err)
log.Fatalf("Failed to parse --open-type flag: %v", err)
}
path, err := v.Path()
if err != nil {
log.Fatal(err)

if len(args) == 0 && openType == "" {
log.Fatal("Please provide a vault name or use --open-type to set the default open type")
}

if len(args) > 0 {
name := args[0]
v := obsidian.Vault{Name: name}
if err := v.SetDefaultName(name); err != nil {
log.Fatal(err)
}
path, err := v.Path()
if err != nil {
log.Fatal(err)
}
fmt.Println("Default vault set to:", name)
fmt.Println("Default vault path set to:", path)
}
fmt.Println("Default vault set to: ", name)
fmt.Println("Default vault path set to: ", path)

if openType != "" {
if openType != "obsidian" && openType != "editor" {
log.Fatalf("Invalid open type %q: must be 'obsidian' or 'editor'", openType)
}
v := obsidian.Vault{}
if err := v.SetDefaultOpenType(openType); err != nil {
log.Fatal(err)
}
fmt.Println("Default open type set to:", openType)
}
},
}

func init() {
setDefaultCmd.Flags().String("open-type", "", "default open type: 'obsidian' (default) or 'editor'")
rootCmd.AddCommand(setDefaultCmd)
}
Binary file modified docs/usage.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
22 changes: 19 additions & 3 deletions mocks/vault.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package mocks

type MockVaultOperator struct {
DefaultNameErr error
PathError error
Name string
DefaultNameErr error
PathError error
Name string
PathValue string
OpenType string
OpenTypeErr error
}

func (m *MockVaultOperator) DefaultName() (string, error) {
Expand All @@ -24,5 +27,18 @@ func (m *MockVaultOperator) Path() (string, error) {
if m.PathError != nil {
return "", m.PathError
}
if m.PathValue != "" {
return m.PathValue, nil
}
return "path", nil
}

func (m *MockVaultOperator) DefaultOpenType() (string, error) {
if m.OpenTypeErr != nil {
return "", m.OpenTypeErr
}
if m.OpenType != "" {
return m.OpenType, nil
}
return "obsidian", nil
}
Loading