Handle paragraphs in swift - swift

Is there a recommended way of handling paragraphs in swift? I am very new to swift so I'm not sure what the recommended solution or any solution for that matter is.
I want to be able to open a .txt file and be able to select a paragraph, selecting the paragraph needs to print the selected paragraph to a label.
I haven't got any code for this yet, other than opening and viewing the text file by doing the following:
let file = "/Users/wade/Desktop/ht.txt"
let path=URL(fileURLWithPath: file)
let text=try! String(contentsOf: path)
textView.stringValue = text
Once the .txt file is displayed I want to be able to click on a paragraph and have the paragraph display in a separate label
I am not fixed on using .txt files if there is a better format for achieving this
I'm guessing that printing to the label should be as easy as
let selectedParagraph = //however we identify the paragraph stringvalue
let thelabel = selectedParagraph.stringValue
But I need to know how to identify and get the text from the paragraph

Create a subsclass of NSTextView and use it to display the whole text. This will always select text by paragraph:
class ParagraphTextView: NSTextView {
override func selectionRange(forProposedRange proposedCharRange: NSRange,
granularity: NSSelectionGranularity) -> NSRange {
return super.selectionRange(forProposedRange: proposedCharRange,
granularity: .selectByParagraph)
}
}
Then set a delegate (NSTextViewDelegate) and track selection changes of the text view to update your secondary label with the current selection.

Related

How can I add text to a document footer using OpenXML?

I have a document template that I want to append some text to the footer. I've seen ways of deleting the footer to replace it, and ways to replace text in the footer, but I want to keep the footer as is from the template and just add to it. I have code to add text to the main doc., but unfortunately, main doc. parts are not setup the same way as footer parts. This is easily accomplished in Interop by a range.InsertAfter(text), but end users need this to work sans Word.
FooterPart footer = _doc.MainDocumentPart.FooterParts.ElementAtOrDefault(0);
string rid = _doc.MainDocumentPart.GetIdOfPart(footer);
footer = _doc.MainDocumentPart.AddNewPart<FooterPart>(rid);
Paragraph para = footer.AddPart(new Paragraph(), rid);
Run run = para.AppendChild(new Run());
// get the last footer of the document
FooterPart footerPart = _doc.MainDocumentPart.FooterParts.LastOrDefault();
// create your paragraph. i created simple, but you will need to add style properties to the run or text class
Paragraph pr = new Paragraph(new Run(new Text("hello")));
// Insert the Paragraph to the end of the footer in footerPart.Footer
footerPart.Footer.AppendChild(pr);
Other way as you said would be putting a text to replace like "txttoreplace" and then you will find it and replace
IEnumerable<FooterPart> footerPartsList = Documento.MainDocumentPart.FooterParts.ToList();
foreach (FooterPart hp in footerPartsList)
foreach (Text text in hp.RootElement.Descendants<Text>())
{
if (text.Text.Contains("txttoreplace"))
{
text.Text = text.Text.Replace("txttoreplace", "new text");
}
}
And another way and the hardest would be, you inser the whole footer, with open xml productivity tools you get the c# code of the footer.xml, and then you delete the footer of the document and you insert.

How to search for and highlight a substring in Codemirror 6?

