-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathsearch.py
More file actions
123 lines (106 loc) · 4.46 KB
/
search.py
File metadata and controls
123 lines (106 loc) · 4.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# search.py
import os
from stack import Stack
from index import InvertedIndex
# Path to the folder that has all text files
PATH = "./documents" # to base dir
class SearchSim:
"""A simple search engine simulation."""
def __init__(self, path=PATH):
self.index = InvertedIndex() # for word search
self.history = Stack() # to store search history
self.redo = Stack() # to redo
self.path = path # folder path
self.results = [] # last search results
self._load() # load documents into index
def _load(self):
"""Load all text files and build the index."""
print("Loading index...")
try:
files = [f for f in os.listdir(self.path) if f.endswith(".txt")]
if not files:
print("No .txt files found in documents folder.")
for f in files:
doc = os.path.splitext(f)[0] # filename without .txt
with open(os.path.join(self.path, f), "r", encoding="utf-8") as file:
self.index.add_doc(doc, file.read())
print(f"Index built with {len(files)} documents.")
except FileNotFoundError:
print("Documents folder not found!")
exit()
def run(self):
"""Main loop for user interaction."""
while True:
user_input = input("\nEnter search query, 'back', 'next', 'show', or 'quit': ").strip().lower()
if user_input == "quit":
print("Goodbye!")
break
elif user_input == "back":
self._back()
elif user_input == "next":
self._next()
elif user_input == "show":
self.history.show()
elif user_input: # if user typed something
self._search(user_input)
def _search(self, query):
"""Handle search queries."""
self.history.push(query)
print(f"\nSearching for: '{query}'")
self.results = self.index.search(query)
if not self.results:
print("No matches found.")
return
print(f"Found {len(self.results)} document(s):")
for i, r in enumerate(self.results, start=1):
print(f"{i}. {r['doc']}.txt | Score: {r['score']}")
self._open_doc()
def _open_doc(self):
"""Open and show the contents of a selected document."""
while True:
choice = input("\nEnter document number to open, or 'continue': ").strip().lower()
if choice == "continue":
break
try:
num = int(choice)
if 1 <= num <= len(self.results):
doc = self.results[num - 1]["doc"]
with open(os.path.join(self.path, f"{doc}.txt"), "r", encoding="utf-8") as f:
print(f"\n--- {doc}.txt ---\n{f.read()}\n------------------")
else:
print("Invalid number.")
except ValueError:
print("Please enter a valid number or 'continue'.")
except FileNotFoundError:
print("File not found.")
def _back(self):
"""Go back to the previous search query."""
if len(self.history.items) <= 1:
print("No previous search available.")
return
current = self.history.pop() # remove current
self.redo.push(current) # store it for redo
prev_query = self.history.peek() # now last one left
print(f"\nBack to: '{prev_query}'")
self.results = self.index.search(prev_query)
if not self.results:
print("No matches found.")
else:
for i, r in enumerate(self.results, start=1):
print(f"{i}. {r['doc']}.txt | Score: {r['score']}")
self._open_doc()
def _next(self):
"""Redo the last undone search query."""
if self.redo.empty():
print("Nothing to Redo!")
return
redo_query = self.redo.pop() # get last undone query
self.history.push(redo_query) # put it back into history
print(f"\nRedo: '{redo_query}'")
self.results = self.index.search(redo_query)
if not self.results:
print("No matches found.")
else:
for i, r in enumerate(self.results, start=1):
print(f"{i}. {r['doc']}.txt | Score: {r['score']}")
self._open_doc()