# How do I create abbreviations and syntax shortcuts?



## argitoth (Jun 24, 2013)

continued from here: http://www.vi-control.net/forum/viewtop ... 13#3711613

Is it possible to write:
variable -> hide := bg 
and get:
hide_part(variable,HIDE_PART_BG)

Ok this is possible Edit:if you declare BG as HIDE_PART_BG, but can you create your own versions of these things in Kscript using macros, functions, properties, or something I don't know about?

Also, you could throw in some "best practice" advice as well.

Edit: Oh, here's a good example that doesn't work
variable -> message


----------



## Big Bob (Jun 24, 2013)

The KSE provides built-in syntax sugar for all the control parameter functions and an abbreviated form for most if not all of the control parameters themselves.
Usually the abbreviation for things like CONTROL_PAR_XXX is just the last word or two in lower case xxx. For example, you can replace CONTROL_PAR_VALUE with 'value'. CONTROL_PAR_TEXT_ALIGNMENT with 'text_alignmen't, CONTROL_PAR_DEFAULT_VALUE with either 'default_value' or just 'default' , etc.

So, you can replace:

set_control_par(id,CONTROL_PAR_VALUE,250)

v1 := get_control_par(id,CONTROL_PAR_VALUE)

with the more compact:

id -> value := 250 

v1 := id -> value

respectively.

Moreover, the KSE is intelligent enough so that if you supply the control id, it will use it directly whereas if you instead use the 'name' of the control, the KSE will wrap it in get_ui_id automatically. For example:

if we have the following code in the ICB.


```
declare ui_slider Foo (0,1000000)
  declare foo_id
  foo_id := get_ui_id(Foo)
  declare v1
```

and, we write the following:


```
foo_id -> value := 1000
Foo -> value := 1500
```

these will compile as:


```
set_control_par($foo_id,$CONTROL_PAR_VALUE,1000)
set_control_par(get_ui_id($Foo),$CONTROL_PAR_VALUE,1500)
```

The KSE is also intelligent enough use set_control_par_str when appropriate. For example, if we write:


```
Foo -> picture := "ABC"
```

It will compile:

```
set_control_par_str(get_ui_id(Foo),CONTROL_PAR_PICTURE,"ABC")
```

For the engine parameters, most serious scripters use properties and or macro-generated properties to simplify the syntax. Generally, you will want to create your own set of custom generators and put them all together in an import module so you can easily make them available for all your applications, as MK already mentioned in your other thread. I'm sure if you ask Mario nicely, he will probably be glad to give you a link to one of his ep import modules for you to study. :wink: 

Rejoice,

Bob


----------



## mk282 (Jun 25, 2013)

I already provided him with the whole KSP file he needs to include to use all the neat syntax enhancements.

By the way - FORGET ABOUT hide_part() command! Just use $CONTROL_PAR_HIDE, which in turn ends up as:


```
<control name> -> hide := 16
```

The hide parameter uses a 4-bit mask to decide which part of the control is going to be hidden, so instead of using $HIDE_PART_BG, $HIDE_WHOLE_CONTROL, etc., you can just use a number directly! Bits are:


```
0 0 0 0
| | | |
| | | |> background
| | |> title
| |> value
|> light
```

Which, translated to decimal system, ends up like this:

0 = None (shows control)
1 = Background
2 = Title
3 = Background, Title
4 = Value
5 = Background, Value
6 = Title, Value
7 = Background, Title, Value
8 = Light
9 = Background, Light
10 = Title, Light
11 = Background, Title, Light
12 = Value, Light
13 = Background, Value, Light
14 = Title, Value, Light
15 = Background, Title, Value, Light
16 = All (hide whole control)


----------



## argitoth (Jun 25, 2013)

mk282 @ Tue Jun 25 said:


> I already provided him with the whole KSP file he needs to include to use all the neat syntax enhancements.


You are right, you did provide that, thanks. The _only_ problem is that compiling takes a "hella" long time. Since I'm still new to scripting, I need to constantly compile and check to see if what I did is working or not, so I just can't afford to "import Parameters.ksp" 

