Commits

Robert Brewer committed 0dcaff0

Top-level modules all synced now between py2/py3.

Comments (0)

Files changed (8)

py2/cherrypy/_cplogging.py

 logfmt = logging.Formatter("%(message)s")
 import os
 import sys
+_py3k = (sys.version_info >= (3, 0))
 
 import cherrypy
 from cherrypy import _cperror
+from cherrypy._cpcompat import ntob
 
 
 class LogManager(object):
     access_log = None
     """The actual :class:`logging.Logger` instance for access messages."""
     
-    access_log_format = \
-        '%(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s"'
+    if _py3k:
+        access_log_format = \
+            '{h} {l} {u} {t} "{r}" {s} {b} "{f}" "{a}"'
+    else:
+        access_log_format = \
+            '%(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s"'
     
     logger_root = None
     """The "top-level" logger name.
         if response.output_status is None:
             status = "-"
         else:
-            status = response.output_status.split(" ", 1)[0]
+            status = response.output_status.split(ntob(" "), 1)[0]
+            if _py3k:
+                status = status.decode('ISO-8859-1')
         
         atoms = {'h': remote.name or remote.ip,
                  'l': '-',
                  'f': dict.get(inheaders, 'Referer', ''),
                  'a': dict.get(inheaders, 'User-Agent', ''),
                  }
-        for k, v in atoms.items():
-            if isinstance(v, unicode):
-                v = v.encode('utf8')
-            elif not isinstance(v, str):
-                v = str(v)
-            # Fortunately, repr(str) escapes unprintable chars, \n, \t, etc
-            # and backslash for us. All we have to do is strip the quotes.
-            v = repr(v)[1:-1]
-            # Escape double-quote.
-            atoms[k] = v.replace('"', '\\"')
-        
-        try:
-            self.access_log.log(logging.INFO, self.access_log_format % atoms)
-        except:
-            self(traceback=True)
+        if _py3k:
+            for k, v in atoms.items():
+                if not isinstance(v, str):
+                    v = str(v)
+                v = v.replace('"', '\\"').encode('utf8')
+                # Fortunately, repr(str) escapes unprintable chars, \n, \t, etc
+                # and backslash for us. All we have to do is strip the quotes.
+                v = repr(v)[2:-1]
+                
+                # in python 3.0 the repr of bytes (as returned by encode) 
+                # uses double \'s.  But then the logger escapes them yet, again
+                # resulting in quadruple slashes.  Remove the extra one here.
+                v = v.replace('\\\\', '\\')
+                
+                # Escape double-quote.
+                atoms[k] = v
+            
+            try:
+                self.access_log.log(logging.INFO, self.access_log_format.format(**atoms))
+            except:
+                self(traceback=True)
+        else:
+            for k, v in atoms.items():
+                if isinstance(v, unicode):
+                    v = v.encode('utf8')
+                elif not isinstance(v, str):
+                    v = str(v)
+                # Fortunately, repr(str) escapes unprintable chars, \n, \t, etc
+                # and backslash for us. All we have to do is strip the quotes.
+                v = repr(v)[1:-1]
+                # Escape double-quote.
+                atoms[k] = v.replace('"', '\\"')
+            
+            try:
+                self.access_log.log(logging.INFO, self.access_log_format % atoms)
+            except:
+                self(traceback=True)
     
     def time(self):
         """Return now() in Apache Common Log Format (no timezone)."""

py2/cherrypy/_cprequest.py

                     exc = sys.exc_info()[1]
                     cherrypy.log(traceback=True, severity=40)
         if exc:
-            raise
+            raise exc
     
     def __copy__(self):
         newmap = self.__class__()
     :attr:`request.body.params<cherrypy._cprequest.RequestBody.params>`.""")
 
 
+_py3k = (sys.version_info >= (3, 0))
+
 class ResponseBody(object):
     """The body of the HTTP response (the response entity)."""
     
+    if _py3k:
+        unicode_err = ("Page handlers MUST return bytes. Use tools.encode "
+                       "if you wish to return unicode.")
+    
     def __get__(self, obj, objclass=None):
         if obj is None:
             # When calling on the class instead of an instance...
     
     def __set__(self, obj, value):
         # Convert the given value to an iterable object.
