New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for slim
files
#1233
Comments
@vinistock can you assign me this issue? |
Thank you for the feature suggestion. Does Slim provide a way to extract just the Ruby code while maintaining the correct line and column information? Ideally, we wouldn't be converting Slim into ERB and then ERB into Ruby, so that we can finally parse the Ruby code. That will be very slow for large files. That is currently the biggest blocker with ERB support and we can't move forward until we figure that part out. |
The ruby:
print_value = true
- if print_value
p = 'Hello World'.capatlize would generate this output when put through the slim parser
Maybe traverse the tree and derive the line numbers and column numbers for the ruby code |
I don't believe that AST will allow using Ruby LSP features. All of our features are based on parsing Ruby with Prism and analyzing the AST. For that to work properly, we need Otherwise, things like semantic highlighting would highlight the wrong range for tokens. Or definition wouldn't be able to find the target based on the position received from the editor. We would need
And return only the Ruby code in its exact positions print_value = true
if print_value
'Hello World'.capatlize Then we can just take that Ruby code, parse it with Prism (which will give us the right line and column information) and all features will just work out of the box. |
@vinistock require 'slim'
require 'pry'
def traverse_sexp(sexp, indent = 0, is_root = true)
code = []
factor = indent.zero? ? 1 : indent
indent_space = " " * factor
sexp.each do |node|
next unless node.is_a?(Array)
case node.first
when :multi
code << traverse_sexp(node[1..-1], indent, is_root)
when :slim
case node[1]
when :embedded
code << traverse_sexp(node[3], is_root ? 0 : indent + 1, false)
when :interpolate, :control, :output
code << indent_space + node[2].strip
code << traverse_sexp(node[3], indent + 1, false) if node.length > 3
end
when :html
extra_whitespaces = convert_html_to_whitespaces(node)
code << indent_space + extra_whitespaces if extra_whitespaces
if node[4].is_a?(Array) && node[4][0] == :slim
if [:output, :interpolate].include?(node[4][1])
index = node[4][1] == :output ? 3 : 2
code << indent_space + node[4][index].strip + "\n"
else
code << traverse_sexp(node[4], indent, false)
end
elsif node[4].is_a?(Array) && node[4][0] != :slim
code << traverse_sexp(node[4], indent, false)
end
when :newline
code << "\n"
end
end
code.join("")
end
def convert_html_to_whitespaces(html_node)
case html_node[1]
when :tag
' ' * html_node[2].to_s.length
when :attrs
html_node[2..-1].reduce(' ') do |whitespaces, attr_node|
attr_format = attr_node[3][0]
subindex = attr_format == :static ? 1 : 3
' ' * (atattr_nodetr[2].length + attr_node[3][subindex].length)
end
end
end
template1 = <<~SLIM
- if items.any?
table id=items class='table yellow'
- for item in items
tr
td.name = item.name
td.price = item.price
- else
p 'No items found.'
SLIM
template2 = <<~SLIM
ruby:
print_value = true
- if print_value
p = 'Hello World'.capitalize
SLIM
sexp1 = Slim::Parser.new.call(template1)
sexp2 = Slim::Parser.new.call(template2)
File.write('example1.rb', traverse_sexp(sexp1))
File.write('example2.rb', traverse_sexp(sexp2)) if items.any?
for item in items
item.name
item.price
else
'No items found.' print_value = true
if print_value
'Hello World'.capitalize |
ok so I got a little carried away and made small gem out of this traverse function https://github.com/omarluq/sx-processor this is for your eyes to review its way more optimized than the traverse function! ideally I would like to add the |
Sorry, but if we were to accept a runtime dependency, it would be only implicit (like we do for rubocop) and only for I'm also wondering if this may be a better fit for addons. There are multiple templating engines out there and we probably don't want to maintain support for all of them inside this codebase. It's not currently possible to do it, but I'm thinking if we might be able to design an API to allow for this. |
@vinistock Apologize for the misunderstanding I didn't mean adding the gem as a runtime dependency I just meant coding the class into the LSP it self, I made the gem for demo proposes, so you can review the approach Im proposing. that being said I do see your point. Im open to both. |
I have checked that this feature is not already implemented
Use case
Slim is a fairly popular choice among ruby/rails devs and adding support for it is actually not a lot of work once
ERB
support is mergedDescription
Ruby intellisense for slim printing lines, none-printing lines and ruby code blocks
Implementation
Following the same Idea in issue#1055 the LSP can require
slim
gem from the main bundle and provide the feature only if it's foundAs for parsing slim, The lsp doesn't have to worry about that!
instead it can use
Slim::ERBConverter.new(options).call(slim_code)
which outputserb
codeThe text was updated successfully, but these errors were encountered: