Xmonad multiple submap key combos - xmonad

This answer describes how to create combo key bindings in Xmonad.
With additionalKeys I add my key bindings as a list to my XConfig configuration:
...
-- Does NOT work
, ((myModMask, xK_a), submap . M.fromList $
[ ((0, xK_l), submap . M.fromList $
[ ((0, xK_1), spawn "xbacklight -set 10" ) ])
])
-- Does work
, ((myModMask, xK_d), submap . M.fromList $
[ ((0, xK_l), submap . M.fromList $
[ ((0, xK_2), spawn "xbacklight -set 20" ) ])
])
-- Does work
, ((myModMask, xK_a), submap . M.fromList $
[ ((0, xK_l), submap . M.fromList $
[ ((0, xK_5), spawn "xbacklight -set 50" ) ])
])
...
But it seems like only the last defined combination of those starting with the same key works (here the first one starting with an "a" seems to be overridden by the last one).
What is different from the example in the linked answer is only that the combinations start with a modkey+key binding instead of just a key.
What could be the problem here?

I'm fairly certain that you can't have keymap list entries with the same keybinding - (myModMask, xK_a). In which case the last entry overrides the previous entry.
You can combine the two entries however:
((myModMask, xK_a), submap . M.fromList $
[ ((0, xK_l), submap . M.fromList $
[
((0, xK_1), spawn "xbacklight -set 10" )
, ((0, xK_5), spawn "xbacklight -set 50" )
]
)
]
)

