init
This commit is contained in:
		
							
								
								
									
										8
									
								
								.editorconfig
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								.editorconfig
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
			
		||||
[*]
 | 
			
		||||
charset = utf-8
 | 
			
		||||
end_of_line = lf
 | 
			
		||||
insert_final_newline = true
 | 
			
		||||
trim_trailing_whitespace = true
 | 
			
		||||
 | 
			
		||||
[*.v]
 | 
			
		||||
indent_style = tab
 | 
			
		||||
							
								
								
									
										8
									
								
								.gitattributes
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								.gitattributes
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
			
		||||
* text=auto eol=lf
 | 
			
		||||
*.bat eol=crlf
 | 
			
		||||
 | 
			
		||||
*.v linguist-language=V
 | 
			
		||||
*.vv linguist-language=V
 | 
			
		||||
*.vsh linguist-language=V
 | 
			
		||||
v.mod linguist-language=V
 | 
			
		||||
.vdocignore linguist-language=ignore
 | 
			
		||||
							
								
								
									
										24
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,24 @@
 | 
			
		||||
# Binaries for programs and plugins
 | 
			
		||||
main
 | 
			
		||||
nex
 | 
			
		||||
*.exe
 | 
			
		||||
*.exe~
 | 
			
		||||
*.so
 | 
			
		||||
*.dylib
 | 
			
		||||
*.dll
 | 
			
		||||
 | 
			
		||||
# Ignore binary output folders
 | 
			
		||||
bin/
 | 
			
		||||
 | 
			
		||||
# Ignore common editor/system specific metadata
 | 
			
		||||
.DS_Store
 | 
			
		||||
.idea/
 | 
			
		||||
.vscode/
 | 
			
		||||
*.iml
 | 
			
		||||
 | 
			
		||||
# ENV
 | 
			
		||||
.env
 | 
			
		||||
 | 
			
		||||
# vweb and database
 | 
			
		||||
*.db
 | 
			
		||||
*.js
 | 
			
		||||
							
								
								
									
										5
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
# n!
 | 
			
		||||
 | 
			
		||||
`n!` (notes!, nex, nexclamation) is a text notes manager.
 | 
			
		||||
 | 
			
		||||
Use it with [completion](completion) script. See [help](src/help.txt) for usage info.
 | 
			
		||||
							
								
								
									
										69
									
								
								completion
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								completion
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,69 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
# n! (notes!, nex, nexclamation) completion script.
 | 
			
		||||
 | 
			
		||||
NPATH="${NPATH:-$HOME/Documents}"
 | 
			
		||||
 | 
			
		||||
_n_list_dirs() {
 | 
			
		||||
    find "$NPATH" -type d -exec echo {}/ \; | sed -E "s%$NPATH/?%%g;/^$/d";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
_n_list_files() {
 | 
			
		||||
    find "$NPATH" -type f | sed -E "s%$NPATH/?%%g;/^$/d"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
_n_get_opts() {
 | 
			
		||||
    local all_opts="$1"
 | 
			
		||||
 | 
			
		||||
    # Find matched opts.
 | 
			
		||||
    local used_opts="$(echo "${COMP_WORDS[@]} $all_opts" \
 | 
			
		||||
        | tr ' ' '\n' | sort | uniq -d \
 | 
			
		||||
    )"
 | 
			
		||||
 | 
			
		||||
    if [ "$used_opts" ]; then
 | 
			
		||||
        # Delete 'help' option.
 | 
			
		||||
        all_opts="$(sed 's%help%%' <<< "$all_opts")"
 | 
			
		||||
        # Delete opts if match.
 | 
			
		||||
        for opt in $used_opts; do
 | 
			
		||||
            all_opts="$(sed "s%$opt%%" <<< "$all_opts")"
 | 
			
		||||
        done
 | 
			
		||||
    fi
 | 
			
		||||
    echo "$all_opts"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
_nexclamation() {
 | 
			
		||||
    local cur prev
 | 
			
		||||
    cur=${COMP_WORDS[COMP_CWORD]}
 | 
			
		||||
    prev=${COMP_WORDS[COMP_CWORD-1]}
 | 
			
		||||
 | 
			
		||||
    case ${COMP_CWORD} in
 | 
			
		||||
        1)  # Commands and options
 | 
			
		||||
            COMPREPLY=($(compgen -W \
 | 
			
		||||
                "-v --version -h --help
 | 
			
		||||
                q quick s search l last mkdir ls lsd rm i info
 | 
			
		||||
                $(_n_list_dirs) $(_n_list_files)" -- ${cur}))
 | 
			
		||||
            ;;
 | 
			
		||||
        2)  # Subcommand completion
 | 
			
		||||
            case ${prev} in
 | 
			
		||||
                ls) COMPREPLY=($(compgen -W "$(_n_list_dirs)" -- ${cur}))
 | 
			
		||||
                    ;;
 | 
			
		||||
                rm) COMPREPLY=($(compgen -W "-f --force
 | 
			
		||||
                    $(_n_list_dirs) $(_n_list_files)" -- ${cur}))
 | 
			
		||||
                    ;;
 | 
			
		||||
                i|info) COMPREPLY=($(compgen -W "$(_n_list_files)" -- ${cur}))
 | 
			
		||||
                    ;;
 | 
			
		||||
                *) COMPREPLY=()
 | 
			
		||||
                    ;;
 | 
			
		||||
            esac;;
 | 
			
		||||
        *)  # Complete file and directory names
 | 
			
		||||
            case ${COMP_WORDS[2]} in
 | 
			
		||||
                *)
 | 
			
		||||
                    COMPREPLY=($(compgen -W \
 | 
			
		||||
                    "$(_n_get_opts "$(_n_list_dirs) $(_n_list_files)")" -- ${cur}))
 | 
			
		||||
                    ;;
 | 
			
		||||
            esac;;
 | 
			
		||||
    esac
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
complete -F _nexclamation nexclamation
 | 
			
		||||
