leadingbridge commited on
Commit
f020607
·
verified ·
1 Parent(s): 0f72655

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +84 -81
app.py CHANGED
@@ -8,7 +8,6 @@ def count_matches(
8
  find_text: str,
9
  case_sensitive: bool,
10
  ) -> str:
11
- """Return the number of matching occurrences."""
12
  if not find_text:
13
  return "Enter text to find."
14
 
@@ -19,10 +18,7 @@ def count_matches(
19
  else:
20
  count = text.lower().count(find_text.lower())
21
 
22
- if count == 1:
23
- return "1 match found."
24
-
25
- return f"{count} matches found."
26
 
27
 
28
  def replace_first(
@@ -31,7 +27,6 @@ def replace_first(
31
  replace_text: str,
32
  case_sensitive: bool,
33
  ) -> tuple[str, str]:
34
- """Replace the first matching occurrence."""
35
  text = text or ""
36
 
37
  if not find_text:
@@ -48,16 +43,9 @@ def replace_first(
48
  if not pattern.search(text):
49
  return text, "No matches found."
50
 
51
- # Lambda prevents backslashes in replacement text from being interpreted.
52
  updated_text = pattern.sub(lambda _: replace_text, text, count=1)
53
 
54
- remaining = count_matches(
55
- updated_text,
56
- find_text,
57
- case_sensitive,
58
- )
59
-
60
- return updated_text, f"Replaced the first match. {remaining}"
61
 
62
 
63
  def replace_all(
@@ -66,7 +54,6 @@ def replace_all(
66
  replace_text: str,
67
  case_sensitive: bool,
68
  ) -> tuple[str, str]:
69
- """Replace all matching occurrences."""
70
  text = text or ""
71
 
72
  if not find_text:
@@ -81,36 +68,30 @@ def replace_all(
81
  updated_text = text.replace(find_text, replace_text)
82
  else:
83
  pattern = re.compile(re.escape(find_text), re.IGNORECASE)
84
- matches = pattern.findall(text)
85
- match_count = len(matches)
86
 
87
  if match_count == 0:
88
  return text, "No matches found."
89
 
90
  updated_text = pattern.sub(lambda _: replace_text, text)
91
 
92
- if match_count == 1:
93
- status = "Replaced 1 match."
94
- else:
95
- status = f"Replaced {match_count} matches."
96
-
97
- return updated_text, status
98
 
99
 
100
  def clear_editor() -> tuple[str, str, str, str]:
101
- """Clear the editor and search fields."""
102
  return "", "", "", "Editor cleared."
103
 
104
 
105
  CSS = """
106
  .gradio-container {
107
- max-width: 1400px !important;
 
108
  margin: 0 auto !important;
109
  }
110
 
111
  #main-editor textarea {
112
- min-height: 600px !important;
113
- height: 65vh !important;
114
  resize: vertical !important;
115
  font-family:
116
  ui-monospace,
@@ -125,63 +106,84 @@ CSS = """
125
  white-space: pre-wrap !important;
126
  }
127
 
 
 
 
 
 
128
  #status-box textarea {
129
- min-height: 45px !important;
130
  }
131
  """
132
 
133
 
134
- with gr.Blocks(title="Plain Text Editor") as demo:
135
  gr.Markdown("# Plain Text Editor")
136
 
137
- editor = gr.Textbox(
138
- label="Text",
139
- placeholder="Type or paste your plain text here...",
140
- lines=24,
141
- max_lines=1000,
142
- elem_id="main-editor",
143
- buttons=["copy"],
144
- autofocus=True,
145
- )
146
-
147
- with gr.Row():
148
- paste_button = gr.Button("Paste")
149
- clear_button = gr.Button("Clear", variant="stop")
150
-
151
- gr.Markdown("## Find and Replace")
152
-
153
- with gr.Row():
154
- find_input = gr.Textbox(
155
- label="Find",
156
- placeholder="Text to find",
157
- )
158
-
159
- replace_input = gr.Textbox(
160
- label="Replace with",
161
- placeholder="Replacement text",
162
- )
163
-
164
- case_sensitive = gr.Checkbox(
165
- label="Case sensitive",
166
- value=False,
167
- )
168
-
169
- with gr.Row():
170
- find_button = gr.Button("Find")
171
- replace_first_button = gr.Button("Replace First")
172
- replace_all_button = gr.Button(
173
- "Replace All",
174
- variant="primary",
175
- )
176
-
177
- status = gr.Textbox(
178
- label="Status",
179
- value="Ready.",
180
- interactive=False,
181
- elem_id="status-box",
182
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
183
 
184
- # The browser asks for clipboard permission when necessary.
185
  paste_button.click(
186
  fn=None,
187
  inputs=None,
@@ -202,8 +204,10 @@ with gr.Blocks(title="Plain Text Editor") as demo:
202
  }
203
 
204
  const currentText = editor.value || "";
205
- const start = editor.selectionStart ?? currentText.length;
206
- const end = editor.selectionEnd ?? currentText.length;
 
 
207
 
208
  return (
209
  currentText.slice(0, start) +
@@ -213,7 +217,7 @@ with gr.Blocks(title="Plain Text Editor") as demo:
213
  } catch (error) {
214
  alert(
215
  "Clipboard access was blocked. " +
216
- "Please allow clipboard permission or use Ctrl+V / Cmd+V."
217
  );
218
 
219
  return (
@@ -275,7 +279,6 @@ with gr.Blocks(title="Plain Text Editor") as demo:
275
  ],
276
  )
277
 
278
- # Update the match count when Enter is pressed in the Find field.
279
  find_input.submit(
280
  fn=count_matches,
281
  inputs=[
@@ -288,4 +291,4 @@ with gr.Blocks(title="Plain Text Editor") as demo:
288
 
289
 
290
  if __name__ == "__main__":
291
- demo.launch(css=CSS)
 
8
  find_text: str,
9
  case_sensitive: bool,
10
  ) -> str:
 
11
  if not find_text:
12
  return "Enter text to find."
13
 
 
18
  else:
19
  count = text.lower().count(find_text.lower())
20
 
21
+ return f"{count} match{'es' if count != 1 else ''} found."
 
 
 
22
 
23
 
24
  def replace_first(
 
27
  replace_text: str,
28
  case_sensitive: bool,
29
  ) -> tuple[str, str]:
 
30
  text = text or ""
31
 
32
  if not find_text:
 
43
  if not pattern.search(text):
44
  return text, "No matches found."
45
 
 
46
  updated_text = pattern.sub(lambda _: replace_text, text, count=1)
47
 
48
+ return updated_text, "Replaced the first match."
 
 
 
 
 
 
49
 
50
 
51
  def replace_all(
 
54
  replace_text: str,
55
  case_sensitive: bool,
56
  ) -> tuple[str, str]:
 
57
  text = text or ""
58
 
59
  if not find_text:
 
68
  updated_text = text.replace(find_text, replace_text)
69
  else:
70
  pattern = re.compile(re.escape(find_text), re.IGNORECASE)
71
+ match_count = len(pattern.findall(text))
 
72
 
73
  if match_count == 0:
74
  return text, "No matches found."
75
 
76
  updated_text = pattern.sub(lambda _: replace_text, text)
77
 
78
+ return updated_text, f"Replaced {match_count} match{'es' if match_count != 1 else ''}."
 
 
 
 
 
79
 
80
 
81
  def clear_editor() -> tuple[str, str, str, str]:
 
82
  return "", "", "", "Editor cleared."
83
 
84
 
85
  CSS = """
86
  .gradio-container {
87
+ max-width: 1800px !important;
88
+ width: 98% !important;
89
  margin: 0 auto !important;
90
  }
91
 
92
  #main-editor textarea {
93
+ min-height: 720px !important;
94
+ height: 78vh !important;
95
  resize: vertical !important;
96
  font-family:
97
  ui-monospace,
 
106
  white-space: pre-wrap !important;
107
  }
108
 
109
+ #side-panel {
110
+ min-width: 260px !important;
111
+ max-width: 320px !important;
112
+ }
113
+
114
  #status-box textarea {
115
+ min-height: 70px !important;
116
  }
