PureBasic - форум

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » PureBasic - форум » Вопросы по PureBasic » Подсветка синтаксиса ScintillaGadget по регулярному выражению


Подсветка синтаксиса ScintillaGadget по регулярному выражению

Сообщений 1 страница 6 из 6

1

Ищу рабочий пример соответствующий названию темы. Есть варианты по ключевым словам, но не по регулярке.
Для примера - нужно после Get подсветить двумя разными цветами Example и _Example:

Код:
Get Example()
Get _Example()

Пример по ключевым словам:

Код:
#DS_EDITOR_KEYWORDS = " if else elseif endif exit free while wend goto label "
#DS_EDITOR_OPENFOLD = " while if "
#DS_EDITOR_CLOSEFOLD = " wend endif "
#DS_EDITOR_ENDCONSTANT = "+=-*/%$ !<>|\/.,()"

Enumeration 0
  #LexerState_Space
  #LexerState_Comment
  #LexerState_NonKeyword
  #LexerState_Keyword
  #LexerState_FoldKeyword
  #LexerState_Constant
  #LexerState_String
EndEnumeration

Procedure.l Scintilla(sciptr.l, p1.l, p2.l=0, p3.l=0)
  ProcedureReturn ScintillaSendMessage(sciptr,p1,p2,p3)
EndProcedure