mk282, was your last post concerning Parameters.ksp or is that also built-in to Kscript?

Anyway, I created this thread to learn if I might create my own syntax shortcuts so that I don't need Parameters.ksp, but if Parameters.ksp has all the examples I need, I can look at that to learn more. Cool, thanks!


----------



## mk282 (Jun 26, 2013)

You mean about bit-mask? That's internal to Kontakt, so nothing specific to KScript - Kontakt simply has all those constants as numbers internally.

And yes, using the parameters.ksp include does make the script longer to parse and compile. I don't care about that, because the code is a lot more readable.


----------



## argitoth (Jun 26, 2013)

Just want to share how I used Kscript properties, and I figured it out without asking for help. :o Here's the code, which needs some explanation (below)

 
_{Kscript Editor 1.5.2}_ 

_{this goes inside a macro for declaring knobs}_
``*property* #*family*#.#name#.K.color
````*function* get() -> result
``````result := #KColor#
````*end* *function*
````*function* set(color)
``````#*family*#.#name#.K -> picture := "knob_" & #*family*#.#name#.K.type & "_" & color
````*end* *function*
``*end property*```

_{this goes inside an "on ui_control" macro }
{if alt = 0}_
#*family*#.#name#.K.color := "blue"``
_{else}_
#*family*#.#name#.K.color := "red"``



Let's say we're dealing with a knob that controls a filter's frequency.

family = filter (does not have anything with family declarations)
name = frequency
K is an abbreviation for knob

Edit: So the reason I put the property in a macro is so that when I create a knob, it also creates a property to go with that knob called filter.frequency.K.color for example

The code basically says
When I write Filter.Frequency.K.color := red, set the knob picture to "knob_" & knob-type-goes-here (bipolar or unipolar) & "_red" or in other words "knob_uni_red"

#Kcolor# is the color I set initially when calling the macro.
#family#.#name#.K.type is where I put if the knob is bipolar or unipolar.

I think the get portion of this property is useless to me in this situation... ok you can actually remove it...

The point of all this:
When the user holds ALT, set the knob to color red. I don't need to reiterate if the knob picture is bipolar or unipolar nor reiterate if the knob is a knob and not a button or a slider picture.
AND when the user holds ALT, apply the knob's parameters to all groups.

So, with the use of ALT it allows the user to either set the filter frequency for this group, that group, or all groups at once. By turning red or blue the user visually knows what is going on. And of course, I have a menu that is used to select the group being edited (color of knob stays red until you readjust it without holding ALT).


----------



## argitoth (Jun 27, 2013)

I was going to create another thread for this but figured this topic is kinda related.

Has anyone released to the public some scripts that turn numbers into midi notes and midi notes into numbers for things like user-input midi names and displaying midi note names for various things?

Or are there any easy scripting tips you can tell me to get a midi note to midi name and vice versa stuff going?


----------



## Big Bob (Jun 27, 2013)

By MIDI note and MIDI Name I presume you are referring to MIDI note number and Scale-tone octave?

such as: 60 -> C3

Are you aware of the following value-edit form?

*on init*
``*declare* ui_value_edit NOTE (0,127,VALUE_EDIT_MODE_NOTE_NAMES)
*end* on

Besides the up/down arrow control of the value edit, you can also double-click and then enter the note in either format. ie you can type in 60 or C3 and then hit Enter to set a new value. Internally, the value edit will of course assume the value 60. 

Of course the conversion can also be scripted in several different ways. 

Rejoice,

Bob


----------



## argitoth (Jun 27, 2013)

Yes *BigBob* that's exactly what I needed.

What about setting a label to display the last hit note in name form? Would that be some if statements and some math? label text = note_name + "128 / 12"

if EVENT_NOTE is some number
note_name = "C"
if EVENT_NOTE is some number
note_name = "D"

and so forth?


----------



## Big Bob (Jun 27, 2013)

You could create a function like this:

*on init*
``*declare* !Scale[12]
````Scale[0] := 'C'
````Scale[1] := 'C#'
````Scale[2] := 'D'
````````_{ etc .. }_
````Scale[11] := 'B' 
``*declare* ui_label ShowNote (1,1) 
*end* on


*function* midi_to_name(N) -> result
``result := Scale[N mod 12] & (N/12 - 2)
*end* *function*

*on note*
``set_text(ShowNote,midi_to_name(EVENT_NOTE))
*end* on


Rejoice,

Bob


----------



## argitoth (Jun 27, 2013)

Thank you *Big Bob*, now for an abstract question...

If I spend hours reformatting code, cleaning code, combining multiple macros into one, replacing code with syntax shortcuts... am I overly obsessed with code cleanliness or will this ultimately save me hours in the future by being a better coder? :o

For example I combined 4 hairy macros into one, so that instead of having 4 different "set knob" macros (for handing "on ui control"), I just have one. I had to, however, make a lot of logic statements so that the macro knows what kind of knob it's dealing with and if it's "bypassed" or not.

``_{SET KNOB edit: features added and slightly more compact}_
*macro* set_knob(#group#,#slot#,#generic#, #parameter#, #*family*#,#name#)
``*on ui_control*(#*family*#.#name#.K)
````#*family*#.#name#.K.state[art.sel.M] := #*family*#.#name#.K
````set_engine_par(#parameter#, #*family*#.#name#.K, #group#,#slot#,#generic#)
````#*family*#.#name#.L -> text := get_engine_par_disp(#parameter#,#group#,#slot#,#generic#)
````message("#name#: " & #*family*#.#name#.K)
````*if* #*family*#.#name#.K -> KEY_ALT = 0 *and* #*family*#.#name#.K.scope = no
``````#*family*#.#name#.K.color := "blue"
``````message(group_name(art.sel.M) & " #name#: " & #*family*#.#name#.K)
``````exit
````*else* *if* #*family*#.#name#.K -> KEY_ALT = 1 *or* #*family*#.#name#.K.scope = gr
``````*for* i := 0 *to* GROUPS-1
````````#*family*#.#name#.K.state_ := #*family*#.#name#.K
``````*end* *for*
``````#*family*#.#name#.K.color := "red"
``````set_engine_par_all_groups(#parameter#, #*family*#.#name#.K, #slot#,#generic#)
``````message("#name#: " & #*family*#.#name#.K)
````*else* *if* #*family*#.#name#.K.bypass = yes *and* #*family*#.bypass.B = on
``````set_engine_par(#parameter#, get_control_par(#*family*#.#name#.K, DEFAULT), #group#,#slot#,#generic#)
````*end* *if*
``*end* on
*end* *macro*__

Edit: And of course the goal here was to avoid repeating the logic statements and code within the macro as well._


----------



## mk282 (Jun 28, 2013)

You are overly obsessed with code cleanliness. I'll tell you that straight away. :D


----------



## Big Bob (Jun 28, 2013)

Well, perhaps accusing you of being obsessed with code cleanliness is a bit harsh so, I'll try to take a more moderate position (since I also tend to be a minimalist when it comes to writing code).

There are a couple of factors involved that have to be considered. I think that when first coming up to speed with a language/application, spending a lot of time on learning techniques for minimizing code and/or just making it more elegant has its place. Moreover, every pass through the code that results in more minimalization can be beneficial to you for future applications. But, beyond some point, one *can* become obsessed with this process to the extent that it can greatly reduce your productivity.

The opposite extreme is a programmer who becomes obsessed with banging out usable code as fast as possible. That type of person often dispenses with things like writing useful comments and doesn't usually worry too much about how inefficient his code might be as long as it does the job. Poor structure, poorly chosen names, and lack of helpful comments generally results in code that is very hard to maintain over any period of time. Fortunately, most modern languages force a certain amount of structure on us or otherwise, this type of programmer would also generate a lot of spaghetti code with go-to's all over the place.

Fortunately, there is a happy median and I think one should strive to achieve it. Personally, I tend to more heavily comment my code than most but, that's partly because my memory isn't too good any more and I know that if I need to modify my code a few months from now, I will benefit greatly from some well thought out comments. As to code minimalization and elegance, I strive to achieve that without spending too much time per project. I think most of the time spent in pursuit of minimized code should be when first learning a language. After that, one should always be on the lookout for better ways to do things but, only as a sideline effort. And, not in such a way so as to slow your output materially.

Of course, if you are coding merely for fun like me, then you can afford to take all the time you want on making your code pretty as long you don't have a whole bunch of things you want to accomplish. On the other hand, if you are coding for pay, your employer is going to expect a reasonable amount of output volume as well as bug-free and efficient code. So, one has to try to strike a balance.

So, while you may appear to be a little obsessed with code cleanliness, I think you are also to be commended for trying to do it right instead of just banging out code wholesale. But remember, moderation is the key to almost everything in life.

Rejoice,

Bob


----------



## argitoth (Jun 28, 2013)

That's sound advice, here's what I gathered from *Big Bob*'s post: because I'm new I really should take as much time as I need to familiarize myself with all features of Kscript explore the best ways of doing things.


----------



## argitoth (Jul 18, 2013)

is there an easier way? :( 

``````i := 0
``````key.E_ := get_ui_id(Kick1.key.E)
``````inc(i)
``````key.E := get_ui_id(Snare1.key.E)
``````inc(i)
``````key.E := get_ui_id(SnareRim1.key.E)
``````inc(i)
``````key.E := get_ui_id(SnareRoll1.key.E)
``````inc(i)
``````key.E := get_ui_id(Piccolo1.key.E)
``````inc(i)
``````key.E := get_ui_id(PiccoloRim1.key.E)
``````inc(i)
``````key.E := get_ui_id(PiccoloRoll1.key.E)
``````inc(i)
``````key.E := get_ui_id(HatTopClosed1.key.E)
``````inc(i)
``````key.E := get_ui_id(HatClosed1.key.E)
``````inc(i)
``````key.E := get_ui_id(HatSemiOpen1.key.E)
``````inc(i)
``````key.E := get_ui_id(HatOpen1.key.E)
``````inc(i)
``````key.E := get_ui_id(HatClosing1.key.E)
``````inc(i)
``````key.E := get_ui_id(HatChoke1.key.E)
``````inc(i)
``````key.E := get_ui_id(Kick2.key.E)
``````inc(i)
``````key.E := get_ui_id(Snare2.key.E)
``````inc(i)
``````key.E := get_ui_id(SnareRim2.key.E)
``````inc(i)
``````key.E := get_ui_id(SnareRoll2.key.E)
``````inc(i)
``````key.E := get_ui_id(Piccolo2.key.E)
``````inc(i)
``````key.E := get_ui_id(PiccoloRim2.key.E)
``````inc(i)
``````key.E := get_ui_id(PiccoloRoll2.key.E)
``````inc(i)
``````key.E := get_ui_id(HatTopClosed2.key.E)
``````inc(i)
``````key.E := get_ui_id(HatClosed2.key.E)
``````inc(i)
``````key.E := get_ui_id(HatSemiOpen2.key.E)
``````inc(i)
``````key.E := get_ui_id(HatOpen2.key.E)
``````inc(i)
``````key.E := get_ui_id(HatClosing2.key.E)
``````inc(i)
``````key.E := get_ui_id(HatChoke2.key.E)
``````inc(i)
``````key.E := get_ui_id(Kick3.key.E)
``````inc(i)
``````key.E := get_ui_id(Snare3.key.E)
``````inc(i)
``````key.E := get_ui_id(SnareRim3.key.E)
``````inc(i)
``````key.E := get_ui_id(SnareRoll3.key.E)
``````inc(i)
``````key.E := get_ui_id(Piccolo3.key.E)
``````inc(i)
``````key.E := get_ui_id(PiccoloRim3.key.E)
``````inc(i)
``````key.E := get_ui_id(PiccoloRoll3.key.E)
``````inc(i)
``````key.E := get_ui_id(HatTopClosed3.key.E)
``````inc(i)
``````key.E := get_ui_id(HatClosed3.key.E)
``````inc(i)
``````key.E := get_ui_id(HatSemiOpen3.key.E)
``````inc(i)
``````key.E := get_ui_id(HatOpen3.key.E)
``````inc(i)
``````key.E := get_ui_id(HatClosing3.key.E)
``````inc(i)
``````key.E := get_ui_id(HatChoke3.key.E)
``````inc(i)
``````key.E := get_ui_id(Kick4.key.E)
``````inc(i)
``````key.E := get_ui_id(Snare4.key.E)
``````inc(i)
``````key.E := get_ui_id(SnareRim4.key.E)
``````inc(i)
``````key.E := get_ui_id(SnareRoll4.key.E)
``````inc(i)
``````key.E := get_ui_id(Piccolo4.key.E)
``````inc(i)
``````key.E := get_ui_id(PiccoloRim4.key.E)
``````inc(i)
``````key.E := get_ui_id(PiccoloRoll4.key.E)
``````inc(i)
``````key.E := get_ui_id(HatTopClosed4.key.E)
``````inc(i)
``````key.E := get_ui_id(HatClosed4.key.E)
``````inc(i)
``````key.E := get_ui_id(HatSemiOpen4.key.E)
``````inc(i)
``````key.E := get_ui_id(HatOpen4.key.E)
``````inc(i)
``````key.E := get_ui_id(HatClosing4.key.E)
``````inc(i)
``````key.E := get_ui_id(HatChoke4.key.E)_


----------



## Big Bob (Jul 18, 2013)

Well for one thing, you could just drop the inc(i) s. If you are going to do it like this, why not just use literals for each assignment?



```
key.E[0] := get_ui_id(Kick1.key.E) 
key.E[1] := get_ui_id(Snare1.key.E) 
key.E[2] := get_ui_id(SnareRim1.key.E) 

