Repository: tableauio/tableau (go)

Issue:
protogen: support workbook alias in metasheet @TABLEAU
Currently, each worksheet in a workbook can be specified an alias, but not the workbook name.

Here, we propose the special sign `#` in `Sheet` column of metasheet `@TABLEAU` to represent this wokbook self:

| Sheet | Alias |
|--|--|
| # | WorkbookAlias |
| Sheet1 | Sheet1Alias |


Pull request description:
protogen: support workbook alias in metasheet @TABLEAU
- close #23 

Patch:
diff --git a/internal/importer/book/book.go b/internal/importer/book/book.go
index 148d5e1..d994be9 100644
--- a/internal/importer/book/book.go
+++ b/internal/importer/book/book.go
@@ -25,8 +25,8 @@ type Book struct {
 
 // NewBook creates a new book.
 // Example:
-// 	- bookName: Test
-// 	- filename: testdata/Test.xlsx
+//   - bookName: Test
+//   - filename: testdata/Test.xlsx
 func NewBook(bookName, filename string, parser SheetParser) *Book {
 	return &Book{
 		name:     bookName,
@@ -148,10 +148,10 @@ func (b *Book) ParseMetaAndPurge() (err error) {
 	}
 
 	if len(b.meta.MetasheetMap) == 0 {
-		// need all sheets except the metasheet "@TABLEAU"
+		// need all sheets except the MetasheetName and BookNameInMetasheet
 		b.meta.MetasheetMap = make(map[string]*tableaupb.Metasheet) // init
 		for _, sheet := range b.GetSheets() {
-			if sheet.Name != MetasheetName {
+			if sheet.Name != MetasheetName && sheet.Name != BookNameInMetasheet {
 				b.meta.MetasheetMap[sheet.Name] = &tableaupb.Metasheet{
 					Sheet: sheet.Name,
 				}
@@ -163,6 +163,9 @@ func (b *Book) ParseMetaAndPurge() (err error) {
 
 	var keepedSheetNames []string
 	for sheetName, sheetMeta := range b.meta.MetasheetMap {
+		if sheetName == BookNameInMetasheet {
+			continue
+		}
 		sheet := b.GetSheet(sheetName)
 		if sheet == nil {
 			return xerrors.E0001(sheetName, b.Filename())
diff --git a/internal/importer/book/sheet.go b/internal/importer/book/sheet.go
index a812016..54d3456 100644
--- a/internal/importer/book/sheet.go
+++ b/internal/importer/book/sheet.go
@@ -15,9 +15,13 @@ import (
 )
 
 // MetasheetName is the name of metasheet which defines the metadata
-// of each worksheet. Default metasheet name is "@TABLEAU".
+// of each worksheet. Default is "@TABLEAU".
 var MetasheetName = "@TABLEAU"
 
+// BookNameInMetasheet is the special sign which represents workbook itself in metasheet.
+// Default is "#".
+const BookNameInMetasheet = "#"
+
 // SetMetasheetName change the metasheet name to the specified name.
 //
 // NOTE: If will not change MetasheetName value if the specified name
diff --git a/internal/protogen/protogen.go b/internal/protogen/protogen.go
index dcd1e1f..066b356 100644
--- a/internal/protogen/protogen.go
+++ b/internal/protogen/protogen.go
@@ -298,7 +298,13 @@ func (gen *Generator) convert(dir, filename string, checkProtoFileConflicts bool
 	var bp *bookParser
 	if pass == firstPass {
 		// create a book parser
-		bp = newBookParser(imp.BookName(), rewrittenWorkbookName, gen)
+		bookName := imp.BookName()
+		alias := getWorkbookAlias(imp)
+		if alias != "" {
+			bookName = alias
+			debugWorkbookName += " (alias: " + alias + ")"
+		}
+		bp = newBookParser(bookName, rewrittenWorkbookName, gen)
 		// cache this new bookParser
 		gen.addBookParser(absPath, bp)
 	} else {
diff --git a/internal/protogen/util.go b/internal/protogen/util.go
index d3a9ce5..ec93092 100644
--- a/internal/protogen/util.go
+++ b/internal/protogen/util.go
@@ -8,6 +8,8 @@ import (
 	"strings"
 
 	"github.com/tableauio/tableau/internal/fs"
+	"github.com/tableauio/tableau/internal/importer"
+	"github.com/tableauio/tableau/internal/importer/book"
 	"github.com/tableauio/tableau/options"
 	"github.com/tableauio/tableau/proto/tableaupb"
 	"github.com/tableauio/tableau/xerrors"
@@ -59,6 +61,16 @@ func prepareOutdir(outdir string, importFiles []string, delExisted bool) error {
 	return nil
 }
 
+// getWorkbookAlias gets the workbook alias from importer.
+func getWorkbookAlias(imp importer.Importer) string {
+	sheetMap := imp.Metabook().GetMetasheetMap()
+	if sheetMap == nil {
+		return ""
+	}
+	meta := sheetMap[book.BookNameInMetasheet]
+	return meta.GetAlias()
+}
+
 func getRelCleanSlashPath(rootdir, dir, filename string) (string, error) {
 	relativeDir, err := filepath.Rel(rootdir, dir)
 	if err != nil {


Test patch:
diff --git a/test/functest/conf/AliasedSheetScalar.json b/test/functest/conf/AliasedSheetScalar.json
new file mode 100644
index 0000000..041c93c
--- /dev/null
+++ b/test/functest/conf/AliasedSheetScalar.json
@@ -0,0 +1,5 @@
+{
+    "id": 1,
+    "name": "Apple",
+    "desc": "A kind of delicious fruit."
+}
\ No newline at end of file
diff --git a/test/functest/conf/HorizontalIncellInStructList.json b/test/functest/conf/HorizontalIncellInStructList.json
new file mode 100644
index 0000000..8c50939
--- /dev/null
+++ b/test/functest/conf/HorizontalIncellInStructList.json
@@ -0,0 +1,22 @@
+{
+    "taskList": [
+        {
+            "paramList": [
+                1
+            ]
+        },
+        {
+            "paramList": [
+                2,
+                3
+            ]
+        },
+        {
+            "paramList": [
+                4,
+                5,
+                6
+            ]
+        }
+    ]
+}
\ No newline at end of file
diff --git a/test/functest/func_test.go b/test/functest/func_test.go
index 49f3252..013f86f 100644
--- a/test/functest/func_test.go
+++ b/test/functest/func_test.go
@@ -100,8 +100,14 @@ func Test_CompareGeneratedJSON(t *testing.T) {
 		}
 		oldPath := filepath.Join(oldConfDir, file.Name())
 		absOldPath, err := filepath.Abs(oldPath)
+		if err != nil {
+			t.Fatal(err)
+		}
 		newPath := filepath.Join(newConfDir, file.Name())
 		absNewPath, err := filepath.Abs(newPath)
+		if err != nil {
+			t.Fatal(err)
+		}
 		oldData, err := os.ReadFile(oldPath)
 		if err != nil {
 			t.Fatal(err)
diff --git a/test/functest/proto/excel__list__horizontal_list.proto b/test/functest/proto/excel__list__horizontal_list.proto
index 8d9e43e..c2a7415 100644
--- a/test/functest/proto/excel__list__horizontal_list.proto
+++ b/test/functest/proto/excel__list__horizontal_list.proto
@@ -31,6 +31,15 @@ message HorizontalEnumList {
   repeated protoconf.FruitType param_list = 1 [(tableau.field) = {name:"Param" layout:LAYOUT_HORIZONTAL}];
 }
 
+message HorizontalIncellInStructList {
+  option (tableau.worksheet) = {name:"HorizontalIncellInStructList" namerow:1 typerow:2 noterow:3 datarow:4};
+
+  repeated Task task_list = 1 [(tableau.field) = {name:"Task" layout:LAYOUT_HORIZONTAL}];
+  message Task {
+    repeated int32 param_list = 1 [(tableau.field) = {name:"Param" layout:LAYOUT_INCELL}];
+  }
+}
+
 message HorizontalIncellPdefStructList {
   option (tableau.worksheet) = {name:"HorizontalIncellPdefStructList" namerow:1 typerow:2 noterow:3 datarow:4};
 
diff --git a/test/functest/proto/excel__metasheet__aliased_workbook.proto b/test/functest/proto/excel__metasheet__aliased_workbook.proto
new file mode 100644
index 0000000..ad58449
--- /dev/null
+++ b/test/functest/proto/excel__metasheet__aliased_workbook.proto
@@ -0,0 +1,19 @@
+// Code generated by tableau (protogen v0.5.0). DO NOT EDIT.
+// clang-format off
+
+syntax = "proto3";
+
+package protoconf;
+
+import "tableau/protobuf/tableau.proto";
+
+option go_package = "github.com/tableauio/tableau/test/functest/protoconf";
+option (tableau.workbook) = {name:"excel/metasheet/BookAlias#*.csv"};
+
+message AliasedSheetScalar {
+  option (tableau.worksheet) = {name:"Scalar" namerow:1 typerow:2 noterow:3 datarow:4};
+
+  uint32 id = 1 [(tableau.field) = {name:"ID"}];
+  string name = 2 [(tableau.field) = {name:"Name"}];
+  string desc = 3 [(tableau.field) = {name:"Desc"}];
+}
diff --git a/test/functest/testdata/excel/list/HorizontalList#HorizontalIncellInStructList.csv b/test/functest/testdata/excel/list/HorizontalList#HorizontalIncellInStructList.csv
new file mode 100644
index 0000000..8f61a02
--- /dev/null
+++ b/test/functest/testdata/excel/list/HorizontalList#HorizontalIncellInStructList.csv
@@ -0,0 +1,4 @@
+Task1Param,Task2Param,Task3Param
+[Task][]int32,[]int32,[]int32
+Task1,Task2,Task3
+1,"2,3","4,5,6"
diff --git a/test/functest/testdata/excel/metasheet/BookAlias#@TABLEAU.csv b/test/functest/testdata/excel/metasheet/BookAlias#@TABLEAU.csv
new file mode 100644
index 0000000..7dfb5ee
--- /dev/null
+++ b/test/functest/testdata/excel/metasheet/BookAlias#@TABLEAU.csv
@@ -0,0 +1,3 @@
+Sheet,Alias
+#,AliasedWorkbook
+Scalar,AliasedSheetScalar,
\ No newline at end of file
diff --git a/test/functest/testdata/excel/metasheet/BookAlias#Scalar.csv b/test/functest/testdata/excel/metasheet/BookAlias#Scalar.csv
new file mode 100644
index 0000000..581b008
--- /dev/null
+++ b/test/functest/testdata/excel/metasheet/BookAlias#Scalar.csv
@@ -0,0 +1,4 @@
+ID,Name,Desc
+uint32,string,string
+Item's ID,Item's Name,Item's Description
+1,Apple,A kind of delicious fruit.