mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-08-15 05:04:27 +08:00
RAGFlow go API server (#13240)
# RAGFlow Go Implementation Plan 🚀 This repository tracks the progress of porting RAGFlow to Go. We'll implement core features and provide performance comparisons between Python and Go versions. ## Implementation Checklist - [x] User Management APIs - [x] Dataset Management Operations - [x] Retrieval Test - [x] Chat Management Operations - [x] Infinity Go SDK --------- Signed-off-by: Jin Hai <haijin.chn@gmail.com> Co-authored-by: Yingfeng Zhang <yingfeng.zhang@gmail.com>
This commit is contained in:
167
internal/cli/table.go
Normal file
167
internal/cli/table.go
Normal file
@@ -0,0 +1,167 @@
|
||||
//
|
||||
// Copyright 2026 The InfiniFlow 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 cli
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
// PrintTableSimple prints data in a simple table format
|
||||
// Similar to Python's _print_table_simple
|
||||
func PrintTableSimple(data []map[string]interface{}) {
|
||||
if len(data) == 0 {
|
||||
fmt.Println("No data to print")
|
||||
return
|
||||
}
|
||||
|
||||
// Collect all column names
|
||||
columnSet := make(map[string]bool)
|
||||
for _, item := range data {
|
||||
for key := range item {
|
||||
columnSet[key] = true
|
||||
}
|
||||
}
|
||||
|
||||
// Sort columns
|
||||
columns := make([]string, 0, len(columnSet))
|
||||
for col := range columnSet {
|
||||
columns = append(columns, col)
|
||||
}
|
||||
// Simple sort - in production you might want specific column ordering
|
||||
for i := 0; i < len(columns); i++ {
|
||||
for j := i + 1; j < len(columns); j++ {
|
||||
if columns[i] > columns[j] {
|
||||
columns[i], columns[j] = columns[j], columns[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate column widths
|
||||
colWidths := make(map[string]int)
|
||||
for _, col := range columns {
|
||||
maxWidth := getStringWidth(col)
|
||||
for _, item := range data {
|
||||
value := fmt.Sprintf("%v", item[col])
|
||||
valueWidth := getStringWidth(value)
|
||||
if valueWidth > maxWidth {
|
||||
maxWidth = valueWidth
|
||||
}
|
||||
}
|
||||
if maxWidth < 2 {
|
||||
maxWidth = 2
|
||||
}
|
||||
colWidths[col] = maxWidth
|
||||
}
|
||||
|
||||
// Generate separator
|
||||
separatorParts := make([]string, 0, len(columns))
|
||||
for _, col := range columns {
|
||||
separatorParts = append(separatorParts, strings.Repeat("-", colWidths[col]+2))
|
||||
}
|
||||
separator := "+" + strings.Join(separatorParts, "+") + "+"
|
||||
|
||||
// Print header
|
||||
fmt.Println(separator)
|
||||
headerParts := make([]string, 0, len(columns))
|
||||
for _, col := range columns {
|
||||
headerParts = append(headerParts, fmt.Sprintf(" %-*s ", colWidths[col], col))
|
||||
}
|
||||
fmt.Println("|" + strings.Join(headerParts, "|") + "|")
|
||||
fmt.Println(separator)
|
||||
|
||||
// Print data rows
|
||||
for _, item := range data {
|
||||
rowParts := make([]string, 0, len(columns))
|
||||
for _, col := range columns {
|
||||
value := fmt.Sprintf("%v", item[col])
|
||||
valueWidth := getStringWidth(value)
|
||||
// Truncate if too long
|
||||
if valueWidth > colWidths[col] {
|
||||
runes := []rune(value)
|
||||
truncated := truncateString(runes, colWidths[col])
|
||||
value = truncated
|
||||
valueWidth = getStringWidth(value)
|
||||
}
|
||||
// Pad to column width
|
||||
padding := colWidths[col] - valueWidth + len(value)
|
||||
rowParts = append(rowParts, fmt.Sprintf(" %-*s ", padding, value))
|
||||
}
|
||||
fmt.Println("|" + strings.Join(rowParts, "|") + "|")
|
||||
}
|
||||
|
||||
fmt.Println(separator)
|
||||
}
|
||||
|
||||
// getStringWidth calculates the display width of a string
|
||||
// Treats CJK characters as width 2
|
||||
func getStringWidth(text string) int {
|
||||
width := 0
|
||||
for _, r := range text {
|
||||
if isHalfWidth(r) {
|
||||
width++
|
||||
} else {
|
||||
width += 2
|
||||
}
|
||||
}
|
||||
return width
|
||||
}
|
||||
|
||||
// isHalfWidth checks if a rune is half-width
|
||||
func isHalfWidth(r rune) bool {
|
||||
// ASCII printable characters and common whitespace
|
||||
if r >= 0x20 && r <= 0x7E {
|
||||
return true
|
||||
}
|
||||
if r == '\t' || r == '\n' || r == '\r' {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// truncateString truncates a string to fit within maxWidth display width
|
||||
func truncateString(runes []rune, maxWidth int) string {
|
||||
width := 0
|
||||
for i, r := range runes {
|
||||
if isHalfWidth(r) {
|
||||
width++
|
||||
} else {
|
||||
width += 2
|
||||
}
|
||||
if width > maxWidth-3 {
|
||||
return string(runes[:i]) + "..."
|
||||
}
|
||||
}
|
||||
return string(runes)
|
||||
}
|
||||
|
||||
// getMax returns the maximum of two integers
|
||||
func getMax(a, b int) int {
|
||||
if a > b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
// isWideChar checks if a character is wide (CJK, etc.)
|
||||
func isWideChar(r rune) bool {
|
||||
return unicode.Is(unicode.Han, r) ||
|
||||
unicode.Is(unicode.Hiragana, r) ||
|
||||
unicode.Is(unicode.Katakana, r) ||
|
||||
unicode.Is(unicode.Hangul, r)
|
||||
}
|
||||
Reference in New Issue
Block a user