How to write annotation for documentation in Kotlin? - kotlin

I would like to add documentation in source code not attached to any specific Kotlin class or method, it's like conceptual, high-level documentation.
I would like to keep it in the Kotlin source file, close to things it describes.
Ideally I would like to be able to write it as:
...
doc(
title = "Some title",
text = "Some text"
)
...
But it's not possible as Kotlin won't allow top level calls, I also tried to use annotations, but it's also not allowed without attaching something to it.
#Doc(
title = "Some title",
text = "Some text"
)
So, the code below works but it's not looks nice. Is there something better?
#Doc private val doc1 = doc(
title = "Some title",
text = "Some text"
)
Or maybe
#Doc(
title = "Some title",
text = "Some text"
) val tmp = 0

Related

Convert kotlin annotation to constant

I have written my custom annotation processor for my bot command system.
It looks like this:
#Command(
name = "User profile",
description = "Fetches user profile",
identifiers = ["user", "u", "гыук", "г"]
)
class UserProfileCommand (
#Argument(
name = "Player",
description = "Something written here",
identifiers = ["nick", "nickname", "тшсл", "тшслтфьу"],
required = true,
implicit = true
)
val actor: String,
#Argument(
name = "Server",
description = "Something written here",
identifiers = ["server", "s", "ыукмук", "ы"],
)
#Default("bancho")
val server: String,
#Argument(
name = "Mode",
description = "Something written here",
identifiers = ["mode", "m", "ьщву", "ь"],
)
#Default("default")
val mode: String,
#Argument(
name = "Render mode",
description = "Enables render mode",
identifiers = ["render", "r", "кутвук", "к"]
)
#Default("false")
val isRenderMode: Boolean
The problem is that I want to reuse some definitions of the arguments in other commands, so I want to move annotations to constants and use them.
object Arguments {
val Actor = Argument(
name = "Actor",
description = "",
identifiers = arrayOf("nick", "nickname", "тшсл", "тшслтфьу"),
required = true,
implicit = true
)
}
I can create instance of Argument like that and move it to constant but I cant find any way to use it. The example below unsurprisingly gives me error:
#Argument = Arguments.Actor
val actor: String,
Is there any way to achieve what I want? Is there any way I can to it without using code generation libraries? If I need to use these libraries, then which one can you recommend? How can I generate annotations with it?

The value of NumberPicker doesn't change