I'm building a simple code editor to help children learn HTML. One feature I'm trying to add is that when users mouseover their rendered code (in an iframe), the corresponding HTML code in the editor is highlighted. So, for example, if a user mouses-over an image of kittens, the actual code, , would be highlighted in the editor.
Mousing-over the iframe to get the html source for that element is the easy part, which I've done (using document.elementFromPoint(e.clientX, e.clientY in the iframe itself, and posting that up to the parent) - so that's not the part I need help with. The part I can't figure out is how to search for and highlight that string of selected code in the code editor.
I'm using Codemirror 6 for this project, as it seems as it will give me the most flexibility to create such a feature. However, as a Codemirror 6 novice, I'm struggling with the documentation to find out where I should start. It seems like the steps I need to complete to accomplish this are:
Search for a range in the editor's text that matches a string (ie.'<img src="kittens.gif"').
Highlight that range in the editor.
Can anyone out there give me some advice as to where in the Codemirror 6 API I should look to start implementing this? It seems like it should be easy, but my unfamiliarity with the Codemirror API and the terse documentation is making this difficult.
1. Search for a range in the editor's text that matches a string (ie.'<img src="kittens.gif"').
You can use SearchCursor class (iterator) to get the character's range where is located the DOM element in your editor.
// the import for SearchCursor class
import {SearchCursor} from "#codemirror/search"
// your editor's view
let main_view = new EditorView({ /* your code */ });
// will create a cursor based on the doc content and the DOM element as a string (outerHTML)
let cursor = new SearchCursor(main_view.state.doc, element.outerHTML);
// will search the first match of the string element.outerHTML in the editor view main_view.state.doc
cursor.next()
// display the range where is located your DOM element in your editor
console.log(cursor.value);
2. Highlight that range in the editor.
As described in the migration documentation here, marked text is replace by decoration. To highlight a range in the editor with codemirror 6, you need to create one decoration and apply it in a dispatch on your view. This decoration need to be provide by an extension that you add in the extensions of your editor view.
// the import for the 3 new classes
import {StateEffect, StateField} from "#codemirror/state"
import {Decoration} from "#codemirror/view"
// code mirror effect that you will use to define the effect you want (the decoration)
const highlight_effect = StateEffect.define();
// define a new field that will be attached to your view state as an extension, update will be called at each editor's change
const highlight_extension = StateField.define({
create() { return Decoration.none },
update(value, transaction) {
value = value.map(transaction.changes)
for (let effect of transaction.effects) {
if (effect.is(highlight_effect)) value = value.update({add: effect.value, sort: true})
}
return value
},
provide: f => EditorView.decorations.from(f)
});
// this is your decoration where you can define the change you want : a css class or directly css attributes
const highlight_decoration = Decoration.mark({
// attributes: {style: "background-color: red"}
class: 'red_back'
});
// your editor's view
let main_view = new EditorView({
extensions: [highlight_extension]
});
// this is where the change takes effect by the dispatch. The of method instanciate the effect. You need to put this code where you want the change to take place
main_view.dispatch({
effects: highlight_effect.of([highlight_decoration.range(cursor.value.from, cursor.value.to)])
});
Hope it will help you to implement what you want ;)
Have a look at #codemirror/search.
Specifically, the source code implementation of Selection Matching may be of use for you to adapt.
It uses Decoration.mark over a range of text.
You can use SearchCursor to iterate over ranges that match your pattern (or RegExpCursor)
Use getSearchCursor, something like this:
var cursor = cmEditor.getSearchCursor(keyword , CodeMirror.Pos(cmEditor.firstLine(), 0), {caseFold: true, multiline: true});
if(cursor.find(false)){ //move to that position.
cmEditor.setSelection(cursor.from(), cursor.to());
cmEditor.scrollIntoView({from: cursor.from(), to: cursor.to()}, 20);
}
Programmatically search and select a keyword
Take a look at getSearchCursor source code it it give some glow about how it works and its usage.
So use getSearchCursor for finding text and optionally use markText for highlighting text because you can mark text with setSelection method of editor.
Selection Marking Demo
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
lineNumbers: true,
styleSelectedText: true
});
editor.markText({line: 6, ch: 26}, {line: 6, ch: 42}, {className: "styled-background"});
And it seem this is what you are looking for:
codemirror: search and highlight multipule words without dialog
RegExpCursor is another option that you can use:
new RegExpCursor(
text: Text,
query: string,
options⁠?: {ignoreCase⁠?: boolean},
from⁠?: number = 0,
to⁠?: number = text.length
)
Sample usage at:
Replacing text between dollar signs for Mathml expression.

Setting the cursor position within a SwiftUI TextEditor

