Is this readable?

new topic     » topic index » view thread      » older message » newer message

Bob Elia wrote:
>Without knowing how you feel about other people working on your 
>program, I took the liberty of porting a few features from my never 
>released Euphoria Editor (originally by David Cuny and Carl White) to Edita.

Bob: I welcome almost all requests and suggestions for improvements. 
Code which already works, which you supplied, even moreso. I have to 
admit I would probably never have thought it could be done without 
seeing your code.

I saw an opportunity to write bracket match code, so I chose to 
rewrite rather than modify, which I hope does not bother you too much.

I would appreciate comments (from you and and others on EUforum) re 
the following code. One thing which does not work is jumping to 
next(/prev) control structure when not on a cs word. I am hesitating, 
especially since I used the same keystroke for bracket matching, over 
whether it would be sensible anyway.

BTW: For those on EUforum not particularly familiar with Edita source,
I am assuming that globals filetext, currfile, CursorX, CursorY, 
wordChar, TokenChar, MapToByte(), paintCursorY(), 
forceCursorOnscreen(), and ExpLength(), are sufficiently self-evident.

global procedure ctrlBracket(integer direction)
--
-- process ctrl [ and ctrl ].
-- jump to matching [end] procedure/function/type/for/while;
-- cycle fwd/back through if/{elsif}/else/endif;
-- jump to matching [,], (,), {,}.
--
sequence oneline	-- scratch var
integer bX, 		-- CursorX of begin position, adjusted
		k, 
		ch, 
		bracketmatch, -- 0=go for if/while etc; else go for {} etc
		wordstart, wordend
sequence onword
sequence r			-- local copy of routines[currfile], speedwise
integer cS, 		-- scratch var
		chunkStart, -- 1..start of 1st routine-1, or:
		chunkEnd	-- start..end of current routine, or:
					-- end prev rtn+1.. start nxt rtn-1, or:
					-- end last rtn+1.. end of file.
integer len, 		-- length(oneline), speedwise
		level, 		-- stack pointer of saved stuff
		bracketTarget, 	-- want stuff at this level
		skipword, 	-- after "end"
		eWord		-- scratch (1=end, 2/3=elsif/else)
sequence oX,oY		-- *The Stack*: examples:
					-- '{' found line 2 col 7, - trashed, or used,
when we find '}', or:
					-- "if" found line 7 col 9; might be replaced by
an elsif/else;
					--  - trashed, or used, when we find the "end".

--	if isEu then	--DEV currently checks for "test2.exw"
--	if isEu and rtnList then
--trace(1)
		--
		-- First determine what we seek
		--
		oneline=filetext[currfile][CursorY+1]
		k=MapToByte(oneline,CursorX)
		if k then
			ch=oneline[k]
			bracketmatch=find(ch,"(){}[]")
		else
			k=length(oneline)+1
			bracketmatch=0
		end if		
		if not bracketmatch then
			-- process eg "else" on the e, l, s, or e, equally..
			while k>1 and wordChar[oneline[k-1]] = TokenChar do
				k-=1
			end while
		end if
		bX=k
		--
		-- Calculate the smallest area to scan
		-- 	 routines[currfile] contains {names,starts,ends},
		--	 eg {{"me","my"},{2,10},{8,18}}
		--
		r=routines[currfile]
		chunkStart=1
		chunkEnd=length(filetext[currfile])
		for i=1 to length(r[rtnNAMES]) do
			cS=r[rtnSTART][i]
			if cS>CursorY+1 then chunkEnd = cS-1 exit end if
			chunkStart=cS
			cS = r[rtnEND][i]
			if cS>=CursorY+1 then chunkEnd = cS exit end if
			chunkStart=cS+1
		end for
		--setText(Main,sprint({chunkStart,chunkEnd}))
		--
		-- And scan!
		--
		level=0
		bracketTarget=-1
		skipword=0
		oX=repeat(0,32)
		oY=repeat(0,32)
		for i=chunkStart to chunkEnd do
			oneline=filetext[currfile][i]
			len=length(oneline)
			k=1
			while k<=len do
				ch=oneline[k]
				if ch='-' and k<len and oneline[k+1]='-' then		--