+        if _py3k and isinstance(value, str):
+            raise ValueError(self.unicode_err)
+        
         if isinstance(value, basestring):
             # strings get wrapped in a list because iterating over a single
             # item list is much faster than iterating over every character
             else:
                 # [''] doesn't evaluate to False, so replace it with [].
                 value = []
+        elif _py3k and isinstance(value, list):
+            # every item in a list must be bytes... 
+            for i, item in enumerate(value):
+                if isinstance(item, str):
+                    raise ValueError(self.unicode_err)
         # Don't use isinstance here; io.IOBase which has an ABC takes
         # 1000 times as long as, say, isinstance(value, str)
         elif hasattr(value, 'read'):
         if isinstance(self.body, basestring):
             return self.body
         
-        newbody = ''.join([chunk for chunk in self.body])
+        newbody = []
+        for chunk in self.body:
+            if _py3k and not isinstance(chunk, bytes):
+                raise TypeError("Chunk %s is not of type 'bytes'." % repr(chunk))
+            newbody.append(chunk)
+        newbody = ntob('').join(newbody)
         
         self.body = newbody
         return newbody

py2/cherrypy/_cptree.py

 """CherryPy Application and Tree objects."""
 
 import os
+import sys
+
 import cherrypy
 from cherrypy._cpcompat import ntou
 from cherrypy import _cpconfig, _cplogging, _cprequest, _cpwsgi, tools
         
         # Correct the SCRIPT_NAME and PATH_INFO environ entries.
         environ = environ.copy()
-        if environ.get(u'wsgi.version') == (u'u', 0):
-            # Python 2/WSGI u.0: all strings MUST be of type unicode
-            enc = environ[u'wsgi.url_encoding']
-            environ[u'SCRIPT_NAME'] = sn.decode(enc)
-            environ[u'PATH_INFO'] = path[len(sn.rstrip("/")):].decode(enc)
+        if sys.version_info < (3, 0):
+            if environ.get(ntou('wsgi.version')) == (ntou('u'), 0):
+                # Python 2/WSGI u.0: all strings MUST be of type unicode
+                enc = environ[ntou('wsgi.url_encoding')]
+                environ[ntou('SCRIPT_NAME')] = sn.decode(enc)
+                environ[ntou('PATH_INFO')] = path[len(sn.rstrip("/")):].decode(enc)
+            else:
+                # Python 2/WSGI 1.x: all strings MUST be of type str
+                environ['SCRIPT_NAME'] = sn
+                environ['PATH_INFO'] = path[len(sn.rstrip("/")):]
         else:
-            # Python 2/WSGI 1.x: all strings MUST be of type str
-            environ['SCRIPT_NAME'] = sn
-            environ['PATH_INFO'] = path[len(sn.rstrip("/")):]
+            if environ.get(ntou('wsgi.version')) == (ntou('u'), 0):
+                # Python 3/WSGI u.0: all strings MUST be full unicode
+                environ['SCRIPT_NAME'] = sn
+                environ['PATH_INFO'] = path[len(sn.rstrip("/")):]
+            else:
+                # Python 3/WSGI 1.x: all strings MUST be ISO-8859-1 str
+                environ['SCRIPT_NAME'] = sn.encode('utf-8').decode('ISO-8859-1')
+                environ['PATH_INFO'] = path[len(sn.rstrip("/")):].encode('utf-8').decode('ISO-8859-1')
         return app(environ, start_response)
-

py2/cherrypy/_cpwsgi.py

 import sys as _sys
 
 import cherrypy as _cherrypy
-from cherrypy._cpcompat import BytesIO
+from cherrypy._cpcompat import BytesIO, ntob, ntou, unicodestr
 from cherrypy import _cperror
 from cherrypy.lib import httputil
 
     """Return a new environ dict for WSGI 1.x from the given WSGI u.x environ."""
     env1x = {}
     
-    url_encoding = environ[u'wsgi.url_encoding']
-    for k, v in environ.items():
-        if k in [u'PATH_INFO', u'SCRIPT_NAME', u'QUERY_STRING']:
+    url_encoding = environ[ntou('wsgi.url_encoding')]
+    for k, v in list(environ.items()):
+        if k in [ntou('PATH_INFO'), ntou('SCRIPT_NAME'), ntou('QUERY_STRING')]:
             v = v.encode(url_encoding)
