diff --git a/inc/file-management b/inc/file-management index 74c593d..884ee88 100644 --- a/inc/file-management +++ b/inc/file-management @@ -23,6 +23,85 @@ Tags: editFile "$filename" } +addFile(){ + vecho "addFile $*" + local copiedFile + local subFolder="" + local ext + local file + local filenameTitle + local yaml + local yamlBlock + local yamlTitle + while [[ $1 = -?* ]]; do + case "$1" in + --asset) mkdir -p "${dataDir}assets"; subFolder+="assets/" ;; + --yaml-header) yaml="header" ;; + --yaml-file) yaml="file" ;; + *) die "invalid add option: '$1'." ;; + esac + shift + done + file="$1" + [ -z "$file" ] && die "You must specify a file" + [ -f "$file" ] || die "File $file not found" + + ext="${file##*.}" + copiedFile="${file##*/}" + + # If the type of yaml entry hasn't been specified on the command line + if [ -z "$yaml" ]; then + # We want a header if it's markdown, otherwise a seperate file + if [ "$ext" = "md" ]; then + yaml="header" + else + yaml="file" + fi + fi + + + [ -e "$dataDir$copiedFile" ] && die "File $copiedFile already exists" + cp "$file" "$dataDir$subFolder$copiedFile" + + # The title as specified in yaml (or empty string) + yamlBlock="$(getYamlBlock "$subFolder$copiedFile")" + yamlTitle="$(getYamlTitle "$subFolder$copiedFile")" + # The title generated from filename + filenameTitle="$(echo "$copiedFile" | tr '_' ' ' | sed -E 's/\..[^.]+$//')" + if [ -z "$yamlTitle" ] || [ "$yamlTitle" = "null" ]; then + # If empty, generate the title from the filename + yamlTitle="$filenameTitle" + else + # If the yaml title and the filename title are different, then use the yaml title + if [ "$yamlTitle" != "$filenameTitle" ]; then + local newFilename=$(escapeFilename "$yamlTitle").$ext + echo mv "$dataDir$subFolder$copiedFile" "$dataDir$subFolder$newFilename" + warn "File renamed from $copiedFile to "$newFilename + copiedFile="$newFilename" + fi + fi + + + yamlBlock="Title: $yamlTitle +$yamlBlock" + + + if [ "$yaml" = "header" ]; then + local tmpfile=$(mktemp) + echo "--- +$yamlBlock +---" > $tmpfile + sed '1 { /^---/ { :a N; /\n---/! ba; d} }' "$dataDir$subFolder$copiedFile" >> "$tmpfile" + mv "$tmpfile" "$dataDir$subFolder$copiedFile" + else + echo "$yamlBlock" > "$dataDir$subFolder$copiedFile.yaml" + fi + + updateFileChange "$subFolder$copiedFile" + + +} + # Takes the filename as a parameter editFile(){ vecho "editFile $*" @@ -37,13 +116,23 @@ editFile(){ # This is used to update the DB when a file is changed # param1 is the file updateFileChange(){ + vecho "updateFileChange $*" + cd "$dataDir" || return local filename + local directory="" local title local newFilename + local filetype="normal" + local ext filename="$(findFile "$1")" + ext="${filename##*.}" [ ! -e "$filename" ] && die "No such file $1" + if echo "$filename" | grep -q '^assets/'; then + filetype="asset" + directory="assets/" + fi title="$(getYamlTitle "$filename")" - newFilename="$(escapeFilename "$title.md")" + newFilename="$directory$(escapeFilename "$title.$ext")" if [ "$filename" = "$newFilename" ]; then # The title hasn't changed # check if the file is in the DB @@ -51,7 +140,7 @@ updateFileChange(){ # If not, add it echo "INSERT INTO items (filename, title, type) VALUES ( '$(safeSQL "$filename")', - '$(safeSQL "$title")', 'normal' );" | + '$(safeSQL "$title")', '$(safeSQL "$filetype")' );" | sqlite3 "${sqliteFile}" fi # Make sure all the tags are up to date @@ -76,7 +165,7 @@ Please resolve manually" # We get here if the title was changed in the create process echo "INSERT INTO items (filename, title, type) VALUES ( '$(safeSQL "$newFilename")', - '$(safeSQL "$title")', 'normal' );" | + '$(safeSQL "$title")', '$(safeSQL "$filetype")' );" | sqlite3 "${sqliteFile}" fi @@ -86,6 +175,7 @@ Please resolve manually" } deleteFile(){ + vecho "deleteFile $*" cd "$dataDir" || return local filename local fileID @@ -108,6 +198,7 @@ deleteFile(){ } viewFile(){ + vecho "viewFile $*" cd "$dataDir" || return local id="$1" diff --git a/inc/init b/inc/init index 9639126..5510625 100644 --- a/inc/init +++ b/inc/init @@ -15,7 +15,8 @@ initKnowledgeBase(){ git init "$dataDir" > "$output" # TODO: make gitignore use new sqlite file - echo "/knowledgebase.sqlite3" >> "${dataDir}/.gitignore" + # Datadir always has a trailing slash + echo "/knowledgebase.sqlite3" >> "${dataDir}.gitignore" git -C "$dataDir" add .gitignore > "$output" git -C "$dataDir" commit -m "Knowledge base initialised" > "$output" diff --git a/inc/yaml b/inc/yaml index b5d4663..ad47c77 100644 --- a/inc/yaml +++ b/inc/yaml @@ -40,8 +40,8 @@ getYamlTitle(){ } getYamlTags(){ - vecho "getYamlTitle $*" + vecho "getYamlTags $*" cd "$dataDir" || return - getYamlBlock "$1" | yq -r '.Tags | join("\n")' + getYamlBlock "$1" | yq -r '.Tags | if . == null then [] else . end | join("\n")' } diff --git a/kb b/kb index 6763555..1ef81d6 100755 --- a/kb +++ b/kb @@ -41,6 +41,10 @@ die(){ exit 1 } +warn(){ + necho -e "${YELLOW}$*${NC}" > /dev/tty +} + # Normal echo # Echo if quiet is 0 necho(){ @@ -53,7 +57,7 @@ necho(){ # Echo if verbose is 1 vecho(){ if [ "$verbose" -eq 1 ]; then - echo "$@" + echo "$@" > /dev/tty fi } @@ -143,9 +147,15 @@ makedb(){ # Makes file names safe escapeFilename(){ vecho "escapeFilename $*" - echo "$1" | - tr ' ' '_' | # replace spaces with underscores - tr -d '/' # Delete slashes + if [[ "$1" = assets/* ]]; then + echo -n "assets/" + echo "$(escapeFilename "${1#*/}")" + #echo "assets/$(escapeFilename "${1#*/}")" + else + echo "$1" | + tr ' ' '_' | # replace spaces with underscores + tr '/' '_' # replace slashes with underscores + fi } findFileId(){ @@ -180,7 +190,7 @@ findFile(){ echo "$filename.md" exit 0 else - die "No such file or ID $filename" + die "No such file or ID '$filename'" exit 1 fi fi @@ -240,7 +250,7 @@ listEntries(){ case "$1" in --noheader) header="" ;; --normal) typeorlist+=" OR items.type = 'normal'" ;; - --assets) typeorlist+=" OR items.type = 'assets'" ;; + --asset|--assets) typeorlist+=" OR items.type = 'asset'" ;; --links) typeorlist+=" OR items.type = 'links'" ;; *) die "invalid list option: '$1'." ;; esac @@ -277,7 +287,7 @@ mainScript() { ############## Begin Script Here ################### #################################################### if [ "${args[0]}" != "init" ]; then - cd "$dataDir" || return + #cd "$dataDir" || return # Check to see if datadir is a git repo if ! git rev-parse 2> /dev/null; then # If not, ensure we don't run git commands @@ -286,6 +296,7 @@ mainScript() { fi case "${args[0]}" in + add) addFile "${args[@]:1}"; safeExit ;; deepsearch) deepSearch "${args[@]:1}"; safeExit ;; del|delete) deleteFile "${args[@]:1}"; safeExit ;; edit) editFile "${args[@]:1}"; safeExit ;; @@ -344,6 +355,10 @@ usage() { update [] Updates the database and git repo of a changed file If 2 files are given, it assumes a move view View a file + add [options] Adds a file + --asset Adds the file as an asset + --yaml-header Adds a yaml header (default for markdown files) + --yaml-file Adds a yaml file (default for non-markdown files) fuzzy [command] Fuzzy select a file command is what to do with the selected file edit or view @@ -400,7 +415,8 @@ while [[ $1 = -?* ]]; do -v|--verbose) verbose=1 ;; -q|--quiet) quiet=1 ;; -d|--debug) debug=1;; - --data) dataDir="$2"; shift ;; + # Ensure that the dataDir has a trailing slash + --data) dataDir="${2%%/}/"; shift ;; --sqlite) sqliteFile="$2"; shift ;; --editor) editor="$2"; shift ;; --pager) pager="$2"; shift ;; @@ -413,7 +429,7 @@ done # If the sqlite file hasn't been specified on the command line, make it a file # called knowledgebase.sqlite3 in the dataDir -[ -z "$sqliteFile" ] && sqliteFile="${dataDir}/knowledgebase.sqlite3" +[ -z "$sqliteFile" ] && sqliteFile="${dataDir}knowledgebase.sqlite3" # Store the remaining part as arguments. args+=("$@")