skip comments
					exit
				elsif ch='\"' then
--- .. and strings
					while k<len do
						k+=1
						ch=oneline[k]
						if ch='\"' then exit end if
						if ch='\\' and k<len then k+=1 end if
					end while
				elsif bracketmatch then								--
count {} etc
					if find(ch,"({[") then
						level+=1
						if level>length(oX) then
							oX&=repeat(0,32)
							oY&=repeat(0,32)
						end if
						oX[level]=k oY[level]=i						--
remember open point
						if i=CursorY+1 and k=bX then
							bracketTarget=level						--
find close for this
						end if
					elsif find(ch,")}]") then
						if i=CursorY+1 and k=bX and level then		--
jump to saved open point
							paintCursorY()
							CursorY=oY[level]-1

CursorX=ExpLength(filetext[currfile][CursorY+1][1..oX[level]-1])
							forceCursorOnscreen()
							paintCursorY()
							return
						elsif level=bracketTarget then				--
we wanted this close point
							paintCursorY()
							CursorY=i-1
							CursorX=ExpLength(oneline[1..k-1])
							forceCursorOnscreen()
							paintCursorY()
							return
						end if
						level-=1
					end if
				elsif k<=length(oneline) and wordChar[oneline[k]] =
TokenChar then
					wordstart=k
					while k<length(oneline) and wordChar[oneline[k+1]]
= TokenChar do
						k+=1
					end while
					wordend=k
					if skipword then
						skipword=0
					else
						onword = oneline[wordstart..wordend]
						if
find(onword,{"if","for","while","procedure","function","type"}) then
							level+=1
							if level>length(oX) then
								oX&=repeat(0,32)
								oY&=repeat(0,32)
							end if
							oX[level]=wordstart oY[level]=i			--
remember cs start
							if i=CursorY+1 and wordstart=bX then
								bracketTarget=level					--
find close (or elsif/else) for this
							end if
						else
							eWord=find(onword,{"end","elsif","else"})
							if eWord then
								--
								-- This code is significantly
complicated by multiple
								-- elsif/else; basically if we are
hunting forward, it is 
								-- all rather easy: landing on the end
means goto start;
								-- except landing on an elsif triggers
"next".
								--  (where "landing" means finding
word at {cY,cX})
								-- OTOH, backward we must update last
jump-back point...
								--
								if i=CursorY+1 and wordstart=bX 	--
on current word
								and level>0							--
(sanity chk: structure found)
								and (direction=-1 or eWord=1) then	--
going back or at end
									paintCursorY()
									CursorY=oY[level]-1

CursorX=ExpLength(filetext[currfile][CursorY+1][1..oX[level]-1])
									forceCursorOnscreen()
									paintCursorY()
									return
								elsif level=bracketTarget			--
this level we want
								 and (eWord=1 -- "end"; goto start of
control strucure...
								   or (direction=1 -- fwd; *AND*
elsif/else *AFTER* start pos.
								   and
compare({CursorY+1,bX},{i,wordstart})=-1)) then
									paintCursorY()
									CursorY=i-1

CursorX=ExpLength(oneline[1..wordstart-1])
									forceCursorOnscreen()
									paintCursorY()
									return
								elsif eWord!=1 and direction=1 and
i=CursorY+1 and wordstart=bX then
									-- fwd, on elsif: trigger "next".
									-- (nb: this will happen on "else"
as well, no matter)
									bracketTarget=level
								end if
								if eWord=1 then
									skipword = 1
									level-=1
								elsif direction = -1 				--
jumping backward:
								and level>0 then					--
(sanity chk: structure found)
									-- keep track; replace "if" with
"elsif"/"else": 
									oX[level]=wordstart oY[level]=i
								end if
							end if
						end if
					end if
				end if
				k+=1
			end while
		end for
--	end if
end procedure


Of course, it'll be extra-unreadable because of pigging linewrap...

Otherwise, all comments welcome

Regards,
Pete

PS bracketTarget should be renamed...

new topic     » topic index » view thread      » older message » newer message

Search



Quick Links

User menu

Not signed in.

Misc Menu