complete -F _nexclamation nex
 | 
			
		||||
complete -F _nexclamation n!
 | 
			
		||||
							
								
								
									
										23
									
								
								src/help.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								src/help.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,23 @@
 | 
			
		||||
Usage: nex [command] [FILE]
 | 
			
		||||
 | 
			
		||||
Commands:
 | 
			
		||||
    d, dir      print notes path.
 | 
			
		||||
    o, open     open file via xdg-open.
 | 
			
		||||
    ls          print dir tree of notes path.
 | 
			
		||||
    lsf         print list of files in notes path.
 | 
			
		||||
    lsd         print list of directories in notes path.
 | 
			
		||||
    s, search   search in notes via 'grep --color=always -rni'.
 | 
			
		||||
    g, grep     search in notes via custom grep.
 | 
			
		||||
    h, help     print this help message and exit.
 | 
			
		||||
 | 
			
		||||
Options:
 | 
			
		||||
    -trace              enable debug mode.
 | 
			
		||||
    -no-notes-path      do not append notes_path to filenames.
 | 
			
		||||
    -no-chdir           do not perform chdir on running commands.
 | 
			
		||||
    -grep-raw           do not add any arguments to grep_args.
 | 
			
		||||
    -grep-no-color      do not add '--color=always' argument to grep_args.
 | 
			
		||||
    -grep-no-recursive  do not add '-rn' arguments to grep_args.
 | 
			
		||||
 | 
			
		||||
Environment:
 | 
			
		||||
    NPATH       path to directory with notes (required).
 | 
			
		||||
    EDITOR      text editor to use.
 | 
			
		||||
							
								
								
									
										140
									
								
								src/main.v
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										140
									
								
								src/main.v
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,140 @@
 | 
			
		||||
module main
 | 
			
		||||
 | 
			
		||||
import os
 | 
			
		||||
import os.cmdline
 | 
			
		||||
 | 
			
		||||
const help = $embed_file('help.txt')
 | 
			
		||||
 | 
			
		||||
struct Preferences {
 | 
			
		||||
mut:
 | 
			
		||||
	trace             bool
 | 
			
		||||
	no_notes_path     bool
 | 
			
		||||
	no_chdir          bool
 | 
			
		||||
	grep_raw          bool
 | 
			
		||||
	grep_no_color     bool
 | 
			
