diff --git a/AUTHORS b/AUTHORS index 7035a5b..16d19a7 100644 --- a/AUTHORS +++ b/AUTHORS @@ -9,6 +9,7 @@ # Please keep the list sorted. Alexander Peters +Bram Leenders Google Inc. Jay Graves Jeremy Jay diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 10ae14f..fdc75b4 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -13,6 +13,7 @@ Alexander Peters Barak Michener +Bram Leenders Jay Graves Jeremy Jay Pius Uzamere diff --git a/db/repl.go b/db/repl.go index da3aff9..04ba6e6 100644 --- a/db/repl.go +++ b/db/repl.go @@ -118,33 +118,38 @@ func Repl(h *graph.Handle, queryLanguage string, cfg *config.Config) error { } if code == "" { - switch { - case strings.HasPrefix(line, ":debug"): + cmd, args := splitLine(line) + + switch cmd { + case ":debug": ses.ToggleDebug() fmt.Println("Debug Toggled") continue - case strings.HasPrefix(line, ":a"): - quad, err := cquads.Parse(line[3:]) - if !quad.IsValid() { - if err != nil { - fmt.Printf("not a valid quad: %v\n", err) - } + case ":a": + quad, err := cquads.Parse(args) + if err != nil { + fmt.Printf("Error: not a valid quad: %v\n", err) continue } + h.QuadWriter.AddQuad(quad) continue - case strings.HasPrefix(line, ":d"): - quad, err := cquads.Parse(line[3:]) - if !quad.IsValid() { - if err != nil { - fmt.Printf("not a valid quad: %v\n", err) - } + case ":d": + quad, err := cquads.Parse(args) + if err != nil { + fmt.Printf("Error: not a valid quad: %v\n", err) continue } h.QuadWriter.RemoveQuad(quad) continue + + default: + if cmd[0] == ':' { + fmt.Printf("Unknown command: %q\n", cmd) + continue + } } } @@ -163,6 +168,26 @@ func Repl(h *graph.Handle, queryLanguage string, cfg *config.Config) error { } } +// Splits a line into a command and its arguments +// e.g. ":a b c d ." will be split into ":a" and " b c d ." +func splitLine(line string) (string, string) { + var command, arguments string + + line = strings.TrimSpace(line) + + // An empty line/a line consisting of whitespace contains neither command nor arguments + if len(line) > 0 { + command = strings.Fields(line)[0] + + // A line containing only a command has no arguments + if len(line) > len(command) { + arguments = line[len(command):] + } + } + + return command, arguments +} + func terminal(path string) (*liner.State, error) { term := liner.NewLiner() diff --git a/db/repl_test.go b/db/repl_test.go new file mode 100644 index 0000000..412796c --- /dev/null +++ b/db/repl_test.go @@ -0,0 +1,66 @@ +// Copyright 2014 The Cayley Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package db + +import ( + "testing" +) + +var testSplitLines = []struct { + line string + expectedCommand string + expectedArguments string + err error +}{ + { + line: ":a arg1 arg2 arg3 .", + expectedCommand: ":a", + expectedArguments: " arg1 arg2 arg3 .", + }, + { + line: ":debug", + expectedCommand: ":debug", + // expectedArguments is nil + }, + { + line: "", + // expectedCommand is nil + // expectedArguments is nil + }, + { + line: `:d . # comments here`, + expectedCommand: ":d", + expectedArguments: ` . # comments here`, + }, + { + line: ` :a subject "predicate with spaces" object . `, + expectedCommand: ":a", + expectedArguments: ` subject "predicate with spaces" object .`, + }, +} + +func TestSplitLines(t *testing.T) { + for _, testcase := range testSplitLines { + command, arguments := splitLine(testcase.line) + + if testcase.expectedCommand != command { + t.Errorf("Error splitting lines: got: %v expected: %v", command, testcase.expectedCommand) + } + + if testcase.expectedArguments != arguments { + t.Errorf("Error splitting lines: got: %v expected: %v", arguments, testcase.expectedArguments) + } + } +} diff --git a/docs/Overview.md b/docs/Overview.md index ff99777..0eeb61f 100644 --- a/docs/Overview.md +++ b/docs/Overview.md @@ -50,6 +50,18 @@ Now it's loaded. We can use Cayley now to connect to the graph. As you might hav Where you'll be given a `cayley>` prompt. It's expecting Gremlin/JS, but that can also be configured with a flag. +New nodes and links can be added with the following command: + +```bash +cayley> :a object predicate subject label . +``` + +Removing links works similarly: + +```bash +cayley> :d object predicate subject . +``` + This is great for testing, and ultimately also for scripting, but the real workhorse is the next step. ### Serve Your Graph