Allow specifying target for get

Change-Id: I4d8c6e7e445a613a384ef16f06448c101e37abcc
diff --git a/src/ast_commands.cpp b/src/ast_commands.cpp
index 74aefd5..aa4756a 100644
--- a/src/ast_commands.cpp
+++ b/src/ast_commands.cpp
@@ -14,7 +14,7 @@
 
 bool get_::operator==(const get_& b) const
 {
-    return this->m_path == b.m_path;
+    return this->m_path == b.m_path && this->m_dsTarget == b.m_dsTarget;
 }
 
 bool cd_::operator==(const cd_& b) const
diff --git a/src/ast_commands.hpp b/src/ast_commands.hpp
index 0d7a476..0a474f0 100644
--- a/src/ast_commands.hpp
+++ b/src/ast_commands.hpp
@@ -152,6 +152,7 @@
         /> get
         /> get /module:path)";
     bool operator==(const get_& b) const;
+    boost::optional<DatastoreTarget> m_dsTarget;
     boost::optional<boost::variant<dataPath_, module_>> m_path;
 };
 
@@ -360,7 +361,7 @@
 BOOST_FUSION_ADAPT_STRUCT(describe_, m_path)
 BOOST_FUSION_ADAPT_STRUCT(help_, m_cmd)
 BOOST_FUSION_ADAPT_STRUCT(discard_)
-BOOST_FUSION_ADAPT_STRUCT(get_, m_path)
+BOOST_FUSION_ADAPT_STRUCT(get_, m_dsTarget, m_path)
 BOOST_FUSION_ADAPT_STRUCT(copy_, m_source, m_destination)
 BOOST_FUSION_ADAPT_STRUCT(move_, m_source, m_destination)
 BOOST_FUSION_ADAPT_STRUCT(dump_, m_format)
diff --git a/src/datastore_access.cpp b/src/datastore_access.cpp
index eba90e0..e421274 100644
--- a/src/datastore_access.cpp
+++ b/src/datastore_access.cpp
@@ -31,6 +31,11 @@
     }
 }
 
+DatastoreTarget DatastoreAccess::target() const
+{
+    return m_target;
+}
+
 void DatastoreAccess::setTarget(const DatastoreTarget target)
 {
     m_target = target;
diff --git a/src/datastore_access.hpp b/src/datastore_access.hpp
index 3012a7e..a718f14 100644
--- a/src/datastore_access.hpp
+++ b/src/datastore_access.hpp
@@ -57,6 +57,7 @@
     virtual void deleteItem(const std::string& path) = 0;
     virtual void moveItem(const std::string& path, std::variant<yang::move::Absolute, yang::move::Relative> move) = 0;
     virtual Tree execute(const std::string& path, const Tree& input) = 0;
+    DatastoreTarget target() const;
     void setTarget(const DatastoreTarget target);
 
     virtual std::shared_ptr<Schema> schema() = 0;
diff --git a/src/grammars.hpp b/src/grammars.hpp
index 71af580..2220b76 100644
--- a/src/grammars.hpp
+++ b/src/grammars.hpp
@@ -131,8 +131,22 @@
     delete_::name >> space_separator > (presenceContainerPath | listInstancePath | leafListElementPath | writableLeafPath);
 #endif
 
+const auto dsTargetSuggestions = staticSuggestions({"running", "startup", "operational"});
+
+struct ds_target_table : x3::symbols<DatastoreTarget> {
+    ds_target_table()
+    {
+        add
+            ("operational", DatastoreTarget::Operational)
+            ("startup", DatastoreTarget::Startup)
+            ("running", DatastoreTarget::Running);
+    }
+} const ds_target_table;
+
 auto const get_def =
-    get_::name >> -(space_separator >> getPath);
+    get_::name
+    >> -(space_separator >> "-" > staticSuggestions({"-datastore"}) > "-datastore" > space_separator > dsTargetSuggestions > ds_target_table)
+    >> -(space_separator >> getPath);
 
 auto const set_def =
     set_::name >> space_separator > writableLeafPath > space_separator > leaf_data;
@@ -332,18 +346,6 @@
 auto const exec_def =
     exec_::name > -(space_separator > -as<dataPath_>[RpcActionPath<AllowInput::No>{}]);
 
-const auto dsTargetSuggestions = staticSuggestions({"running", "startup", "operational"});
-
-struct ds_target_table : x3::symbols<DatastoreTarget> {
-    ds_target_table()
-    {
-        add
-            ("operational", DatastoreTarget::Operational)
-            ("startup", DatastoreTarget::Startup)
-            ("running", DatastoreTarget::Running);
-    }
-} const ds_target_table;
-
 auto const switch_rule_def =
     switch_::name > space_separator > dsTargetSuggestions > ds_target_table;
 
diff --git a/src/interpreter.cpp b/src/interpreter.cpp
index 8030f3f..0fe96da 100644
--- a/src/interpreter.cpp
+++ b/src/interpreter.cpp
@@ -10,6 +10,7 @@
 #include <boost/mpl/for_each.hpp>
 #include <iostream>
 #include <sstream>
+#include "UniqueResource.hpp"
 #include "datastore_access.hpp"
 #include "interpreter.hpp"
 #include "utils.hpp"
@@ -83,6 +84,14 @@
 
 void Interpreter::operator()(const get_& get) const
 {
+    auto targetSwitcher = make_unique_resource([] {}, [this, oldTarget = m_datastore.target()] {
+        m_datastore.setTarget(oldTarget);
+    });
+
+    if (get.m_dsTarget) {
+        m_datastore.setTarget(*get.m_dsTarget);
+    }
+
     auto items = m_datastore.getItems(pathToString(toCanonicalPath(get.m_path)));
     printTree(items);
 }
diff --git a/src/proxy_datastore.cpp b/src/proxy_datastore.cpp
index 3bd6719..67a3cb3 100644
--- a/src/proxy_datastore.cpp
+++ b/src/proxy_datastore.cpp
@@ -108,6 +108,11 @@
     }
 }
 
+DatastoreTarget ProxyDatastore::target() const
+{
+    return m_datastore->target();
+}
+
 void ProxyDatastore::setTarget(const DatastoreTarget target)
 {
     m_datastore->setTarget(target);
diff --git a/src/proxy_datastore.hpp b/src/proxy_datastore.hpp
index 21fbfc5..20a877d 100644
--- a/src/proxy_datastore.hpp
+++ b/src/proxy_datastore.hpp
@@ -28,6 +28,7 @@
     void discardChanges();
     void copyConfig(const Datastore source, const Datastore destination);
     [[nodiscard]] std::string dump(const DataFormat format) const;
+    DatastoreTarget target() const;
     void setTarget(const DatastoreTarget target);
 
     void initiate(const std::string& path);