		||||
	grep_no_recursive bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn main() {
 | 
			
		||||
	editor := os.getenv_opt('EDITOR') or { '/usr/bin/vim' }
 | 
			
		||||
	mut notes_path := os.getenv('NPATH')
 | 
			
		||||
	mut pref := Preferences{}
 | 
			
		||||
	argv := arguments()[1..]
 | 
			
		||||
	opts := cmdline.only_options(argv)
 | 
			
		||||
	match true {
 | 
			
		||||
		'-trace' in opts {
 | 
			
		||||
			pref.trace = true
 | 
			
		||||
		}
 | 
			
		||||
		'-no-notes-path' in opts {
 | 
			
		||||
			pref.no_notes_path = true
 | 
			
		||||
		}
 | 
			
		||||
		'-no-chdir' in opts {
 | 
			
		||||
			pref.no_chdir = true
 | 
			
		||||
		}
 | 
			
		||||
		'-grep-raw' in opts {
 | 
			
		||||
			pref.grep_raw = true
 | 
			
		||||
		}
 | 
			
		||||
		'-grep-no-color' in opts {
 | 
			
		||||
			pref.grep_no_color = true
 | 
			
		||||
		}
 | 
			
		||||
		'-grep-no-recursive' in opts {
 | 
			
		||||
			pref.grep_no_recursive = true
 | 
			
		||||
		}
 | 
			
		||||
		else {}
 | 
			
		||||
	}
 | 
			
		||||
	args := cmdline.only_non_options(argv)
 | 
			
		||||
	if args.len == 0 {
 | 
			
		||||
		os.chdir(notes_path)!
 | 
			
		||||
		os.execvp(editor, []string{})!
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	arg := args[0]
 | 
			
		||||
	if notes_path == '' && arg !in ['h', 'help'] {
 | 
			
		||||
		eprintln('E: NPATH environment variable is not set')
 | 
			
		||||
		eprintln('E: NPATH must contain path to notes dir')
 | 
			
		||||
		exit(1)
 | 
			
		||||
	}
 | 
			
		||||
	match arg {
 | 
			
		||||
		'd', 'dir' {
 | 
			
		||||
			println(notes_path)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		'o', 'open' {
 | 
			
		||||
			if pref.no_notes_path {
 | 
			
		||||
				os.execvp('xdg-open', [argv[0]])!
 | 
			
		||||
			}
 | 
			
		||||
			os.execvp('xdg-open', [os.join_path_single(notes_path, argv[0])])!
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		's', 'search' {
 | 
			
		||||
			if !pref.no_chdir {
 | 
			
		||||
				os.chdir(notes_path)!
 | 
			
		||||
			}
 | 
			
		||||
			result := os.execute_or_exit("grep --color=always -rni '${argv[1]}'")
 | 
			
		||||
			println(result.output.trim_space())
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		'g', 'grep' {
 | 
			
		||||
			if !pref.no_chdir {
 | 
			
		||||
				os.chdir(notes_path)!
 | 
			
		||||
			}
 | 
			
		||||
			mut pc := os.new_process('/usr/bin/grep')
 | 
			
		||||
			mut grep_args := []string{}
 | 
			
		||||
			if !pref.grep_raw {
 | 
			
		||||
				if !pref.grep_no_color {
 | 
			
		||||
					grep_args << '--color=always'
 | 
			
		||||
				}
 | 
			
		||||
				if !pref.grep_no_recursive {
 | 
			
		||||
					grep_args << ['--recursive', '--line-number']
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			if arg == 'g' {
 | 
			
		||||
				grep_args << argv[argv.index('g') + 1..]
 | 
			
		||||
			}
 | 
			
		||||
			if arg == 'grep' {
 | 
			
		||||
				grep_args << argv[argv.index('grep') + 1..]
 | 
			
		||||
			}
 | 
			
		||||
			if pref.trace {
 | 
			
		||||
				eprintln('I: grep_args: ${grep_args}')
 | 
			
		||||
			}
 | 
			
		||||
			pc.set_args(grep_args)
 | 
			
		||||
			pc.run()
 | 
			
		||||
			pc.wait()
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		'ls', 'lsf', 'lsd' {
 | 
			
		||||
			mut dir := notes_path
 | 
			
		||||
			if !pref.no_chdir {
 | 
			
		||||
				os.chdir(notes_path)!
 | 
			
		||||
				dir = '.'
 | 
			
		||||
			}
 | 
			
		||||
			cmd := match arg {
 | 
			
		||||
				'ls' { 'env LC_ALL=C tree -FC ${dir}' }
 | 
			
		||||
				'lsf' { 'find ${dir} -type f' }
 | 
			
		||||
				'lsd' { 'find ${dir} -type d' }
 | 
			
		||||
				else { '' }
 | 
			
		||||
			}
 | 
			
		||||
			if pref.trace {
 | 
			
		||||
				eprintln('I: command to execute: ${cmd}')
 | 
			
		||||
			}
 | 
			
		||||
			result := os.execute_or_exit(cmd)
 | 
			
		||||
			println(result.output.trim_space())
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		'h', 'help' {
 | 
			
		||||
			println(help.to_string().trim_space())
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		else {
 | 
			
		||||
			if arg.starts_with('-') {
 | 
			
		||||
				eprintln('E: unrecognized option: ${arg}')
 | 
			
		||||
				exit(2)
 | 
			
		||||
			}
 | 
			
		||||
			if pref.no_notes_path {
 | 
			
		||||
				os.execvp(editor, [arg])!
 | 
			
		||||
			}
 | 
			
		||||
			os.execvp(editor, [os.join_path_single(notes_path, arg)])!
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user