-        elif isinstance(v, unicode):
+        elif isinstance(v, unicodestr):
             v = v.encode('ISO-8859-1')
         env1x[k.encode('ISO-8859-1')] = v
     
             environ = environ.copy()
             try:
                 return self.nextapp(environ, start_response)
-            except _cherrypy.InternalRedirect, ir:
+            except _cherrypy.InternalRedirect:
+                ir = _sys.exc_info()[1]
                 sn = environ.get('SCRIPT_NAME', '')
                 path = environ.get('PATH_INFO', '')
                 qs = environ.get('QUERY_STRING', '')
         self.started_response = True
         return self
     
-    def next(self):
-        return self.trap(self.iter_response.next)
+    if _sys.version_info >= (3, 0):
+        def __next__(self):
+            return self.trap(next, self.iter_response)
+    else:
+        def next(self):
+            return self.trap(self.iter_response.next)
     
     def close(self):
         if hasattr(self.response, 'close'):
                 raise
             
             if self.started_response:
-                return "".join(b)
+                return ntob("").join(b)
             else:
                 return b
 
     """WSGI response iterable for CherryPy applications."""
     
     def __init__(self, environ, start_response, cpapp):
-        if environ.get(u'wsgi.version') == (u'u', 0):
-            environ = downgrade_wsgi_ux_to_1x(environ)
+        if _sys.version_info < (3, 0):
+            if environ.get(ntou('wsgi.version')) == (ntou('u'), 0):
+                environ = downgrade_wsgi_ux_to_1x(environ)
         self.environ = environ
         self.cpapp = cpapp
         try:
     def __iter__(self):
         return self
     
-    def next(self):
-        return self.iter_response.next()
+    if _sys.version_info >= (3, 0):
+        def __next__(self):
+            return next(self.iter_response)
+    else:
+        def next(self):
+            return self.iter_response.next()
     
     def close(self):
         """Close and de-reference the current request and response. (Core)"""
         path = httputil.urljoin(self.environ.get('SCRIPT_NAME', ''),
                                 self.environ.get('PATH_INFO', ''))
         qs = self.environ.get('QUERY_STRING', '')
+
+        if _sys.version_info >= (3, 0):
+            # This isn't perfect; if the given PATH_INFO is in the wrong encoding,
+            # it may fail to match the appropriate config section URI. But meh.
+            old_enc = self.environ.get('wsgi.url_encoding', 'ISO-8859-1')
+            new_enc = self.cpapp.find_config(self.environ.get('PATH_INFO', ''),
+                                             "request.uri_encoding", 'utf-8')
+            if new_enc.lower() != old_enc.lower():
+                # Even though the path and qs are unicode, the WSGI server is
+                # required by PEP 3333 to coerce them to ISO-8859-1 masquerading
+                # as unicode. So we have to encode back to bytes and then decode
+                # again using the "correct" encoding.
+                try:
+                    u_path = path.encode(old_enc).decode(new_enc)
+                    u_qs = qs.encode(old_enc).decode(new_enc)
+                except (UnicodeEncodeError, UnicodeDecodeError):
+                    # Just pass them through without transcoding and hope.
+                    pass
+                else:
+                    # Only set transcoded values if they both succeed.
+                    path = u_path
+                    qs = u_qs
+        
         rproto = self.environ.get('SERVER_PROTOCOL')
         headers = self.translate_headers(self.environ)
         rfile = self.environ['wsgi.input']

py3/cherrypy/_cplogging.py

 logfmt = logging.Formatter("%(message)s")
 import os
 import sys
+_py3k = (sys.version_info >= (3, 0))
 
 import cherrypy
 from cherrypy import _cperror
+from cherrypy._cpcompat import ntob
 
 
 class LogManager(object):
     access_log = None
     """The actual :class:`logging.Logger` instance for access messages."""
     
