def run(self, edit): """ Called when the enter key is pressed in a lisp file """ offset = self.caret_offset() start_pos = offset - 2000 start_pos = start_pos if start_pos >= 0 else 0 code = '' rx_str_comment = re.compile('comment\.|string\.') curr_line = self.get_line() curr_indent = re.search('^\s*', curr_line).end() while start_pos != offset: # Build a string with the previous 2000 or so characters with any # strings and comments ignored(replaced with some dummy primitive) scope_name = self.view.scope_name(start_pos) curr_char = self.view.substr(start_pos) start_pos += 1 if rx_str_comment.search(scope_name): code += '0' else: code += curr_char dialect = get_dialect(self.view) yasi_args = '--no-compact --dialect={0}'.format(dialect) result = yasi.indent_code(code, yasi_args) open_brackets = result['bracket_locations'] indent_level = 0 if open_brackets: indent_level = open_brackets[-1]['indent_level'] elif rx_str_comment.search(self.view.scope_name(offset)): indent_level = curr_indent else: indent_level = 0 self.view.insert(edit, offset, '\n' + ' ' * indent_level)
def do_is_complete(self, code): # status: 'complete', 'incomplete', 'invalid', or 'unknown' ## First, remove magic lines: ## need to distinguish between "%magic", and "%magic\n" if code.startswith("%"): lines = code.split("\n") start_line = 0 for line in lines: if not line.startswith("%"): break start_line += 1 code = ("\n".join(lines[start_line:])) if lines[-1] == '': return {'status': 'complete'} elif code == '': return {'status': 'incomplete'} if yasi is not None: data = yasi.indent_code(code + "\n(", opts) ## where does next expression go? if data["indented_code"][-1] == "(": return {'status': 'complete'} else: return { 'status': 'incomplete', 'indent': data["indented_code"][-1][:-1] } elif scheme.ready_to_eval(code): return {'status': 'complete'} else: return {'status': 'incomplete', 'indent': ' ' * 4}
def run(self, edit): """ Entry point """ if not self.indent_file_on_save(): return contents = self.file_contents() dialect = get_dialect(self.view) yasi_args = '--no-compact -ic --dialect={0}'.format(dialect) result = yasi.indent_code(contents, yasi_args) indented_code = ''.join(result['indented_code']) file_region = sublime.Region(0, self.view.size()) self.view.replace(edit, file_region, indented_code)
def indent_line(self, linenum, context_lines): """ indent_line(linenum : int, context_lines : int) -> [...] Indents the last x number of lines and returns information on the current state e.g open brackets, the indented code, string/comment states """ prev_x_lines = ''.join(self.prev_lines(context_lines, linenum)) dialect = get_dialect(self.view) yasi_args = '--no-compact --dialect={0}'.format(dialect) result = yasi.indent_code(prev_x_lines, yasi_args) return result
def ready_to_eval(text): if yasi: data = yasi.indent_code(text + "\n(", opts) ## where does next expression go? if data["indented_code"][-1] == "(": return (True, "") else: return (False, "... " + data["indented_code"][-1][:-1]) elif text: lines = text.split("\n") if len(lines) > 0 and lines[-1].strip() == "": return (True, "") ## force it ## else, only if valid parse return (try_parse(text), "... ") return (True, "")
def run(self, edit): """ Entry point """ regions = self.view.sel() if len(regions) > 1 or not regions[0].empty(): # Indent selected code for region in regions: if not region.empty(): # Get the selected text selection = self.view.substr(region) # Indent it with yasi dialect = get_dialect(self.view) yasi_args = '--no-compact -ic --dialect={0}'.format(dialect) result = yasi.indent_code(selection, yasi_args) indented_code = ''.join(result['indented_code']) # Replace the selection with transformed text self.view.replace(edit, region, indented_code) else: # Indent current line if command is invoked when there's no selection indented_lines = self.indent_line(self.curr_line(), 50)['indented_code'] indented_line = '' if indented_lines: indented_line = indented_lines[-1] curr_line_region = self.line_region(self.curr_line()) self.view.replace(edit, curr_line_region, indented_line)
def test_all_case_files(self): self.maxDiff = None cases = [ { 'before': 'tests/cases/#1-if-expression.lisp', 'after': 'tests/cases/#1-if-expression~.lisp', 'args': '--dialect=lisp' }, { 'before': 'tests/cases/#2-multiple-value-bind.lisp', 'after': 'tests/cases/#2-multiple-value-bind~.lisp', 'args': '--dialect=lisp' }, { 'before': 'tests/cases/#3-multiple-value-bind.lisp', 'after': 'tests/cases/#3-multiple-value-bind~.lisp', 'args': '--uniform --dialect=lisp' }, { 'before': 'tests/cases/#4-flet-indentation.lisp', 'after': 'tests/cases/#4-flet-indentation~.lisp', 'args': '--dialect=lisp' }, { 'before': 'tests/cases/#5-looks-like-a-macro.lisp', 'after': 'tests/cases/#5-looks-like-a-macro~.lisp', 'args': '--dialect=lisp' }, { 'before': 'tests/cases/#6-default-indent.lisp', 'after': 'tests/cases/#6-default-indent~.lisp', 'args': '--dialect=lisp --default-indent 2' }, { 'before': 'tests/cases/#7-uniform-if-expression.lisp', 'after': 'tests/cases/#7-uniform-if-expression~.lisp', 'args': '--dialect=lisp --uniform' }, { 'before': 'tests/cases/#8-macrolet-special-operator.lisp', 'after': 'tests/cases/#8-macrolet-special-operator~.lisp', 'args': '--dialect=lisp --indent-comments' }, { 'before': 'tests/cases/#9-standard-emacs-form-indentation.lisp', 'after': 'tests/cases/#9-standard-emacs-form-indentation~.lisp', 'args': '--dialect=all' }, { 'before': 'tests/cases/#10-newlisp-hash-comment.lsp', 'after': 'tests/cases/#10-newlisp-hash-comment~.lsp', 'args': '--dialect=newlisp' }, { 'before': 'tests/cases/#11-gradual-space-reduction-reindentation.lsp', 'after': 'tests/cases/#11-gradual-space-reduction-reindentation~.lsp', 'args': '--dialect=newlisp' }, { 'before': 'tests/cases/#12-zero-level-hanging-indentation.lsp', 'after': 'tests/cases/#12-zero-level-hanging-indentation~.lsp', 'args': '--dialect=newlisp --no-compact' }, { 'before': 'tests/cases/#13-hanging-with-non-hanging.lsp', 'after': 'tests/cases/#13-hanging-with-non-hanging~.lsp', 'args': '--dialect=newlisp --no-compact' }, { 'before': 'tests/cases/#14-tabbed-indentation.lsp', 'after': 'tests/cases/#14-tabbed-indentation~.lsp', 'args': '--dialect=newlisp --no-compact --tab=4' }, { 'before': 'tests/cases/#15-input-space-output-tabs.lisp', 'after': 'tests/cases/#15-input-space-output-tabs~.lisp', 'args': '--dialect=lisp --no-compact --tab=4' }, { 'before': 'tests/cases/#16-lisp-flets-and-labels.lisp', 'after': 'tests/cases/#16-lisp-flets-and-labels~.lisp', 'args': '--dialect=lisp' }, { 'before': 'tests/cases/#17-clojure-letfn.clj', 'after': 'tests/cases/#17-clojure-letfn~.clj', 'args': '--dialect=clojure' }, { 'before': 'tests/cases/#18-letfn-binding-block-indentation-only.clj', 'after': 'tests/cases/#18-letfn-binding-block-indentation-only~.clj', 'args': '--dialect=clojure' }, { 'before': 'tests/cases/#19-hash-quoted-expressions.lisp', 'after': 'tests/cases/#19-hash-quoted-expressions~.lisp', 'args': '--dialect=lisp' }, { 'before': 'tests/cases/#20-unclosed-string.lisp', 'after': 'tests/cases/#20-unclosed-string~.lisp', 'args': '--dialect=lisp' }, { 'before': 'tests/cases/#21-closing-brackets-separate-lines.lisp', 'after': 'tests/cases/#21-closing-brackets-separate-lines~.lisp', 'args': '--dialect=lisp' }, { 'before': 'tests/cases/#22-defmacro-example.lisp', 'after': 'tests/cases/#22-defmacro-example~.lisp', 'args': '--dialect=lisp' }, { 'before': 'tests/cases/#23-newlisp-long-string-tag-spacing.lsp', 'after': 'tests/cases/#23-newlisp-long-string-tag-spacing~.lsp', 'args': '--dialect=newlisp' } ] for i in range(0, 23): case = cases[i] before_path = os.path.join(PROJECT_DIR, case['before']) after_path = os.path.join(PROJECT_DIR, case['after']) before = yasi.read_file(before_path) after = yasi.read_file(after_path) args = '--no-rc ' + case['args'] result = yasi.indent_code(before, args=args) indented_code = ''.join(result['indented_code']) try: self.assertEqual(indented_code, after) except AssertionError as exception: message = '\nFAIL: %s\n\n%s' % (case['before'], exception) try: print(addcolour(message)) except NameError: print(message)
def test_all_case_files(self): self.maxDiff = None cases = [ { 'before': 'tests/cases/#1-if-expression.lisp', 'after': 'tests/cases/#1-if-expression~.lisp', 'options': '--dialect=lisp' }, { 'before': 'tests/cases/#2-multiple-value-bind.lisp', 'after': 'tests/cases/#2-multiple-value-bind~.lisp', 'options': '--dialect=lisp' }, { 'before': 'tests/cases/#3-multiple-value-bind.lisp', 'after': 'tests/cases/#3-multiple-value-bind~.lisp', 'options': '--uniform --dialect=lisp' }, { 'before': 'tests/cases/#4-flet-indentation.lisp', 'after': 'tests/cases/#4-flet-indentation~.lisp', 'options': '--dialect=lisp' }, { 'before': 'tests/cases/#5-looks-like-a-macro.lisp', 'after': 'tests/cases/#5-looks-like-a-macro~.lisp', 'options': '--dialect=lisp' }, { 'before': 'tests/cases/#6-default-indent.lisp', 'after': 'tests/cases/#6-default-indent~.lisp', 'options': '--dialect=lisp --default-indent 2' }, { 'before': 'tests/cases/#7-uniform-if-expression.lisp', 'after': 'tests/cases/#7-uniform-if-expression~.lisp', 'options': '--dialect=lisp --uniform' }, { 'before': 'tests/cases/#8-macrolet-special-operator.lisp', 'after': 'tests/cases/#8-macrolet-special-operator~.lisp', 'options': '--dialect=lisp --indent-comments' }, { 'before': 'tests/cases/#9-standard-emacs-form-indentation.lisp', 'after': 'tests/cases/#9-standard-emacs-form-indentation~.lisp', 'options': '--dialect=all' }, { 'before': 'tests/cases/#10-newlisp-hash-comment.lsp', 'after': 'tests/cases/#10-newlisp-hash-comment~.lsp', 'options': '--dialect=newlisp' }, { 'before': 'tests/cases/#11-gradual-space-reduction-reindentation.lsp', 'after': 'tests/cases/#11-gradual-space-reduction-reindentation~.lsp', 'options': '--dialect=newlisp' }, { 'before': 'tests/cases/#12-zero-level-hanging-indentation.lsp', 'after': 'tests/cases/#12-zero-level-hanging-indentation~.lsp', 'options': '--dialect=newlisp --no-compact' }, { 'before': 'tests/cases/#13-hanging-with-non-hanging.lsp', 'after': 'tests/cases/#13-hanging-with-non-hanging~.lsp', 'options': '--dialect=newlisp --no-compact' }, { 'before': 'tests/cases/#14-tabbed-indentation.lsp', 'after': 'tests/cases/#14-tabbed-indentation~.lsp', 'options': '--dialect=newlisp --no-compact --tab=4' }, { 'before': 'tests/cases/#15-input-space-output-tabs.lisp', 'after': 'tests/cases/#15-input-space-output-tabs~.lisp', 'options': '--dialect=lisp --no-compact --tab=4' }, { 'before': 'tests/cases/#16-lisp-flets-and-labels.lisp', 'after': 'tests/cases/#16-lisp-flets-and-labels~.lisp', 'options': '--dialect=lisp' }, { 'before': 'tests/cases/#17-clojure-letfn.clj', 'after': 'tests/cases/#17-clojure-letfn~.clj', 'options': '--dialect=clojure' }, { 'before': 'tests/cases/#18-letfn-binding-block-indentation-only.clj', 'after': 'tests/cases/#18-letfn-binding-block-indentation-only~.clj', 'options': '--dialect=clojure' }, { 'before': 'tests/cases/#19-hash-quoted-expressions.lisp', 'after': 'tests/cases/#19-hash-quoted-expressions~.lisp', 'options': '--dialect=lisp' } ] for i in range(0, 19): case = cases[i] before_path = os.path.join(PROJECT_DIR, case['before']) after_path = os.path.join(PROJECT_DIR, case['after']) before = yasi.read_file(before_path) after = yasi.read_file(after_path) options = '--no-rc ' + case['options'] result = yasi.indent_code(before, options=options) indented_code = ''.join(result['indented_code']) try: self.assertEqual(indented_code, after) except AssertionError as exception: print('??? Test failed: ' + case['before'] + '\n') print(exception)
def test_all_case_files(self): self.maxDiff = None cases = [{ 'before': 'tests/cases/#1-if-expression.lisp', 'after': 'tests/cases/#1-if-expression~.lisp', 'options': '--dialect=lisp' }, { 'before': 'tests/cases/#2-multiple-value-bind.lisp', 'after': 'tests/cases/#2-multiple-value-bind~.lisp', 'options': '--dialect=lisp' }, { 'before': 'tests/cases/#3-multiple-value-bind.lisp', 'after': 'tests/cases/#3-multiple-value-bind~.lisp', 'options': '--uniform --dialect=lisp' }, { 'before': 'tests/cases/#4-flet-indentation.lisp', 'after': 'tests/cases/#4-flet-indentation~.lisp', 'options': '--dialect=lisp' }, { 'before': 'tests/cases/#5-looks-like-a-macro.lisp', 'after': 'tests/cases/#5-looks-like-a-macro~.lisp', 'options': '--dialect=lisp' }, { 'before': 'tests/cases/#6-default-indent.lisp', 'after': 'tests/cases/#6-default-indent~.lisp', 'options': '--dialect=lisp --default-indent 2' }, { 'before': 'tests/cases/#7-uniform-if-expression.lisp', 'after': 'tests/cases/#7-uniform-if-expression~.lisp', 'options': '--dialect=lisp --uniform' }, { 'before': 'tests/cases/#8-macrolet-special-operator.lisp', 'after': 'tests/cases/#8-macrolet-special-operator~.lisp', 'options': '--dialect=lisp --indent-comments' }, { 'before': 'tests/cases/#9-standard-emacs-form-indentation.lisp', 'after': 'tests/cases/#9-standard-emacs-form-indentation~.lisp', 'options': '--dialect=all' }, { 'before': 'tests/cases/#10-newlisp-hash-comment.lsp', 'after': 'tests/cases/#10-newlisp-hash-comment~.lsp', 'options': '--dialect=newlisp' }, { 'before': 'tests/cases/#11-gradual-space-reduction-reindentation.lsp', 'after': 'tests/cases/#11-gradual-space-reduction-reindentation~.lsp', 'options': '--dialect=newlisp' }, { 'before': 'tests/cases/#12-zero-level-hanging-indentation.lsp', 'after': 'tests/cases/#12-zero-level-hanging-indentation~.lsp', 'options': '--dialect=newlisp --no-compact' }, { 'before': 'tests/cases/#13-hanging-with-non-hanging.lsp', 'after': 'tests/cases/#13-hanging-with-non-hanging~.lsp', 'options': '--dialect=newlisp --no-compact' }, { 'before': 'tests/cases/#14-tabbed-indentation.lsp', 'after': 'tests/cases/#14-tabbed-indentation~.lsp', 'options': '--dialect=newlisp --no-compact --tab=4' }, { 'before': 'tests/cases/#15-input-space-output-tabs.lisp', 'after': 'tests/cases/#15-input-space-output-tabs~.lisp', 'options': '--dialect=lisp --no-compact --tab=4' }, { 'before': 'tests/cases/#16-lisp-flets-and-labels.lisp', 'after': 'tests/cases/#16-lisp-flets-and-labels~.lisp', 'options': '--dialect=lisp' }, { 'before': 'tests/cases/#17-clojure-letfn.clj', 'after': 'tests/cases/#17-clojure-letfn~.clj', 'options': '--dialect=clojure' }, { 'before': 'tests/cases/#18-letfn-binding-block-indentation-only.clj', 'after': 'tests/cases/#18-letfn-binding-block-indentation-only~.clj', 'options': '--dialect=clojure' }, { 'before': 'tests/cases/#19-hash-quoted-expressions.lisp', 'after': 'tests/cases/#19-hash-quoted-expressions~.lisp', 'options': '--dialect=lisp' }] for i in range(0, 19): case = cases[i] before_path = os.path.join(PROJECT_DIR, case['before']) after_path = os.path.join(PROJECT_DIR, case['after']) before = yasi.read_file(before_path) after = yasi.read_file(after_path) options = '--no-rc ' + case['options'] result = yasi.indent_code(before, options=options) indented_code = ''.join(result['indented_code']) try: self.assertEqual(indented_code, after) except AssertionError as exception: print('??? Test failed: ' + case['before'] + '\n') print(exception)