Initial Commit
This commit is contained in:
		
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | |||||||
|  | # Ignore the binary | ||||||
|  | mark | ||||||
							
								
								
									
										30
									
								
								helpers.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								helpers.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | |||||||
|  | package main | ||||||
|  |  | ||||||
|  | // helpers.go contains some helper functions for manipulating/processing data | ||||||
|  | // that doesn't really fit in elsewhere | ||||||
|  |  | ||||||
|  | // matchStringInSlice finds the closes match to 'ndl' in 'hay' | ||||||
|  | // It starts at the beginning of 'ndl' and matches letters in 'hay' until either | ||||||
|  | // we've matched the whole 'ndl' or there is only one result left | ||||||
|  | func matchStringInSlice(ndl string, hay []string) string { | ||||||
|  | 	var nextHay []string | ||||||
|  |  | ||||||
|  | 	for i := range ndl { | ||||||
|  | 		for _, p := range hay { | ||||||
|  | 			if p[i] == ndl[i] { | ||||||
|  | 				nextHay = append(hay, p) | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		// If we get here and there is only one parameter left, return it | ||||||
|  | 		hay = nextHay | ||||||
|  | 		if len(nextHay) == 1 { | ||||||
|  | 			break | ||||||
|  | 		} | ||||||
|  | 		// Otherwise, loop | ||||||
|  | 		nextHay = []string{} | ||||||
|  | 	} | ||||||
|  | 	if len(hay) == 0 { | ||||||
|  | 		return "" | ||||||
|  | 	} | ||||||
|  | 	return hay[0] | ||||||
|  | } | ||||||
							
								
								
									
										108
									
								
								main.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								main.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,108 @@ | |||||||
|  | package main | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"os" | ||||||
|  |  | ||||||
|  | 	userConfig "github.com/br0xen/user-config" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | const AppName = "mark" | ||||||
|  | const DefDBName = AppName + ".db" | ||||||
|  |  | ||||||
|  | var mdb *MarkDB | ||||||
|  | var cfg *userConfig.Config | ||||||
|  |  | ||||||
|  | // Valid command line options | ||||||
|  | var validFlags []cliFlag | ||||||
|  |  | ||||||
|  | func main() { | ||||||
|  | 	err := initialize() | ||||||
|  | 	if err != nil { | ||||||
|  | 		fmt.Println(err) | ||||||
|  | 		os.Exit(1) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// If no command line options are given, go into gui mode | ||||||
|  | 	if len(os.Args) > 1 { | ||||||
|  | 		fmt.Println(os.Args[1]) | ||||||
|  | 		if os.Args[1] == "-a" { | ||||||
|  | 			// Adding a new bookmark | ||||||
|  | 		} | ||||||
|  | 	} else { | ||||||
|  | 		// Enter cui mode | ||||||
|  | 		fmt.Println("Entering CUI Mode") | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // initialize sets up the application for general use | ||||||
|  | func initialize() error { | ||||||
|  | 	var err error | ||||||
|  | 	// Build the list of valid command line options | ||||||
|  | 	addValidFlag("-a", "add", []string{"Add a new bookmark"}) | ||||||
|  | 	addValidFlag("-h", "help", []string{"Print the usage (this message)"}) | ||||||
|  | 	addValidFlag("-n", "name", []string{ | ||||||
|  | 		"When adding/updating, specify the name you wish to give a bookmark.", | ||||||
|  | 		"When searching, specifiy the name of the bookmark(s) you're searching for.", | ||||||
|  | 	}) | ||||||
|  | 	addValidFlag("-t", "tag", []string{ | ||||||
|  | 		"Comma delimited tags", | ||||||
|  | 		"When adding/updating, specify the tags you wish to give a bookmark.", | ||||||
|  | 		"When searching, specifiy the name of the tags you're searching for.", | ||||||
|  | 	}) | ||||||
|  | 	addValidFlag("-u", "update", []string{"Update an existing bookmark"}) | ||||||
|  |  | ||||||
|  | 	// Load the config | ||||||
|  | 	cfg, err = userConfig.NewConfig(AppName) | ||||||
|  | 	if err != nil { | ||||||
|  | 		fmt.Println(err.Error()) | ||||||
|  | 		fmt.Println("Creating new config") | ||||||
|  | 		cfg.Save() | ||||||
|  | 	} | ||||||
|  | 	// if dbdir isn't set, set it to the config directory | ||||||
|  | 	if cfg.Get("dbdir") == "" { | ||||||
|  | 		cfg.Set("dbdir", cfg.GetConfigPath()+"/") | ||||||
|  | 	} | ||||||
|  | 	// if dbname isn't set, set it to the default db name | ||||||
|  | 	if cfg.Get("dbname") == "" { | ||||||
|  | 		cfg.Set("dbname", DefDBName) | ||||||
|  | 	} | ||||||
|  | 	// Get a reference to the database | ||||||
|  | 	if mdb, err = NewDatabase(cfg.Get("dbdir"), cfg.Get("dbname")); err != nil { | ||||||
|  | 		fmt.Println("Error loading the database") | ||||||
|  | 		os.Exit(1) | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Adds an option to the "validFlags" slice | ||||||
|  | func addValidFlag(flag, name string, desc []string) { | ||||||
|  | 	validFlags = append(validFlags, cliFlag{ | ||||||
|  | 		Flag:        flag, | ||||||
|  | 		Name:        name, | ||||||
|  | 		Description: desc, | ||||||
|  | 	}) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func printUsage() { | ||||||
|  | 	help := []string{ | ||||||
|  | 		"mark is a tool for keeping your bookmarks organized", | ||||||
|  | 		"", | ||||||
|  | 		"Usage: ", | ||||||
|  | 		"\tmark", | ||||||
|  | 		"", | ||||||
|  | 		"If no arguments are given, we enter gui mode", | ||||||
|  | 		"", | ||||||
|  | 		"Valid arguments are:", | ||||||
|  | 		"", | ||||||
|  | 	} | ||||||
|  | 	for _, ln := range help { | ||||||
|  | 		fmt.Println(ln) | ||||||
|  | 	} | ||||||
|  | 	for _, v := range validFlags { | ||||||
|  | 		fmt.Println(v.Flag, "\t", v.Name) | ||||||
|  | 		for _, hv := range v.Description { | ||||||
|  | 			fmt.Println("\t", hv) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										76
									
								
								model.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								model.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,76 @@ | |||||||
|  | package main | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"errors" | ||||||
|  |  | ||||||
|  | 	"github.com/br0xen/boltease" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // model.go contains some basic database stuff | ||||||
|  |  | ||||||
|  | // MarkDB is an abstraction of a boltease.DB (which is an abstraction of | ||||||
|  | // a bolt.DB) | ||||||
|  | type MarkDB struct { | ||||||
|  | 	db             *boltease.DB | ||||||
|  | 	dbOpened       int // Track how many 'open' requests are outstanding | ||||||
|  | 	path, filename string | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func NewDatabase(path, name string) (*MarkDB, error) { | ||||||
|  | 	if path[len(path)-1] != '/' { | ||||||
|  | 		path = path + "/" | ||||||
|  | 	} | ||||||
|  | 	mdb := MarkDB{ | ||||||
|  | 		path:     path, | ||||||
|  | 		filename: name, | ||||||
|  | 	} | ||||||
|  | 	return &mdb, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (mdb *MarkDB) openDatabase() error { | ||||||
|  | 	mdb.dbOpened += 1 | ||||||
|  | 	if mdb.dbOpened == 1 { | ||||||
|  | 		// We actually need to open the DB | ||||||
|  | 		var err error | ||||||
|  | 		mdb.db, err = boltease.Create(mdb.path+mdb.filename, 0600, nil) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (mdb *MarkDB) closeDatabase() error { | ||||||
|  | 	mdb.dbOpened -= 1 | ||||||
|  | 	if mdb.dbOpened == 0 { | ||||||
|  | 		// Actually close the database | ||||||
|  | 		return mdb.db.CloseDB() | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (mdb *MarkDB) initDatabase() error { | ||||||
|  | 	var err error | ||||||
|  | 	if err = mdb.openDatabase(); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	defer mdb.closeDatabase() | ||||||
|  |  | ||||||
|  | 	// Create the path to the bucket to store bookmarks | ||||||
|  | 	if err = mdb.db.MkBucketPath([]string{"bookmarks"}); err != nil { | ||||||
|  | 		return errors.New("Error creating 'bookmarks' bucket: " + err.Error()) | ||||||
|  | 	} | ||||||
|  | 	// Create the path to the bucket to store additional config | ||||||
|  | 	if err = mdb.db.MkBucketPath([]string{"config"}); err != nil { | ||||||
|  | 		return errors.New("Error creating 'config' bucket: " + err.Error()) | ||||||
|  | 	} | ||||||
|  | 	if err = mdb.db.SetInt([]string{"config"}, "lastIdx", 0); err != nil { | ||||||
|  | 		return errors.New("Error setting 'lastIdx' to 0: " + err.Error()) | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // getNextIndex returns the next | ||||||
|  | func (mdb *MarkDB) getNextIndex() int { | ||||||
|  | 	return 0 | ||||||
|  | } | ||||||
							
								
								
									
										23
									
								
								model_bookmark.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								model_bookmark.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | |||||||
|  | package main | ||||||
|  |  | ||||||
|  | import "time" | ||||||
|  |  | ||||||
|  | type Bookmark struct { | ||||||
|  | 	Id       int | ||||||
|  | 	Name     string | ||||||
|  | 	Url      string | ||||||
|  | 	Desc     string | ||||||
|  | 	Tags     []string | ||||||
|  | 	Created  time.Time | ||||||
|  | 	LastUsed time.Time | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func NewBookmark(url string) *Bookmark { | ||||||
|  | 	// First, search for a bookmark with this same URL | ||||||
|  | 	// If we didn't find one, create a new bookmark struct | ||||||
|  | 	b := Bookmark{ | ||||||
|  | 		Id:  0, | ||||||
|  | 		Url: url, | ||||||
|  | 	} | ||||||
|  | 	return &b | ||||||
|  | } | ||||||
							
								
								
									
										12
									
								
								structs.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								structs.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | |||||||
|  | package main | ||||||
|  |  | ||||||
|  | // structs.go contains structs for types that don't warrant their own 'model' | ||||||
|  | // file. | ||||||
|  |  | ||||||
|  | // A command line option, used to parse command lines | ||||||
|  | // and also to display the usage | ||||||
|  | type cliFlag struct { | ||||||
|  | 	Flag        string | ||||||
|  | 	Name        string | ||||||
|  | 	Description []string | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user