File: pre_processing_code.py

package info (click to toggle)
gnat-gps 18-5
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 45,716 kB
  • sloc: ada: 362,679; python: 31,031; xml: 9,597; makefile: 1,030; ansic: 917; sh: 264; java: 17
file content (158 lines) | stat: -rw-r--r-- 5,752 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
"""
This file provides support for displaying Ada preprocessing code as generated
by GNAT (-gnateG switch).
"""

import os
import distutils.dep_util
import GPS
from gps_utils import in_ada_file, interactive, hook

inactive_code_pref = GPS.Preference("Editor/Fonts & Colors:" +
                                    "General/preprocessor")
# Preference used for the display of the inactive code


@hook("preferences_changed")
def __on_preferences_changed():
    for srcbuf in GPS.EditorBuffer.list():
        if hasattr(srcbuf, "gnatprep_overlay"):
            style, fg, bg = inactive_code_pref.get().split("@")
            if style != "DEFAULT":
                srcbuf.gnatprep_overlay.set_property("style", style.lower())
            srcbuf.gnatprep_overlay.set_property("foreground", fg)
            srcbuf.gnatprep_overlay.set_property("background", bg)


def create_overlay(file_name):
    """Create a new overlay"""
    srcbuf = GPS.EditorBuffer.get(GPS.File(file_name))
    overlay = srcbuf.create_overlay("Inactive code")
    style, fg, bg = inactive_code_pref.get().split("@")
    if style != "DEFAULT":
        overlay.set_property("style", style.lower())
    overlay.set_property("foreground", fg)
    overlay.set_property("background", bg)
    srcbuf.gnatprep_overlay = overlay


def subprogram_bounds(cursor):
    """Return the first and last line of the current subprogram, and (0,0) if
       the current subprogram could not be determined."""
    blocks = {"CAT_PROCEDURE": 1, "CAT_FUNCTION": 1, "CAT_ENTRY": 1,
              "CAT_PROTECTED": 1, "CAT_TASK": 1, "CAT_PACKAGE": 1}

    if cursor.block_type() == "CAT_UNKNOWN":
        return 0, 0

    min = cursor.buffer().beginning_of_buffer()
    while not (cursor.block_type() in blocks) and cursor > min:
        cursor = cursor.block_start() - 1

    if cursor > min:
        return cursor.block_start_line(), cursor.block_end_line()
    else:
        return 0, 0


def reset_state(file_name):
    """Reset the state of the file and delete the overlay"""
    srcbuf = GPS.EditorBuffer.get(GPS.File(file_name))
    if hasattr(srcbuf, "gnatprep_overlay"):
        srcbuf.remove_overlay(srcbuf.gnatprep_overlay)


def get_prep_file(for_subprogram=False, reset=False):
    """Retreive the .prep file in the project"""
    context = GPS.current_context()
    local_file = context.file().path
    file = context.file().name("Build_Server")

    if context.project():
        list_dir = context.project().object_dirs(False)
    else:
        list_dir = GPS.Project.root().object_dirs(False)

    if list_dir:
        objdir = list_dir[0]
    else:
        objdir = GPS.get_tmp_dir()
        GPS.Console("Messages").write(
            "Could not find an object directory for %s, reverting to %s" %
            (file, objdir))
    prep_file = os.path.join(objdir, os.path.basename(local_file)) + ".prep"
    return local_file, prep_file


def show_inactive_code(file_name, prep_name, for_subprogram=False):
    """Parse the file prep_name and show the inactive code"""
    # Explain to the user how to generate the .prep file
    if not os.path.isfile(prep_name):
        GPS.Console("Messages").write("No preprocessing data file " +
                                      str(prep_name) +
                                      " found: The project must be compiled " +
                                      "with -gnateG to generate .prep file.\n",
                                      mode="error")
    # Do nothing is the .prep file is too old
    elif distutils.dep_util.newer(file_name, prep_name):
        GPS.Console("Messages").write("The .prep file is too old," +
                                      " please recompile the ada file.\n",
                                      mode="error")
    else:
        reset_state(file_name)
        srcbuf = GPS.EditorBuffer.get(GPS.File(file_name))

        if for_subprogram:
            block_first, block_last = subprogram_bounds(
                srcbuf.current_view().cursor())
        else:
            block_first, block_last = (0, 0)

        # Get the text
        prep_file = open(prep_name)
        prep_text = prep_file.read()
        prep_file.close()

        # The file start at the line 1
        current_line = 1
        create_overlay(file_name)

        for line in prep_text.splitlines():
            if line.startswith("--! "):
                if (block_first == 0 or
                        (block_first < current_line <= block_last)):
                    frm = srcbuf.at(current_line, 1)
                    to = frm.end_of_line()
                    srcbuf.apply_overlay(srcbuf.gnatprep_overlay, frm, to)
            current_line += 1

#################################
# Register the contextual menus #
#################################


@interactive("Ada", in_ada_file,
             contextual="Preprocessing/Show subprogram",
             name="Show inactive code for subprogram", before="Align")
def show_inactive_subprogram():
    """Show the file state after the preprocessing"""
    file_name, prep_name = get_prep_file(for_subprogram=True)
    show_inactive_code(file_name, prep_name, for_subprogram=True)


@interactive("Ada", in_ada_file,
             contextual="Preprocessing/Show entire file",
             name="Show inactive code for file", before="Align")
def show_inactive_file():
    """Show the subprogram state after the preprocessing"""
    file_name, prep_name = get_prep_file()
    show_inactive_code(file_name, prep_name)


@interactive("Ada", in_ada_file,
             contextual="Preprocessing/Clear",
             name="Clear inactive code display", before="Align")
def clear_display():
    """Clear the preprocessing display"""
    file_name, _ = get_prep_file()
    reset_state(file_name)