Worklog for oofoe

bb-mode for emacs

Return to Worklogs

Aha! (Autocomplete works...)(Posted 2009-12-03)
OK. Now we are cooking with the gas. Through no great effort of my own (although it seemed painful at the time (see below)), I now have autocomplete working properly with all the defined Blitz 3D constants, keywords and functions -- without having to define them all twice.

Yes, OK, Visual Studio has, like, *had* this forever, and probably every other Blitz editor, but it's nice to get it working here. For me, it's almost magical to see the alternatives pop up when I start typing a word. Extra big thanks to Tomohiro Matsuyama for his autocomplete.el implementation.

Here's the latest mode. You'll also need to get autocomplete from http://github.com/m2ym/auto-complete if you want that to work.




The pain of autocomplete...(Posted 2009-12-03)
I'm trying to get autocomplete.el working with my bb-mode. The problem is that I don't want to have to specify all the keywords a second time to feed them to the autocompleter. I should be able to take a nice list of stuff from the bb-constants, bb-keywords and bb-functions and hand it over.

Unfortunately, there is (to me) serious macro magick that precludes this. I'm trying to replicate what ac-define-dictionary-source does, except without the big list of keywords.

So far, the results have been tantalizingly frustrating -- just the default of having it work inside the file is pretty darn cool -- I get these nice drop downs as I type. Unfortunately for now, it's only for stuff already in the file.

There has to be a way to deal with this. I'll read more about dealing with emacs macros in the morning.


Compiling and running...(Posted 2009-12-02)
Well, I think at this point I can start using Emacs for serious work in Blitz3d. I've gotten compilation working! And... Not just compile, but run and debug compiles (OK, ok, after getting compile, that part was easy...).

Emacs' compile command really wants to find a make file. You can do it other ways, but you have to set environment variables (for the blitzpath) and stuff like that, which is actually messier. So, here is an example Makefile, which goes in the same directory as the %.bb files.

export blitzpath := c:/programs/blitz3d

CC=c:/programs/blitz3d/bin/blitzcc 
CFLAGS=

all: fernando.exe

run: fernando.bb
	$(CC) $(CFLAGS) fernando.bb # Run mode.

debug: fernando.bb
	$(CC) $(CFLAGS) -d fernando.bb # Debug mode.

fernando.exe: fernando.bb
	$(CC) $(CFLAGS) -o fernando.exe fernando.bb # Make %.exe.

clean: rm fernando.exe


The most important part is at the top, which sets the blitzpath for the compiler. Aside from that, it's pretty much a standard Makefile, although I've added entries for debug and run (without creating an executable).

There doesn't seem to be a way to create an executable with the debugger embedded, so Emacs just waits until you're through debugging. The debugger is the standard Blitz debugger. There doesn't seem to be a way to get output from it for the Emacs debugging methods.

Once you've got the Makefile set up, you can compile with "Alt-X compile", then hit [enter]. Alternatively for run or debug, say "Alt-X compile", type "run" or "debug", then [enter]. Compilation errors are reported in the *compilation* buffer in Emacs. Unfortunately, because Windows allows spaces in filenames, the Blitz compiler has to report errors with quotes around the filename, which Emacs doesn't understand by default. You can still select an error and Emacs will prompt you for the correct filename (type it without the quotes) and then jump to the right line of source -- almost working!

Yes, this is clumsy (for now). I'm going to add shortcut keys (probably f5, S-f5 and C-f5) to launch this stuff and I will probably also need to add something that will build/update the Makefile for the unitiated. Emacs seems to have a built in make that should serve if you don't have cygwin installed, so I'm not worried about that.


A new beginnning!(Posted 2009-11-30)
Here's a new version of my Blitz 3D Emacs mode -- this time for GNU Emacs 22.2.1 (might work with Xemacs, but you'll probably have to make changes).

