diff --git a/scholar/cmd/add.go b/scholar/cmd/add.go index 99f0cde..1843155 100644 --- a/scholar/cmd/add.go +++ b/scholar/cmd/add.go @@ -121,7 +121,6 @@ func init() { rootCmd.AddCommand(addCmd) addCmd.Flags().StringVarP(&addDoi, "doi", "d", "", "Specify the DOI to retrieve metadata") - addCmd.Flags().StringVar(¤tLibrary, "to", "", "Specify which library to add") addCmd.Flags().StringVarP(&addAttach, "attach", "a", "", "attach a file to the entry") // Here you will define your flags and configuration settings. diff --git a/scholar/cmd/config.go b/scholar/cmd/config.go index 58d8246..ad2b92a 100644 --- a/scholar/cmd/config.go +++ b/scholar/cmd/config.go @@ -91,7 +91,7 @@ func configure() { path, _ := homedir.Dir() path = filepath.Join(path, ".config", "scholar", "config.yaml") - if err := ioutil.WriteFile(path, configDefault, 0644); err != nil { + if err := ioutil.WriteFile(path, configTemplate, 0644); err != nil { panic(nil) } diff --git a/scholar/cmd/export.go b/scholar/cmd/export.go index a9e30be..1c36585 100644 --- a/scholar/cmd/export.go +++ b/scholar/cmd/export.go @@ -56,8 +56,6 @@ TODO: add flag to specify which library to export func init() { rootCmd.AddCommand(exportCmd) - exportCmd.Flags().StringVarP(¤tLibrary, "from", "f", "", "Specify which library to export") - // Here you will define your flags and configuration settings. // Cobra supports Persistent Flags which will work for this command @@ -70,7 +68,7 @@ func init() { } func export() { - path := viper.GetString("deflib") + path := libraryPath() if currentLibrary != "" { path = viper.Sub("LIBRARIES").GetString(currentLibrary) } diff --git a/scholar/cmd/general.go b/scholar/cmd/general.go index 8be46d5..878bd5c 100644 --- a/scholar/cmd/general.go +++ b/scholar/cmd/general.go @@ -18,7 +18,7 @@ import ( func edit(entry *scholar.Entry) { key := entry.GetKey() - saveTo := filepath.Join(viper.GetString("deflib"), key) + saveTo := filepath.Join(libraryPath(), key) file := filepath.Join(saveTo, "entry.yaml") @@ -37,7 +37,7 @@ func edit(entry *scholar.Entry) { func update(entry *scholar.Entry) { key := entry.GetKey() - saveTo := filepath.Join(viper.GetString("deflib"), key) + saveTo := filepath.Join(libraryPath(), key) file := filepath.Join(saveTo, "entry.yaml") @@ -97,8 +97,25 @@ func clean(filename string) string { return strings.ToLower(filename) } +func libraryPath() string { + if currentLibrary != "" { + if !viper.Sub("LIBRARIES").IsSet(currentLibrary) { + fmt.Println("No library called", currentLibrary, "was found!") + fmt.Println("Available libraries:") + for k, v := range viper.GetStringMapString("LIBRARIES") { + fmt.Println(" ", k) + fmt.Println(" ", v) + } + os.Exit(1) + } + + return viper.Sub("LIBRARIES").GetString(currentLibrary) + } + return viper.Sub("LIBRARIES").GetString(viper.GetString("GENERAL.default")) +} + func entryQuery(search string) *scholar.Entry { - dirs, err := ioutil.ReadDir(viper.GetString("deflib")) + dirs, err := ioutil.ReadDir(libraryPath()) if err != nil { panic(err) } @@ -107,7 +124,7 @@ func entryQuery(search string) *scholar.Entry { for _, dir := range dirs { if dir.IsDir() { - d, err := ioutil.ReadFile(filepath.Join(viper.GetString("deflib"), dir.Name(), "entry.yaml")) + d, err := ioutil.ReadFile(filepath.Join(libraryPath(), dir.Name(), "entry.yaml")) if err != nil { panic(err) } diff --git a/scholar/cmd/import.go b/scholar/cmd/import.go index b1c68d2..f612108 100644 --- a/scholar/cmd/import.go +++ b/scholar/cmd/import.go @@ -48,7 +48,6 @@ Import a bibtex/biblatex file into a library in Scholar. func init() { rootCmd.AddCommand(importCmd) - importCmd.Flags().StringVarP(¤tLibrary, "to", "t", "", "Specify which library to import to") // Here you will define your flags and configuration settings. // Cobra supports Persistent Flags which will work for this command diff --git a/scholar/cmd/open.go b/scholar/cmd/open.go index ded33aa..3b348a7 100644 --- a/scholar/cmd/open.go +++ b/scholar/cmd/open.go @@ -21,7 +21,6 @@ import ( "github.com/cgxeiji/scholar" "github.com/spf13/cobra" - "github.com/spf13/viper" yaml "gopkg.in/yaml.v2" ) @@ -67,14 +66,14 @@ func init() { } func entryFromKey(key string) *scholar.Entry { - dirs, err := ioutil.ReadDir(viper.GetString("deflib")) + dirs, err := ioutil.ReadDir(libraryPath()) if err != nil { panic(err) } for _, dir := range dirs { if dir.IsDir() && dir.Name() == strings.TrimSpace(key) { - d, err := ioutil.ReadFile(filepath.Join(viper.GetString("deflib"), dir.Name(), "entry.yaml")) + d, err := ioutil.ReadFile(filepath.Join(libraryPath(), dir.Name(), "entry.yaml")) if err != nil { panic(err) } diff --git a/scholar/cmd/root.go b/scholar/cmd/root.go index 389a576..9e8bdf1 100644 --- a/scholar/cmd/root.go +++ b/scholar/cmd/root.go @@ -21,9 +21,10 @@ package cmd import ( - "bytes" "fmt" + "io/ioutil" "os" + "path/filepath" "github.com/cgxeiji/scholar" homedir "github.com/mitchellh/go-homedir" @@ -66,28 +67,11 @@ func init() { // Here you will define your flags and configuration settings. // Cobra supports persistent flags, which, if defined here, // will be global for your application. - rootCmd.PersistentFlags().StringVar(&confFile, "config", "", "config file (default $HOME/.config/scholar/config.yaml)") - rootCmd.PersistentFlags().StringVar(&typesFile, "types", "", "entry types file (default $HOME/.config/scholar/types.yaml)") + //rootCmd.PersistentFlags().StringVar(&confFile, "config", "", "config file (default $HOME/.config/scholar/config.yaml)") + //rootCmd.PersistentFlags().StringVar(&typesFile, "types", "", "entry types file (default $HOME/.config/scholar/types.yaml)") + rootCmd.PersistentFlags().StringVarP(¤tLibrary, "library", "l", "", "specify the library") } -var configDefault = []byte(` -# General Settings -GENERAL: - # Set the default library. - # Scholar will retrieve and save entries from this library. - default: scholar - # Set the default text editor - editor: vi - # Set the email for polite use of CrossRef - mailto: mail@example.com - -# Path locations for the libraries. -# You can add as many libraries as you want. -# You can name the library however you want. -LIBRARIES: - scholar: ~/ScholarLibrary -`) - // initConfig reads in config file and ENV variables if set. func initConfig() { if confFile != "" && confFile != "which" { @@ -102,11 +86,25 @@ func initConfig() { viper.AutomaticEnv() // read in environment variables that match - // If a config file is found, read it in. + // Load the configuration file. If not found, auto-generate one. if err := viper.ReadInConfig(); err != nil { fmt.Println(err) - fmt.Println("Using default values") - viper.ReadConfig(bytes.NewBuffer(configDefault)) + fmt.Println("Setting up a new configuration file") + + path, _ := homedir.Dir() + path = filepath.Join(path, ".config", "scholar") + if err := os.MkdirAll(path, os.ModePerm); err != nil { + panic(err) + } + + path = filepath.Join(path, "config.yaml") + if err := ioutil.WriteFile(path, configTemplate, 0644); err != nil { + panic(err) + } + + if err := viper.ReadInConfig(); err != nil { + panic(err) + } } if confFile == "which" { @@ -142,11 +140,25 @@ func initConfig() { et.AddConfigPath("$HOME/.config/scholar") } - err = et.ReadInConfig() - if err != nil { + // Load the configuration file. If not found, auto-generate one. + if err := et.ReadInConfig(); err != nil { fmt.Println(err) - fmt.Println("Please, set an entry types file at any of those locations.") - panic("no types.yaml found") + fmt.Println("Setting up a new types file") + + path, _ := homedir.Dir() + path = filepath.Join(path, ".config", "scholar") + if err := os.MkdirAll(path, os.ModePerm); err != nil { + panic(err) + } + + path = filepath.Join(path, "types.yaml") + if err := ioutil.WriteFile(path, typesTemplate, 0644); err != nil { + panic(err) + } + + if err := et.ReadInConfig(); err != nil { + panic(err) + } } if typesFile == "which" { diff --git a/scholar/cmd/templates.go b/scholar/cmd/templates.go new file mode 100644 index 0000000..60b0924 --- /dev/null +++ b/scholar/cmd/templates.go @@ -0,0 +1,217 @@ +package cmd + +var configTemplate = []byte(`# Scholar Configuration Template + +# This is a template auto-generated by Scholar. +# Feel free to modify it as you like. +# If there is any problem with the configuration, delete this file +# and Scholar will auto-generate another file. + +# General Settings +GENERAL: + # Set the default library. + # Scholar will retrieve and save entries from this library. + default: scholar + # Set the default text editor + editor: vi + # Set the email for polite use of CrossRef + mailto: mail@example.com + +# Path locations for the libraries. +# You can add as many libraries as you want. +# You can name the library however you want. +LIBRARIES: + scholar: ~/ScholarLibrary + papers: ~/ScholarPapers + books: ~/ScholarBooks +`) + +var typesTemplate = []byte(`# Entry Types Template + +# This is a template auto-generated by Scholar. +# Feel free to modify it as you like. +# If there is any problem with the configuration, delete this file +# and Scholar will auto-generate another file. + +article: + desc: An article in a journal, magazine, newspaper, or other periodical which forms a self-contained unit with its own title. + req: + author: Author(s) of the article. + title: Title of the article. + journaltitle: Title of the journal. + date: YYYY-MM-DD format. + opt: + editor: Editor(s) of the journal. + language: Language of the article. + series: Series of the journal. + volume: Volume of the journal. + number: Number of the journal. + issn: ISSN number of the article. + doi: DOI code of the article. + url: URL of the article. + urldate: Access date in YYY-MM-DD format. + +book: + desc: A single-volume book with one or more authors where the authors share credit for the work as a whole. + req: + author: Author(s) of the book. + title: Title of the book. + date: YYYY-MM-DD format. + opt: + editor: Editor(s) of the book. + publisher: Publisher of the book. + location: Location of the publisher. + language: Language of the book. + series: Series of the book. + volume: Volume of the book. + number: Number of the book. + pages: Number of pages is the book. + isbn: ISBN number of the book. + doi: DOI code of the book. + url: URL of the book. + urldate: Access date in YYY-MM-DD format. + +mvbook: + desc: A multi-volume @book. + req: + author: Author(s) of the book. + title: Title of the book. + date: YYYY-MM-DD format. + opt: + editor: Editor(s) of the book. + publisher: Publisher of the book. + location: Location of the publishing company. + language: Language of the book. + series: Series of the book. + volume: Volume of the book. + number: Number of the book. + pages: Number of pages is the book. + isbn: ISBN number of the book. + doi: DOI code of the book. + url: URL of the book. + urldate: Access date in YYY-MM-DD format. + +inbook: + desc: A part of a book which forms a self-contained unit with its own title. + req: + author: Author(s) of the book section. + title: Title of the book section. + booktitle: Title of the book. + date: YYYY-MM-DD format. + opt: + bookauthor: Author(s) of the book. + editor: Editor(s) of the book. + publisher: Publisher of the book. + location: Location of the publisher. + language: Language of the book. + series: Series of the book. + volume: Volume of the book. + number: Number of the book. + pages: Range of pages in the book. + isbn: ISBN number of the book. + doi: DOI code of the book. + url: URL of the book. + urldate: Access date in YYY-MM-DD format. + +collection: + desc: A single-volume collection with multiple, self-contained contributions by distinct authors which have their own title. The work as a whole has no overall author but it will usually have an editor. + req: + editor: Editor(s) of the collection. + title: Title of the collection. + date: YYYY-MM-DD format. + opt: + publisher: Publisher of the collection. + location: Location of the publisher. + language: Language of the collection. + series: Series of the collection. + volume: Volume of the collection. + number: Number of the collection. + pages: Number of pages is the collection. + isbn: ISBN number of the collection. + doi: DOI code of the collection. + url: URL of the collection. + urldate: Access date in YYY-MM-DD format. + +inproceedings: + desc: An article in a conference proceedings. + req: + author: Author(s) of the article. + title: Title of the article. + booktitle: Title of the conference proceedings. + date: YYYY-MM-DD format. + opt: + editor: Editor(s) of the conference proceedings. + publisher: Publisher of the conference proceedings. + organization: Organization in charge of the conference proceedings. + language: Language of the article. + series: Series of the conference proceedings. + volume: Volume of the conference proceedings. + number: Number of the conference proceedings. + pages: Range of pages in the conference proceedings. + isbn: ISBN number of the article. + doi: DOI code of the article. + url: URL of the article. + urldate: Access date in YYY-MM-DD format. + +report: + desc: A technical report, research report, or white paper published by a university or some other institution. + req: + author: Author(s) of the report. + title: Title of the report. + type: Specify the type of report. + institution: Institution where the report was published. + date: YYYY-MM-DD format. + opt: + language: Language of the report. + version: Version of the report. + number: Number of the report. + isrn: ISRN number of the report. + doi: DOI code of the report. + url: URL of the report. + urldate: Access date in YYY-MM-DD format. + +thesis: + desc: A thesis written for an educational institution to satisfy the requirements for a degree. + req: + author: Author(s) of the thesis. + title: Title of the thesis. + type: Specify the type of thesis. + institution: Institution where the thesis was published. + date: YYYY-MM-DD format. + opt: + chapter: Chapter where the thesis is located. + pages: Range of pages where the thesis is located. + pagetotal: Total number of pages of the thesis. + language: Language of the thesis. + location: Location where the thesis was published. + isbn: ISBN number of the thesis. + doi: DOI code of the thesis. + url: URL of the thesis. + urldate: Access date in YYY-MM-DD format. + +misc: + desc: A fallback for entries which do not fit into any other category. + req: + author: Author(s) of the work. + title: Title of the work. + date: YYY-MM-DD format. + opt: + howpublished: Supply publishing information in free format. + type: Specify the type of work. + url: URL of the work. + urldate: Access date in YYY-MM-DD work. + +online: + desc: An online resource. This entry type is intended for sources such as web sites. Note that all entry types suppert the url field. + req: + author: Author(s) of the resource. + title: Title of the resource. + url: URL of the resource. + date: YYYY-MM-DD format. + opt: + language: Language of the resource. + version: Version of the resource. + note: Notes regarding the resource. + organization: Organization associated with the resource. + urldate: Access date in YYY-MM-DD work. +`)