-    access_log_format = \
-        '{h} {l} {u} {t} "{r}" {s} {b} "{f}" "{a}"'
+    if _py3k:
+        access_log_format = \
+            '{h} {l} {u} {t} "{r}" {s} {b} "{f}" "{a}"'
+    else:
+        access_log_format = \
+            '%(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s"'
     
     logger_root = None
     """The "top-level" logger name.
         if response.output_status is None:
             status = "-"
         else:
-            status = str(response.output_status.split(b" ", 1)[0], 'ISO-8859-1')
+            status = response.output_status.split(ntob(" "), 1)[0]
+            if _py3k:
+                status = status.decode('ISO-8859-1')
         
         atoms = {'h': remote.name or remote.ip,
                  'l': '-',
                  'f': dict.get(inheaders, 'Referer', ''),
                  'a': dict.get(inheaders, 'User-Agent', ''),
                  }
-        for k, v in atoms.items():
-            if not isinstance(v, str):
-                v = str(v)
-            v = v.replace('"', '\\"').encode('utf8')
-            # Fortunately, repr(str) escapes unprintable chars, \n, \t, etc
-            # and backslash for us. All we have to do is strip the quotes.
-            v = repr(v)[2:-1]
+        if _py3k:
+            for k, v in atoms.items():
+                if not isinstance(v, str):
+                    v = str(v)
+                v = v.replace('"', '\\"').encode('utf8')
+                # Fortunately, repr(str) escapes unprintable chars, \n, \t, etc
+                # and backslash for us. All we have to do is strip the quotes.
+                v = repr(v)[2:-1]
+                
+                # in python 3.0 the repr of bytes (as returned by encode) 
+                # uses double \'s.  But then the logger escapes them yet, again
+                # resulting in quadruple slashes.  Remove the extra one here.
+                v = v.replace('\\\\', '\\')
+                
+                # Escape double-quote.
+                atoms[k] = v
             
-            # in python 3.0 the repr of bytes (as returned by encode) 
-            # uses double \'s.  But then the logger escapes them yet, again
-            # resulting in quadruple slashes.  Remove the extra one here.
-            v = v.replace('\\\\', '\\')
+            try:
+                self.access_log.log(logging.INFO, self.access_log_format.format(**atoms))
+            except:
+                self(traceback=True)
+        else:
+            for k, v in atoms.items():
+                if isinstance(v, unicode):
+                    v = v.encode('utf8')
+                elif not isinstance(v, str):
+                    v = str(v)
+                # Fortunately, repr(str) escapes unprintable chars, \n, \t, etc
+                # and backslash for us. All we have to do is strip the quotes.
+                v = repr(v)[1:-1]
+                # Escape double-quote.
+                atoms[k] = v.replace('"', '\\"')
             
-            # Escape double-quote.
-            atoms[k] = v
-        
-        try:
-            self.access_log.log(logging.INFO, self.access_log_format.format(**atoms))
-        except:
-            self(traceback=True)
+            try:
+                self.access_log.log(logging.INFO, self.access_log_format % atoms)
+            except:
+                self(traceback=True)
     
     def time(self):
         """Return now() in Apache Common Log Format (no timezone)."""

py3/cherrypy/_cprequest.py

                     raise
                 except (cherrypy.HTTPError, cherrypy.HTTPRedirect,
                         cherrypy.InternalRedirect):
-                    exc = sys.exc_info()
+                    exc = sys.exc_info()[1]
                 except:
-                    exc = sys.exc_info()
+                    exc = sys.exc_info()[1]
                     cherrypy.log(traceback=True, severity=40)
         if exc:
-            raise exc[0](*exc[1].args).with_traceback(exc[2])
+            raise exc
     
     def __copy__(self):
         newmap = self.__class__()
     :attr:`request.body.params<cherrypy._cprequest.RequestBody.params>`.""")
 
 
+_py3k = (sys.version_info >= (3, 0))
+
 class ResponseBody(object):
     """The body of the HTTP response (the response entity)."""
     
-    unicode_err = ("Page handlers MUST return bytes. Use tools.encode "
-                   "if you wish to return unicode.")
+    if _py3k:
+        unicode_err = ("Page handlers MUST return bytes. Use tools.encode "
+                       "if you wish to return unicode.")
     
     def __get__(self, obj, objclass=None):
         if obj is None:
     
     def __set__(self, obj, value):
         # Convert the given value to an iterable object.