Is there any way to programmatically move the cursor to a specific text line or select it within a SwifUI TextEditor?
For example, if there is a TextEditor with 10 lines written in it.
When the user presses a button, the cursor will navigate to, or the text will be selected on the 3rd line.
This is currently not possible using the default SwiftUI TextEditor. You can achieve the desired behavior by wrapping NSTextField(/UITextField) in a NSViewRepresentable(/UIViewRepresentable).
I recently implemented this for CodeEditor. You can check out the implementation there (especially the changes from my PR).
However, since you mentioned code in one of the comments, you might also just want to use CodeEditor as a whole.
With my implementation, you can provide the editor with a binding to a Range<String.Index>.
struct ContentView: View {
static private let initialSource = "let a = 42\n"
#State private var source = Self.initialSource
#State private var selection = Self.initialSource.endIndex..<Self.initialSource.endIndex
var body: some View {
CodeEditor(source: $source,
selection: $selection,
language: .swift,
theme: .ocean,
autoscroll: true)
Button("Select All") {
selection = source.startIndex..<source.endIndex
}
}
}
You can move the cursor by updating selection. If the range is "empty" you just move the cursor to the start index. Otherwise the characters from start (included) to end index (excluded) get selected.
The solutions provided here should allow you to find the right String.Index for the line you want to place your cursor in.
If you want to select the whole line, scan the string from this String.Index in both directions until you find a newline character.

NSSearchField - How to select all text? (Swift/Storyboards on macOS)

It seems everything online is mostly about iOS/UI controls, not macOS/Cocoa NS controls. Anyway, How does one make an NSSearchField select all text in the field programatically? I have tried multiple methods adapted from the iOS UISearchBar implementations, but none of them compiled or worked. I just want to, for instance, press a button and have it hilight the text that is inside the NSSearchField's text field. I can't seem to find a method within it that allows this to happen.
Thank you for your help/consideration!
All editing in NSTextField is handled by NSText (which inherits from NSTextView). So, to select the text in your search field, you need to set the selected range in field's current editor. This example highlights the whole text.
Objective-C:
NSRange range = NSMakeRange(0, searchField.stringValue.length);
NSText *editor = [searchField currentEditor];
[editor setSelectedRange:range];
Swift
let range = NSRange(location: 0, length: searchField.stringValue.length)
let editor = searchField.currentEditor()
editor?.selectedRange = range

Add Placeholder to UITextField, how to set the placeholder text programmatically in swift?

I'm pulling out a phone number from a database, and when the user begins editing in the text field to change that phone number I'd like to use the number I currently have in the database as the placeholder. Since this information changes with each user, how can I set it programmatically in swift?
You need to get the phone number from your database first (convert them to String), then you set placeholder of your textField to that String, like so
textField.placeholder = phoneNumberString
Swift 3
If your textField has text, you need to first set text property to nil, then set placeholder text:
textField.text = nil
textField.placeholder = "My Placeholder Text"
Important to note for anyone else reading this, setting placeholder text in the main.storyboard seems to nullify this solution, so I had to first clear out my placeholders in the storyboard before implementing this. Once that was done #Khuong and #Himanshu's answer worked perfectly.
Apply this line of code in to View Did Load
new_Password.attributedPlaceholder =
NSAttributedString(string: " New Password", attributes: [NSForegroundColorAttributeName : UIColor.white]) // new_Password : our text feild name
Fetch your desired data from your database (Core data) and after converting it into string format... say phoneString
use this line to set this string as a placeholder text
phoneTextField.placeholder = phoneString
Objective-C code:
[usernameText setPlaceholder:#"My Placeholder Text"];
Just a note to say if you have changed your textfield's text and background colors programmatically, you can't do that with the placeholder text's colors and must set up an Attributed Placeholder instead. This is a problem if your device is in put in "dark mode" and are trying to make a non-dark mode screen by hand - you might not be able to see the placeholder!