Skip to content
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

Fix python call syntax highlighting #1987

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
61 changes: 43 additions & 18 deletions lib/rouge/lexers/python.rb
Expand Up @@ -68,12 +68,34 @@ def self.exceptions
end

identifier = /[[:alpha:]_][[:alnum:]_]*/
lower_identifier = /[[:lower:]_][[:alnum:]_]*/
upper_identifier = /[[:upper:]_][[:alnum:]_]*/
dotted_identifier = /[[:alpha:]_.][[:alnum:]_.]*/

def current_string
@string_register ||= StringRegister.new
end

# Yield a token for an identifier. Handle keywords/builtins, attr accesses
def token_for_identifier(word, fallback)
if self.class.keywords.include? word
token Keyword
elsif not in_state?(:dot) and self.class.exceptions.include? word
token Name::Builtin
elsif not in_state?(:dot) and self.class.builtins.include? word
token Name::Builtin
elsif not in_state?(:dot) and self.class.builtins_pseudo.include? word
token Name::Builtin::Pseudo
else
token fallback
end

# Reset attr access state
if in_state?(:dot)
pop!
end
end

state :root do
rule %r/\n+/m, Text
rule %r/^(:)(\s*)([ru]{,2}""".*?""")/mi do
Expand All @@ -84,10 +106,16 @@ def current_string

rule %r/[^\S\n]+/, Text
rule %r(#(.*)?\n?), Comment::Single
rule %r/[\[\]{}:(),;.]/, Punctuation
rule %r/[\[\]{}:(),;]/, Punctuation
rule %r/\\\n/, Text
rule %r/\\/, Text

# Push the :dot state to the stack to keep track of attr accesses
rule %r/\./ do
token Punctuation
push :dot if not (in_state?(:generic_string) or in_state?(:dot))
end

rule %r/@#{dotted_identifier}/i, Name::Decorator

rule %r/(in|is|and|or|not)\b/, Operator::Word
Expand Down Expand Up @@ -116,9 +144,6 @@ def current_string
push :classname
end

rule %r/([a-z_]\w*)[ \t]*(?=(\(.*\)))/m, Name::Function
rule %r/([A-Z_]\w*)[ \t]*(?=(\(.*\)))/m, Name::Class

# TODO: not in python 3
rule %r/`.*?`/, Str::Backtick
rule %r/([rfbu]{0,2})('''|"""|['"])/i do |m|
Expand All @@ -127,22 +152,18 @@ def current_string
push :generic_string
end

# using negative lookbehind so we don't match property names
rule %r/(?<!\.)#{identifier}/ do |m|
if self.class.keywords.include? m[0]
token Keyword
elsif self.class.exceptions.include? m[0]
token Name::Builtin
elsif self.class.builtins.include? m[0]
token Name::Builtin
elsif self.class.builtins_pseudo.include? m[0]
token Name::Builtin::Pseudo
else
token Name
end
# Identifiers used in a call expr
rule %r/#{lower_identifier}(?=[[:blank:]]*\()/m do |m|
token_for_identifier m[0], Name::Function
end
rule %r/#{upper_identifier}(?=[[:blank:]]*\()/m do |m|
token_for_identifier m[0], Name::Class
end

rule identifier, Name
# All other identifiers
rule identifier do |m|
token_for_identifier m[0], Name
end

digits = /[0-9](_?[0-9])*/
decimal = /((#{digits})?\.#{digits}|#{digits}\.)/
Expand All @@ -158,6 +179,10 @@ def current_string
rule %r/([1-9](_?[0-9])*|0(_?0)*)/, Num::Integer
end

state :dot do
mixin :root
end

state :funcname do
rule identifier, Name::Function, :pop!
end
Expand Down
10 changes: 10 additions & 0 deletions spec/visual/samples/python
Expand Up @@ -218,3 +218,13 @@ def do_nothing():

app = FastAPI()
FastAPIInstrumentor.instrument_app(app)

# Keyword shouldn't be read as function call
def take_first(pairs):
for (first, _) in pairs:
yield first

self.for('nonsense')

# Distinguish between builtins and method calls
self.filter(filter(lambda x: x == 1, items))