You might also like to try EZConfig, which makes submaps for you given binding strings inspired by those in Emacs. For example:
import XMonad.Util.EZConfig
myKeymap :: [(String, X ())]
myKeymap =
[ ("M-; s m", namedScratchpadAction myScratchpads "mongod" )
, ("M-; s a m", namedScratchpadAction myScratchpads "mongod2" )
, ("M-; s z", namedScratchpadAction myScratchpads "zk" )
, ("M-; s k", namedScratchpadAction myScratchpads "kafka" )
-- ... and so on ...
use that with additionalKeys, see https://hackage.haskell.org/package/xmonad-contrib-0.13/docs/XMonad-Util-EZConfig.html

Related

What is wrong with my haskell general tree?

Here is my code and there are so many things wrong about it that i can't see.
What is the problem? or what "are" the problems?? I get these errors for several lines:
Data constructor not in scope. NBaum
Couldn't match expected type [NBaum [Char]]' with actual type `NBaum [Char]'
In the second argument of NKnoten', namely `(NBlatt "Io")'
In the sixth argument of `NBaum', namely
data NBaum a = NBlatt a | NKnoten a [NBaum a]
deriving(Eq,Show)
tree :: NBaum String
tree =
NBaum "Sonne"
(NKnoten "Erde"
(NBlatt "MOND" )
)
(NBlatt "Merkur" )
(NBlatt "Venus" )
(NKnoten "MARS"
(NBlatt "PHOBOS" )
(NBlatt "DEIMOS" )
)
(NKnoten "JUPITER"
(NBlatt "Io" )
(NBlatt "EUROPA" )
(NBlatt "GANYMED" )
(NBlatt "KALLISTO" )
)
The problem is that if you describe a list [], you do this between square brackets separated with commas, like [1,4,2,5]. Not between round brackets: that is a tuple.
tree :: NBaum String
tree = NKnoten "Sonne" [
NKnoten "Erde" [NBlatt "MOND"],
NBlatt "Merkur",
NBlatt "Venus",
NKnoten "MARS" [
NBlatt "PHOBOS",
NBlatt "DEIMOS"
],
NKnoten "JUPITER" [
NBlatt "Io",
NBlatt "EUROPA",
NBlatt "GANYMED",
NBlatt "KALLISTO"
]
]
Furthermore - as is highlighted in the code fragment - you (probably accidentally) - wrote the type name (NBaum) instead of constructor name (NKnoten) at the first object (the "Sonne").

Why does each behave differently inside word definitions?

To do a quotation for each in an array:
(scratchpad) { "3.1415" "4" } [ string>number ] each
3.1415
4
To do this inside a word:
(scratchpad) : conveach ( x -- y z ) [ string>number ] each ;
(scratchpad) { "3.1415" "4" } conveach .
But this throws an error:
The word conveach cannot be executed because it failed to compile
The input quotation to “each” doesn't match its expected effect
Input Expected Got
[ string>number ] ( ... x -- ... ) ( x -- x )
What am I doing wrong?
Factor requires all words to have a known stack effect. The compiler wants to know how many items the word eats from the stack and how many it puts back. In the listener, the code you type in doesn't have that restriction.
{ "3.1415" "4" } [ string>number ] each
Takes no items from the stack but puts two there. The stack effect would be denoted as ( -- x y ).
[ string>number ] each
This code on the other hand, takes one item but puts 0 to many items back on the stack. The number varies depending on how long the sequence given to each is.
! ( x -- x y z w )
{ "3" "4" "5" "6" } [ string>number ] each
! ( x -- )
{ } [ string>number ] each
! ( x -- x )
{ "2" } [ string>number ] each
You probably want to use the map word instead which would transform your sequence from one containing strings, to one containing numbers. Like this:
: convseq ( strings -- numbers ) [ string>number ] map ;
IN: scratchpad { "3" "4" } convseq .
{ 3 4 }

Combining a matrix of numbers, with array of strings

I am trying to compute the code seen below, in a more clever way, using MatLAB:
f=zeros(5,2) %Values irrelevant.
y = {'A1', 'B1';
f(1,1) f(1,2);
f(2,1) f(2,2);
f(3,1) f(3,2);
f(4,1) f(4,2);
f(5,1) f(5,2)};
What I get out is the f matrix with the text of A1 and B1 above the two vectors.
I suppose there is a simpler way to write this, for more complex purposing, but I've tried any combination of parenthesis, brackets and curly brackets, num2str that I could think of.
Any suggestions?
The simplest solution is to use num2cell and concatenate the result with the strings:
y = [{'A1', 'B1'}; num2cell(f)];
Example
>> f = reshape(1:10, 2, [])';
>> y = [{'A1', 'B1'}; num2cell(f)]
y =
'A1' 'B1'
[ 1] [ 2]
[ 3] [ 4]
[ 5] [ 6]
[ 7] [ 8]
[ 9] [10]

Clojure: Transform string into key-value pairs in hash-map

I'll start with my test using the speclj framework.
(it "turns the string into a hash-map"
(should= {1 "1" 2 "2" 3 "3"}
(format-string "1=1 2=2 3=3")))
Then my code:
(:use [clojure.string :only (split)])
(defn format-string [string]
(split string #"\s+"))
Right now, the format-string function returns ["1=1" "2=2" "3=3"] and the test fails. As you can see in my test, I want it to return a hash-map with key-value pairs indicated by the = sign.
I've tried a few things and I've gotten close, but can't quite understand how to make this transformation.
EDIT
Figured out one solution, although the keys are strings instead of integers.
My code:
(defn format-board [route]
(let [[first second third] (split route #"\s+")]
(merge
(apply hash-map (split-at-equals first))
(apply hash-map (split-at-equals second))
(apply hash-map (split-at-equals third))
This returns {"1" "1" "2" "2" "3" "3"}.
You have split at the spaces, but then you need to split again at the = delimiter. You can use regular expressions to do the parsing. Once you have your pairs you can assoc into a hash-map. Here I've used reduce to effect the transformation.
user=> (reduce #(assoc % (read-string (nth %2 1)) (nth %2 2)) {}
#_> (re-seq #"([^=\s]+)=([^=\s]+)" "1=1 2=2 3=3") )
{3 "3", 2 "2", 1 "1"}
Note key order is not applicable to hash-maps
user=> (= {1 "1", 2 "2", 3 "3"} *1)
true
Here is the potential parallel version using clojure.core.reducers:
(require '[clojure.core.reducers :as r])
(require '[clojure.string :as s])
(def string-of-pairs "1=1 2=2 3=3 4=4")
; reducing fn to convert seq of (key, value) to hash-map
(defn rf ([] {}) ([acc [k v]] (assoc acc k v)))
; for large colls, fold will parallelize execution
(r/fold merge rf (r/map #(s/split % #"=") (s/split string-of-pairs #"\s+")))
For better understanding of reducers, watch this video where
Rich explains motivation behind reducers and demonstrates some usage.

Haskell: define list over multiple lines

I'm defining a TestList (HUnit) and want to spread the definition over multiple lines. I came to the following solution:
tests = TestList ([TestLabel "test1" test1] ++
[TestLabel "test2" test2] ++
[TestLabel "test3" test3] ++
[TestLabel "test4" test4] ++
[TestLabel "test5" test5])
Is the use of the ++ operator the proper way to do such things?
Are there better or more elegant ways to do this?
I'd write
tests = TestList
[ TestLabel "test1" test1
, TestLabel "test2" test2
, TestLabel "test3" test3
, TestLabel "test4" test4
, TestLabel "test5" test5 ]
There's still place for improvements for #ephemient variant: don't use TestLabel at all, use ~: shortcut:
tests = TestList
[ "test1" ~: test1
, "test2" ~: test2
, "test3" ~: test3
, "test4" ~: test4
, "test5" ~: test5 ]
Note that there are more operators to construct assertions: #?, #=?, #?=. See http://hunit.sourceforge.net/HUnit-1.0/Guide.html or http://hackage.haskell.org/package/HUnit for details. The shortcuts use priorities and type classes cleverly, so you will get much less parentheses noise at the cost of slightly worse error messages.
Maybe I'm missing something, but why not just commas? This doesn't seem particularly unlike a normal list.
tests = TestList ([TestLabel "test1" test1,
TestLabel "test2" test2,
TestLabel "test3" test3,
TestLabel "test4" test4,
TestLabel "test5" test5])

Resources