... etc
```

I presume however that you were hoping to make these assignments in a for-loop? Unfortunately, until you build the ui_id array, you can only refer to these ui components by 'name'. And, currently, there is no way to cycle through such a list of names in a loop.

However, a ui_array is usually built with the declarative macros. For example:


```
macro declare_key(#name#,cx)
   declare ui_XXX #name#
   key.E[cx] := get_ui_id(#name#)
   ... etc.
end macro

declare_key(Kick1.key.E,0)
declare_key(Snare1.key.E,1)
  ... etc
```

It doesn't reduce the number of code lines compiled but it probably looks nicer at the source level. :lol: 

Rejoice,

Bob


----------



## argitoth (Jul 18, 2013)

Big Bob @ Thu Jul 18 said:


> Well for one thing, you could just drop the inc(i) s. If you are going to do it like this, why not just use literals for each assignment?


I tried that, but it's easy to skip one number as I have done multiple times. Another thing I might try is having the inc(i) inside the macro, so everytime the macro is called, it includes the inc(i). But your macro is a good idea as well.


----------



## Big Bob (Jul 19, 2013)

> Another thing I might try is having the inc(i) inside the macro, so every time the macro is called, it includes the inc(i). But your macro is a good idea as well.



Actually, my UI Library uses that idea to both assign an index and populate the ui_id array automatically with each ui declare. In addition I usually have my declare macros automatically populate several other arrays to facilitate show/hide panel groupings. 

However, I think that each scripter likes to find their own favorite way to handle such things.

Rejoice,

Bob


----------



## mk282 (Jul 20, 2013)

I just declare the ID array and use literal assignments. It's the fastest way to do it, because my Excel spreadsheet autogenerates it for me. :D


----------



## argitoth (Jul 20, 2013)

mk282 @ Sat Jul 20 said:


> I just declare the ID array and use literal assignments. It's the fastest way to do it, because my Excel spreadsheet autogenerates it for me. :D


ooo good idea!


----------