-        if isinstance(value, str):
+        if _py3k and isinstance(value, str):
             raise ValueError(self.unicode_err)
         
-        if isinstance(value, bytes):
+        if isinstance(value, basestring):
             # strings get wrapped in a list because iterating over a single
             # item list is much faster than iterating over every character
             # in a long string.
             else:
                 # [''] doesn't evaluate to False, so replace it with [].
                 value = []
-        elif isinstance(value, list):
+        elif _py3k and isinstance(value, list):
             # every item in a list must be bytes... 
             for i, item in enumerate(value):
                 if isinstance(item, str):
         
         newbody = []
         for chunk in self.body:
-            if not isinstance(chunk, bytes):
+            if _py3k and not isinstance(chunk, bytes):
                 raise TypeError("Chunk %s is not of type 'bytes'." % repr(chunk))
             newbody.append(chunk)
-        newbody = b''.join(newbody)
+        newbody = ntob('').join(newbody)
         
         self.body = newbody
         return newbody

py3/cherrypy/_cptree.py

 """CherryPy Application and Tree objects."""
 
 import os
+import sys
+
 import cherrypy
 from cherrypy._cpcompat import ntou
 from cherrypy import _cpconfig, _cplogging, _cprequest, _cpwsgi, tools
         
         # Correct the SCRIPT_NAME and PATH_INFO environ entries.
         environ = environ.copy()
-        if environ.get('wsgi.version') == ('u', 0):
-            # Python 3/WSGI u.0: all strings MUST be full unicode
-            environ['SCRIPT_NAME'] = sn
-            environ['PATH_INFO'] = path[len(sn.rstrip("/")):]
+        if sys.version_info < (3, 0):
+            if environ.get(ntou('wsgi.version')) == (ntou('u'), 0):
+                # Python 2/WSGI u.0: all strings MUST be of type unicode
+                enc = environ[ntou('wsgi.url_encoding')]
+                environ[ntou('SCRIPT_NAME')] = sn.decode(enc)
+                environ[ntou('PATH_INFO')] = path[len(sn.rstrip("/")):].decode(enc)
+            else:
+                # Python 2/WSGI 1.x: all strings MUST be of type str
+                environ['SCRIPT_NAME'] = sn
+                environ['PATH_INFO'] = path[len(sn.rstrip("/")):]
         else:
-            # Python 3/WSGI 1.x: all strings MUST be ISO-8859-1 str
-            environ['SCRIPT_NAME'] = sn.encode('utf-8').decode('ISO-8859-1')
-            environ['PATH_INFO'] = path[len(sn.rstrip("/")):].encode('utf-8').decode('ISO-8859-1')
+            if environ.get(ntou('wsgi.version')) == (ntou('u'), 0):
+                # Python 3/WSGI u.0: all strings MUST be full unicode
+                environ['SCRIPT_NAME'] = sn
+                environ['PATH_INFO'] = path[len(sn.rstrip("/")):]
+            else:
+                # Python 3/WSGI 1.x: all strings MUST be ISO-8859-1 str
+                environ['SCRIPT_NAME'] = sn.encode('utf-8').decode('ISO-8859-1')
+                environ['PATH_INFO'] = path[len(sn.rstrip("/")):].encode('utf-8').decode('ISO-8859-1')
         return app(environ, start_response)
-

py3/cherrypy/_cpwsgi.py

 import sys as _sys
 
 import cherrypy as _cherrypy
-from cherrypy._cpcompat import BytesIO
+from cherrypy._cpcompat import BytesIO, ntob, ntou, unicodestr
 from cherrypy import _cperror
 from cherrypy.lib import httputil
 
 