I'm a beginner in android and Kotlin.
I want to get string values I set as displayedValues from NumberPicker.
I tried, but It only returns Int numbers.
After some search, I found a question Formatted value of NumberPicker disappears onClick which might be the solution to my problem.
But I'm beginner and never studied java, so I couldn't apply it to my code. I need your help to figure out whether my code is correct and if it is, I hope to get a solution which can be applied to kotlin
Thankyou!
val pickers = arrayListOf(picker1,picker2,picker3,picker4,picker5,picker6,picker7)
for (picker in pickers) {
picker.displayedValues = arrayOf(
"0", "30", "40", "50", "60", "1시간", "1시간 30분", "2시간", "2시간 30분", "3시간", "3시간 30분", "4시간",
"4시간 30분", "5시간"
)
picker.minValue = 0
picker.maxValue = 13
picker.setFormatter { num -> picker.displayedValues[num] }
The translation of the answer there to Kotlin is
// do this outside the loop because it doesn't depend on picker
val f = NumberPicker::class.java.getDeclaredField("mInputText")
f.setAccessible(true)
// inside the loop
val inputText = f.get(picker) as EditText
inputText.setFilters(arrayOf())
(it's surrounded by try-catch which you can do in Kotlin as well if you want but the particular catch there is useless; and if you do it should be outside the for loop).

NSJSONSerialization.JSONObjectWithData changes field type

I'm getting the following JSON response from the server:
{
"userId":"123456789",
"displayName":"display name"
}
When I use NSJSONSerialization.JSONObjectWithData and then prints the result NSDictionary I see in the console the following:
userId = 123456789
displayName = "display name"
Why do JSONObjectWithData changes the userId field type from String to a number?
It doesn't. The JSON deserialisation respects the data type and will maintain it. You can't tell the data type from a simple description log, you need to actually interrogate the class. The description log will quote some things if it makes more sense for the human reader, like spaces in the description, but it also omits quotes in some cases.
It doesn't.
Don't infer a variable type from its log representation, just test. Fire a Playground with this, for example:
let str = "{\"userId\":\"123456789\",\"displayName\":\"display name\"}"
if let data = str.dataUsingEncoding(NSUTF8StringEncoding),
jsonResult = try? NSJSONSerialization.JSONObjectWithData(data, options: []),
jsonObject = jsonResult as? [String:String],
id = jsonObject["userId"] {
print("User ID is " + id)
}

Finding and replacing text in Intellij IDEA

What do I have:
More then 100 lines of fields with same structure:
var type1Name:String = "<some text>";
var type2Name:String = "<some text>";
<some text> is always different. name is always same.
What I want:
Delete all <some text> in all fields. This is more likely to "find and replace" operation, to find something like Name:String = "***"; and replace it with Name:String = ""; in all cases.
How can i do this with Intellij IDEA?
if it is in one file : ctrl + r check the tick box Regex and look for Name:String = \"[^\"]*\" : this should match what you want.
Then replace it with whatever you want.
If it is in multiple file, use ctrl + shift + r

Lucene Highlighter class: highlight different words in different colors

Probably most people reading the title who know a bit about Lucene won't need much further explanation. NB I use Jython but I think most Java users will understand the Java equivalent...
It's a classic thing to want to do: you have more than one term in your search string... in Lucene terms this returns a BooleanQuery. Then you use something like this code to highlight (NB I am a Lucene newbie, this is all closely tweaked from Net examples):
yellow_highlight = SimpleHTMLFormatter( '<b style="background-color:yellow">', '</b>' )
green_highlight = SimpleHTMLFormatter( '<b style="background-color:green">', '</b>' )
...
stream = FrenchAnalyzer( Version.LUCENE_46 ).tokenStream( "both", StringReader( both ) )
scorer = QueryScorer( fr_query, "both" )
fragmenter = SimpleSpanFragmenter(scorer)
highlighter = Highlighter( yellow_highlight, scorer )
highlighter.setTextFragmenter(fragmenter)
best_fragments = highlighter.getBestTextFragments( stream, both, True, 5 )
if best_fragments:
for best_frag in best_fragments:
print "=== best frag: %s, type %s" % ( best_frag, type( best_frag ))
html_text += "&bull %s<br>\n" % unicode( best_frag )
... and then the html_text is put in a JTextPane for example.
But how would you make the first word in your query highlight with a yellow background and the second word highlight with a green background? I have tried to understand the various classes in org.apache.lucene.search... to no avail. So my only way of learning was googling. I couldn't find any clues...
I asked this question four years ago... At the time I did manage to implement a solution using javax.swing.text.html.HTMLDocument. There's also the interface org.w3c.dom.html.HTMLDocument in the standard Java library. This way is hard work.
But for anyone interested there's a far simpler solution. Taking advantage of the fact that Lucene's SimpleHTMLFormatter returns about the simplest imaginable "marked up" piece of text: chosen words are highlighted with the HTML B tag. That's it. It's not even a "proper" HTML fragment, just a String with <B>s and </B>s in it.
A multi-word query generates a BooleanQuery... from which you can extract multiple TermQuerys by going booleanQuery.clauses() ... getQuery()
I'm working in Groovy. The colouring I want to apply is console codes, as per BASH (or Cygwin). Other types of colouring can be worked out on this model.
So you set up a map before to hold your "markup details":
def markupDetails = [:]
Then for each TermQuery, you call this, with the same text param each time, stipulating a different colour param for each term. NB I'm using Lucene 6.
def createHighlightAndAnalyseMarkup( TermQuery tq, String text, String colour ) {
def termQueryScorer = new QueryScorer( tq )
def termQueryHighlighter = new Highlighter( formatter, termQueryScorer )
TokenStream stream = TokenSources.getTokenStream( fieldName, null, text, analyser, -1 )
String[] frags = termQueryHighlighter.getBestFragments( stream, text, 999999 )
// not sure under what circs you get > 1 fragment...
assert frags.size() <= 1
// NB you don't always get all terms in all returned LDocuments...
if( frags.size() ) {
String highlightedFrag = frags[ 0 ]
Matcher boldTagMatcher = highlightedFrag =~ /<\/?B>/
def pos = 0
def previousEnd = 0
while( boldTagMatcher.find()) {
pos += boldTagMatcher.start() - previousEnd
previousEnd = boldTagMatcher.end()
markupDetails[ pos ] = boldTagMatcher.group() == '<B>'? colour : ConsoleColors.RESET
}
}
}
As I said, I wanted to colourise console output. The colour parameter in the method here is per the console colour codes as found here, for example. E.g. yellow is \033[033m. ConsoleColors.RESET is \033[0m and marks the place where each coloured bit of text stops.
... after you've finished doing this with all TermQuerys you will have a nice map telling you where individual colours begin and end. You work backwards from the end of the text so as to insert the "markup" at the right position in the String. NB here text is your original unmarked-up String:
markupDetails.sort().reverseEach{ pos, markup ->
String firstPart = text.substring( 0, pos )
String secondPart = text.substring( pos )
text = firstPart + markup + secondPart
}
... at the end of which text contains your marked-up String: print to console. Lovely.