New features:
* C-c C-f shows online help (don't forget to set your bb-blitzpath at the top of the file, or in your .emacs).
* Better and more consistent highlighting (more a function of emacs than anything I did).

Missing features:
* No more automatic indentation (but it was buggy, anyway).
* Doesn't change word case like the Blitz IDE does.

;; bb-mode.el
;; jrlf 2009-11-29
;; Blitz3D mode -- version 2.0.0.

;; References: http://xahlee.org/emacs/elisp_syntax_coloring.html


(defvar bb-blitzpath "c:/programs/Blitz3D")

(defun bb-comment-dwim (arg)
  "Comment or uncomment current line or region."
  (interactive "*P")
  (require 'newcomment)
  (let ((deactivate-mark nil)
	(comment-start ";")
	(comment-end ""))
    (comment-dwim arg))
)


(defun bb-help-browse (path)
  "( path --) Launch browser to view help file."

  (browse-url (browse-url-file-url path)))

(defun bb-help-function ()
  "( --) Find and display function help."
  (interactive)
  (let* ((bounds (bounds-of-thing-at-point 'word))
	 (keyword (buffer-substring (car bounds) (cdr bounds)))
	 (h2d (format "%s/help/commands/2d_commands/%s.htm" 
		      bb-blitzpath keyword))
	 (h3d (format "%s/help/commands/3d_commands/%s.htm" 
		      bb-blitzpath keyword))
	 )
    (message h2d)
    (if (file-exists-p h2d) (bb-help-browse h2d)
      (if (file-exists-p h3d) (bb-help-browse h3d)
	(message "No help found for %s..." keyword)))
    )
  )

(defvar bb-constants
  '("True" "False" "Pi") "Blitz 3D Constants")

(defvar bb-keywords
  '("Abs" "After" "And" "Before" "Case" "Const" "Data" "Default" "Delete"
    "Dim" "Each" "Else" "ElseIf" "EndIf" "Exit" "Field" "First"
    "Float" "For" "Forever" "Function" "Global" "Gosub" "Goto" "Handle"
    "If" "Include" "Insert" "Int" "Last" "Local" "Mod" "New" "Next" "Not"
    "Null" "Object" "Or" "Read" "Repeat" "Restore" "Return" "Sar"
    "Select" "Sgn" "Shl" "Shr" "Step" "Str" "Then" "To" "Type"
    "Until" "Wend" "While" "Xor")
  "Blitz 3D Keywords")

(defvar bb-functions
  '("DebugLog" "FreeTimer" "WaitTimer" "CreateTimer" "SetEnv" "GetEnv"
    "SystemProperty" "CommandLine" "MilliSecs" "Delay" "ExecFile"
    "RuntimeError" "AppTitle" "Stop" "End" "RuntimeStats" "EntityClass"
    "EntityName" "NameEntity" "FreeEntity" "ShowEntity" "HideEntity"
    "EntityOrder" "EntityAutoFade" "EntityFX" "EntityBlend"
    "EntityTexture" "EntityShininess" "EntityAlpha" "EntityColor"
    "PaintEntity" "FindChild" "GetChild" "CountChildren" "EntityParent"
    "Animating" "AnimLength" "AnimTime" "AnimSeq" "ExtractAnimSeq"
    "AddAnimSeq" "SetAnimKey" "Animate" "SetAnimTime" "AlignToVector"
    "PointEntity" "RotateEntity" "ScaleEntity" "PositionEntity"
    "TranslateEntity" "TurnEntity" "MoveEntity" "CollisionTriangle"
    "CollisionSurface" "CollisionEntity" "CollisionTime" "CollisionNZ"
    "CollisionNY" "CollisionNX" "CollisionZ" "CollisionY" "CollisionX"
    "CountCollisions" "EntityCollided" "EntityDistance" "EntityBox"
    "EntityRadius" "GetEntityType" "GetParent" "EntityPickMode"
    "EntityType" "ResetEntity" "DeltaYaw" "DeltaPitch" "VectorPitch"
    "VectorYaw" "TFormedZ" "TFormedY" "TFormedX" "TFormNormal"
    "TFormVector" "TFormPoint" "GetMatElement" "EntityRoll" "EntityYaw"
    "EntityPitch" "EntityZ" "EntityY" "EntityX" "CopyEntity" "EmitSound"
    "CreateListener" "ModifyTerrain" "TerrainHeight" "TerrainSize"
    "TerrainZ" "TerrainY" "TerrainX" "TerrainShading" "TerrainDetail"
    "LoadTerrain" "CreateTerrain" "CreatePlane" "CreateMirror"
    "BSPAmbientLight" "BSPLighting" "LoadBSP" "MD2Animating"
    "MD2AnimLength" "MD2AnimTime" "AnimateMD2" "LoadMD2" "SpriteViewMode"
    "HandleSprite" "ScaleSprite" "RotateSprite" "LoadSprite"
    "CreateSprite" "CreatePivot" "LightConeAngles" "LightRange"
    "LightColor" "CreateLight" "PickedTriangle" "PickedSurface"
    "PickedEntity" "PickedTime" "PickedNZ" "PickedNY" "PickedNX" "PickedZ"
    "PickedY" "PickedX" "CameraPick" "LinePick" "EntityPick"
    "EntityVisible" "EntityInView" "ProjectedZ" "ProjectedY" "ProjectedX"
    "CameraProject" "CameraFogMode" "CameraFogRange" "CameraFogColor"
    "CameraViewport" "CameraProjMode" "CameraClsMode" "CameraClsColor"
    "CameraRange" "CameraZoom" "CreateCamera" "TriangleVertex" "VertexW"
    "VertexV" "VertexU" "VertexAlpha" "VertexBlue" "VertexGreen"
    "VertexRed" "VertexNZ" "VertexNY" "VertexNX" "VertexZ" "VertexY"
    "VertexX" "CountTriangles" "CountVertices" "VertexTexCoords"
    "VertexColor" "VertexNormal" "VertexCoords" "AddTriangle" "AddVertex"
    "PaintSurface" "ClearSurface" "FindSurface" "GetEntityBrush"
    "GetSurfaceBrush" "CreateSurface" "GetSurface" "CountSurfaces"
    "MeshesIntersect" "MeshDepth" "MeshHeight" "MeshWidth" "LightMesh"
    "UpdateNormals" "AddMesh" "PaintMesh" "FlipMesh" "FitMesh"
    "PositionMesh" "RotateMesh" "ScaleMesh" "CopyMesh" "CreateCone"
    "CreateCylinder" "CreateSphere" "CreateCube" "CreateMesh"
    "LoadAnimSeq" "LoadAnimMesh" "LoadMesh" "BrushFX" "BrushBlend"
    "GetBrushTexture" "BrushTexture" "BrushShininess" "BrushAlpha"
    "BrushColor" "FreeBrush" "LoadBrush" "CreateBrush" "TextureFilter"
    "ClearTextureFilters" "TextureBuffer" "SetCubeMode" "SetCubeFace"
    "TextureName" "TextureHeight" "TextureWidth" "PositionTexture"
    "RotateTexture" "ScaleTexture" "TextureCoords" "TextureBlend"
    "FreeTexture" "LoadAnimTexture" "LoadTexture" "CreateTexture"
    "Stats3D" "TrisRendered" "ActiveTextures" "ClearWorld" "RenderWorld"
    "CaptureWorld" "UpdateWorld" "Collisions" "ClearCollisions"
    "AmbientLight" "WireFrame" "AntiAlias" "Dither" "WBuffer"
    "GfxDriverCaps3D" "HWTexUnits" "HWMultiTex" "LoaderMatrix"
    "NetMsgData" "NetMsgTo" "NetMsgFrom" "NetMsgType" "RecvNetMsg"
    "SendNetMsg" "NetPlayerLocal" "NetPlayerName" "DeleteNetPlayer"
    "CreateNetPlayer" "StopNetGame" "JoinNetGame" "HostNetGame"
    "StartNetGame" "Load3DSound" "ChannelPlaying" "ChannelPan"
    "ChannelVolume" "ChannelPitch" "ResumeChannel" "PauseChannel"
    "StopChannel" "PlayCDTrack" "PlayMusic" "PlaySound" "SoundPan"
    "SoundVolume" "SoundPitch" "LoopSound" "FreeSound" "LoadSound"
    "DirectInputEnabled" "EnableDirectInput" "FlushJoy" "JoyVDir"
    "JoyUDir" "JoyZDir" "JoyYDir" "JoyXDir" "JoyHat" "JoyRoll" "JoyYaw"
    "JoyPitch" "JoyV" "JoyU" "JoyZ" "JoyY" "JoyX" "JoyWait" "WaitJoy"
    "GetJoy" "JoyHit" "JoyDown" "JoyType" "MoveMouse" "FlushMouse"
    "MouseZSpeed" "MouseYSpeed" "MouseXSpeed" "MouseZ" "MouseY" "MouseX"
    "MouseWait" "WaitMouse" "GetMouse" "MouseHit" "MouseDown" "FlushKeys"
    "WaitKey" "GetKey" "KeyHit" "KeyDown" "HidePointer" "ShowPointer"
    "Locate" "Input" "Print" "Write" "ImageRectCollide" "ImageRectOverlap"
    "RectsOverlap" "ImagesCollide" "ImagesOverlap" "TFormFilter"
    "TFormImage" "RotateImage" "ResizeImage" "ScaleImage" "ImageYHandle"
    "ImageXHandle" "ImageHeight" "ImageWidth" "AutoMidHandle" "MidHandle"
    "HandleImage" "MaskImage" "DrawBlockRect" "DrawImageRect" "TileBlock"
    "TileImage" "DrawBlock" "DrawImage" "ImageBuffer" "GrabImage"
    "SaveImage" "FreeImage" "LoadAnimImage" "CreateImage" "CopyImage"
    "LoadImage" "CloseMovie" "MoviePlaying" "MovieHeight" "MovieWidth"
    "DrawMovie" "OpenMovie" "StringHeight" "StringWidth" "FontHeight"
    "FontWidth" "FreeFont" "LoadFont" "CopyRect" "Text" "Line" "Oval"
    "Rect" "Plot" "Cls" "SetFont" "ClsColor" "ColorBlue" "ColorGreen"
    "ColorRed" "GetColor" "Color" "Viewport" "Origin" "CopyPixelFast"
    "CopyPixel" "WritePixelFast" "ReadPixelFast" "WritePixel" "ReadPixel"
    "UnlockBuffer" "LockBuffer" "SaveBuffer" "LoadBuffer" "GraphicsBuffer"
    "SetBuffer" "GraphicsDepth" "GraphicsHeight" "GraphicsWidth" "Flip"
    "VWait" "ScanLine" "BackBuffer" "FrontBuffer" "GammaBlue" "GammaGreen"
    "GammaRed" "UpdateGamma" "SetGamma" "EndGraphics" "Graphics3D"
    "Graphics" "Windowed3D" "GfxMode3D" "GfxMode3DExists"
    "CountGfxModes3D" "GfxDriver3D" "TotalVidMem" "AvailVidMem"
    "GfxModeDepth" "GfxModeHeight" "GfxModeWidth" "GfxModeExists"
    "CountGfxModes" "SetGfxDriver" "GfxDriverName" "CountGfxDrivers"
    "CallDLL" "WriteBytes" "ReadBytes" "PokeFloat" "PokeInt" "PokeShort"
    "PokeByte" "PeekFloat" "PeekInt" "PeekShort" "PeekByte" "CopyBank"
    "ResizeBank" "BankSize" "FreeBank" "CreateBank" "DeleteFile"
    "CopyFile" "FileType" "FileSize" "DeleteDir" "CreateDir" "ChangeDir"
    "CurrentDir" "NextFile" "CloseDir" "ReadDir" "SeekFile" "FilePos"
    "CloseFile" "WriteFile" "ReadFile" "OpenFile" "TCPTimeouts"
    "TCPStreamPort" "TCPStreamIP" "AcceptTCPStream" "CloseTCPServer"
    "CreateTCPServer" "CloseTCPStream" "OpenTCPStream" "UDPTimeouts"
    "UDPMsgPort" "UDPMsgIP" "UDPStreamPort" "UDPStreamIP" "RecvUDPMsg"
    "SendUDPMsg" "CloseUDPStream" "CreateUDPStream" "HostIP"
    "CountHostIPs" "DottedIP" "CopyStream" "WriteLine" "WriteString"
    "WriteFloat" "WriteInt" "WriteShort" "WriteByte" "ReadLine"
    "ReadString" "ReadFloat" "ReadInt" "ReadShort" "ReadByte" "ReadAvail"
    "Eof" "CurrentTime" "CurrentDate" "Bin" "Hex" "Len" "Asc" "Chr" "RSet"
    "LSet" "Trim" "Lower" "Upper" "Mid" "Instr" "Replace" "Right" "Left"
    "String" "RndSeed" "SeedRnd" "Rand" "Rnd" "Log10" "Log" "Exp" "Ceil"
    "Floor" "Sqr" "ATan2" "ATan" "ACos" "ASin" "Tan" "Cos" "Sin"
    "HasFocus")
  "Blitz 3D Functions")

(defvar bb-constants-re (regexp-opt bb-constants 'words))
(defvar bb-keywords-re  (regexp-opt bb-keywords 'words))
(defvar bb-functions-re (regexp-opt bb-functions 'words))

(setq bb-font-lock-keywords
      (list
	(cons bb-functions-re 'font-lock-function-name-face)
	(cons bb-keywords-re  'font-lock-keyword-face)
	(cons bb-constants-re 'font-lock-constant-face)
        )
      )

(define-derived-mode bb-mode fundamental-mode
  "Blitz 3D mode"
  "Major mode for editing Blitz Basic 3D code."

  ;; Syntax highlighting.
  (setq font-lock-defaults '(bb-font-lock-keywords))

  ;; Modify keymap.
  (define-key bb-mode-map [remap comment-dwim] 'bb-comment-dwim)
  (define-key bb-mode-map "\C-c\C-f" 'bb-help-function)

  ;; Comment: ";".
  (modify-syntax-entry ?\; "< b" bb-mode-syntax-table)
  (modify-syntax-entry ?\n "> b" bb-mode-syntax-table)
)

(provide 'bb-mode)



A beginning...(Posted 2006-12-28)
This is probably a bit strange, but emacs is my editor, and I'm sticking to it... ;-) This is a first stab at a Blitz3D mode for Windows Xemacs.

You will want to add a file association as well.

(setq load-path (cons "~/.xemacs" load-path))
(require 'b3d-mode)
(setq auto-mode-alist (cons '("\\.bb\\'" . b3d-mode) auto-mode-alist))


(I'm assuming that you put the file into your ~/.xemacs directory.)