+def downgrade_wsgi_ux_to_1x(environ):
+    """Return a new environ dict for WSGI 1.x from the given WSGI u.x environ."""
+    env1x = {}
+    
+    url_encoding = environ[ntou('wsgi.url_encoding')]
+    for k, v in list(environ.items()):
+        if k in [ntou('PATH_INFO'), ntou('SCRIPT_NAME'), ntou('QUERY_STRING')]:
+            v = v.encode(url_encoding)
+        elif isinstance(v, unicodestr):
+            v = v.encode('ISO-8859-1')
+        env1x[k.encode('ISO-8859-1')] = v
+    
+    return env1x
+
+
 class VirtualHost(object):
     """Select a different WSGI application based on the Host header.
     
             environ = environ.copy()
             try:
                 return self.nextapp(environ, start_response)
-            except _cherrypy.InternalRedirect as ir:
+            except _cherrypy.InternalRedirect:
+                ir = _sys.exc_info()[1]
                 sn = environ.get('SCRIPT_NAME', '')
                 path = environ.get('PATH_INFO', '')
                 qs = environ.get('QUERY_STRING', '')
         self.started_response = True
         return self
     
-    def __next__(self):
-        return self.trap(next, self.iter_response)
+    if _sys.version_info >= (3, 0):
+        def __next__(self):
+            return self.trap(next, self.iter_response)
+    else:
+        def next(self):
+            return self.trap(self.iter_response.next)
     
     def close(self):
         if hasattr(self.response, 'close'):
                 raise
             
             if self.started_response:
-                return b"".join(b)
+                return ntob("").join(b)
             else:
                 return b
 
     """WSGI response iterable for CherryPy applications."""
     
     def __init__(self, environ, start_response, cpapp):
+        if _sys.version_info < (3, 0):
+            if environ.get(ntou('wsgi.version')) == (ntou('u'), 0):
+                environ = downgrade_wsgi_ux_to_1x(environ)
         self.environ = environ
         self.cpapp = cpapp
         try:
     def __iter__(self):
         return self
     
-    def __next__(self):
-        return next(self.iter_response)
+    if _sys.version_info >= (3, 0):
+        def __next__(self):
+            return next(self.iter_response)
+    else:
+        def next(self):
+            return self.iter_response.next()
     
     def close(self):
         """Close and de-reference the current request and response. (Core)"""
         path = httputil.urljoin(self.environ.get('SCRIPT_NAME', ''),
                                 self.environ.get('PATH_INFO', ''))
         qs = self.environ.get('QUERY_STRING', '')
-        # This isn't perfect; if the given PATH_INFO is in the wrong encoding,
-        # it may fail to match the appropriate config section URI. But meh.
-        old_enc = self.environ.get('wsgi.url_encoding', 'ISO-8859-1')
-        new_enc = self.cpapp.find_config(self.environ.get('PATH_INFO', ''),
-                                         "request.uri_encoding", 'utf-8')
-        if new_enc.lower() != old_enc.lower():
-            # Even though the path and qs are unicode, the WSGI server is
-            # required by PEP 3333 to coerce them to ISO-8859-1 masquerading
-            # as unicode. So we have to encode back to bytes and then decode
-            # again using the "correct" encoding.
-            try:
-                u_path = path.encode(old_enc).decode(new_enc)
-                u_qs = qs.encode(old_enc).decode(new_enc)
-            except (UnicodeEncodeError, UnicodeDecodeError):
-                # Just pass them through without transcoding and hope.
-                pass
-            else:
-                # Only set transcoded values if they both succeed.
-                path = u_path
-                qs = u_qs
+
+        if _sys.version_info >= (3, 0):
+            # This isn't perfect; if the given PATH_INFO is in the wrong encoding,
+            # it may fail to match the appropriate config section URI. But meh.
+            old_enc = self.environ.get('wsgi.url_encoding', 'ISO-8859-1')
+            new_enc = self.cpapp.find_config(self.environ.get('PATH_INFO', ''),
+                                             "request.uri_encoding", 'utf-8')
+            if new_enc.lower() != old_enc.lower():
+                # Even though the path and qs are unicode, the WSGI server is
+                # required by PEP 3333 to coerce them to ISO-8859-1 masquerading
+                # as unicode. So we have to encode back to bytes and then decode
+                # again using the "correct" encoding.
+                try:
+                    u_path = path.encode(old_enc).decode(new_enc)
+                    u_qs = qs.encode(old_enc).decode(new_enc)
+                except (UnicodeEncodeError, UnicodeDecodeError):
+                    # Just pass them through without transcoding and hope.
+                    pass
+                else:
+                    # Only set transcoded values if they both succeed.
+                    path = u_path
+                    qs = u_qs
         
         rproto = self.environ.get('SERVER_PROTOCOL')
         headers = self.translate_headers(self.environ)
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.