Procedure Highlight(sciptr.l, startpos.l, endpos.l)

  If startpos = -1
    endstyled.l = Scintilla(sciptr, #SCI_GETENDSTYLED)
    linenumber.l = Scintilla(sciptr, #SCI_LINEFROMPOSITION, endstyled)
  Else
    linenumber = Scintilla(sciptr, #SCI_LINEFROMPOSITION, startpos)
  EndIf
  
  If linenumber = 0
    level = #SC_FOLDLEVELBASE
  Else
    linenumber - 1
    level = Scintilla(sciptr, #SCI_GETFOLDLEVEL, linenumber) & ~ #SC_FOLDLEVELHEADERFLAG
  EndIf
  
  thislevel.l = level
  nextlevel.l = level
  
  currentpos.l = Scintilla(sciptr, #SCI_POSITIONFROMLINE, linenumber)
  Scintilla(sciptr, #SCI_STARTSTYLING, currentpos, $1f | #INDICS_MASK)
  state = #LexerState_Space
  startkeyword = currentpos
  keyword.s = ""
  
  qpos.l = -1 ;quote pos
  
  While currentpos <= endpos
    
    oldstate = state
    lastchar.l = char.l    
    
    char.l = Scintilla(sciptr, #SCI_GETCHARAT, currentpos)
    If char = ';'
      state = #LexerState_Comment
    ElseIf char = '"' And state<>#LexerState_String And state<>#LexerState_Comment
      state = #LexerState_String
      qpos = currentpos
    ElseIf state = #LexerState_String
      If (qpos<>currentpos-1 And lastchar = '"') Or char = 10 Or char = 13
        state=#LexerState_Space
        qpos=-1
      EndIf         
    ElseIf char = 10 Or char = 13
      state = #LexerState_Space
    ElseIf state <> #LexerState_Comment
      If state=#LexerState_Constant
        If FindString(#DS_EDITOR_ENDCONSTANT,Chr(char),1) Or char=10 Or char=13 Or char=9
          state=#LexerState_Space
        EndIf 
      Else             
        If char='#'
          state = #LexerState_Constant                
        ElseIf char = 9 Or char = ' ' Or char = '.'
          state = #LexerState_Space
        Else
          state = #LexerState_NonKeyword
          keyword + Chr(char)
        EndIf
      EndIf 
    EndIf
    If oldstate <> state Or currentpos = endpos
      If oldstate = #LexerState_NonKeyword
        lkeyword.s = LCase(keyword)
        If FindString(#DS_EDITOR_OPENFOLD," "+LCase(keyword)+" ",1)
          thislevel | #SC_FOLDLEVELHEADERFLAG
          nextlevel + 1
        ElseIf FindString(#DS_EDITOR_CLOSEFOLD," "+LCase(keyword)+" ",1) 
          nextlevel - 1
          If nextlevel < #SC_FOLDLEVELBASE
            nextlevel = #SC_FOLDLEVELBASE
          EndIf
        EndIf
        
        If FindString(#DS_EDITOR_KEYWORDS," "+LCase(keyword)+" ",1)
          oldstate = #LexerState_Keyword                                    
        EndIf                
        
        keyword = ""
      EndIf
      Scintilla(sciptr, #SCI_SETSTYLING, currentpos - startkeyword, oldstate)
      startkeyword = currentpos
    EndIf
    
    If char = 10 Or currentpos = endpos
      Scintilla(sciptr, #SCI_SETFOLDLEVEL, linenumber, thislevel)
      thislevel = nextlevel
      linenumber + 1
    EndIf
    
    currentpos + 1
  Wend
EndProcedure 

ProcedureDLL ScCallBack(EditorGadget.l, *scinotify.SCNotification)
  If *scinotify\nmhdr\code = #SCN_STYLENEEDED
    Highlight(1, -1, *scinotify\position) 
  ElseIf *scinotify\nmhdr\code = #SCN_MARGINCLICK
    modifiers = *scinotify\modifiers
    position = *scinotify\position
    margin = *scinotify\margin
    linenumber = Scintilla(1, #SCI_LINEFROMPOSITION, position)
    Select margin
      Case 2
        Scintilla(1, #SCI_TOGGLEFOLD, linenumber)
    EndSelect 
  EndIf
EndProcedure

OpenWindow(0,0,0,600,600,"")

RemoveKeyboardShortcut(0, #PB_Shortcut_Tab)
RemoveKeyboardShortcut(0, #PB_Shortcut_Tab | #PB_Shortcut_Shift)

InitScintilla("Scintilla.dll")

ScintillaGadget(1,0,0,600,500,@ScCallBack())
ButtonGadget(2,0,510,100,50,"GetText")

; Margins
Scintilla(1, #SCI_STYLESETSIZE, #STYLE_DEFAULT, 10) 
Scintilla(1, #SCI_SETMARGINTYPEN, 0, #SC_MARGIN_NUMBER)
Scintilla(1, #SCI_SETMARGINMASKN, 2, #SC_MASK_FOLDERS)
Scintilla(1, #SCI_SETMARGINWIDTHN, 0, 34)
Scintilla(1, #SCI_SETMARGINWIDTHN, 1, 1)
Scintilla(1, #SCI_SETMARGINWIDTHN, 2, 15)
Scintilla(1, #SCI_SETMARGINSENSITIVEN, 2, #True)

; Choose folding icons
Scintilla(1, #SCI_MARKERDEFINE, #SC_MARKNUM_FOLDEROPEN, #SC_MARK_CIRCLEMINUS)
Scintilla(1, #SCI_MARKERDEFINE, #SC_MARKNUM_FOLDER, #SC_MARK_CIRCLEPLUS)
Scintilla(1, #SCI_MARKERDEFINE, #SC_MARKNUM_FOLDERSUB, #SC_MARK_VLINE)
Scintilla(1, #SCI_MARKERDEFINE, #SC_MARKNUM_FOLDERTAIL, #SC_MARK_LCORNERCURVE)
Scintilla(1, #SCI_MARKERDEFINE, #SC_MARKNUM_FOLDEREND, #SC_MARK_CIRCLEPLUSCONNECTED)
Scintilla(1, #SCI_MARKERDEFINE, #SC_MARKNUM_FOLDEROPENMID, #SC_MARK_CIRCLEMINUSCONNECTED)
Scintilla(1, #SCI_MARKERDEFINE, #SC_MARKNUM_FOLDERMIDTAIL, #SC_MARK_TCORNERCURVE)

; Choose folding icon colours
Scintilla(1, #SCI_MARKERSETFORE, #SC_MARKNUM_FOLDER, $FFFFFF)
Scintilla(1, #SCI_MARKERSETBACK, #SC_MARKNUM_FOLDER, 0)
Scintilla(1, #SCI_MARKERSETFORE, #SC_MARKNUM_FOLDEROPEN, $FFFFFF)
Scintilla(1, #SCI_MARKERSETBACK, #SC_MARKNUM_FOLDEROPEN, 0)
Scintilla(1, #SCI_MARKERSETBACK, #SC_MARKNUM_FOLDEROPENMID, 0)
Scintilla(1, #SCI_MARKERSETBACK, #SC_MARKNUM_FOLDERSUB, 0)
Scintilla(1, #SCI_MARKERSETBACK, #SC_MARKNUM_FOLDERTAIL, 0)
Scintilla(1, #SCI_MARKERSETBACK, #SC_MARKNUM_FOLDERMIDTAIL, 0) 

;lex setup
ScintillaSendMessage(1,#SCI_SETLEXER, #SCLEX_CONTAINER, 0);
ScintillaSendMessage(1,#SCI_STYLESETFORE, #STYLE_DEFAULT, RGB(0,0,0));
ScintillaSendMessage(1,#SCI_STYLESETBACK, #STYLE_DEFAULT, RGB(255,255,255));
ScintillaSendMessage(1,#SCI_STYLECLEARALL)                                 ;

; Set caret line colour
ScintillaSendMessage(1, #SCI_SETCARETLINEBACK, RGB(231, 245, 255))
ScintillaSendMessage(1, #SCI_SETCARETLINEVISIBLE, #True)

; Set styles for custom lexer
ScintillaSendMessage(1, #SCI_STYLESETFORE, #LexerState_Comment, $8800)
ScintillaSendMessage(1, #SCI_STYLESETITALIC, #LexerState_Comment, 1)
ScintillaSendMessage(1, #SCI_STYLESETFORE, #LexerState_NonKeyword, 0)
ScintillaSendMessage(1, #SCI_STYLESETFORE, #LexerState_Keyword, 0)
ScintillaSendMessage(1, #SCI_STYLESETBOLD, #LexerState_NonKeyword, 0)
ScintillaSendMessage(1, #SCI_STYLESETBOLD, #LexerState_Keyword, 1)
ScintillaSendMessage(1, #SCI_STYLESETFORE, #LexerState_FoldKeyword, $ff) 
ScintillaSendMessage(1, #SCI_STYLESETFORE, #LexerState_Constant, RGB(180,0,0))
ScintillaSendMessage(1, #SCI_STYLESETFORE, #LexerState_String, RGB(0,100,170))


*Text + UTF8(";test comment"+#CRLF$+"If abc=1"+#CRLF$+"   Goto hi_there"+#CRLF$+"EndIf")

ScintillaSendMessage(1, #SCI_SETTEXT, #Null, *Text)

Repeat
  
  event=WaitWindowEvent()
  
  If event=#PB_Event_Gadget
    If EventGadget()=2
      MessageRequester("Get",GetGadgetText(1))
    EndIf
  EndIf
  
Until event=#PB_Event_CloseWindow
End

Отредактировано Webarion (27.05.2022 20:19:07)

0

2

Код:
; Устанавливает режим поиска (REGEX + POSIX фигурные скобки)
ScintillaMsg(*sciptr, #SCI_SETSEARCHFLAGS, #SCFIND_REGEXP | #SCFIND_POSIX)

Смотреть Grub2-generator

0

3

AZJIO написал(а):

Смотреть Grub2-generator

Спасибо! С этим я разобрался. Но, у меня дополнительная проблема возникла. Если создавать инструмент для IDE, то IDE вылетает на этой строке:

Код:
firstMatchPos = SendMessage_(*Sci, #SCI_SEARCHINTARGET, regexLength, *regex)

Хочу создать дополнительные стили кода, потому-что мне не хватает. Возможно стоит собрать свою IDE из официального репозитория, но с этим я пока не разобрался. Поэтому, прошу помощи с рабочими вариантами с инструментом для IDE (имею ввиду, когда через GetEnvironmentVariable("PB_TOOL_Scintilla") )

Отредактировано Webarion (29.05.2022 03:56:58)

0

4

Webarion
Тогда наверно надо смотреть плаг Highlight

0

5

AZJIO написал(а):

Webarion
Тогда наверно надо смотреть плаг Highlight

В нём используется эта же строка, для получения позиции найденного. Пока IDE на ней вылетает. Ищу другие способы.
А так, хороший инструмент. AZJIO. Есть ли в плагине подсветка синтаксиса внутри групп? Как пример:

Код:
EnableExplicit
InitScintilla()

Declare Color(Gadget, regex$, KeyGroup1, KeyGroup2)

Declare MakeUTF8Text(text.s)
Declare MakeScintillaText(text.s, *sciLength.Integer=0)
Declare ScCallBack(Gadget, *scinotify.SCNotification)

Define txt$=" Procedure User_RegExGroup1(*pPointer, Var1, RegExGroup2$)" + #LF$ +
     "  Define a=1" + #LF$ +
     " EndProcedure" + #LF$ +
     " Procedure _Internal_RegExGroup1(Var1, RegExGroup2$)" + #LF$

Define txtLen=StringByteLength(txt$, #PB_UTF8)


OpenWindow(100, 0, 0, 900, 600, "Редактор Scintilla", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_SizeGadget | #PB_Window_MaximizeGadget | #PB_Window_MinimizeGadget)

; Создание гаджета размером на всё окно
ScintillaGadget(0, 0, 0, WindowWidth(100), WindowHeight(100), @ScCallBack())

; Устанавливает режим текста
ScintillaSendMessage(0, #SCI_SETCODEPAGE, #SC_CP_UTF8)   ; в кодировке UTF-8

ScintillaSendMessage(0, #SCI_SETTEXT, 0, MakeUTF8Text(txt$)) ; Установить текст гаджета
ScintillaSendMessage(0, #SCI_GOTOPOS, txtLen)                ; Курсор в конец текста
SetActiveGadget(0)                                           ; Установить гаджет активным, фокус ввода

#SCI_GETTEXTRANGE  = 2162

; Эти константы будут использоваться для подсветки синтаксиса.
Enumeration 100
  #LexerState_Key1Group1
  #LexerState_Key1Group2
  #LexerState_Key2Group1
  #LexerState_Key2Group2
EndEnumeration

ScintillaSendMessage(0, #SCI_STYLESETFORE, #LexerState_Key1Group1, $0000FF)             ; Цвет Группы1
ScintillaSendMessage(0, #SCI_STYLESETFORE, #LexerState_Key1Group2, $FF9F00)             ; Цвет Группы2
ScintillaSendMessage(0, #SCI_STYLESETFORE, #LexerState_Key2Group1, $8B8B00)      
ScintillaSendMessage(0, #SCI_STYLESETFORE, #LexerState_Key2Group2, $FF9F00)        

Repeat
  Define Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow

CloseWindow(100)
End


ProcedureDLL ScCallBack(Gadget, *scinotify.SCNotification)
  If *scinotify\nmhdr\code = #SCN_STYLENEEDED
    
    Color( Gadget, "Procedure\s+([a-zA-Z]\w+)\(.+?(\w+\$)", #LexerState_Key1Group1, #LexerState_Key1Group2 ) ; подсвечиваем первый тип процедур и две группы
    Color( Gadget, "Procedure\s+(_\w+)\(.+?(\w+\$)", #LexerState_Key2Group1, #LexerState_Key2Group2 ) ; подсвечиваем второй тип процедур и две группы
    
  EndIf
EndProcedure

; Преобразование текста в текст для вставки в Scintilla
Procedure MakeUTF8Text(text.s)
	Static buffer.s
	buffer=Space(StringByteLength(text, #PB_UTF8))
	PokeS(@buffer, text, -1, #PB_UTF8)
	ProcedureReturn @buffer
EndProcedure

Procedure MakeScintillaText(text.s, *sciLength.Integer=0)
	Static sciLength : sciLength=StringByteLength(text, #PB_UTF8) ; #TextEncoding
	Static sciText.s : sciText = Space(sciLength)
	If *sciLength : *sciLength\i=sciLength : EndIf ;<--- Возвращает длину буфера scintilla  (требуется для определенной команды scintilla)
	PokeS(@sciText, text, -1, #PB_UTF8)    	   ; #TextEncoding
	ProcedureReturn @sciText
EndProcedure


; Подсвечивание через стиль
Procedure Color(Gadget, regex$, KeyGroup1, KeyGroup2)
  Protected txtLen, StartPos, EndPos, firstMatchPos   
  Protected TextLength
  Protected *regex = MakeScintillaText(regex$, @TextLength), regexLength = Len(regex$)

  ScintillaSendMessage(Gadget, #SCI_SETSEARCHFLAGS, #SCFIND_REGEXP | #SCFIND_POSIX ); Устанавливает режим поиска (REGEX + POSIX фигурные скобки)
  
  txtLen = ScintillaSendMessage(Gadget, #SCI_GETTEXTLENGTH) ; получает длину текста
  
  EndPos = 0
  Repeat
    ScintillaSendMessage(Gadget, #SCI_SETTARGETSTART, EndPos)       ; от начала (задаём область поиска) используя позицию конца предыдущего поиска
    ScintillaSendMessage(Gadget, #SCI_SETTARGETEND, txtLen)         ; до конца по длине текста
    
    ;                                             \/ - эта отправка сообщения в инструменте IDE завершает работу IDE
    firstMatchPos = ScintillaSendMessage(Gadget, #SCI_SEARCHINTARGET, regexLength, *regex) ; возвращает позицию первого найденного. В параметрах длина искомого и указатель
    
    If firstMatchPos>-1 ; если больше -1, то есть найдено, то

      StartPos = ScintillaSendMessage(Gadget, #SCI_GETTARGETSTART)                         ; получает позицию начала найденного
      EndPos   = ScintillaSendMessage(Gadget, #SCI_GETTARGETEND)                           ; получает позицию конца найденного
      
      ; получаем найденный текст чтобы подсветит по группам регулярки
      Protected *StringBuffer = AllocateMemory(EndPos - StartPos + 1)
      Protected Range.TextRange
      Range\chrg\cpMin = StartPos
      Range\chrg\cpMax = EndPos
      Range\lpstrText  = *StringBuffer
      ScintillaSendMessage(Gadget, #SCI_GETTEXTRANGE, 0, Range)
      Protected FindedText$ = PeekS(*StringBuffer, EndPos - StartPos + 1, #PB_UTF8)
      FreeMemory(*StringBuffer)

      Define RegEx = CreateRegularExpression(#PB_Any, regex$)
      If RegEx
        If ExamineRegularExpression(RegEx, FindedText$)
          
          Define GroupsCount = CountRegularExpressionGroups(RegEx), iGroup, OffsetStartPos, OffsetLen
          While NextRegularExpressionMatch(RegEx)
            Define iGroup
            For iGroup = 1 To GroupsCount
              
              OffsetStartPos = RegularExpressionGroupPosition(RegEx, iGroup)
              OffsetLen      = RegularExpressionGroupLength(RegEx, iGroup)
              
              ScintillaSendMessage(Gadget, #SCI_STARTSTYLING, StartPos + OffsetStartPos - 1, Gadget) ; устанавливает позицию начала
              
              Select iGroup
                Case 1
                  ScintillaSendMessage(Gadget, #SCI_SETSTYLING, OffsetLen, KeyGroup1)             ; ширина и номер стиля
                Case 2
                  ScintillaSendMessage(Gadget, #SCI_SETSTYLING, OffsetLen, KeyGroup2)
              EndSelect
              
            Next
          Wend
          
        EndIf
      Else
        Debug RegularExpressionError()
      EndIf

    Else
      Break
    EndIf
    
  ForEver
EndProcedure

Отредактировано Webarion (30.05.2022 00:22:26)

0

6

А разница здесь в том, что плагин для Notepad++, как dll загружается и работает, с общей памятью одного процесса. А инструмент PureBasic IDE, это отдельный процесс, со своей выделенной памятью. И во втором случае, при том коде, который был описан ранее, инструмент PB, отправляет указатель *regex находящийся внутри своей памяти, а компонент Scintilla из PureBasicIDE, получая этот указатель, читает значение не в памяти того процесса, который его отправит(наш инструмент), а читает его в памяти своего процесса, что не соответствует тому, что мы пытаемся сделать, думая, что работаем в одной и той же доступной нам памяти.
Для того, чтобы это сработало, нужно выделить соответствующую память в IDE, записать туда нужные данные и с полученным новым указателем отправить сообщение в Scintilla IDE.
Сначала:

Код:
    *MemoryIDE_RegEx = VirtualAllocEx_(hpid, 0, regexLength, #MEM_RESERVE | #MEM_COMMIT, #PAGE_EXECUTE_READWRITE) ; выделяем в IDE виртуальную память под *regex
     WriteProcessMemory_(hpid, *MemoryIDE_RegEx, *regex, regexLength, #Null) ; пишем *regex в память IDE

А потом уже:

Код:
firstMatchPos = SendMessage_(hSciIDE, #SCI_SEARCHINTARGET, regexLength, *MemoryIDE_RegEx)

Ну и не забывать правильно освобождать выделенную память.
Вот так уже работает инструмент для IDE.

P.S
Это всё пока только на Windows.

Отредактировано Webarion (30.05.2022 06:31:41)

0


Вы здесь » PureBasic - форум » Вопросы по PureBasic » Подсветка синтаксиса ScintillaGadget по регулярному выражению