Testing... 8pt font.
Uncle Bob would be refactoring that
render_source( ) method like mad, I feel :smile: . Or would he reimplement the renderer while writing a comprehensive test suite for it? :razz:
Z_CODE_LIGHTER2 is courtessy of
manish.kumar19
REPORT z_code_lighter2.
CLASS lcl_sedi_adt_html_renderer DEFINITION
FINAL
CREATE PRIVATE .
PUBLIC SECTION.
CLASS-METHODS create_instance
RETURNING
value(result) TYPE REF TO lcl_sedi_adt_html_renderer .
METHODS render_source
IMPORTING
!source TYPE rswsourcet
!css_class_keyword TYPE string DEFAULT 'keyword'
!css_class_comment TYPE string DEFAULT 'comment'
!css_class_literal TYPE string DEFAULT 'literal'
!css_class_number TYPE string DEFAULT 'number'
RETURNING
!value(html_source) TYPE rswsourcet .
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
CLASS lcl_sedi_adt_html_renderer IMPLEMENTATION.
METHOD create_instance.
CREATE OBJECT result.
ENDMETHOD.
METHOD render_source.
CONSTANTS:
co_regex_numbers TYPE string VALUE '[[:digit:]]+' ##no_text,
co_regex_inline_decl_data TYPE string VALUE 'DATA\([^\)[:space:]]+\)' ##no_text,
co_regex_inline_decl_field_sym TYPE string VALUE 'FIELD\-SYMBOL\(<[^\)[:space:]]+>\)' ##no_text.
DATA:
statements TYPE STANDARD TABLE OF sstmnt,
tokens TYPE sana_stokesx_tab,
offset_end_of_token TYPE i,
offset_to_split_token TYPE i,
length_rest_of_splitted_token TYPE i,
in_string_template TYPE abap_bool VALUE abap_false.
FIELD-SYMBOLS:
<statement> LIKE LINE OF statements,
<token> LIKE LINE OF tokens,
<source_line> LIKE LINE OF source.
SCAN ABAP-SOURCE source STATEMENTS INTO statements TOKENS INTO tokens WITH ANALYSIS WITH COMMENTS.
html_source = source.
LOOP AT statements ASSIGNING <statement> WHERE type NA 'MBE'.
CALL FUNCTION 'RS_QUALIFY_ABAP_TOKENS_STR'
EXPORTING
statement_type = <statement>-type
index_from = <statement>-from
index_to = <statement>-to
CHANGING
stokesx_tab = tokens
EXCEPTIONS
OTHERS = 5.
IF sy-subrc <> 0.
CONTINUE.
ENDIF.
ENDLOOP.
SORT tokens BY row DESCENDING col DESCENDING.
DELETE ADJACENT DUPLICATES FROM tokens.
LOOP AT tokens ASSIGNING <token>.
TRY.
READ TABLE html_source INDEX <token>-row ASSIGNING <source_line>.
IF ( sy-subrc = 0 ).
offset_end_of_token = <token>-col + <token>-len1.
IF ( <token>-len1 > 0 ).
CASE <token>-type.
WHEN sana_tok_keyword OR sana_tok_word.
<source_line> =
<source_line>(<token>-col) &&
|<span class="{ css_class_keyword }">| &&
escape(
val = <source_line>+<token>-col(<token>-len1)
format = cl_abap_format=>e_html_text ) &&
'</span>' && <source_line>+offset_end_of_token.
IF ( <token>-str = '|' ).
in_string_template = boolc( in_string_template = abap_false ).
ENDIF.
WHEN sana_tok_field.
IF in_string_template = abap_true AND <token>-len1 > 1.
<token>-len1 = <token>-len1 - 2 + count( val = <token>-str regex = '[\\{}|]' ).
offset_end_of_token = <token>-col + <token>-len1.
ENDIF.
IF ( ( <token>-str(1) = '''' ) OR ( <token>-str(1) = '`' ) ).
<source_line> =
<source_line>(<token>-col) &&
|<span class="{ css_class_literal }">| &&
escape(
val = <source_line>+<token>-col(<token>-len1)
format = cl_abap_format=>e_html_text ) &&
'</span>' && <source_line>+offset_end_of_token.
ELSEIF ( matches( val = <token>-str regex = co_regex_numbers ) ).
<source_line> =
<source_line>(<token>-col) &&
|<span class="{ css_class_number }">| &&
escape(
val = <source_line>+<token>-col(<token>-len1)
format = cl_abap_format=>e_html_text ) &&
'</span>' && <source_line>+offset_end_of_token.
ELSEIF ( matches( val = <token>-str regex = co_regex_inline_decl_data ) ).
offset_end_of_token = <token>-col + strlen( <token>-str ).
offset_to_split_token = <token>-col + 4.
length_rest_of_splitted_token = strlen( <token>-str ) - 4.
<source_line> =
<source_line>(<token>-col) &&
|<span class="{ css_class_keyword }">| &&
escape(
val = <source_line>+<token>-col(4)
format = cl_abap_format=>e_html_text ) &&
'</span>' &&
escape(
val = <source_line>+offset_to_split_token(length_rest_of_splitted_token)
format = cl_abap_format=>e_html_text ) &&
<source_line>+offset_end_of_token.
ELSE.
DATA: lv_off TYPE i,
lv_len TYPE i.
lv_off = <token>-col + <token>-off3.
lv_len = <token>-len3.
<source_line> = replace( val = <source_line> off = lv_off len = lv_len
with = escape(
val = <source_line>+lv_off(lv_len)
format = cl_abap_format=>e_html_text ) ) .
lv_off = <token>-col + <token>-off2.
lv_len = <token>-len2.
<source_line> = replace( val = <source_line> off = lv_off len = lv_len
with = escape(
val = <source_line>+lv_off(lv_len)
format = cl_abap_format=>e_html_text ) ) .
lv_off = <token>-col.
lv_len = <token>-len1.
<source_line> = replace( val = <source_line> off = lv_off len = lv_len
with = escape(
val = <source_line>+lv_off(lv_len)
format = cl_abap_format=>e_html_text ) ) .
ENDIF.
WHEN sana_tok_field_def.
IF ( matches( val = <token>-str regex = co_regex_inline_decl_field_sym ) ).
offset_end_of_token = <token>-col + strlen( <token>-str ).
offset_to_split_token = <token>-col + 12.
length_rest_of_splitted_token = strlen( <token>-str ) - 12.
<source_line> =
<source_line>(<token>-col) &&
|<span class="{ css_class_keyword }">| &&
escape(
val = <source_line>+<token>-col(12)
format = cl_abap_format=>e_html_text ) &&
'</span>' &&
escape(
val = <source_line>+offset_to_split_token(length_rest_of_splitted_token)
format = cl_abap_format=>e_html_text ) &&
<source_line>+offset_end_of_token.
ELSE.
<source_line> =
<source_line>(<token>-col) &&
escape(
val = <source_line>+<token>-col(<token>-len1)
format = cl_abap_format=>e_html_text ) &&
<source_line>+offset_end_of_token.
ENDIF.
WHEN 'C'.
<source_line> =
<source_line>(<token>-col) &&
|<span class="{ css_class_comment }">| &&
escape(
val = <source_line>+<token>-col
format = cl_abap_format=>e_html_text ) &&
'</span>'.
WHEN OTHERS.
<source_line> =
<source_line>(<token>-col) &&
escape(
val = <source_line>+<token>-col(<token>-len1)
format = cl_abap_format=>e_html_text ) &&
<source_line>+offset_end_of_token.
ENDCASE.
ELSE.
<source_line> =
<source_line>(<token>-col) &&
escape(
val = <source_line>+<token>-col(<token>-len1)
format = cl_abap_format=>e_html_text ) &&
<source_line>+offset_end_of_token.
ENDIF.
ENDIF.
CATCH cx_sy_range_out_of_bounds.
CONTINUE.
ENDTRY.
ENDLOOP.
ENDMETHOD.
ENDCLASS.
DATA:
go_dock TYPE REF TO cl_gui_docking_container,
go_container_1 TYPE REF TO cl_gui_container,
go_editor_1 TYPE REF TO cl_gui_textedit,
go_container_2 TYPE REF TO cl_gui_container,
go_editor_2 TYPE REF TO cl_gui_textedit,
gt_code TYPE STANDARD TABLE OF text1024.
SELECTION-SCREEN BEGIN OF SCREEN 2000.
SELECTION-SCREEN END OF SCREEN 2000.
START-OF-SELECTION.
CALL SELECTION-SCREEN 2000.
AT SELECTION-SCREEN.
FIELD-SYMBOLS <gs_code> LIKE LINE OF gt_code.
DATA gv_xml TYPE string.
DATA go_root TYPE REF TO cx_root.
DATA gt_rswsourcet TYPE rswsourcet.
REFRESH gt_code.
CALL METHOD go_editor_1->get_text_as_r3table
IMPORTING
table = gt_code.
gt_rswsourcet = gt_code.
gt_rswsourcet = lcl_sedi_adt_html_renderer=>create_instance( )->render_source(
source = gt_rswsourcet
).
gt_code = gt_rswsourcet.
LOOP AT gt_code ASSIGNING <gs_code>.
CONCATENATE
'<span style="font-family: courier new,courier; font-size: 8pt;">'
<gs_code> '</span><br/>'
INTO <gs_code>.
ENDLOOP.
INSERT '<pre class="jive_text_macro jive_macro_quote" jivemacro="quote"><p>'
INTO gt_code INDEX 1.
APPEND '</p></pre>' TO gt_code.
gv_xml = concat_lines_of( gt_code ).
TRY .
CALL TRANSFORMATION z_code_lighter2
SOURCE XML gv_xml
RESULT XML gt_code.
CATCH cx_root INTO go_root.
gv_xml = go_root->get_text( ).
ENDTRY.
CALL METHOD go_editor_2->set_text_as_stream
EXPORTING
text = gt_code
EXCEPTIONS
error_dp = 1
error_dp_create = 2
OTHERS = 3.
CALL SELECTION-SCREEN 2000.
AT SELECTION-SCREEN OUTPUT.
CHECK go_dock IS NOT BOUND.
CREATE OBJECT go_dock
EXPORTING
parent = cl_gui_container=>screen0
side = cl_gui_docking_container=>dock_at_left
ratio = 90.
DATA go_splitter TYPE REF TO cl_gui_splitter_container.
CREATE OBJECT go_splitter
EXPORTING
parent = go_dock
rows = 1
columns = 2.
CHECK go_container_1 IS NOT BOUND.
CALL METHOD go_splitter->get_container
EXPORTING
row = 1
column = 1
RECEIVING
container = go_container_1.
CHECK go_editor_1 IS NOT BOUND.
CREATE OBJECT go_editor_1
EXPORTING
parent = go_container_1
wordwrap_mode = cl_gui_textedit=>wordwrap_at_fixed_position
wordwrap_position = 1024
wordwrap_to_linebreak_mode = cl_gui_textedit=>true.
CHECK go_container_2 IS NOT BOUND.
CALL METHOD go_splitter->get_container
EXPORTING
row = 1
column = 2
RECEIVING
container = go_container_2.
CHECK go_container_2 IS BOUND.
CHECK go_editor_2 IS NOT BOUND.
CREATE OBJECT go_editor_2
EXPORTING
parent = go_container_2
wordwrap_mode = cl_gui_textedit=>wordwrap_at_fixed_position
wordwrap_position = 1024
wordwrap_to_linebreak_mode = cl_gui_textedit=>true.
IF go_editor_2 IS BOUND.
CALL METHOD go_editor_2->set_readonly_mode.
ENDIF.