117
  """
118
 
119
 
120
+ with gr.Blocks(title="Plain Text Editor", css=CSS) as demo:
121
  gr.Markdown("# Plain Text Editor")
122
 
123
+ with gr.Row(equal_height=False):
124
+ with gr.Column(scale=8, min_width=700):
125
+ editor = gr.Textbox(
126
+ label="Text",
127
+ placeholder="Type or paste your plain text here...",
128
+ lines=30,
129
+ max_lines=2000,
130
+ elem_id="main-editor",
131
+ buttons=["copy"],
132
+ autofocus=True,
133
+ )
134
+
135
+ with gr.Column(
136
+ scale=2,
137
+ min_width=260,
138
+ elem_id="side-panel",
139
+ ):
140
+ paste_button = gr.Button(
141
+ "Paste",
142
+ variant="primary",
143
+ )
144
+
145
+ clear_button = gr.Button(
146
+ "Clear Text",
147
+ variant="stop",
148
+ )
149
+
150
+ gr.Markdown("### Find and Replace")
151
+
152
+ find_input = gr.Textbox(
153
+ label="Find",
154
+ placeholder="Text to find",
155
+ lines=1,
156
+ )
157
+
158
+ replace_input = gr.Textbox(
159
+ label="Replace with",
160
+ placeholder="Replacement text",
161
+ lines=1,
162
+ )
163
+
164
+ case_sensitive = gr.Checkbox(
165
+ label="Case sensitive",
166
+ value=False,
167
+ )
168
+
169
+ find_button = gr.Button("Find")
170
+
171
+ replace_first_button = gr.Button(
172
+ "Replace First"
173
+ )
174
+
175
+ replace_all_button = gr.Button(
176
+ "Replace All",
177
+ variant="primary",
178
+ )
179
+
180
+ status = gr.Textbox(
181
+ label="Status",
182
+ value="Ready.",
183
+ interactive=False,
184
+ elem_id="status-box",
185
+ )
186
 
 
187
  paste_button.click(
188
  fn=None,
189
  inputs=None,
 
204
  }
205
 
206
  const currentText = editor.value || "";
207
+ const start =
208
+ editor.selectionStart ?? currentText.length;
209
+ const end =
210
+ editor.selectionEnd ?? currentText.length;
211
 
212
  return (
213
  currentText.slice(0, start) +
 
217
  } catch (error) {
218
  alert(
219
  "Clipboard access was blocked. " +
220
+ "Please allow clipboard access or use Ctrl+V / Cmd+V."
221
  );
222
 
223
  return (
 
279
  ],
280
  )
281
 
 
282
  find_input.submit(
283
  fn=count_matches,
284
  inputs=[
 
291
 
292
 
293
  if __name__ == "__main__":
294
+ demo.launch()