How to change the auto completion button in squeak? - smalltalk

is there a way to change the shortcut to invoke auto completion in the squeak vm (standard is tab)?
Thanks in advance

(I assume you use OCompletion or ECompletion)
The only way to change this currently is to change the code.
OController>>handleKeystrokeBefore: kbEvent editor: theEditor
"I return a boolean. true when I have handled the event and no futher processing is needed by the caller."
| keyValue ctrl cmd down tab colon alphanum del esc enter up |
self editor: theEditor.
self setModel: theEditor model.
keyValue := kbEvent keyValue.
ctrl := kbEvent controlKeyPressed.
cmd := kbEvent commandKeyPressed.
down := keyValue = 31.
up := keyValue = 30.
tab := kbEvent keyCharacter = Character tab. "<-- change this to your desired key"
enter := kbEvent keyCharacter = Character cr.
colon := kbEvent keyCharacter = $:.
alphanum := kbEvent keyCharacter isAlphaNumeric.
"..."
Or, when you only use ECompletion
ECController>>handleKeystrokeBefore: aKeyboardEvent editor: anEditor
"I return a boolean. true when I have handled the event and no futher processing is needed by the caller."
| theEditor keyValue controlKeyPressed isSpaceKey |
self editor: anEditor.
theEditor := self editor.
self setModel: theEditor model.
keyValue := aKeyboardEvent keyValue.
controlKeyPressed := aKeyboardEvent controlKeyPressed.
isSpaceKey := #(0 32 ) includes: keyValue.
"Ctrl-Space or Tab for open"
self isMenuOpen
ifFalse: [(isSpaceKey & controlKeyPressed
or: [keyValue = 9 " <-- change this to your desired key"
and: [theEditor isCaretBehindChar
and: [controlKeyPressed not]]])
"..."

Related

Why I cannot find window?

I use this example to send a string between two applications.
When I press the Send button for the first time, the string is sent to the Receiver, but only a part of the string is received.
When I press the Send button for the second time, I get "Window not found!".
The window is right there on screen. Why it works when I press the button the first time, but not the second time?
This is the sender:
procedure TfrmSender.SendString;
var
stringToSend : string;
copyDataStruct : TCopyDataStruct;
begin
Caption:= 'Sending';
stringToSend := 'About - Delphi - Programming';
copyDataStruct.dwData := 12821676; //use it to identify the message contents
copyDataStruct.cbData := 1 + Length(stringToSend) ;
copyDataStruct.lpData := PChar(stringToSend);
SendData(copyDataStruct) ;
end;
procedure TfrmSender.SendData(CONST copyDataStruct: TCopyDataStruct);
VAR
receiverHandle : THandle;
res : integer;
begin
receiverHandle := FindWindow(PChar('TfrmReceiver'), PChar('frmReceiver')) ;
if receiverHandle = 0 then
begin
Caption:= 'Receiver window NOT found!';
EXIT;
end;
res:= SendMessage(receiverHandle, WM_COPYDATA, Integer(Handle), Integer(#copyDataStruct));
if res= 0 then Caption:= 'Receiver window found but msg not hand';
end;
And this is the receiver:
procedure TfrmReceiver.WMCopyData(var Msg: TWMCopyData);
VAR
s : string;
begin
if Msg.CopyDataStruct.dwData = 12821676 then
begin
s := PChar(Msg.CopyDataStruct.lpData);
msg.Result := 2006; //Send something back
Winapi.Windows.Beep(800, 300);
Caption:= s;
end
end;
To summarize the comments there are two errors
1) (See #Tom Brunberg) is that the length is set incorrectly which is why you only get part (about half? of the string)
It should be
copyDataStruct.cbData := sizeof( Char )*(Length(stringToSend) + 1 );
2) The forms caption is being changed which invalidates the expression
FindWindow(PChar('TfrmReceiver'), PChar('frmReceiver'))
because the second parameter is the form's caption (in Delphi terminology)

How to add access key to button in Inno Setup

I want to add Alt functions to my audio button;
Alt+M for Mute and Alt+P for Play
Like this
How? What code should be entered? Where will I insert the code? Here's my script:
SoundCtrlButton := TNewButton.Create(WizardForm);
SoundCtrlButton.Parent := WizardForm;
SoundCtrlButton.Left := 8;
SoundCtrlButton.Top := WizardForm.ClientHeight -
SoundCtrlButton.Height - 8;
SoundCtrlButton.Width := 40;
SoundCtrlButton.Caption :=
ExpandConstant('{cm:SoundCtrlButtonCaptionSoundOff}');
SoundCtrlButton.OnClick := #SoundCtrlButtonClick;
In Windows controls, you just prefix a letter in control caption with & to mark is as an access key.
See https://learn.microsoft.com/en-us/cpp/windows/defining-mnemonics-access-keys#mnemonics-access-keys
SoundCtrlButton.Caption := '&Mute';
Or in your case, indirectly via a custom message:
[CustomMessages]
SoundCtrlButtonCaptionSoundOff=&Mute
See how the standard button captions are defined in Default.isl:
ButtonBack=< &Back
ButtonNext=&Next >
ButtonInstall=&Install

Creating a Caesar Cipher Method

So I need to get the Caesar Cipher code in smalltalk and create a method and use it so I can do the following test on it
|aString|
aString:=Caesar new encrypt: 'CAESAR'.
Transcript show: aString.
I already have the class made. But I need to make the method of it.
I found this but how can I make a method out of this so I can all the above code in playground.
| i c strCipherText strText iShiftValue iShift |
strText := 'the quick brown fox jumps over the lazy dog'.
iShiftValue := 3.
strCipherText := ''.
iShift := iShiftValue \\ 26.
i := 1.
[ i <= (strText size) ]
whileTrue: [
c := (strText at: i) asUppercase.
( ( c >= $A) & ( c <= $Z ) )
ifTrue: [
((c asciiValue) + iShift > $Z asciiValue)
ifTrue: [
strCipherText := strCipherText, (((c asciiValue) + iShift - 26)
asCharacter asString).
]
ifFalse: [
strCipherText := strCipherText, (((c asciiValue) + iShift)
asCharacter asString).
].
]
ifFalse: [
strCipherText := strCipherText, ' '.
].
i := i + 1.
].
Transcript show: strCipherText.
Transcript cr.
So to make thing clear, I need to make a method using the Caesar Cipher code and use the "aString" code at the beginning and test it with that. I have this code above but this has already text in it and can't be put into the method.
Any help will be appreciated.
As Max said in his comment the code above can be put in a method. The only missing part is a first line with the selector and the formal argument:
caesarCipherOf: strText
<insert the code here>
Another good suggestion by Max is to call the argument aString rather than strText because that's more aligned with how Smalltalkers name things.
But now let's take a look at the source code itself:
The comparison c >= $A & (c <= $Z) means c isLetter.
The conditional calculation of the next character means that we want to shift-rotate c by moving it 3 characters to the right, wrapping it around if it gets beyond $Z. This can be easily expressed as:
(c codePoint - 64 + 3 \\ 26 + 64) asCharacter
where 64 = $A codePoint - 1, is the offset between $A and any given uppercase character c. Note also that I've replaced asciiValue with codePoint.
With these two observations the method can be re-written as
caesarCipherOf: aString
^aString collect: [:c |
c isLetter
ifTrue: [(c asUppercase codePoint - 64 + 3 \\ 26 + 64) asCharacter]
ifFalse: [$ ]]
This is not only shorter, it is more efficient because it avoids creating two new instances of String at every character. Specifically, any expression of the form
string := string , <character> asString
creates two Strings: one as the result of sending #asString, another as the result of sending the concatenation message #,. Instead, #collect: creates only one instance, the one that the method returns.

How to concatenate a string in a do block?

I'm trying to go though a array and add characters from that array to another object. The problem is I keep getting a error "Instances of character are not indexable". However when I run tag := tag,char outside of the do block then it works.
|data startTag tag|.
data := '123456778'
startTag := false.
tag := ''.
data asArray do: [:char |
tag := tag,char]
The , is defined as
Collection>>, aCollection
^self copy addAll: aCollection; yourself
so that tries to operate on your single character as if it were a collection. That explains the error.
For larger collections you do not want to build up using , because of the copy that happens each time. Therefore use the streaming protocol:
|data tag|
data := '123456778'.
tag := String streamContents: [:s |
data do: [ :char |
s nextPut: char]]
Also take a look at Collection>>do:separatedBy: to add separators between your data.
[edit] Ah, ok, that's something like
|data tag tags state|
data := '<html>bla 12 <h1/></html>'.
state := #outside.
tags := OrderedCollection new.
tag := ''.
data do: [ :char |
state = #outside ifTrue: [
char = $< ifTrue: [
state := #inside.
tag := '' ]]
ifFalse: [
char = $> ifTrue: [
state := #outside.
tags add: tag]
ifFalse: [ tag := tag, (char asString)]]].
tags
"an OrderedCollection('html' 'h1/' '/html')"

How to reverse a unicode string using AutoHotKey and paste it?

I have this reverse function which works in english,
However it doesn't work with hebrew,
Reverse(string)
{
length := StrLen(string)
Loop, parse, string
{
loc := Abs(A_Index - length) + 1
revloc%loc% := A_LoopField
}
Loop %length%
final .= revloc%A_index%
return final
}
ReverseByAddress(address,len){
Loop % (len){
out.=Chr(NumGet(address+0,len-A_index,"Char"))
}
Return out
}
^m::
;ClipSaved := ClipboardAll
;text.="new line of some text`n"
text= %Clipboard%
clipboard := Reverse(text)
send, ^v
Any help with making this work with Unicode will be appreciated.
This has been solved without saving the data back to the clipboard:
^,::
text= %Clipboard%
newText := Reverse(text)
send, %newText%
Can you get this kind of schedule, at 2 or 3 characters?
2 character ex. -AutoHotKey -> uAotoHKtYe
................................uA ot oH Kt Ye
or
3 character ex. -AutoHotKey -> tuAoHoeKty
......tuA oHo eKt y