Repository: spyder-ide/spyder

Issue:
Built-in 'print' statement is displayed as two different colors depending on indentation
_From [doug.t...@gmail.com](https://code.google.com/u/107157864673511712940/) on 2015-02-05T17:05:42Z_

Summary:
The built-in 'print' statement is displayed as two different colors (in Spyder/Dark theme: blue, purple) depending on indentation. It appears that the issue is because "print" belongs to both keywords.kwlist and dir(**builtins**)

Spyder Version:  2.3.2
Python Version:  2.7.6
Qt Version    :  4.8.4, PyQt4 (API v2) 4.9.6 on Windows
IPython >=0.13  :  1.1.0 (OK)
coverage >=0.25 :  3.7.1 (OK)
matplotlib >=1.0:  1.3.1 (OK)
pandas >=0.13.1 :  0.14.1 (OK)
pep8 >=0.6      :  1.4.6 (OK)
pyflakes >=0.5.0:  0.7.3 (OK)
pygments >=1.6  :  1.6 (OK)
pylint >=0.25   :  1.0.0 (OK)
rope >=0.9.2    :  0.10.2 (OK)
sphinx >=0.6.6  :  1.2 (OK)
sympy >=0.7.0   :  0.7.4.1 (OK)
zmq >=2.1.11    :  14.0.1 (OK)

To Reproduce:
1. In an empty .py file, type 'print' on line 1 and '    print' on line two.

Expected Output: both words are the same color
Actual Output: line 1 is color coded as a "keyword" and line 2 is color coded as a "builtin".

Additional Info:
I checked all the default themes for the editor - each one has the same issue. I also checked all of the python keywords as given by `keywords.kwlist` and built-in functions given by `dir(__builtins__)`. Only "print" has this issue, though other builtins are not colored as such.

I've attached a file which you can load into Spyder and see for yourself.

The purpose of this issue is to choose a color (builtin or keyword) for "print" and use it in all cases. I would prefer it being labeled as a builtin.

**Attachment:** [print_keyword_color_discrepency_example.py](http://code.google.com/p/spyderlib/issues/detail?id=2159)

_Original issue: http://code.google.com/p/spyderlib/issues/detail?id=2159_



Discussion:
_From [doug.t...@gmail.com](https://code.google.com/u/107157864673511712940/) on 2015-02-05T14:11:55Z_

In Python 3.4.2, "print" is only listed in dir(**builtins**), so this issue doesn't appear.

However, other items, such as True, False, None, exec, are incorrectly colored. Some are colored as builtins while others are colored as keywords.

For True, False, and None, this might be because these values are listed in both keywords.kwlist and dir(**builtins**)

_From [ccordoba12](https://code.google.com/u/ccordoba12/) on 2015-02-05T14:20:14Z_

Thanks for reporting. We'll see what we can do about it for 2.3.4

**Status:** Accepted  
  **Labels:** Cat-Editor MS-v2.3.4  

Adding comment so that I get notifications and so that I can find my issues/comments more easily.

@dougthor42

Hi @ccordoba12 what do you think we should do in this case?

on the syntaxhighlighter file we have

``` Python

def make_python_patterns(additional_keywords=[], additional_builtins=[]):
    "Strongly inspired from idlelib.ColorDelegator.make_pat"
    kw = r"\b" + any("keyword", keyword.kwlist+additional_keywords) + r"\b"
    builtinlist = [str(name) for name in dir(builtins)
                   if not name.startswith('_')]+additional_builtins
    builtin = r"([^.'\"\\#]\b|^)" + any("builtin", builtinlist) + r"\b"
```

So we could turn the list into sets and define what has precedence with some set operations? or just hard code in this function which should be taken as kw and which as builtins

sets seems cleaner that hardcoding.


Resolving patch:
diff --git a/spyder/utils/syntaxhighlighters.py b/spyder/utils/syntaxhighlighters.py
--- a/spyder/utils/syntaxhighlighters.py
+++ b/spyder/utils/syntaxhighlighters.py
@@ -281,9 +281,13 @@ def any(name, alternates):
 
 def make_python_patterns(additional_keywords=[], additional_builtins=[]):
     "Strongly inspired from idlelib.ColorDelegator.make_pat"
-    kw = r"\b" + any("keyword", keyword.kwlist+additional_keywords) + r"\b"
+    kwlist = keyword.kwlist + additional_keywords
     builtinlist = [str(name) for name in dir(builtins)
-                   if not name.startswith('_')]+additional_builtins
+                   if not name.startswith('_')] + additional_builtins
+    repeated = set(kwlist) & set(builtinlist)
+    for repeated_element in repeated:
+        kwlist.remove(repeated_element)
+    kw = r"\b" + any("keyword", kwlist) + r"\b"
     builtin = r"([^.'\"\\#]\b|^)" + any("builtin", builtinlist) + r"\b"
     comment = any("comment", [r"#[^\n]*"])
     instance = any("instance", [r"\bself\b"])


Test patch: