Skip to content

Commit e9efcac

Browse files
Add function search option
1 parent 0d08499 commit e9efcac

File tree

9 files changed

+432
-88
lines changed

9 files changed

+432
-88
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
/EmployeeApp
22
/gopdfsuit
3-
/gochromedp
3+
/gochromedp
4+
/kubernetes

cmd/server/main.go

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ func main() {
4848

4949
// API routes
5050
router.GET("/api/relations", handleRelations)
51+
router.GET("/api/search", handleSearch)
5152
router.POST("/api/reload", func(c *gin.Context) {
5253
if err := load(repoPath); err != nil {
5354
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
@@ -290,6 +291,127 @@ func handleRelations(c *gin.Context) {
290291
})
291292
}
292293

294+
// handleSearch searches for functions by name and returns their dependency closure with pagination
295+
// Query params: q (search query), page (1-based), pageSize
296+
// Response: { query, page, pageSize, totalResults, matchingFunctions: [...], data: [OutRelation ...] }
297+
func handleSearch(c *gin.Context) {
298+
global.mu.RLock()
299+
defer global.mu.RUnlock()
300+
301+
query := strings.TrimSpace(c.Query("q"))
302+
if query == "" {
303+
c.JSON(http.StatusBadRequest, gin.H{"error": "search query 'q' is required"})
304+
return
305+
}
306+
307+
// Parse pagination parameters
308+
page := parseInt(c.Query("page"), 1)
309+
pageSize := parseInt(c.Query("pageSize"), 10)
310+
if page < 1 {
311+
page = 1
312+
}
313+
if pageSize <= 0 || pageSize > 200 {
314+
pageSize = 10
315+
}
316+
317+
// Convert query to lowercase for case-insensitive search
318+
lowerQuery := strings.ToLower(query)
319+
320+
// First, try to find functions by name only (prioritized search)
321+
var matchingFunctions []analyzer.OutRelation
322+
for _, rel := range global.relations {
323+
lowerName := strings.ToLower(rel.Name)
324+
if strings.Contains(lowerName, lowerQuery) {
325+
matchingFunctions = append(matchingFunctions, rel)
326+
}
327+
}
328+
329+
// If no results found in function names, search in both function names and file paths
330+
if len(matchingFunctions) == 0 {
331+
for _, rel := range global.relations {
332+
lowerName := strings.ToLower(rel.Name)
333+
lowerPath := strings.ToLower(rel.FilePath)
334+
if strings.Contains(lowerName, lowerQuery) || strings.Contains(lowerPath, lowerQuery) {
335+
matchingFunctions = append(matchingFunctions, rel)
336+
}
337+
}
338+
}
339+
340+
// Sort matching functions for consistent pagination
341+
sort.Slice(matchingFunctions, func(i, j int) bool {
342+
if matchingFunctions[i].Name == matchingFunctions[j].Name {
343+
return matchingFunctions[i].FilePath < matchingFunctions[j].FilePath
344+
}
345+
return matchingFunctions[i].Name < matchingFunctions[j].Name
346+
})
347+
348+
// Apply pagination to matching functions
349+
totalResults := len(matchingFunctions)
350+
start := (page - 1) * pageSize
351+
if start > totalResults {
352+
start = totalResults
353+
}
354+
end := start + pageSize
355+
if end > totalResults {
356+
end = totalResults
357+
}
358+
paginatedMatches := matchingFunctions[start:end]
359+
360+
// Build dependency closure for paginated matching functions
361+
closureMap := make(map[string]analyzer.OutRelation)
362+
ck := func(name, file string) string { return name + "|" + file }
363+
364+
var collect func(name, file string)
365+
collect = func(name, file string) {
366+
k := ck(name, file)
367+
if _, exists := closureMap[k]; exists {
368+
return
369+
}
370+
rel, ok := global.index[k]
371+
if !ok {
372+
return
373+
}
374+
// Exclude internal functions from search results
375+
if strings.HasPrefix(name, "analyzer.") || name == "main.findFunctions" || name == "main.load" {
376+
for _, c := range rel.Called {
377+
collect(c.Name, c.FilePath)
378+
}
379+
return
380+
}
381+
closureMap[k] = rel
382+
for _, c := range rel.Called {
383+
collect(c.Name, c.FilePath)
384+
}
385+
}
386+
387+
// Collect closure for each paginated matching function
388+
for _, match := range paginatedMatches {
389+
collect(match.Name, match.FilePath)
390+
}
391+
392+
// Convert to slice and sort
393+
var closure []analyzer.OutRelation
394+
for _, v := range closureMap {
395+
closure = append(closure, v)
396+
}
397+
sort.Slice(closure, func(i, j int) bool {
398+
if closure[i].Name == closure[j].Name {
399+
return closure[i].FilePath < closure[j].FilePath
400+
}
401+
return closure[i].Name < closure[j].Name
402+
})
403+
404+
c.JSON(http.StatusOK, gin.H{
405+
"query": query,
406+
"page": page,
407+
"pageSize": pageSize,
408+
"totalResults": totalResults,
409+
"matchingFunctions": paginatedMatches,
410+
"data": closure,
411+
"loadedAt": global.loadedAt,
412+
})
413+
}
414+
293415
// Helpers --------------------------------------------------------------------------------
294416

295417
func parseInt(s string, def int) int {

docs/assets/index-BrKfIxoH.css renamed to docs/assets/index-CQyv4Z3u.css

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/assets/index-DO3v75Fj.js

Lines changed: 71 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/assets/index-DzPb4jhv.js

Lines changed: 0 additions & 71 deletions
This file was deleted.

docs/index.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
content="Function Mind Map - Visualize your code structure"
1111
/>
1212
<title>Function Mind Map</title>
13-
<script type="module" crossorigin src="/gomindmapper/assets/index-DzPb4jhv.js"></script>
14-
<link rel="stylesheet" crossorigin href="/gomindmapper/assets/index-BrKfIxoH.css">
13+
<script type="module" crossorigin src="/gomindmapper/assets/index-DO3v75Fj.js"></script>
14+
<link rel="stylesheet" crossorigin href="/gomindmapper/assets/index-CQyv4Z3u.css">
1515
</head>
1616
<body>
1717
<noscript>You need to enable JavaScript to run this app.</noscript>

kubernetes

Lines changed: 0 additions & 1 deletion
This file was deleted.

mind-map-react/src/App.css

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,80 @@ body {
196196
transition: all 0.2s ease;
197197
}
198198

199+
/* Server controls container */
200+
.server-controls {
201+
display: flex;
202+
flex-direction: column;
203+
gap: 12px;
204+
}
205+
206+
/* Search bar styles */
207+
.search-bar {
208+
display: flex;
209+
align-items: center;
210+
gap: 8px;
211+
background: var(--bg-secondary);
212+
border: 1px solid var(--border-primary);
213+
padding: 8px 12px;
214+
border-radius: 8px;
215+
}
216+
217+
.search-input {
218+
flex: 1;
219+
background: var(--bg-primary);
220+
color: var(--text-primary);
221+
border: 1px solid var(--border-primary);
222+
padding: 6px 10px;
223+
border-radius: 6px;
224+
font-size: 13px;
225+
transition: border-color 0.2s ease, box-shadow 0.2s ease;
226+
}
227+
228+
.search-input:focus {
229+
outline: none;
230+
border-color: #6366f1;
231+
box-shadow: 0 0 0 2px rgba(99, 102, 241, 0.2);
232+
}
233+
234+
.search-input:disabled {
235+
opacity: 0.6;
236+
cursor: not-allowed;
237+
}
238+
239+
.search-btn, .clear-search-btn {
240+
background: #6366f1;
241+
color: white;
242+
border: none;
243+
padding: 6px 12px;
244+
border-radius: 6px;
245+
font-size: 12px;
246+
font-weight: 500;
247+
cursor: pointer;
248+
transition: all 0.2s ease;
249+
min-width: 60px;
250+
}
251+
252+
.search-btn:hover:not(:disabled) {
253+
background: #5855eb;
254+
transform: translateY(-1px);
255+
}
256+
257+
.search-btn:disabled {
258+
opacity: 0.6;
259+
cursor: not-allowed;
260+
}
261+
262+
.clear-search-btn {
263+
background: var(--btn-secondary-bg);
264+
color: var(--btn-secondary-text);
265+
border: 1px solid var(--btn-secondary-border);
266+
}
267+
268+
.clear-search-btn:hover:not(:disabled) {
269+
background: var(--btn-secondary-hover);
270+
transform: translateY(-1px);
271+
}
272+
199273
.pagination-bar {
200274
display: flex;
201275
align-items: center;

0 commit comments

Comments
 (0)