@@ -45,7 +45,7 @@ def __iter__(self):
4545 return iter ((self .a , self .b ))
4646
4747 def __str__ (self ) -> str :
48- return "(" + str (self .a ) + ", " + str (self .b ) + ")"
48+ return "Region (" + str (self .a ) + ", " + str (self .b ) + ")"
4949
5050 def __repr__ (self ) -> str :
5151 if self .xpos == - 1 :
@@ -160,6 +160,131 @@ def intersects(self, region: Region) -> bool:
160160 (rb > lb and rb < le ) or (re > lb and re < le ) or
161161 (lb > rb and lb < re ) or (le > rb and le < re ))
162162
163+ class Selection :
164+ """
165+ Maintains a set of sorted non-overlapping Regions. A selection may be
166+ empty.
167+
168+ This is primarily used to represent the textual selection.
169+ """
170+
171+ def __init__ (self , regions ):
172+ self .regions = list (regions )
173+
174+ def __iter__ (self ) -> Iterator [Region ]:
175+ """
176+ Iterate through all the regions in the selection.
177+
178+ .. since:: 4023 3.8
179+ """
180+ return iter (self .regions )
181+
182+ def __len__ (self ) -> int :
183+ """ :returns: The number of regions in the selection. """
184+ return len (self .regions )
185+
186+ def __getitem__ (self , index : int ) -> Region :
187+ """ :returns: The region at the given ``index``. """
188+ return self .regions (index )
189+
190+ def __delitem__ (self , index : int ):
191+ """ Delete the region at the given ``index``. """
192+ del self .regions [index ]
193+
194+ def __eq__ (self , rhs : object ) -> bool :
195+ """ :returns: Whether the selections are identical. """
196+ return rhs is not None and isinstance (rhs , Selection ) and list (self ) == list (rhs )
197+
198+ def __lt__ (self , rhs : Optional [Selection ]) -> bool :
199+ """ """
200+ return rhs is not None and list (self ) < list (rhs )
201+
202+ def __bool__ (self ) -> bool :
203+ """ The selection is ``True`` when not empty. """
204+ return len (self ) > 0
205+
206+ def __str__ (self ) -> str :
207+ return f"{ self !r} [{ ', ' .join (map (str , self ))} ]"
208+
209+ def __repr__ (self ) -> str :
210+ return f'Selection'
211+
212+ # def is_valid(self) -> bool:
213+ # """ :returns: Whether this selection is for a valid view. """
214+ # return True
215+
216+ def clear (self ):
217+ """ Remove all regions from the selection. """
218+ self .regions .clear ()
219+
220+ def add (self , x : Region ):
221+ """
222+ Add a `Region` or `Point` to the selection. It will be merged with the
223+ existing regions if intersecting.
224+ """
225+ self .regions .append (x )
226+
227+ def add_all (self , regions : Iterable [Region ]):
228+ """ Add all the regions from the given iterable. """
229+ for r in regions :
230+ self .add (r )
231+
232+ # def subtract(self, region: Region):
233+ # """
234+ # Subtract a region from the selection, such that the whole region is no
235+ # longer contained within the selection.
236+ # """
237+ # sublime_api.view_selection_subtract_region(self.view_id, region.a, region.b)
238+
239+ # def contains(self, region: Region) -> bool:
240+ # """ :returns: Whether the provided region is contained within the selection. """
241+ # return sublime_api.view_selection_contains(self.view_id, region.a, region.b)
242+
243+ class View :
244+ def __init__ (self , text = "" , sel = None ):
245+ self .text = text
246+ self .text_lines = text .split ('\n ' )
247+ self ._sel = Selection (sel ) if sel else Selection ([Region (0 , 0 )])
248+
249+ def sel (self ):
250+ return self ._sel
251+
252+ def rowcol (self , point ):
253+ row = 0
254+ offset = 0
255+ for line in self .text_lines :
256+ line_len = len (line ) + 1
257+ if offset + line_len <= point :
258+ row += 1
259+ offset += line_len
260+ else :
261+ col = point - offset
262+ return (row , col )
263+ return (row , offset )
264+ # lines = self.text[:point].split('\n')
265+ # row = len(lines) - 1
266+ # col = len(lines[-1]) if lines else 0
267+ # return (row, col)
268+
269+ def substr (self , region ):
270+ return self .text [region .begin ():region .end ()]
271+
272+ def size (self ):
273+ return len (self .text )
274+
275+ def replace (self , edit , region , new_text ):
276+ self .text = self .text [:region .begin ()] + new_text + self .text [region .end ():]
277+ self .text_lines = self .text .split ('\n ' )
278+
279+ def lines (self , region ):
280+ start = 0
281+ res = []
282+ for line in self .text_lines :
283+ if start + len (line ) >= region .begin () or start < region .end ():
284+ res .append (Region (start , start + len (line )))
285+ start += len (line ) + 1
286+ return res
287+
163288platform = {'Darwin' : 'osx' , 'Linux' : 'linux' , 'Windows' : 'windows' }[platform .system ()]
164289
165290def platform () -> Literal ["osx" , "linux" , "windows" ]:
0 commit comments